Files
clean-architecture-frontend…/tests/e2e/accessibility.spec.js

46 lines
1.4 KiB
JavaScript

import AxeBuilder from "@axe-core/playwright";
import { expect, test } from "@playwright/test";
for (const route of [
"/",
"/examples/ui",
"/examples/states",
"/examples/auth",
"/sample/resources",
"/not-found",
]) {
test(`@a11y ${route} has no critical or serious axe violations`, async ({
page,
}) => {
await page.goto(route);
await expect(page.getByRole("main")).toBeVisible();
const results = await new AxeBuilder({ page })
.withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"])
.analyze();
const blocking = results.violations.filter((violation) =>
["critical", "serious"].includes(violation.impact ?? ""),
);
expect(blocking).toEqual([]);
});
}
test("@a11y keyboard reaches the primary route action with visible focus", async ({
page,
}) => {
await page.goto("/");
const action = page.getByRole("link", { name: "UI 구성요소 보기" });
await expect(action).toBeVisible();
await page.keyboard.press("Tab");
await expect(action).toBeFocused();
await expect(action).toHaveCSS("outline-style", "solid");
});
test("@a11y reduced-motion policy disables long animation", async ({ page }) => {
await page.emulateMedia({ reducedMotion: "reduce" });
await page.goto("/");
const duration = await page
.locator("body")
.evaluate((body) => getComputedStyle(body).animationDuration);
expect(["0s", "0.00001s", "1e-05s"]).toContain(duration);
});