Skip to main content

Testing

La regla del proyecto

El backend se desarrolla con TDD. El frontend y el mobile, no.

En oxitesa-front y oxitec-mobile-app no hay specs y no hay que escribirlos: se validan con tsc --noEmit, el build, y revisión visual del usuario.

Comandos (backend)

npm test # toda la suite
npm run test:watch
npm run test:coverage # → coverage/
npm run test:docker # la suite dentro de node:20-slim (requiere Docker Desktop)

npx jest tests/unit/GrantUtils.test.ts # un archivo
npx jest -t "devuelve true para una ruta" # por nombre del test

Lo importante: MySQL y Redis están mockeados

tests/setup/mockConnections.ts (registrado en setupFiles) mockea la conexión a base y a Redis en todas las suites. Ningún test toca MySQL, MSSQL ni Redis reales.

Para stubear datos en un test, importá el singleton (ya mockeado) y usá las factories de tests/mocks/typeorm.ts:

createMockRepository()
createMockQueryRunner()
createMockDataSource()

La plantilla mínima está en tests/unit/mocks.smoke.test.ts.

Estructura

tests/
├── unit/ unidades puras (SearchUtils, SpErrorUtils, GrantUtils, middlewares…)
├── integration/ app.e2e.test.ts — Supertest, hoy en describe.skip
├── modules/ el grueso de la suite, por dominio:
│ ├── deliveryNote/ entrega · visita · retiro · cancelacion · comentarios ·
│ │ list · reclasificacion
│ ├── dispatch/ hojas de ruta: creación, editar, fallar/reanudar/transferir
│ │ tarea, reordenar, optimizar ruta, reservas, stock de vehículo
│ ├── mercaderia/ ingreso, transferencia, unicidad de serial
│ ├── patient/ carga de suministros
│ └── reports/
├── mocks/ setup/ utils/
"integration" no significa base real

Los *.integration.test.ts de tests/modules/ siguen usando los mocks globales. Acá "integration" quiere decir que ejercitan varias capas, no que peguen a una base.

Cada carpeta grande tiene su test.md con el inventario de casos cubiertos.

Dos suites que no son Jest

1. Tests SQL de los stored procedures

oxitesa-backend/migrations/finances/test/*.sql. Corren contra una base real (PRE) y son la única forma de probar el pipeline de cierre de verdad.

Patrón: abrir transacción → crear entidades frescas → assertions → ROLLBACK. Aislamiento total del entorno productivo.

  • Naming: T<sección>.<n> (T2.3, T_BUG_CART_1, T_DN13701_REPRO).
  • Las constantes se resuelven por CODE, nunca por id hardcodeado.
  • El catálogo grande es transaction_close_delivery_note_edge_cases.sql.
  • Bugs conocidos y sus fixes: test/SP_BUGS_FOUND.md.

2. Entorno Docker reproducible

Dockerfile.test (node:20-slim, npm ci) + docker-compose.test.yml corren la suite Jest en un contenedor, con instalación determinística desde el lockfile. No levanta MySQL ni Redis: todo está mockeado.

npm run test:docker

Husky

HookQué corre
pre-commitlint-staged: Prettier + ESLint + jest --findRelatedTests solo sobre lo staged
pre-pushaudit:whitelist + la suite completa

Para que --findRelatedTests pueda mapear src/ → tests, jest.config.js incluye src en roots (y testMatch restringe los specs a tests/).

No uses --no-verify salvo emergencia real.

Gotchas

TESTS=true cambia el comportamiento de producción

jest.setup.ts carga el .env y fuerza TESTS=true. Con esa variable puesta:

  • unhandledException devuelve el mensaje crudo del error al cliente.
  • logRequest persiste en ErrorLog (sin ella, no persiste nada).

No la dejes seteada fuera de tests.

  • El e2e con Supertest está en describe.skip porque arrastra el bootstrap completo (controllers + módulos), no porque necesite servicios externos. Se puede habilitar.
  • Los tests compilan con tsconfig.test.json y los alias de path se resuelven por moduleNameMapper de Jest. Si agregás un alias nuevo, tenés que ponerlo en los dos lados.