/** * Startet fuer die Testlaeufe eine echte, frische PostgreSQL-Instanz. * * Bewusst kein Mock und kein SQLite: die Tests fuer gleichzeitige Buchungen * und Gutscheineinloesungen pruefen Zeilensperren (SELECT … FOR UPDATE) und * Datenbank-Trigger, die nur eine echte PostgreSQL-Instanz abbildet. * * Alternativ laesst sich eine vorhandene Datenbank per TEST_DATABASE_URL * nutzen (z. B. in CI mit einem postgres-Service). Deren Inhalt wird dabei * zurueckgesetzt. */ import EmbeddedPostgres from "embedded-postgres"; import { execFileSync } from "node:child_process"; import { mkdtempSync, rmSync } from "node:fs"; import os from "node:os"; import path from "node:path"; let pg: EmbeddedPostgres | null = null; let dir: string | null = null; export async function setup(): Promise { let url = process.env.TEST_DATABASE_URL; if (!url) { dir = mkdtempSync(path.join(os.tmpdir(), "artista-test-db-")); const port = 55000 + Math.floor(Math.random() * 1000); pg = new EmbeddedPostgres({ databaseDir: dir, user: "test", password: "test", port, persistent: false, onLog: () => {}, }); await pg.initialise(); await pg.start(); await pg.createDatabase("artista_test"); url = `postgresql://test:test@localhost:${port}/artista_test`; } process.env.DATABASE_URL = url; const prismaCli = path.resolve("node_modules/prisma/build/index.js"); try { // Nicht-destruktiv: wendet nur fehlende Migrationen an. Die Tests leeren // ihre Tabellen selbst (tests/support/db.ts). execFileSync(process.execPath, [prismaCli, "migrate", "deploy"], { env: { ...process.env, DATABASE_URL: url }, stdio: "pipe", }); } catch (error) { const stderr = (error as { stderr?: Buffer }).stderr?.toString() ?? ""; throw new Error(`Migration der Testdatenbank fehlgeschlagen:\n${stderr}`); } } export async function teardown(): Promise { if (pg) await pg.stop(); if (dir) rmSync(dir, { recursive: true, force: true }); }