import { expect, test } from "@playwright/test"; import { ADMIN_EMAIL, ADMIN_PASSWORT, WEHR_NAME } from "./wehr"; /** * Beispiel-E2E-Test für Phase 0. * * Geprüft wird der Weg, ohne den nichts anderes funktioniert: jemand ruft die * Anwendung auf, wird zur Anmeldung geschickt, meldet sich an und landet auf * der Übersicht seiner Wehr. * * Voraussetzung: Stack läuft, Datenbank ist migriert und geseedet. * docker compose up -d && npm run db:migrate && npm run db:seed */ test.describe("Anmeldung", () => { 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, }) => { await page.goto("/anmelden"); // Bewusst eine Adresse, die es nicht gibt, statt der des Administrators. // // Ein Fehlversuch zählt auf das Konto, und nach fünf davon ist es fünf // Minuten gesperrt. Bei zwei Projekten und Wiederholungen kamen im vollen // Lauf genug zusammen, um andere Testdateien mitzureißen — sie fielen // dann mit „Anmeldung fehlgeschlagen“ aus, ohne dass es etwas mit dem zu // tun hatte, was sie prüfen. // // Die Meldung muss ohnehin dieselbe sein: sie darf nicht verraten, ob es // die Adresse gibt. Genau das prüft dieser Test mit. await page.getByLabel("E-Mail-Adresse").fill("gibt-es-nicht@teststelle.de"); await page.getByLabel("Passwort").fill("definitiv-das-falsche-passwort"); await page.getByRole("button", { name: "Anmelden" }).click(); // Nicht ueber die Rolle "alert" suchen: Next.js haengt einen eigenen // Routen-Ansager mit derselben Rolle in die Seite. const meldung = page.getByTestId("anmeldefehler"); await expect(meldung).toBeVisible(); await expect(meldung).toContainText("stimmt nicht"); // Und niemand ist hineingekommen. await expect(page).toHaveURL(/\/anmelden/); }); 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); await page.getByLabel("Passwort").fill(ADMIN_PASSWORT); await page.getByRole("button", { name: "Anmelden" }).click(); await page.waitForURL("/"); // 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(); // Der Sicherheitshinweis muss stehen, solange nichts freigegeben ist. await expect(page.getByRole("note")).toContainText("analoge Überwachung"); }); test("zeigt die Navigation mit allen umgesetzten Modulen", async ({ page }) => { await page.goto("/anmelden"); await page.getByLabel("E-Mail-Adresse").fill(ADMIN_EMAIL); await page.getByLabel("Passwort").fill(ADMIN_PASSWORT); 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(); // 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(); // Die Kasse ist seit Phase 9 ein Verweis. // // Bis dahin stand hier die Gegenprobe: der Eintrag sichtbar, aber // ausgegraut, weil das Modul noch fehlte. Mit Phase 9 gibt es kein // künftiges Modul mehr — eine Zusicherung über ein Modul, das es nicht // gibt, wäre keine. Kommt später eines dazu, gehört sie hierher zurück. await expect(navigation.getByRole("link", { name: "Kasse" })).toBeVisible(); }); }); test.describe("Erreichbarkeit", () => { 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; }; }; expect(daten.status).toBe("ok"); expect(daten.dienste.datenbank).toBe(true); expect(daten.dienste.speicher).toBe(true); expect(daten.dienste.warteschlange).toBe(true); }); });