import { SQL } from "bun"; import { afterAll, afterEach, beforeEach, describe } from "bun:test"; import { createDb, type Db } from "./db.ts"; import type { Dialect } from "./dialect.ts"; import { migrateToLatest } from "./migrate.ts"; /** * Register `describe(" []")` for SQLite, and for Postgres when * `TEST_POSTGRES_URL` is set. Every test gets a fresh, migrated database: * SQLite `:memory:`, or a new `st_` database on the Postgres server. */ export function forEachDialect(name: string, fn: (getDb: () => Db) => void): void { const dialects: Dialect[] = ["sqlite"]; const pgUrl = process.env.TEST_POSTGRES_URL; if (pgUrl) dialects.push("postgres"); for (const dialect of dialects) { describe(`${name} [${dialect}]`, () => { let current: Db | undefined; const created: string[] = []; beforeEach(async () => { let url = "sqlite://:memory:"; if (dialect === "postgres") { const dbName = `st_${crypto.randomUUID().replaceAll("-", "")}`; await withAdmin(pgUrl!, (admin) => admin.unsafe(`create database "${dbName}"`)); created.push(dbName); const u = new URL(pgUrl!); u.pathname = `/${dbName}`; url = u.toString(); } current = await createDb(url); await migrateToLatest(current); }); afterEach(async () => { await current?.close(); current = undefined; }); afterAll(async () => { if (created.length === 0) return; await withAdmin(pgUrl!, async (admin) => { for (const dbName of created) await admin.unsafe(`drop database if exists "${dbName}" with (force)`); }); }); fn(() => { if (!current) throw new Error("getDb() called outside a test"); return current; }); }); } } async function withAdmin(url: string, f: (admin: SQL) => Promise): Promise { const admin = new SQL(url); try { return await f(admin); } finally { await admin.close(); } }