import { randomUUID } from "node:crypto"; import AxeBuilder from "@axe-core/playwright"; import { expect, test, type Page } from "@playwright/test"; import { authenticatedStatePath } from "../global-setup"; test.use({ storageState: authenticatedStatePath }); async function createProposal(page: Page): Promise { return page.evaluate(async ({ idempotencyKey, correlationId }) => { const csrfResponse = await fetch("/api/v1/auth/csrf"); const csrf = await csrfResponse.json() as { token: string; headerName: string }; const response = await fetch("/api/v1/ingestion-proposals", { method: "POST", headers: { "content-type": "application/json", [csrf.headerName]: csrf.token, "Idempotency-Key": idempotencyKey }, body: JSON.stringify({ manifest: "# E2E mobiele beoordeling", correlationId }), }); if (!response.ok) throw new Error(`Voorstel maken mislukte (${response.status}): ${await response.text()}`); return (await response.json() as { id: string }).id; }, { idempotencyKey: randomUUID(), correlationId: `e2e-review-${randomUUID()}` }); } test.describe("intakebeoordeling: responsieve, toegankelijke werkruimte", () => { test("houdt reviewpanelen en voortgang toegankelijk op desktop, tablet en mobiel", async ({ page, browserName }, testInfo) => { test.skip(browserName !== "chromium", "Deze bounded responsive matrix gebruikt Chromium."); const isMobileProject = testInfo.project.name === "chromium-mobile"; await page.setViewportSize(isMobileProject ? { width: 390, height: 844 } : { width: 1440, height: 1000 }); await page.goto("/"); const proposalId = await createProposal(page); await page.goto(`/knowledge/intake/${proposalId}`); await expect(page.getByRole("heading", { name: "Voorstel beoordelen" })).toBeVisible(); await expect(page.locator('[data-testid="ingestion-progress"]')).toBeVisible(); await expect(page.locator(".proposal-sources-panel")).toBeVisible(); expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true); if (!isMobileProject) { await expect(page.getByRole("region", { name: "Analyse en onderbouwing" })).toBeVisible(); await expect(page.locator('[data-mobile-step="decision"]')).toBeVisible(); await page.setViewportSize({ width: 1024, height: 900 }); await expect(page.locator(".mobile-review-navigator")).toBeVisible(); await expect(page.locator(".proposal-sources-panel")).toBeVisible(); await expect(page.getByRole("region", { name: "Analyse en onderbouwing" })).toBeVisible(); await expect(page.locator('[data-mobile-step="decision"]')).toBeVisible(); expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true); await page.setViewportSize({ width: 390, height: 844 }); } await expect(page.locator(".mobile-review-navigator")).toBeVisible(); await expect(page.locator('[data-mobile-step="evidence"]')).toBeHidden(); await expect(page.locator('[data-mobile-step="decision"]')).toBeHidden(); expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true); await page.getByRole("button", { name: "Volgende stap" }).focus(); await page.keyboard.press("Enter"); await expect(page.locator('[data-testid="ingestion-progress"]')).toHaveText("Stap 2 van 3: Onderbouwing"); await expect(page.locator('[data-mobile-step="sources"]')).toBeHidden(); await expect(page.getByRole("region", { name: "Analyse en onderbouwing" })).toBeVisible(); await expect(page.getByText("Waarschuwingen en conflicten")).toBeVisible(); await page.getByRole("button", { name: "Volgende stap" }).click(); await expect(page.locator('[data-mobile-step="decision"]')).toBeVisible(); await expect(page.getByRole("button", { name: "Goedkeuren" })).toBeVisible(); expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true); const axe = new AxeBuilder({ page }); await expect(page.locator('[data-testid="ingestion-progress"]')).toBeVisible(); expect((await axe.analyze()).violations).toEqual([]); }); });