Files
Harlekin e0b03ea336
Prüfung / Lint, Typen, Tests (push) Canceled after 0s
Prüfung / Images bauen (pdf) (push) Canceled after 0s
Prüfung / Images bauen (web) (push) Canceled after 0s
Prüfung / Images bauen (worker) (push) Canceled after 0s
Images / bauen (pdf, docker/pdf.Dockerfile) (push) Canceled after 0s
Images / bauen (web, docker/web.Dockerfile) (push) Canceled after 0s
Images / bauen (worker, docker/worker.Dockerfile) (push) Canceled after 0s
Gedankenstriche durch Bindestriche ersetzt
375 Vorkommen in 210 Dateien. Betrifft Kommentare, Oberflaechentexte und die
README; an keiner Stelle Bedeutung, nur Zeichensetzung.
2026-09-04 08:54:52 +02:00

108 lines
3.8 KiB
JavaScript

import { execFileSync } from 'node:child_process'
import { createRequire } from 'node:module'
import { fileURLToPath } from 'node:url'
import pg from 'pg'
import { loadEnvFromRepoRoot } from '../dist/loadEnv.js'
import { resolveTestDatabaseUrl } from '../dist/testDatabase.js'
/**
* Setzt die Testdatenbank neu auf und bringt sie auf den Migrationsstand.
* Wird von `pnpm test` vorgeschaltet.
*
* **Neu aufsetzen, nicht nur anlegen.** Verlaufseinträge, Akten und
* Protokollzeilen sind nach Zusicherung 2 der README nicht löschbar - was
* ein Testlauf anlegt, bleibt für immer stehen. Nach einigen Dutzend Läufen
* standen 2487 Akten in der Datenbank, und Tests, die eine auf zehn Einträge
* begrenzte Liste prüfen, fanden ihre eigene Akte nicht mehr darin. Solche
* Fehlschläge sehen aus wie ein Fehler im Code und sind keiner; das kostet mehr
* Zeit als das Neuaufsetzen.
*
* `KEEP_TEST_DB=1` behält den Bestand. Für das schnelle Nacheinander beim
* Arbeiten an einer einzelnen Testdatei.
*
* Läuft nur in der Entwicklung und in der CI, nie im Betrieb.
*/
loadEnvFromRepoRoot()
const testUrl = resolveTestDatabaseUrl()
const dbName = new URL(testUrl).pathname.replace(/^\//, '')
const maintenance = new URL(testUrl)
maintenance.pathname = '/postgres'
const client = new pg.Client({ connectionString: maintenance.toString() })
await client.connect()
// Bezeichner lassen sich nicht als Parameter binden, deshalb quotiert. Der Name
// kommt aus resolveTestDatabaseUrl und endet immer auf _test.
const quoted = `"${dbName.replace(/"/g, '""')}"`
if (!dbName.endsWith('_test')) {
throw new Error(`Sicherung: ${dbName} endet nicht auf _test, wird nicht angefasst`)
}
try {
const { rowCount } = await client.query('SELECT 1 FROM pg_database WHERE datname = $1', [dbName])
const behalten = process.env.KEEP_TEST_DB === '1'
if (rowCount > 0 && !behalten) {
// Offene Verbindungen verhindern das Verwerfen - etwa ein Prisma Studio
// oder ein abgebrochener Testlauf.
await client.query(
`SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE datname = $1 AND pid <> pg_backend_pid()`,
[dbName],
)
await client.query(`DROP DATABASE ${quoted}`)
console.log(`[test-db] ${dbName} verworfen`)
}
if (rowCount === 0 || !behalten) {
await client.query(`CREATE DATABASE ${quoted}`)
console.log(`[test-db] ${dbName} angelegt`)
} else {
console.log(`[test-db] ${dbName} behalten (KEEP_TEST_DB=1)`)
}
} finally {
await client.end()
}
const require = createRequire(import.meta.url)
const prismaCli = require.resolve('prisma/build/index.js')
const testEnv = { ...process.env, DATABASE_URL: testUrl, DIRECT_DATABASE_URL: testUrl }
execFileSync(process.execPath, [prismaCli, 'migrate', 'deploy'], {
stdio: 'inherit',
env: testEnv,
})
// Der Auslieferungszustand gehört auch in die Testdatenbank: Freigabestufen und
// Änderungsrichtlinie werden von Tests vorausgesetzt. Der Seed ist idempotent.
const tsxCli = require.resolve('tsx/cli')
execFileSync(process.execPath, [tsxCli, 'prisma/seed.ts'], {
stdio: 'inherit',
cwd: fileURLToPath(new URL('..', import.meta.url)),
env: testEnv,
})
// Die Änderungsrichtlinie ist eine einzige Zeile für die ganze Anwendung. Der
// Seed lässt sie bewusst in Ruhe, damit er die Einstellung des Leiters nicht
// überschreibt - in der Testdatenbank soll sie aber bei jedem Lauf im
// Auslieferungszustand starten, sonst hängt das Ergebnis davon ab, was der
// vorige Lauf hinterlassen hat.
const reset = new pg.Client({ connectionString: testUrl })
await reset.connect()
try {
await reset.query(
`UPDATE "AppSetting"
SET "entryEditPolicy" = 'GRACE_WINDOW',
"entryEditGraceMinutes" = 15,
"entryEditMarkGrace" = false
WHERE id = 1`,
)
} finally {
await reset.end()
}
console.log(`[test-db] ${dbName} ist auf Stand`)