import AxeBuilder from "@axe-core/playwright"; import { expect, test, type Page } from "@playwright/test"; // P6 exit (spec ยง17): a11y sign-off. Serious and critical axe violations // fail the build on every primary surface. const OWNER_EMAIL = "owner@acme.test"; const OWNER_PASSWORD = "e2e-password"; async function signIn(page: Page) { await page.goto("/login"); await page.getByLabel("Email").fill(OWNER_EMAIL); await page.getByLabel("Password").fill(OWNER_PASSWORD); await page.getByRole("button", { name: "Sign in" }).click(); await expect(page.getByRole("heading", { name: "Clawmates" })).toBeVisible(); } async function expectClean(page: Page, context: string) { // Route-enter fades opacity; scanning mid-animation reads false // contrast failures. Let running animations settle first. await page.evaluate(() => Promise.allSettled(document.getAnimations().map((a) => a.finished)), ); const results = await new AxeBuilder({ page }).analyze(); const blocking = results.violations.filter( (v) => v.impact === "serious" || v.impact === "critical", ); expect( blocking.map((v) => `${v.id}: ${v.help} (${v.nodes.length} nodes)`), `axe violations on ${context}`, ).toEqual([]); } test("login page is clean", async ({ page }) => { await page.goto("/login"); await expect(page.getByRole("button", { name: "Sign in" })).toBeVisible(); await expectClean(page, "login"); }); test("shell, chat, and computer panel are clean", async ({ page }) => { await signIn(page); await expectClean(page, "workspace home"); await page.getByRole("link", { name: /Scout/ }).click(); await expect(page).toHaveURL(/\/claws\/.+\/chat\//); await expectClean(page, "chat"); await page.getByRole("button", { name: "Computer" }).click(); const panel = page.getByRole("complementary", { name: "Computer" }); await expect(panel.getByText(/Scout's Computer/)).toBeVisible(); await expectClean(page, "computer home"); await panel.getByRole("button", { name: "Settings" }).click(); await expect(panel.getByText("Managed by")).toBeVisible(); await expectClean(page, "settings app"); }); test("global pages are clean", async ({ page }) => { await signIn(page); for (const [link, marker] of [ ["Skills", /Skill Library/], ["Approvals", /review/i], ["Team", /workspace/], ["Credits", /Available credits/], ] as const) { await page.getByRole("link", { name: link, exact: true }).click(); await expect(page.getByText(marker).first()).toBeVisible(); await expectClean(page, link); } }); test("the wizard is clean", async ({ page }) => { await signIn(page); await page.getByRole("link", { name: "New claw" }).click(); await expect(page.getByText("Create your Claw")).toBeVisible(); await expectClean(page, "wizard"); });