import AxeBuilder from "@axe-core/playwright"; import { expect, test } from "../support/browser/strict-browser-test.ts"; import { gotoTechLog } from "../support/browser/tech-log-fixtures.ts"; function blockingViolations(results: Awaited>) { return results.violations.filter((violation) => ["critical", "serious"].includes(violation.impact ?? ""), ); } test("Public shell exposes one main landmark, one h1, labelled navigation, and current link", async ({ page, }) => { await gotoTechLog(page, "/projects"); await expect(page.getByRole("main")).toHaveCount(1); await expect(page.getByRole("heading", { level: 1 })).toHaveCount(1); await expect(page.getByRole("navigation", { name: "주요 탐색" })).toBeVisible(); await expect(page.getByRole("link", { name: "프로젝트", exact: true })).toHaveAttribute( "aria-current", "page", ); }); test("Studio mobile navigation is keyboard reachable and exposes its expanded state", async ({ page, }) => { await page.setViewportSize({ width: 390, height: 844 }); await gotoTechLog(page, "/studio"); const trigger = page.locator(".studio-menu-trigger"); await trigger.focus(); await page.keyboard.press("Enter"); await expect(trigger).toHaveAttribute("aria-expanded", "true"); await expect(page.getByRole("navigation", { name: "Studio 모바일 탐색" })).toBeVisible(); }); test("dirty-leave dialog is labelled, traps focus, and restores the invoking link", async ({ page, }) => { await gotoTechLog( page, "/studio/documents/11111111-1111-4111-8111-111111111111/edit", ); await page.getByLabel("요약").fill("저장하지 않은 접근성 검증 변경"); const trigger = page.getByRole("link", { name: "게시 기록", exact: true }).first(); await trigger.click(); const dialog = page.getByRole("dialog", { name: "저장하지 않은 변경" }); await expect(dialog).toBeVisible(); await expect(dialog.getByRole("button", { name: "이 페이지에 머무르기" })).toBeFocused(); await page.keyboard.press("Escape"); await expect(dialog).toBeHidden(); await expect(trigger).toBeFocused(); }); test("open Public search and Studio leave dialogs have no blocking Axe findings", async ({ page, }) => { await gotoTechLog(page, "/"); await page.getByRole("button", { name: "검색 열기" }).click(); let results = await new AxeBuilder({ page }) .include("dialog") .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"]) .analyze(); expect(blockingViolations(results)).toEqual([]); await gotoTechLog( page, "/studio/documents/11111111-1111-4111-8111-111111111111/edit", ); await page.getByLabel("요약").fill("dialog axe state"); await page.getByRole("link", { name: "게시 기록", exact: true }).first().click(); results = await new AxeBuilder({ page }) .include("dialog") .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"]) .analyze(); expect(blockingViolations(results)).toEqual([]); });