# 0048 — Visual tests via primitives_gallery (golden screenshots) + CI gate para nuevas funciones ## Metadata | Campo | Valor | |-------|-------| | **ID** | 0048 | | **Estado** | pendiente | | **Prioridad** | media | | **Tipo** | feature — testing infra + CI | ## Dependencias Bloquea-por: **0047** (Catch2 montado). --- ## Objetivo 1. Anadir captura automatica de screenshots por demo en `primitives_gallery`, comparados pixel-a-pixel contra goldens en `cpp/tests/golden/`. Cada PR que toque un primitivo de UI muestra el diff. 2. CI gate: PR que anada funcion nueva en `cpp/functions/` exige `tested: true` en el `.md`. ## Contexto `primitives_gallery` ya renderiza cada primitivo del registry con datos sinteticos. Si capturamos PNGs por demo y los comparamos con goldens commiteados, tenemos test visual automatico para cualquier cambio que afecte a render. ## Arquitectura ``` cpp/ ├── apps/primitives_gallery/ │ ├── main.cpp # MOD — flag --capture │ └── capture.{h,cpp} # NEW — render headless por demo, dump PNG ├── tests/ │ ├── golden/ # NEW │ │ ├── button.png │ │ ├── select.png │ │ ├── kpi_card.png │ │ └── ... (1 png por demo del gallery) │ ├── test_visual.cpp # NEW — corre gallery con --capture, compara con golden │ └── CMakeLists.txt # MOD └── scripts/ ├── run_tests.sh # MOD — incluye visual └── update_goldens.sh # NEW — regenera goldens ``` ## Tareas ### Fase 1 — Capture mode en primitives_gallery 1.1 Anadir flag `--capture `. Cuando esta activo: - Inicializa GLFW en modo offscreen (`glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE)`) o usa headless via EGL si esta disponible. - Para cada demo en `k_demos[]`: setea `g_selected_id`, hace 3 frames de warmup (para tooltips/animaciones estables), captura framebuffer con `glReadPixels`, guarda como PNG via `stb_image_write`. - Output: `/.png`. - Sale tras procesar todas. 1.2 Si `--capture` no esta presente: comportamiento normal (interactivo). ### Fase 2 — Goldens iniciales 2.1 `scripts/update_goldens.sh`: ```bash #!/usr/bin/env bash mkdir -p cpp/tests/golden ./cpp/build/apps/primitives_gallery/primitives_gallery --capture cpp/tests/golden ``` 2.2 Generar y commitear los PNGs como linea base. ### Fase 3 — Test visual 3.1 `test_visual.cpp` (Catch2): para cada demo, lanzar gallery con `--capture` a un dir temporal, comparar contra `cpp/tests/golden/.png` con tolerancia configurable (por defecto: 1% pixels distintos, threshold por canal 5/255). 3.2 Si difiere, fallar con info: `expected golden/X.png, actual /tmp/.../X.png, diff Y%`. ### Fase 4 — CI gate para tested:true 4.1 Crear `cpp/scripts/check_tested.sh` que valida: ```bash sqlite3 registry.db "SELECT id FROM functions WHERE lang='cpp' AND tested=0 AND created_at > date('now','-30 days')" ``` Si hay alguno → exit 1 con mensaje "anade test antes de mergear". 4.2 Ganchar en `cpp/scripts/run_tests.sh` (post-ctest). ### Fase 5 — Documentar en PATTERNS 5.1 En `cpp/PATTERNS.md` (de 0041) anadir seccion "Tests visuales": - Como capturar nuevo golden cuando se anade un primitivo (`update_goldens.sh`). - Como diagnosticar diff (renderiza el png actual vs golden lado a lado). ## Decisiones - Headless via GLFW invisible es lo simple. Si no funciona en algun entorno, usar EGL/swiftshader como fallback. - Tolerancia 1% para evitar flakes por antialiasing/font rendering distinto. Ajustable. - Goldens en repo (PNGs binarios) — pesa poco si los demos son pequenos (200x200 max). ## Riesgos - Diferencias de rendering entre Linux dev y CI: usar mesa software rendering (`LIBGL_ALWAYS_SOFTWARE=1`) en ambos lados para consistencia. - Cambios cosmeticos legitimos en primitivos requieren regenerar goldens — flujo: `update_goldens.sh && git diff cpp/tests/golden/` para revisar visualmente. ## Validacion ```bash cmake --build cpp/build -j ctest --test-dir cpp/build -R visual --output-on-failure # Cambia un color en tokens, run otra vez, debe FALLAR. # update_goldens.sh + git diff muestra los pngs cambiados. ```