test: enforce accessible portfolio interaction
This commit is contained in:
99
tests/browser/accessibility-axe.spec.ts
Normal file
99
tests/browser/accessibility-axe.spec.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import AxeBuilder from "@axe-core/playwright";
|
||||
import type { Page } from "@playwright/test";
|
||||
import { expect, test } from "../helpers/serve-dist";
|
||||
|
||||
type AccessibilityState =
|
||||
| "default"
|
||||
| "audio-running"
|
||||
| "static"
|
||||
| "reduced-motion"
|
||||
| "media-failure"
|
||||
| "missing-social";
|
||||
|
||||
const states: readonly AccessibilityState[] = [
|
||||
"default",
|
||||
"audio-running",
|
||||
"static",
|
||||
"reduced-motion",
|
||||
"media-failure",
|
||||
"missing-social",
|
||||
];
|
||||
|
||||
async function enterState(
|
||||
page: Page,
|
||||
distUrl: string,
|
||||
state: AccessibilityState,
|
||||
): Promise<void> {
|
||||
if (state === "reduced-motion") {
|
||||
await page.emulateMedia({ reducedMotion: "reduce" });
|
||||
}
|
||||
if (state === "media-failure") {
|
||||
await page.addInitScript(() => {
|
||||
const nativeGetContext = HTMLCanvasElement.prototype.getContext;
|
||||
Object.defineProperty(HTMLCanvasElement.prototype, "getContext", {
|
||||
configurable: true,
|
||||
value(
|
||||
this: HTMLCanvasElement,
|
||||
contextId: string,
|
||||
options?: unknown,
|
||||
): RenderingContext | null {
|
||||
if (
|
||||
contextId === "webgl" ||
|
||||
contextId === "webgl2" ||
|
||||
contextId === "experimental-webgl"
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return Reflect.apply(nativeGetContext, this, [
|
||||
contextId,
|
||||
options,
|
||||
]) as RenderingContext | null;
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
await page.goto(distUrl, { waitUntil: "domcontentloaded" });
|
||||
|
||||
if (state === "audio-running") {
|
||||
await page.getByRole("button", { name: "START THE DRIVE" }).click();
|
||||
await expect(
|
||||
page.getByRole("button", { name: "Mute sound" }),
|
||||
).toBeVisible();
|
||||
} else if (state === "static") {
|
||||
await page.getByLabel("Quality control").selectOption("static");
|
||||
await expect(
|
||||
page.getByRole("button", { name: "Enable motion" }),
|
||||
).toBeVisible();
|
||||
} else if (state === "reduced-motion") {
|
||||
await expect(page.getByRole("status")).toContainText(
|
||||
"reduced motion requested",
|
||||
);
|
||||
} else if (state === "media-failure") {
|
||||
await expect(page.locator(".journey-world")).toHaveAttribute(
|
||||
"data-scene-state",
|
||||
"failed",
|
||||
);
|
||||
} else if (state === "missing-social") {
|
||||
await page.locator('#contact a[target="_blank"]').evaluateAll((links) => {
|
||||
for (const link of links) link.closest("li")?.remove();
|
||||
});
|
||||
await expect(page.locator('#contact a[target="_blank"]')).toHaveCount(0);
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible();
|
||||
}
|
||||
}
|
||||
|
||||
for (const state of states) {
|
||||
test(`${state} has no WCAG 2.2 A or AA axe violations`, async ({
|
||||
page,
|
||||
distUrl,
|
||||
}) => {
|
||||
await enterState(page, distUrl, state);
|
||||
|
||||
const result = await new AxeBuilder({ page })
|
||||
.withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"])
|
||||
.analyze();
|
||||
|
||||
expect(result.violations).toEqual([]);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user