Aufraeumarbeiten: ESLint, DOM-Verschachtelung, eigene Testwehr
ESLint hatte keine Konfiguration — das Skript "npm run lint" pruefte nichts. Jetzt Flat Config ohne Formatierungsregeln, dafuer mit den Regeln, die die Fehler dieses Projekts gemeldet haetten. Er hat gleich zwei gefunden, die niemand gesucht hatte. Das Badge rendert ein span statt eines div. Damit ist die Meldung "div cannot be a descendant of p" weg, die seit Phase 3 auf der Einsatzseite stand — sie ist der klassische Ausloeser fuer einen Hydration-Fehler. Die E2E-Tests laufen gegen eine eigene Wehr. Nach fuenf Phasen standen in der Beispielwehr 120 Atemschutz-Ueberwachungen statt einer und 115 Geraete statt 45; bei jedem Lauf aenderten sich alle Bildschirmfotos. Der Bestand ist einmal zurueckgesetzt, npm run db:test-reset baut die Testwehr neu auf. Behoben nebenbei: - Die Fehlerflaeche der Karte konnte nie etwas anzeigen. - Zwei useMemo der Lagekarte rechneten bei jedem Rendern neu. - tests/e2e war vom Typecheck ausgenommen und liess einen doppelt deklarierten Bezeichner durch. Closes #10 Closes #11 Closes #12 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8081131eb7
commit
7196c7110c
+45
-20
@@ -1,4 +1,5 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { ADMIN_EMAIL, ADMIN_PASSWORT, WEHR_NAME } from "./wehr";
|
||||
|
||||
/**
|
||||
* Beispiel-E2E-Test für Phase 0.
|
||||
@@ -11,17 +12,18 @@ import { expect, test } from "@playwright/test";
|
||||
* docker compose up -d && npm run db:migrate && npm run db:seed
|
||||
*/
|
||||
|
||||
const ADMIN_EMAIL = process.env.SEED_ADMIN_EMAIL ?? "admin@beispielwehr.de";
|
||||
const ADMIN_PASSWORT = process.env.SEED_ADMIN_PASSWORT ?? "Feuerwehr2026";
|
||||
|
||||
test.describe("Anmeldung", () => {
|
||||
test("schickt nicht angemeldete Aufrufe zur Anmeldeseite", async ({ page }) => {
|
||||
test("schickt nicht angemeldete Aufrufe zur Anmeldeseite", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto("/");
|
||||
await expect(page).toHaveURL(/\/anmelden/);
|
||||
await expect(page.getByRole("heading", { name: "FLORIAN" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("weist eine falsche Kombination ab und nennt den Grund auf Deutsch", async ({ page }) => {
|
||||
test("weist eine falsche Kombination ab und nennt den Grund auf Deutsch", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto("/anmelden");
|
||||
|
||||
await page.getByLabel("E-Mail-Adresse").fill(ADMIN_EMAIL);
|
||||
@@ -37,7 +39,9 @@ test.describe("Anmeldung", () => {
|
||||
await expect(page).toHaveURL(/\/anmelden/);
|
||||
});
|
||||
|
||||
test("lässt den Administrator hinein und zeigt die Übersicht seiner Wehr", async ({ page }) => {
|
||||
test("lässt den Administrator hinein und zeigt die Übersicht seiner Wehr", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto("/anmelden");
|
||||
|
||||
await page.getByLabel("E-Mail-Adresse").fill(ADMIN_EMAIL);
|
||||
@@ -46,15 +50,18 @@ test.describe("Anmeldung", () => {
|
||||
|
||||
await page.waitForURL("/");
|
||||
|
||||
// Die Wehr aus dem Seed.
|
||||
await expect(
|
||||
page.getByRole("heading", { name: "Freiwillige Feuerwehr Musterhausen" }),
|
||||
).toBeVisible();
|
||||
// Die Wehr, gegen die getestet wird — nicht die Beispielwehr aus der
|
||||
// Anleitung. Welche das ist, steht in wehr.ts.
|
||||
await expect(page.getByRole("heading", { name: WEHR_NAME })).toBeVisible();
|
||||
|
||||
// Die Kennzahlen aus dem Seed: 15 Mitglieder, 3 Fahrzeuge, 40 Geräte.
|
||||
await expect(page.getByText("Aktive Mitglieder")).toBeVisible();
|
||||
await expect(page.getByText("Fahrzeuge", { exact: true }).first()).toBeVisible();
|
||||
await expect(page.getByText("Geräte", { exact: true }).first()).toBeVisible();
|
||||
await expect(
|
||||
page.getByText("Fahrzeuge", { exact: true }).first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText("Geräte", { exact: true }).first(),
|
||||
).toBeVisible();
|
||||
|
||||
// Der Sicherheitshinweis muss stehen, solange nichts freigegeben ist.
|
||||
await expect(page.getByRole("note")).toContainText("analoge Überwachung");
|
||||
@@ -69,31 +76,49 @@ test.describe("Anmeldung", () => {
|
||||
await page.getByRole("button", { name: "Anmelden" }).click();
|
||||
await page.waitForURL("/");
|
||||
|
||||
const navigation = page.getByRole("navigation", { name: "Hauptnavigation" });
|
||||
await expect(navigation.getByRole("link", { name: "Übersicht" })).toBeVisible();
|
||||
const navigation = page.getByRole("navigation", {
|
||||
name: "Hauptnavigation",
|
||||
});
|
||||
await expect(
|
||||
navigation.getByRole("link", { name: "Übersicht" }),
|
||||
).toBeVisible();
|
||||
|
||||
// Termine, Dienstausweis und Benachrichtigungen stehen seit Phase 7 zur
|
||||
// Verfügung und sind Verweise.
|
||||
await expect(navigation.getByRole("link", { name: "Termine" })).toBeVisible();
|
||||
await expect(navigation.getByRole("link", { name: "Dienstausweis" })).toBeVisible();
|
||||
await expect(navigation.getByRole("link", { name: "Benachrichtigungen" })).toBeVisible();
|
||||
await expect(
|
||||
navigation.getByRole("link", { name: "Termine" }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
navigation.getByRole("link", { name: "Dienstausweis" }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
navigation.getByRole("link", { name: "Benachrichtigungen" }),
|
||||
).toBeVisible();
|
||||
|
||||
// Die Kasse kommt erst in Phase 9 — der Eintrag ist sichtbar, aber kein
|
||||
// Verweis. Beim Abschluss einer Phase wandert diese Zusicherung eine Zeile
|
||||
// weiter nach unten.
|
||||
await expect(navigation.getByText("Kasse")).toBeVisible();
|
||||
await expect(navigation.getByRole("link", { name: "Kasse" })).toHaveCount(0);
|
||||
await expect(navigation.getByRole("link", { name: "Kasse" })).toHaveCount(
|
||||
0,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Erreichbarkeit", () => {
|
||||
test("meldet den Zustand der Randsysteme unter /api/health", async ({ request }) => {
|
||||
test("meldet den Zustand der Randsysteme unter /api/health", async ({
|
||||
request,
|
||||
}) => {
|
||||
const antwort = await request.get("/api/health");
|
||||
expect(antwort.status()).toBe(200);
|
||||
|
||||
const daten = (await antwort.json()) as {
|
||||
status: string;
|
||||
dienste: { datenbank: boolean; speicher: boolean; warteschlange: boolean };
|
||||
dienste: {
|
||||
datenbank: boolean;
|
||||
speicher: boolean;
|
||||
warteschlange: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
expect(daten.status).toBe("ok");
|
||||
|
||||
Reference in New Issue
Block a user