feat(doku): Anleitung, PDF und Ende-zu-Ende-Abnahme (#36)
Prüfung / pruefung (push) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s

This commit was merged in pull request #36.
This commit is contained in:
2026-09-26 09:04:15 +00:00
parent 9bd198a531
commit fbbb634e56
104 changed files with 4527 additions and 299 deletions
+41 -20
View File
@@ -1,5 +1,7 @@
import { expect, test, type Page } from "@playwright/test";
import "dotenv/config";
import { prisma } from "@/lib/db";
import { anmelden } from "./helfer";
/**
* Der Vorlagen-Editor durch die Oberflaeche (#010).
@@ -10,31 +12,20 @@ import "dotenv/config";
* angehaengtem React gelingt — anlegen, tippen, sortieren, speichern — und
* anschliessend, ob es wirklich in der Datenbank steht: durch Neuladen.
*
* Voraussetzung: ein **gebauter** Stand laeuft (`pnpm build && pnpm start`) und
* `SEED_ADMIN_EMAIL`/`SEED_ADMIN_PASSWORD` sind gesetzt. Gegen `pnpm dev`
* schlaegt das hier fehl, und das ist richtig so — siehe CLAUDE.md,
* „Oberflaeche pruefen“.
* Voraussetzungen prueft `tests/e2e/global-setup.ts` vor dem ersten Ablauf: ein
* **gebauter** Stand antwortet, der Seed-Bestand steht, und der Server liest
* dieselbe Datenbank wie dieser Lauf. Gegen `pnpm dev` schlaegt das hier fehl,
* und das ist richtig so — siehe CLAUDE.md, „Oberflaeche pruefen“.
*
* Der Ablauf legt seine eigene Vorlage an und **archiviert** sie am Ende. Nicht
* loescht: eine veroeffentlichte Version laesst sich nicht mehr entfernen, auch
* nicht ueber einen Kaskadenloeschvorgang — der Trigger aus #009 verweigert das
* ausdruecklich, und genau das ist die Zusage, an der das ganze Archiv haengt.
* Wer diese Tests oft laufen laesst, braucht deshalb eine Wegwerf-Datenbank
* (kommt mit #018).
* Der Ablauf legt seine eigene Vorlage an, **archiviert** sie ueber die
* Oberflaeche — das ist der Weg, den die Anwendung kennt, geloescht wird dort
* nichts — und raeumt sie hinterher ueber die Datenbank weg. Ohne diesen
* Nachlauf blieb nach jedem Durchgang eine archivierte „ZZ E2E Editor“-Vorlage
* stehen; in der Entwicklungsdatenbank lagen davon zuletzt ueber hundert (#018).
*/
const NAME = `ZZ E2E Editor ${Date.now()}`;
async function anmelden(seite: Page) {
const email = process.env["SEED_ADMIN_EMAIL"];
const passwort = process.env["SEED_ADMIN_PASSWORD"];
if (!email || !passwort) throw new Error("SEED_ADMIN_EMAIL und SEED_ADMIN_PASSWORD fehlen.");
await seite.goto("/anmelden");
await seite.fill('input[name="email"]', email);
await seite.fill('input[name="passwort"]', passwort);
await Promise.all([seite.waitForURL("**/"), seite.click('button[type="submit"]')]);
}
/** Legt die Vorlage an und fuehrt in ihren Entwurf. Gibt die Adresse des Editors zurueck. */
async function entwurfAnlegen(seite: Page, name: string): Promise<string> {
await seite.goto("/vorlagen");
@@ -176,3 +167,33 @@ test.describe("Vorlagen-Editor", () => {
await aufraeumen(page, name);
});
});
test.afterAll(async () => {
/*
* Aufgeraeumt wird ueber die Datenbank, weil die Anwendung fuer eine Vorlage
* bewusst keinen Loeschweg kennt — archivieren ist das Gegenteil von
* Aufraeumen. Die veroeffentlichte Version steht dem nicht im Weg: der Trigger
* aus #009 schuetzt Abschnitte und Schritte einer veroeffentlichten Version,
* und beim Kaskadenloeschen ist die Version bereits fort, wenn sie fallen.
*
* An diesen Vorlagen haengt kein Lauf — dieser Ablauf startet keinen. Haengte
* einer, verweigerte der Fremdschluessel das Loeschen, und das waere richtig.
*/
const vorlagen = await prisma.vorlage.findMany({
where: { name: { startsWith: "ZZ E2E Editor" } },
select: { id: true, versionen: { select: { id: true } } },
});
if (vorlagen.length === 0) {
await prisma.$disconnect();
return;
}
const kennungen = vorlagen.flatMap((vorlage) => [
vorlage.id,
...vorlage.versionen.map((version) => version.id),
]);
// Das Protokoll haelt Anlegen und Veroeffentlichen fest; `entitaetId` ist kein
// Fremdschluessel, die Zeilen bleiben also sonst als Waisen stehen.
await prisma.protokoll.deleteMany({ where: { entitaetId: { in: kennungen } } });
await prisma.vorlage.deleteMany({ where: { id: { in: vorlagen.map((zeile) => zeile.id) } } });
await prisma.$disconnect();
});