Files
DeskcommCRM/vitest.db.config.ts
T
Rafael MelgaçoandClaude Opus 5 afc8e0f1fb fix(#207): o gate de invariantes para de dar veredito por sorteio
Fecha a #207. `invariants` e check obrigatorio e carrega o teste de isolamento
multi-tenant — mas o veredito dele nao era funcao do codigo. Medido em a8b09280,
100 arquivos, `--sequence.shuffle.files`:

  seed 101 -> EXIT 0
  seed 202 -> EXIT 1   agent-send-template-turn (4 testes)
  seed 303 -> EXIT 1   gov-1b-team-manager-read (beforeAll: FK de organization_id)
  seed 404 -> EXIT 1   agent-send-template-turn (4 testes)

3 de 4 vermelhas — por colisao de fixture ENTRE ARQUIVOS, nao por defeito do
produto. E a ordem "default" tambem nao e estavel: tres maquinas deram tres
vitimas diferentes, incluindo "nenhuma".

CAUSA, com prova direta (dois runs seguidos, sem reset entre eles):
  human-cases.test.ts:39           SESSION_A    = cccccccc-…-0003, provider waha
  agent-send-template-turn.ts:54   SESSION_META = o MESMO uuid,    provider meta_cloud
  Quem chega depois usa `on conflict (id) do nothing`: nao cria, NAO RECLAMA. Se
  human-cases roda antes, o provider fica `waha`, `loadChannelProvider` devolve
  waha, o motor apaga a tool `send_template`, e 4 assercoes caem dizendo "o
  template nao saiu" com o produto CERTO.
  Idem colisao de slug entre gov-1b (dddddddd-…-0001) e gov-6 (eeeeeeee-…-0002).

O CONSERTO NAO TOCA `tests/invariants/**` — e isso foi restricao de projeto, nao
sorte: `loop/hooks/freeze-invariants.sh` bloqueia M/D/R ali, e o hook diz que
invariante mal-escrito vai para a inbox, nao para o Edit. Entao o isolamento
passou a morar no HARNESS, que esta fora do congelamento: o baseline e aplicado
UMA vez num banco-MOLDE (`inv_baseline`) e cada ARQUIVO recebe uma copia nova
dele (`create database postgres template inv_baseline`, ~0,2s), por um setupFile
declarado em vitest.db.config.ts. Renomear UUID arquivo a arquivo consertaria as
duas instancias; o molde conserta a CLASSE, e nenhuma fixture nova pode
reintroduzi-la.

Com isso o `--sequence.shuffle.files=true` entra no proprio script — a ordem
deixa de ser um acordo tacito e passa a ser exercitada a cada run.

MEDIDO POR MIM, com o script real (nao replica), nas tres seeds que eram vermelhas:
  seed 202 -> EXIT 0   Test Files 101 passed (101)
  seed 303 -> EXIT 0   Test Files 101 passed (101)
  seed 404 -> EXIT 0   Test Files 101 passed (101) | 720 passed | 1 expected fail | 1 skipped

CUSTO, com o par de numeros discordantes rotulado: a contabilidade do vitest diz
+22,8s de setup em 101 arquivos (~0,23s/arquivo, +20% wall-clock); mas as rodadas
da loteria levavam 153-155s contra ~161s do conserto, porque um arquivo que
estoura no beforeAll "termina" rapido. O gate ficou ~5% mais lento e passou a
medir o que diz medir.

DESTRAVA A #236: dois invariantes inserem o MESMO meta_phone_number_id='111' em
orgs diferentes, o que hoje impede criar a unique que aquela issue pede. Com o
banco por arquivo, a colisao deixa de existir.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfAjBEKuCkL6tpUo77kUe
2026-08-13 10:06:23 -03:00

43 lines
2.2 KiB
TypeScript

import { defineConfig } from "vitest/config";
import path from "node:path";
// Config dedicada da suíte de invariantes de banco (tests/invariants/**).
// Roda SÓ via `pnpm test:db` (scripts/test-db.sh), que sobe o Postgres efêmero
// e exporta TEST_DB_CONTAINER. Não faz parte do `pnpm test:unit`.
export default defineConfig({
test: {
environment: "node",
include: ["tests/invariants/**/*.test.ts"],
globals: false,
// Seed + queries via docker exec são lentos o suficiente pro default de 5s.
testTimeout: 30_000,
hookTimeout: 60_000,
// Todos os arquivos batem no MESMO container Postgres efêmero, com estado
// GLOBAL compartilhado entre arquivos: helpers de contagem não-escopada
// (ex.: automation-engine.test.ts's runsCount() sobre automation_rule_runs)
// E o ponteiro platform do playbook (playbook-seed deleta/recria;
// agent-no-credential depende dele). Rodar os arquivos em paralelo cria
// interferência cross-file (flakiness real observada nos dois casos).
fileParallelism: false,
// Banco NOVO por arquivo, copiado do molde que scripts/test-db.sh preparou.
// É o que tira a ordem de execução de dentro do veredito (issue #207): sem
// isto os arquivos dividem estado global, colidem em UUID de fixture e
// `--sequence.shuffle.files` fica vermelho em 3 de 4 seeds — por colisão de
// fixture, não por defeito do produto. Guardado por
// tests/invariants/harness-isola-por-arquivo.test.ts.
setupFiles: ["./tests/db/banco-limpo-por-arquivo.ts"],
// webhooks-trigger-events.test.ts chama os handlers REST diretamente (não
// só SQL cru), e eles importam lib/env transitivamente (via lib/audit) —
// sem isso o import falha (env obrigatória ausente) e derruba a suíte
// inteira. audit()/emit_event reais nunca são alcançados (fetch falha
// rápido contra porta fechada, engolido pelo try/catch de audit()).
env: {
NEXT_PUBLIC_SUPABASE_URL: "http://127.0.0.1:1",
NEXT_PUBLIC_SUPABASE_ANON_KEY: "test-anon-key",
SUPABASE_SERVICE_ROLE_KEY:
"test-service-role-key-not-a-placeholder-1234567890-1234567890",
},
},
resolve: { alias: { "@": path.resolve(__dirname, ".") } },
});