import AxeBuilder from "@axe-core/playwright"; import { expect, loginAs, test, type Persona } from "./fixtures"; const routes: { path: string; persona: Persona }[] = [ { path: "/", persona: "hub-viewer" }, { path: "/projects", persona: "hub-viewer" }, { path: "/servers", persona: "hub-viewer" }, { path: "/tools", persona: "hub-viewer" }, { path: "/connectors", persona: "hub-viewer" }, { path: "/clients", persona: "hub-viewer" }, { path: "/policies", persona: "hub-viewer" }, { path: "/operations", persona: "hub-viewer" }, { path: "/audit", persona: "hub-auditor" }, { path: "/settings", persona: "hub-viewer" }, ]; test.describe("accessibility and responsive baseline", () => { test("the unauthenticated gateway has landmarks, a skip link, and no serious axe findings", async ({ page }) => { await page.goto("/"); await expect(page.getByRole("link", { name: "Skip to main content" })).toBeVisible(); await expect(page.getByRole("main")).toHaveCount(1); const result = await new AxeBuilder({ page }).analyze(); expect(result.violations.filter((violation) => ["serious", "critical"].includes(violation.impact ?? ""))).toEqual([]); }); for (const viewport of [{ width: 390, height: 844 }, { width: 1440, height: 900 }]) { test(`authorized routes have no serious axe findings or page overflow at ${viewport.width}px`, async ({ page }) => { test.setTimeout(90_000); await page.setViewportSize(viewport); for (const persona of ["hub-viewer", "hub-auditor"] as const) { const personaRoutes = routes.filter((route) => route.persona === persona); if (!personaRoutes.length) continue; await loginAs(page, persona); for (const route of personaRoutes) { await page.goto(route.path); await expect(page.getByRole("main")).toBeVisible(); const overflow = await page.evaluate(() => document.documentElement.scrollWidth > window.innerWidth + 1); expect(overflow, `${route.path} must not cause page-level horizontal overflow`).toBe(false); const result = await new AxeBuilder({ page }).analyze(); expect(result.violations.filter((violation) => ["serious", "critical"].includes(violation.impact ?? "")), route.path).toEqual([]); } } }); } test("mobile drawer and modal preserve keyboard focus", async ({ page }) => { await page.setViewportSize({ width: 390, height: 844 }); await loginAs(page, "hub-viewer"); await page.goto("/"); const trigger = page.getByRole("button", { name: "Open navigation" }); await trigger.focus(); await trigger.press("Enter"); await page.getByRole("button", { name: "Close navigation" }).press("Escape"); await expect(trigger).toBeFocused(); }); });