Files
soft_usite/pkg/services/plantilla_preview_test.go
T
Lizandro GuarnizoandClaude Opus 5 86cdb2d368 feat(plantillas): ver cómo queda la plantilla mientras se edita
Se editaba HTML a ciegas: había que guardar y generar un documento real para
saber si estaba bien. Ahora el modal tiene un panel de vista previa al lado del
editor, que se actualiza mientras se escribe y se abre solo al editar una
plantilla o al importar una con IA.

Se ejecuta la plantilla de verdad contra datos de ejemplo, no se reemplaza
texto: es la única forma de que {{range .Items}} y los campos anidados se vean
como van a salir, y de que un error de sintaxis aparezca mientras se edita en
vez de al generar el PDF. Los datos de ejemplo salen de DatosBaseDocumento,
igual que en producción, para que la vista previa no muestre una cosa y el
documento otra.

El iframe va en sandbox sin scripts ni same-origin: el HTML lo escribe un
admin, pero no tiene por qué correr con los permisos del panel.

De paso, la ayuda de variables ofrecía {{.Cliente.Nit}}, que no existe en el
modelo — el campo es Documento.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 21:28:06 -05:00

69 lines
2.5 KiB
Go

package services
import (
"strings"
"testing"
)
// La vista previa ejecuta la plantilla de verdad: es lo que hace que un
// {{range}} se vea como va a salir y que un error de sintaxis aparezca mientras
// se edita, y no recién al generar el documento.
func TestRenderizarPlantillaEjemplo(t *testing.T) {
html := `<h1>{{.Cliente.Nombre}}{{.Cliente.Documento}}</h1>
<p>{{.Alcance}}</p>
<table>{{range .Items}}<tr><td>{{.Descripcion}}</td><td>{{.Cantidad}}</td></tr>{{end}}</table>
<p>Total: {{.Total}}{{.Fecha}}{{.EmpresaNombre}}</p>`
out, err := RenderizarPlantillaEjemplo("cotizacion", html)
if err != nil {
t.Fatalf("RenderizarPlantillaEjemplo: %v", err)
}
for _, quiero := range []string{"Acme S.A.S.", "900.123.456-7", "Diseño de interfaz", "Integración con pasarela", "U-SITE"} {
if !strings.Contains(out, quiero) {
t.Errorf("falta %q en:\n%s", quiero, out)
}
}
if strings.Contains(out, "{{") {
t.Errorf("quedaron variables sin resolver:\n%s", out)
}
}
func TestRenderizarPlantillaEjemploAvisaDeErrores(t *testing.T) {
if _, err := RenderizarPlantillaEjemplo("cotizacion", "{{range .Items}}sin fin"); err == nil {
t.Error("un {{range}} sin {{end}} debería dar error")
}
// Una variable que no existe no rompe: se renderiza como "<no value>", igual
// que en la generación real. Eso se ve en la vista previa, que es el punto —
// hacerla más estricta que producción rechazaría plantillas que sí andan.
out, err := RenderizarPlantillaEjemplo("cotizacion", "Hola {{.NoExiste}}")
if err != nil {
t.Fatalf("no debería fallar: %v", err)
}
if !strings.Contains(out, "no value") {
t.Errorf("una variable inexistente tendría que notarse en la vista previa: %q", out)
}
}
// Cada tipo agrega sus propios campos; si esto se desincroniza de los
// generadores, la vista previa muestra una cosa y el PDF sale con otra.
func TestDatosDeEjemploPorTipo(t *testing.T) {
casos := map[string][]string{
"contrato": {"Servicio", "Periodicidad"},
"acta": {"Proyecto", "Entregables"},
"cuenta_cobro": {"Concepto", "Numero"},
}
for tipo, campos := range casos {
datos := DatosDeEjemploPlantilla(tipo)
for _, campo := range campos {
if _, ok := datos[campo]; !ok {
t.Errorf("faltan datos de ejemplo de %q para el tipo %q", campo, tipo)
}
}
for _, comun := range []string{"Cliente", "Fecha", "EmpresaNombre", "Total"} {
if _, ok := datos[comun]; !ok {
t.Errorf("falta el campo común %q en el tipo %q", comun, tipo)
}
}
}
}