fix: isolate Prisma Client per test file, re-enable fileParallelism

Root-cause fix for cross-file DB pollution in the vitest suite, which
surfaced as intermittent FK-violation failures once the suite hit 12
test files. tests/setup.ts previously mutated the global
process.env.DATABASE_URL and relied on src/lib/prisma.ts's singleton
picking it up, which is racy across files sharing a worker process
(process.env isn't reset between files even though Vitest resets each
file's module registry). fileParallelism: false only masked this.

Now each test file's own tests/setup.ts creates its own throwaway
Postgres database and vi.mock()s "@/lib/prisma" with a dedicated
PrismaClient constructed via the explicit datasourceUrl option, so no
mutable state is shared between files and fileParallelism can go back
to its default (true).

Verified with 4 consecutive full `npm test` runs (327/327 passing each
time) and no leftover throwaway databases after each run.
This commit is contained in:
toanhoang
2026-08-04 06:04:23 -04:00
parent 91624d5f07
commit 7e1351bde2
3 changed files with 71 additions and 34 deletions
+7 -13
View File
@@ -20,18 +20,12 @@ export default defineConfig({
// second worktree existed.
include: ["tests/**/*.test.ts"],
setupFiles: ["./tests/setup.ts"],
// Each test file spins up its own throwaway Postgres database by
// mutating process.env.DATABASE_URL in tests/setup.ts's beforeAll (see
// that file). That per-file DB switch is not safe under Vitest's default
// parallel file execution: two files' beforeAll/query timing can
// interleave such that both end up issuing real queries against the
// same throwaway DB (confirmed empirically once Request gained a real
// FK to Employee — tests/employees.test.ts and tests/requests.test.ts
// started intermittently deleting/reading each other's rows, causing
// spurious FK-violation and row-count failures that disappear when run
// sequentially). Disabling file parallelism trades a bit of wall-clock
// test time for correctness — each file's throwaway DB is now genuinely
// private for the duration of that file's run.
fileParallelism: false,
// Each test file gets its own throwaway Postgres database and its own
// dedicated PrismaClient, wired up via a `vi.mock("@/lib/prisma", ...)`
// factory in tests/setup.ts (not by mutating the ambient
// process.env.DATABASE_URL, which used to be shared/racy across files —
// see the long comment at the top of tests/setup.ts for the history).
// With no mutable state shared between files, parallel file execution
// (Vitest's default) is safe again.
},
});