68 lines
1.9 KiB
TypeScript
68 lines
1.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
MANUAL_A11Y_ROUTE_IDS,
|
|
validateManualA11yEvidence,
|
|
} from "../../scripts/lib/manual-a11y-evidence.ts";
|
|
import { ROUTE_REGISTRY } from "../../src/features/installed-feature-contracts.ts";
|
|
|
|
const reviewed = `Status: reviewed
|
|
Route ID: APP_HOME
|
|
Release ID: release-1
|
|
Reviewer: reviewer@example.test
|
|
Reviewed at: 2026-07-25T12:00:00Z
|
|
Signature: review-record-1
|
|
Attestation: accepted
|
|
M1 Keyboard: pass
|
|
M2 Visible focus: pass
|
|
M3 Route focus: pass
|
|
M4 Modal focus: not-applicable (no modal)
|
|
M5 Error association: not-applicable (no form error)
|
|
M6 Color signal: pass
|
|
M7 Reduced motion: pass
|
|
Screen reader: pass
|
|
Notes: no defects`;
|
|
|
|
describe("manual accessibility evidence", () => {
|
|
it("requires evidence for every registered user-visible route", () => {
|
|
expect([...MANUAL_A11Y_ROUTE_IDS].sort()).toEqual(
|
|
Object.keys(ROUTE_REGISTRY).sort(),
|
|
);
|
|
});
|
|
|
|
it("accepts a complete signed human review record", () => {
|
|
expect(validateManualA11yEvidence(reviewed)).toMatchObject({
|
|
failures: [],
|
|
passed: true,
|
|
});
|
|
});
|
|
|
|
it("rejects pending, unsigned, or incomplete evidence", () => {
|
|
expect(
|
|
validateManualA11yEvidence(
|
|
reviewed
|
|
.replace("Status: reviewed", "Status: pending-manual-review")
|
|
.replace("Signature: review-record-1", "Signature:")
|
|
.replace("Screen reader: pass", "Screen reader: pending"),
|
|
),
|
|
).toMatchObject({
|
|
failures: ["Status", "Signature", "Screen reader"],
|
|
passed: false,
|
|
});
|
|
});
|
|
|
|
it("does not treat an unexplained not-applicable verdict as evidence", () => {
|
|
expect(
|
|
validateManualA11yEvidence(
|
|
reviewed.replace(
|
|
"M4 Modal focus: not-applicable (no modal)",
|
|
"M4 Modal focus: not-applicable",
|
|
),
|
|
),
|
|
).toMatchObject({
|
|
failures: ["M4 Modal focus"],
|
|
passed: false,
|
|
});
|
|
});
|
|
});
|