hbox-docs/backend/TESTS-1013.md

144 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Pruebas del 13-oct — backend (tareas, plan, inventario, sitios) y páginas
Todo se corrió en el sandbox contra `backend/app.py` arrancado con carpetas temporales
(`ACTAS_DIR=<tmp>/actas`; las demás colecciones se deducen de ahí). Sin nginx: el usuario se
inyecta con la cabecera `X-Remote-User` tal como la fija nginx en producción. Nada de lo de
abajo toca el servidor real.
## 1 · Backend — `backend/tests-1013.sh` (61 comprobaciones)
El script arranca `app.py` en un puerto libre, ejercita cada endpoint nuevo con `curl` como
**leo** (admin) y como **alan** (técnico), corre la siembra dos veces y una importación `--extra`.
Se puede repetir en cualquier máquina con Python 3 + Flask:
```bash
bash backend/tests-1013.sh /ruta/a/hbox-docs 8098
```
Resultado de la corrida (13-oct-2026):
```
## salud y endpoints viejos
✓ salud
✓ whoami leo admin
✓ actas vacías
## tareas
✓ sin usuario → 403
✓ POST (alan)
✓ POST id duplicado → 409
✓ POST pista inválida → 400
✓ POST fecha inválida → 400
✓ GET filtro pista
✓ GET filtro responsable
✓ vencida calculada
✓ PATCH mover (alan) → historial con quién
✓ PATCH sin cambios
✓ PATCH estado inválido → 400
✓ PATCH inexistente → 404
✓ POST orden (renumera columna: t-b cambia de columna, t-a de posición)
✓ resumen
✓ resumen vencidas
✓ DELETE alan → 403
✓ DELETE leo → ok
✓ índice CSV escrito
## plan
✓ GET sin archivo → por omisión
✓ PUT alan → 403
✓ PUT leo
✓ PUT conserva etapas
✓ PUT sin versiones → 400
## inventario
✓ POST ítem (alan)
✓ POST código duplicado → 409
✓ POST categoría inválida → 400
✓ POST con stock_inicial → entrada
✓ salida sin stock → 409
✓ entrada
✓ salida
✓ ajuste (conteo 4 → delta −3)
✓ sin motivo → 400
✓ alerta = stock < mínimo
✓ PATCH stock a mano → 400
✓ PATCH ubicación → historial
✓ movimientos del ítem
✓ export CSV
✓ export CSV cabecera
## sitios
✓ POST alan → 403
✓ POST leo
✓ POST duplicado → 409
✓ PATCH alan → 403
✓ PATCH leo → historial
✓ GET sitios
✓ unidades del sitio
✓ coincidencia por slug
✓ coincidencia por texto (terminal/destino)
✓ instalada con fecha
✓ marca de daño en la unidad
✓ sitio inexistente → 404
✓ /api/unidad trae sitio
✓ /api/actas trae sitio
## siembra (idempotente)
✓ primera corrida crea
✓ sitios: 3 nuevos (icave ya existía)
✓ segunda corrida no duplica
✓ inventario no duplica
✓ --extra importa
✓ resumen tras siembra (1 + 12 sembrados + 1 extra)
RESULTADO: 61 correctas · 0 fallidas · datos en <tmp>
```
Qué cubre, por colección:
| Colección | Probado |
|---|---|
| `tareas` | 403 sin usuario; POST con y sin `id`; 409 por id duplicado; 400 por pista/estado/fecha inválidos; filtros `pista`, `responsable`; `vencida`; PATCH que mueve de columna y deja `historial` con **quién**; PATCH sin cambios; 404; `POST /api/tareas/orden`; `resumen` (conteo y vencidas); DELETE 403 para técnico y ok para admin; `_indice.csv` |
| `plan` | GET devuelve el plan por omisión (`_default`) sin archivo; PUT 403 para técnico; PUT admin guarda `actualizado_por` y conserva las `etapas`; 400 sin versiones |
| `inventario` | POST ítem; 409 código duplicado (insensible a mayúsculas); 400 categoría inválida; `stock_inicial` → entrada; salida mayor al stock → 409; entrada/salida/ajuste con `delta` y `stock_despues`; 400 sin motivo; `alerta` = stock < mínimo; PATCH `stock` rechazado; PATCH con historial; listado de movimientos; CSV con cabecera `text/csv` |
| `sitios` | POST/PATCH 403 para técnico; POST admin; 409 duplicado; PATCH con historial; GET; `/api/sitio/unidades` con coincidencia por slug (`sitio`) y por texto (`terminal`, destino de envío), fecha de instalación, marca de daño; 404 |
| actas existentes | `/api/actas` y `/api/unidad` ahora traen `sitio` (y `fecha`, `componentes` en las propias) sin romper lo demás |
| `seed_1013.py` | primera corrida crea plan, 4 sitios, 18 ítems, 12 pendientes; la segunda no duplica nada; `--extra archivo.json` importa pendientes adicionales (Notion) de forma idempotente |
Además, antes del script: `python3 -m py_compile backend/app.py` sin errores; los endpoints
viejos (`/api/salud`, `/api/whoami`, `/api/actas`, `/api/acta`, `/api/adjuntos`, `/api/unidad`,
`/api/series`, `/api/estado`, `/api/danos`) se usaron desde las páginas durante las pruebas de
navegador sin cambios de comportamiento.
## 2 · Páginas — navegador real (Chromium headless con Playwright)
Se sirvió `docs/` tal cual con un proxy que reenvía `/api/` al backend y pone `X-Remote-User`
(un servidor como **leo** y otro como **alan**). Pruebas en teléfono (390×844, táctil) y escritorio.
| Página | Probado | Resultado |
|---|---|---|
| `tableros/kanban.html` | carga 12 pendientes sembrados; en teléfono se ve «Mover a…» y mueve de columna; el historial del detalle dice `alan · estado: por-hacer → en-curso`; alan no ve «Borrar»; crear pendiente con fecha pasada → tarjeta roja (vencida); filtro por pista; en escritorio **arrastrar y soltar** a Hecho; leo borra con confirmación | ✓ sin errores de consola |
| `tableros/ingenieria.html` | 4 tarjetas de versión con enlaces; pendientes filtrados a Ingeniería; contador por versión | ✓ |
| `tableros/produccion.html` | KPIs, plan vs real, embudo, bloqueos, alertas, daños; leo ve «Editar plan» y guarda una fecha objetivo; alan no ve el botón | ✓ |
| `inventario/inventario.html` | 18 ítems; ajuste a 15 desde el diálogo; salida de 99 → error visible «No hay stock suficiente»; historial del ítem; nuevo ítem con stock inicial 3; filtro «solo alertas»; export CSV con `Content-Disposition` | ✓ (el único mensaje de consola es el 409 esperado) |
| `formularios/instalacion.html` | lista de sitios desde `/api/sitios`; técnico precargado; unidad «otra»; exige las 3 fotos obligatorias; con fotos subidas envía: «Registro enviado … con 3 foto(s)»; segunda visita muestra el historial | ✓ |
| `formularios/envio.html` · `dano.html` | el select de sitio existe; en daño solo aparece al elegir «En campo / transporte / no se sabe» | ✓ |
| `sitios/sitio.html` | LZC muestra la unidad recién instalada; ICAVE muestra RTK-014 «por texto» (acta vieja sin sitio) y DAÑADA; alan no ve «Editar sitio»; leo edita ubicación + contacto y crea un sitio nuevo desde el selector | ✓ |
| `unidad.html` | bloque «Trazabilidad»: cadena de producción (módulos deducidos del número de unidad cuando no hay ensamble) y cadena de campo con sitio y fecha | ✓ |
Artefactos de Playwright (no van al repo): capturas `kanban-leo.png`, `produccion.png`,
`inventario-movil.png`, `instalacion-movil.png`, `sitio-icave.png`, `unidad.png`.
Dos falsos negativos que salieron en el camino y son del arnés de prueba, no de las páginas:
(1) Playwright hace scroll entre `mousedown` y `dragstart`, así que con una ventana corta
arrastraba la tarjeta equivocada — se resolvió con una ventana alta; (2) disparar `change`
sintético en el campo «otra unidad» y luego el `change` nativo al perder el foco hacía dos
`loadSerie()` — se resolvió haciendo blur normal (Tab), como lo haría un usuario.
## 3 · Sitio estático
- `mkdocs build --strict` sobre una copia: **55 advertencias, las mismas 55 de antes** (PDF y
binarios que no existen en esta copia). Ninguna menciona `tableros/`, `inventario/`, `sitios/`,
`instalacion.html` ni `unidad.html`. Las tres páginas `.md` nuevas se construyen (quedan fuera
del `nav` hasta que se aplique la nueva navegación; ver `NUEVOS-1013.md`).
- Comprobación de referencias en los HTML nuevos y modificados (todo `src`/`href` relativo y
los enlaces `../hardware/…/` dentro del JS): **0 rotas**.
- `node --check` sobre `tableros/kanban.js` y `formularios/acta.js`: sin errores de sintaxis.
- El `<script>` embebido en `sitios/index.md` sobrevive al render de Markdown (verificado en
el HTML generado).