import { execFileSync } from "node:child_process" import { PostgreSqlContainer, type StartedPostgreSqlContainer, } from "@testcontainers/postgresql" import type { PrismaClient } from "@/generated/prisma/client" type TestDatabaseState = { container?: StartedPostgreSqlContainer databaseUrl?: string } const state: TestDatabaseState = {} const TABLES_TO_TRUNCATE = [ "Movement", "Assignment", "Asset", "Item", "Category", "Recipient", "User", ] export async function startIntegrationTestDatabase() { if (state.container && state.databaseUrl) { return state.databaseUrl } const container = await new PostgreSqlContainer("postgres:18-alpine") .withDatabase("stock_manager_test") .withUsername("test") .withPassword("test") .start() const databaseUrl = container.getConnectionUri() state.container = container state.databaseUrl = databaseUrl process.env.DATABASE_URL = databaseUrl process.env.AUTH_SECRET = process.env.AUTH_SECRET || "test-auth-secret" try { execFileSync("bunx", ["prisma", "migrate", "deploy"], { env: { ...process.env, DATABASE_URL: databaseUrl, }, stdio: "inherit", }) } catch (error) { await stopIntegrationTestDatabase() throw error } return databaseUrl } export async function resetIntegrationTestDatabase(prisma: PrismaClient) { const quotedTables = TABLES_TO_TRUNCATE.map((table) => `"${table}"`).join( ", ", ) await prisma.$executeRawUnsafe(`TRUNCATE TABLE ${quotedTables} CASCADE`) } export async function stopIntegrationTestDatabase() { await state.container?.stop() state.container = undefined state.databaseUrl = undefined }