// Creates a throwaway Postgres database per test-file run against the // docker-compose `db` service, points DATABASE_URL at it so tests never // touch a shared dev database, and drops it afterwards. Mirrors the old // sqlite temp-file-per-run isolation, adapted to Postgres (CREATE/DROP // DATABASE instead of a throwaway file). // // Creating/dropping the throwaway database itself stays raw `pg` (test // infra, not the app's data-access layer) — but applying the schema to the // fresh database, and tearing down the pooled connection afterwards, now // goes through Prisma instead of the old db.ts. import { randomUUID } from "node:crypto"; import { execSync } from "node:child_process"; import { Client } from "pg"; import { afterAll, beforeAll } from "vitest"; import { prisma } from "@/lib/prisma"; const baseUrl = new URL( process.env.DATABASE_URL || "postgres://asset_license_mgmt:change-me-local-dev@db:5432/asset_license_mgmt" ); const testDbName = `test_${randomUUID().replace(/-/g, "_")}`; function adminUrl(): string { const url = new URL(baseUrl.toString()); url.pathname = "/postgres"; return url.toString(); } async function withAdminClient(fn: (client: Client) => Promise): Promise { const client = new Client({ connectionString: adminUrl() }); await client.connect(); try { return await fn(client); } finally { await client.end(); } } beforeAll(async () => { await withAdminClient((client) => client.query(`CREATE DATABASE ${testDbName}`)); const testUrl = new URL(baseUrl.toString()); testUrl.pathname = `/${testDbName}`; process.env.DATABASE_URL = testUrl.toString(); // Apply the Prisma migration history to the fresh throwaway database. // `migrate deploy` replays the same real migrations production uses // (prisma/migrations), rather than a schema-diffing shortcut like // `db push` — keeping this test setup honest about what actually runs // outside tests too. execSync("npx prisma migrate deploy", { stdio: "inherit" }); }, 30_000); afterAll(async () => { // Disconnect the app's Prisma Client singleton first so the admin // connection is free to drop the database (DROP DATABASE ... WITH // (FORCE) would also disconnect it, but closing cleanly first avoids // relying on that). await prisma.$disconnect(); await withAdminClient((client) => client.query(`DROP DATABASE IF EXISTS ${testDbName} WITH (FORCE)`) ); });