package services import ( "strings" "testing" ) // Cuando se agotan las rondas de herramientas, el visitante recibía un mensaje // genérico aunque el modelo ya le hubiera escrito una respuesta completa: el // texto que viene junto con una llamada a herramienta se descartaba. // // Se prueba la lógica de selección, que es la que decide qué ve la persona. func TestSePrefiereElTextoDelModeloAlMensajeGenerico(t *testing.T) { const generico = "Un momento, por favor — dame un poco más de detalle sobre lo que necesitas." elegir := func(final, parcial string) string { if final != "" { return final } if strings.TrimSpace(parcial) != "" { return parcial } return generico } casos := []struct { nombre string final string parcial string esperado string }{ {"respuesta normal", "Los 4 pilares son…", "", "Los 4 pilares son…"}, {"se agotaron las rondas pero el modelo había escrito", "", "Los 4 pilares son…", "Los 4 pilares son…"}, {"el modelo nunca escribió nada", "", "", generico}, {"texto parcial en blanco no cuenta", "", " \n ", generico}, } for _, c := range casos { if got := elegir(c.final, c.parcial); got != c.esperado { t.Errorf("%s: eligió %q, esperaba %q", c.nombre, got, c.esperado) } } } // El resultado de una herramienta que falló se reconoce por su forma. Si esa // detección se rompe, el evento de diagnóstico deja de registrarse y "se // agotaron las rondas" vuelve a no decir dónde mirar. func TestSeDetectaElErrorDeUnaHerramienta(t *testing.T) { casos := map[string]bool{ `{"error": "consulta requerida"}`: true, ` {"error": "el servicio de embeddings no está configurado"}`: true, `{"resultados": ["texto"]}`: false, `{"resultados": [], "nota": "No se encontró información relacionada"}`: false, } for entrada, esError := range casos { got := strings.HasPrefix(strings.TrimSpace(entrada), `{"error"`) if got != esError { t.Errorf("%q: detectado como error = %v, esperaba %v", entrada, got, esError) } } }