import { test, expect } from "@playwright/test"; /** * Login-Rate-Limit (Definition of Done #8, Querschnittsstandard 8). * * NICHT in der Sandbox ausführbar (kein Server/DB) — deferred. Wird über * `npm run test:e2e` gegen einen laufenden, geseedeten Server ausgeführt. * * Beweist: Der Rate-Limit greift im `authorize`-Callback (5 Fehlversuche / * 15 min, src/lib/auth/rate-limit.ts) und damit auf dem Pfad, der über die * Credentials-Login-Action (loginAction) tatsächlich durchläuft. Ab dem 6. * Versuch wird gedrosselt; login_attempts.fail >= 5. */ test.use({ storageState: { cookies: [], origins: [] } }); test("7x falsches Passwort -> Drosselung ab Versuch 6", async ({ page }) => { const email = "wehr-admin-a@example.test"; for (let attempt = 1; attempt <= 7; attempt++) { await page.goto("/login"); await page.getByLabel(/E-Mail/i).fill(email); await page.getByLabel(/Passwort/i).fill(`falsch-${attempt}`); await page.getByRole("button", { name: /Anmelden/i }).click(); // Bleibt auf /login (kein erfolgreicher Login). await expect(page).toHaveURL(/\/login/); const text = await page.locator("body").innerText(); if (attempt >= 6) { // Drosselung: generische Fehlermeldung, weiterhin kein Zugang. expect(text.toLowerCase()).toMatch(/fehlgeschlagen|zu viele|gesperrt|versuch/); } } });