/** * Test-Runner: führt alle `scripts/test-*.ts` nacheinander via tsx aus und liefert eine * Zusammenfassung + Exit-Code (≠ 0, sobald ein Test scheitert). * * Voraussetzungen: lokale Infra (Postgres/Redis/Garage) läuft, `.env` gesetzt, Datenbank * migriert und geseedet (`npx prisma migrate deploy && npx prisma db seed`). * * Lauf: npm run test (alle) * npm run test -- mail tenant (nur Tests, deren Name einen der Filter enthält) */ import { spawnSync } from "node:child_process"; import { readdirSync } from "node:fs"; import { join, dirname } from "node:path"; import { fileURLToPath } from "node:url"; const SCRIPTS_DIR = dirname(fileURLToPath(import.meta.url)); const filters = process.argv.slice(2); const tests = readdirSync(SCRIPTS_DIR) .filter((f) => /^test-.+\.ts$/.test(f)) .filter((f) => filters.length === 0 || filters.some((flt) => f.includes(flt))) .sort(); if (tests.length === 0) { console.error("Keine Tests gefunden."); process.exit(1); } const results: { name: string; ok: boolean; ms: number }[] = []; for (const file of tests) { const started = Date.now(); console.log(`\n━━━ ${file} ━━━`); const run = spawnSync(process.execPath, ["--import", "tsx", join(SCRIPTS_DIR, file)], { stdio: "inherit", env: process.env, }); results.push({ name: file, ok: run.status === 0, ms: Date.now() - started }); } const failed = results.filter((r) => !r.ok); console.log("\n══════════ Test-Zusammenfassung ══════════"); for (const r of results) console.log(`${r.ok ? "✓" : "✗"} ${r.name.padEnd(36)} ${(r.ms / 1000).toFixed(1)}s`); console.log(`\n${results.length - failed.length}/${results.length} Testskripte grün${failed.length ? ` — ${failed.length} fehlgeschlagen` : ""}.`); process.exit(failed.length ? 1 : 0);