test: add accessibility coverage for the status-recommendation panel
Adds aria-live="polite" to the status-conflict panel (matching the existing resolved-issue success-panel convention) so the applied-status confirmation is announced to screen readers, and a Playwright test covering: keyboard-only activation of both the "Review recommendation" and "Change status to X" actions, reduced-motion emulation, and that status is never conveyed by colour alone (the badge always carries its own localized text). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
1fdd2b3ccf
commit
1e407754e6
@@ -85,3 +85,38 @@ test("key demo pages load without console errors", async ({ page }) => {
|
||||
|
||||
expect(errors, `Unexpected console errors: ${errors.join("\n")}`).toEqual([]);
|
||||
});
|
||||
|
||||
test("status-recommendation panel is fully keyboard operable, respects reduced motion, and never signals status by colour alone", async ({
|
||||
page,
|
||||
request,
|
||||
}) => {
|
||||
await request.post("/api/v1/demo/login", { data: { role: "operations_manager" } });
|
||||
await request.post("/api/v1/demo/reset");
|
||||
await request.post("/api/v1/demo/login", { data: { role: "operations_manager" } });
|
||||
|
||||
await page.emulateMedia({ reducedMotion: "reduce" });
|
||||
await page.goto("/login");
|
||||
await page.getByRole("button", { name: "Verken als Operations Manager" }).click();
|
||||
await expect(page).toHaveURL(/\/dashboard$/);
|
||||
await page.goto("/data-quality/DQ-DEMO-STATUS");
|
||||
|
||||
const reviewButton = page.getByRole("button", { name: "Aanbeveling bekijken" });
|
||||
await reviewButton.focus();
|
||||
await expect(reviewButton).toBeFocused();
|
||||
await page.keyboard.press("Enter");
|
||||
|
||||
const confirmButton = page.getByRole("button", { name: /^Status wijzigen naar/ });
|
||||
await expect(confirmButton).toBeVisible();
|
||||
|
||||
// Status is never conveyed by colour alone: the badge always carries its own text.
|
||||
const badge = page.locator(".status-decision .badge").first();
|
||||
await expect(badge).not.toHaveText("");
|
||||
|
||||
// The confirm action itself is a real, focusable, keyboard-activatable button (the
|
||||
// previous "Aanbeveling bekijken" button is unmounted once the decision panel
|
||||
// replaces it, so focus is verified directly rather than via a Tab chain from it).
|
||||
await confirmButton.focus();
|
||||
await expect(confirmButton).toBeFocused();
|
||||
await page.keyboard.press("Enter");
|
||||
await expect(page.getByText("Toegepast", { exact: false })).toBeVisible();
|
||||
});
|
||||
|
||||
@@ -566,7 +566,7 @@ function VehicleStatusConflictPanel({ issue, onResolved }: { issue: IssueDetail;
|
||||
recommendation.safe_to_apply;
|
||||
|
||||
return (
|
||||
<section className="panel" aria-labelledby="status-conflict-heading">
|
||||
<section className="panel" aria-labelledby="status-conflict-heading" aria-live="polite">
|
||||
<SectionHeading
|
||||
headingId="status-conflict-heading"
|
||||
title={t("detail.vehicleStatusConflict.heading")}
|
||||
|
||||
Reference in New Issue
Block a user