import { test, expect } from "@playwright/test"; /** * E2E-Tests der dynamischen Suche & Filter (Workstream 5). * * NICHT in der Sandbox ausführbar (kein Server/DB) — deferred. Wird über * `npm run test:e2e` gegen einen laufenden, geseedeten Server mit * authentifizierter Session (Storage-State aus dem Auth-Setup) ausgeführt. * * Abgedeckte Garantien (Plan WS5 Verifikation 8–10): * - /fahrzeuge rendert je active-Merkmal genau ein Filter-UI des richtigen Typs. * - Filter ändern schreibt `f.=…` bzw. `?bereit=1` in die URL (kein Reload), * Trefferzahl sinkt, Reload liefert identisches Ergebnis. * - Anonymer Aufruf von /fahrzeuge redirectet auf /login. */ test.describe("Suche – Default-deny", () => { test("anonymer Aufruf von /fahrzeuge leitet auf /login um", async ({ browser, }) => { // Frischer Kontext OHNE gespeicherte Session. const ctx = await browser.newContext({ storageState: undefined }); const page = await ctx.newPage(); await page.goto("/fahrzeuge"); await expect(page).toHaveURL(/\/login/); await ctx.close(); }); }); test.describe("Suche – Tabs & URL-Sync (authentifiziert)", () => { test("Tabs navigieren zwischen Fahrzeuge/Geräte/Wehren", async ({ page }) => { await page.goto("/fahrzeuge"); await page.getByRole("tab", { name: "Geräte" }).click(); await expect(page).toHaveURL(/\/geraete/); await page.getByRole("tab", { name: "Wehren" }).click(); await expect(page).toHaveURL(/\/wehren/); }); test("Status-Switch schreibt ?bereit=1 in die URL ohne Reload", async ({ page, }) => { await page.goto("/fahrzeuge"); await page.getByLabel("Nur einsatzbereit").click(); await expect(page).toHaveURL(/bereit=1/); }); test("Filter-Reset entfernt f.*-Parameter, behält q", async ({ page }) => { await page.goto("/fahrzeuge?q=HLF&bereit=1"); await page.getByRole("button", { name: "Filter zurücksetzen" }).click(); await expect(page).toHaveURL(/q=HLF/); await expect(page).not.toHaveURL(/bereit=1/); }); test("Freitext-Suche schreibt q debounced in die URL", async ({ page }) => { await page.goto("/fahrzeuge"); await page.getByLabel("Suchbegriff").fill("HLFA 3"); await expect(page).toHaveURL(/q=HLFA(\+|%20)3/, { timeout: 2000 }); }); test("Reload mit Filter-URL liefert identische Trefferzahl", async ({ page, }) => { await page.goto("/fahrzeuge?bereit=1"); const before = await page.getByText(/Treffer/).textContent(); await page.reload(); const after = await page.getByText(/Treffer/).textContent(); expect(after).toBe(before); }); }); test.describe("Suche – dynamisches Filter-UI", () => { test("jede Number-Facette hat einen Slider, jede Boolean einen Tri-State", async ({ page, }) => { await page.goto("/fahrzeuge"); // Mindestens ein Slider (number) und eine Ja/Nein/egal-Gruppe (boolean). await expect(page.getByRole("slider").first()).toBeVisible(); await expect( page.getByRole("button", { name: "egal" }).first(), ).toBeVisible(); }); });