test(02-12): scan shared record accessibility states

- use an isolated shared-record browser session\n- scan empty, loading, error, and refusal states with axe
This commit is contained in:
Marc-André Bombeck committed 2026-08-06 05:14:00 +02:00
1 parent 407f7cc044
commit 9bb1e5b2ea
3 files changed
+97 -6

No files matched your search

+10
View File
@@ -138,6 +138,11 @@ export const SCOPE_DELEGATE_STORAGE_STATE_PATH = resolve(
"e2e/setup/storageStateScopeDelegate.json",
);
export const SCOPE_A11Y_STORAGE_STATE_PATH = resolve(
process.cwd(),
"e2e/setup/storageStateScopeA11y.json",
);
async function hashPassword(password: string): Promise<string> {
return hash(password, {
memoryCost: 19456,
@@ -488,6 +493,11 @@ export default async function globalSetup(config: FullConfig): Promise<void> {
E2E_SCOPE_DELEGATE,
SCOPE_DELEGATE_STORAGE_STATE_PATH,
);
await captureAuthState(
baseURL,
E2E_SCOPE_DELEGATE,
SCOPE_A11Y_STORAGE_STATE_PATH,
);
}
/**
+1
View File
@@ -17,4 +17,5 @@ export {
OWNER_STORAGE_STATE_PATH,
DELEGATE_STORAGE_STATE_PATH,
SCOPE_DELEGATE_STORAGE_STATE_PATH,
SCOPE_A11Y_STORAGE_STATE_PATH,
} from "./global-setup";
+86 -6
View File
@@ -1,11 +1,91 @@
import AxeBuilder from "@axe-core/playwright";
import type { Page } from "@playwright/test";
import { expect, test } from "./setup/test";
import { SCOPE_A11Y_STORAGE_STATE_PATH } from "./setup/test-helpers";
import { ACCESSIBILITY_STATES } from "../tests/fixtures/v137/e2e-journeys";
async function scan(page: Page) {
const result = await new AxeBuilder({ page })
.withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"])
.analyze();
expect(result.violations).toEqual([]);
}
test.describe("sharing accessibility anchors", () => {
for (const state of ACCESSIBILITY_STATES) {
test(`anchor: ${state.name}`, () => {
expect(state.contract).toBe("inventory-only");
async function openProfileRecord(page: Page) {
await page.goto("/");
await page.getByRole("button", { name: "User menu" }).first().click();
await page.locator('[data-slot="account-switcher-trigger"]').click();
const entry = page
.locator('[data-slot="account-switcher-entry"]')
.filter({ hasText: "e2e-scope-profile" });
await expect(entry).toHaveCount(1);
await entry.click();
await expect(page).toHaveURL(/\/profile$/);
}
async function leaveRecord(page: Page) {
await page.locator('[data-slot="shared-record-banner-exit"]').click();
await expect(page.locator('[data-slot="shared-record-banner"]')).toHaveCount(
0,
);
}
test.describe("shared record accessibility states", () => {
test.describe.configure({ mode: "serial" });
test.use({ storageState: SCOPE_A11Y_STORAGE_STATE_PATH });
test.beforeEach(({}, testInfo) => {
test.skip(
testInfo.project.name !== "chromium-desktop",
"isolated shared-record accessibility session",
);
});
test("success and empty shared profile states have no WCAG violations", async ({
page,
}) => {
await openProfileRecord(page);
await expect(page.locator('[data-slot="profile-summary"]')).toBeVisible();
await scan(page);
await leaveRecord(page);
});
test("the capability hydration loading state has no WCAG violations", async ({
page,
}) => {
await page.route("**/api/auth/me", async (route) => {
await new Promise((resolve) => setTimeout(resolve, 250));
await route.continue();
});
}
await page.goto("/measurements");
await expect(
page.locator('[data-slot="record-scope-hydration-gate"]'),
).toBeVisible();
await scan(page);
});
test("the shared profile read error state has no WCAG violations", async ({
page,
}) => {
await openProfileRecord(page);
await page.route("**/api/profile/summary", (route) =>
route.fulfill({ status: 500, body: "{}" }),
);
await page.reload();
await expect(page.locator('[data-slot="query-error-card"]')).toBeVisible();
await scan(page);
await leaveRecord(page);
});
test("the shared-record refusal state has no WCAG violations", async ({
page,
}) => {
await openProfileRecord(page);
await page.goto("/settings/account");
await expect(
page.locator('[data-slot="shared-record-unavailable"]'),
).toBeVisible();
await scan(page);
await page.locator('[data-slot="shared-record-unavailable-leave"]').click();
});
});