From 7a3ecffebb48667dbbbf7d34ba218ddff5b5c64e Mon Sep 17 00:00:00 2001
From: "Patrick Seidler (via Claude Code)"
Date: Wed, 5 Aug 2026 21:32:00 +0000
Subject: [PATCH] test: zwei bekannte Flakes entschaerfen
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1) Kollisionstests (booking/beleg): toBe(5000) prueft die falsche Zusage. Die
Eindeutigkeit garantiert nicht der Generator, sondern UNIQUE + Retry in
booking-core.ts. Bei 40 Bit Entropie liegt die Kollisionswahrscheinlichkeit
ueber 5000 Ziehungen bei rund 1:88.000 pro Lauf — der Test waere im Schnitt
alle 88.000 Laeufe grundlos rot geworden. Jetzt >= 4995: laesst einzelne
Kollisionen zu, schlaegt aber an, wenn die Streuung zusammenbricht.
2) hookTimeout global auf 60 s. Die beforeAll-Hooks der Integrationstests
werfen das Schema weg und fahren die ganze Migrationskette hoch; deren Dauer
waechst mit jeder Migration, der Standard-Timeout nicht. email-change.test.ts
lief deshalb sporadisch in einen Timeout, einzeln aber gruen.
Beides ist dieselbe Sorge: Ein roter Lauf ohne echten Fehler wird beim naechsten
Mal weggeklickt — und dann faellt ein echter Fehler auch nicht mehr auf.
Co-Authored-By: Claude Opus 5 (1M context)
Claude-Session: https://claude.ai/code/session_018YNj1kkesDywuEGvNweBHM
---
app/src/lib/polls/__tests__/beleg.test.ts | 8 ++++++--
app/src/lib/verification/__tests__/booking.test.ts | 13 +++++++++++--
app/vitest.config.ts | 8 ++++++++
3 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/app/src/lib/polls/__tests__/beleg.test.ts b/app/src/lib/polls/__tests__/beleg.test.ts
index 4439891..70e3bcc 100644
--- a/app/src/lib/polls/__tests__/beleg.test.ts
+++ b/app/src/lib/polls/__tests__/beleg.test.ts
@@ -59,10 +59,14 @@ describe("Beleg-Code Format (Unit)", () => {
}
});
- it("streut breit (CSPRNG) — keine Kollisionen über 5000 Codes", () => {
+ // Siehe verification/__tests__/booking.test.ts: geprüft wird die Streuung des
+ // CSPRNG, nicht die Eindeutigkeit — für die sorgt der UNIQUE-Constraint mit
+ // Retry. toBe(5000) wäre bei 40 Bit Entropie im Schnitt alle 88.000 Läufe
+ // grundlos rot geworden (Geburtstagsproblem).
+ it("streut breit (CSPRNG) — praktisch kollisionsfrei über 5000 Codes", () => {
const set = new Set();
for (let i = 0; i < 5000; i++) set.add(generateBelegCode());
- expect(set.size).toBe(5000);
+ expect(set.size).toBeGreaterThanOrEqual(4995);
});
});
diff --git a/app/src/lib/verification/__tests__/booking.test.ts b/app/src/lib/verification/__tests__/booking.test.ts
index aa83e60..62d45d2 100644
--- a/app/src/lib/verification/__tests__/booking.test.ts
+++ b/app/src/lib/verification/__tests__/booking.test.ts
@@ -60,10 +60,19 @@ describe("Termin-Code Format (Unit)", () => {
expect(c.replace(/^TERMIN-/, "")).not.toMatch(/[ILOU]/);
}
});
- it("streut breit (keine Kollision über 5000)", () => {
+ // Prüft die STREUUNG des Generators, nicht die Eindeutigkeit der Codes — die
+ // garantiert nicht er, sondern UNIQUE + Retry in booking-core.ts (fünf
+ // Versuche mit onConflictDoNothing auf den Code-Constraint).
+ //
+ // toBe(5000) war deshalb die falsche Erwartung und dazu flaky: Bei 40 Bit
+ // Entropie liegt die Kollisionswahrscheinlichkeit über 5000 Ziehungen bei
+ // rund 1:88.000 pro Lauf (Geburtstagsproblem) — der Test wäre im Schnitt alle
+ // 88.000 Läufe grundlos rot geworden. Die Schranke lässt einzelne Kollisionen
+ // zu und schlägt trotzdem an, wenn die Streuung wirklich zusammenbricht.
+ it("streut breit (praktisch kollisionsfrei über 5000 Codes)", () => {
const set = new Set();
for (let i = 0; i < 5000; i++) set.add(generateBookingCode());
- expect(set.size).toBe(5000);
+ expect(set.size).toBeGreaterThanOrEqual(4995);
});
});
diff --git a/app/vitest.config.ts b/app/vitest.config.ts
index 837127d..a044606 100644
--- a/app/vitest.config.ts
+++ b/app/vitest.config.ts
@@ -12,6 +12,14 @@ export default defineConfig({
alias: {
"@": path.resolve(__dirname, "./src"),
},
+ // Setup-Hooks der Integrationstests werfen das Schema weg und fahren die
+ // gesamte Migrationskette neu hoch. Deren Dauer wächst mit jeder Migration,
+ // der Standard-Timeout von 10 s aber nicht — email-change.test.ts lief
+ // deshalb sporadisch in einen beforeAll-Timeout, einzeln aber grün. Ein
+ // roter Lauf ohne echten Fehler ist teurer als eine großzügige Schranke:
+ // Er wird beim nächsten Mal weggeklickt, und dann fällt ein echter Fehler
+ // auch nicht mehr auf.
+ hookTimeout: 60_000,
// Sequentielle Ausführung: Integrationstests teilen dieselbe Test-DB
// und würden sich bei paralleler Ausführung gegenseitig beim Schema-Reset stören.
pool: "forks",