CreaRack-SL

Workspace · Tests de integración con D1 real (pnpm run test:integration)

Claves de búsqueda: pnpm run test:integration · vitest · miniflare · workerd · cloudflare:test · @cloudflare/vitest-plugin · readD1Migrations · applyD1Migrations · tests D1 · vitest.workers.config.ts.

Qué es

El workspace (CreaRackSL-workspace) tiene dos capas de tests con vitest:

CapaComandoConfigDónde correQué prueba
Unitariapnpm run testvitest.config.tsNodeHelpers puros (test/*.test.ts: sanitize, markdown, front-matter, validate, guards…)
Integración D1pnpm run test:integrationvitest.workers.config.tsworkerd (miniflare) con una D1 efímera realHandlers de functions/api/** de punta a punta contra la BD (test/integration/*.test.ts)

La capa de integración nació en la Auditoría Suprema del Workspace: los handlers tocaban D1 con validaciones que ningún test unitario podía cubrir (un .bind() con un objeto daba un 500 opaco, etc.).

Cómo funciona (mecanismo)

  1. vitest.workers.config.ts carga el plugin cloudflareTest de @cloudflare/vitest-plugin (v1.x desde el 28-08-2026, task #275 / WS #164). El plugin levanta workerd vía miniflare, igual que wrangler dev.
  2. En ese config se lee la carpeta migrations/ con readD1Migrations('migrations') y se inyecta como binding de solo-test TEST_MIGRATIONS. Solo se declara el binding DB (d1Databases: ['DB']): no hay Vectorize, AI ni R2 — estos tests cubren lógica de BD pura (CRUD/validación), no el Oráculo ni el grafo.
  3. El setupFiles test/integration/apply-migrations.ts hace await applyD1Migrations(env.DB, env.TEST_MIGRATIONS) con top-level await: corre una vez por worker y siembra el storage; cada test recibe una copia limpia aislada (aislamiento del propio plugin).
  4. Los tests importan env desde el módulo virtual cloudflare:test y llaman a los handlers directamente (onRequestPost({ env, request, params })), luego comprueban filas con env.DB.prepare(...).
  5. test/integration/env.d.ts declara el módulo cloudflare:test mínimo (env.DB, env.TEST_MIGRATIONS, applyD1Migrations) para que tsc --noEmit (job “TypeScript check” del CI) resuelva los imports.

compatibilityDate: '2026-04-01' y compatibilityFlags: ['nodejs_compat'] van fijados en el config, no en wrangler.toml.

Tests que existen (28-08-2026)

  • news-crud.test.ts — CRUD de noticias: validaciones WS6-B9/B10 (tipo + longitud, simétricas POST/PUT) aplicadas de verdad contra D1.
  • deps-snapshot.test.ts — snapshot de la tool Dependencias (/api/tools/deps): los campos del motor fiable (migración 0052) y los de retención deliberada (0053, task #275); un payload viejo sin esos campos sigue entrando.

En el CI

.github/workflows/ci.yml corre las dos capas en secuencia: pnpm run test y después pnpm run test:integration. Cualquier migración nueva en migrations/ se aplica sola en el siguiente run (no hay que registrarla en ningún sitio para los tests).

Cómo añadir un test de integración

  1. Fichero en test/integration/<tema>.test.ts (el include del config es test/integration/**/*.test.ts).
  2. import { env } from 'cloudflare:test' + el handler de functions/api/....
  3. beforeEach que limpie las tablas que uses (DELETE FROM ...): el storage es por worker, no por test.
  4. Si el test necesita un binding nuevo (R2, Vectorize…), hay que declararlo en miniflare del config y en env.d.ts; hoy solo existe DB.

Trampas conocidas

  • El módulo cloudflare:test solo existe dentro del pool de workerd: importarlo desde un test unitario (config Node) falla.
  • Las migraciones se leen del repo, no de la D1 remota: si una migración se aplicó a mano en PROD sin fichero (footgun d1_migrations_out_of_band), los tests no la ven.
  • Correr pnpm run test:integration en local necesita que workerd se haya descargado (dependencia de miniflare; la primera vez tarda).

Véase también

  • [[workspace-tech—bd—tecnico]]
  • [[concept—workspace—supercontexto-05-crons]]