test: add axe a11y pass and device visual regression (phase 4c)

Add scoped axe accessibility audit (a11y.spec.ts, device-a11y.spec.ts)
scanning home, one tool per modality, editor, and login across desktop
chromium and mobile-chromium in EN and AR locales. Uses a committed
baseline (a11y-baseline.json) to gate on NEW critical/serious violations
while documenting existing debt.

Add device-visual.spec.ts with curated screenshots (home, resize tool,
settings dialog) on mobile-chromium and tablet-chromium. Six darwin
baselines generated; linux baselines deferred to the existing
update-visual-baselines workflow.

Trivial a11y fixes applied:
- Login page: outer div -> main (fixes landmark-one-main, reduces region)
- Editor page: outer div -> main for both desktop and mobile gate
- AppLayout main: add tabIndex={-1} for skip-link focusability

Updated DEVICE_SPECS regex to route device-visual and device-a11y specs.
Added @axe-core/playwright as a devDependency.
This commit is contained in:
SnapOtter
2026-06-20 03:44:26 +08:00
parent 692c8ebf91
commit 0705de8f1b
17 changed files with 27491 additions and 8 deletions
@@ -37,7 +37,11 @@ export function AppLayout({ children, breadcrumb, navVariant }: AppLayoutProps)
/>
{/* Main content area */}
<main id="main-content" className={cn("flex-1 overflow-y-auto", isMobile && "pb-20")}>
<main
id="main-content"
tabIndex={-1}
className={cn("flex-1 overflow-y-auto", isMobile && "pb-20")}
>
{children}
</main>
+4 -4
View File
@@ -143,16 +143,16 @@ export function EditorPage() {
if (isMobile) {
return (
<div className="flex flex-col items-center justify-center h-full p-8 text-center">
<main className="flex flex-col items-center justify-center h-full p-8 text-center">
<Monitor size={48} className="text-muted-foreground mb-4" />
<h2 className="text-lg font-semibold text-foreground mb-2">{t.editor.mobile.heading}</h2>
<p className="text-sm text-muted-foreground max-w-sm">{t.editor.mobile.description}</p>
</div>
</main>
);
}
return (
<div className="flex flex-col h-screen overflow-hidden bg-background text-foreground">
<main className="flex flex-col h-screen overflow-hidden bg-background text-foreground">
<h1 className="sr-only">{t.editor.welcome.heading}</h1>
<EditorMenuBar
onNewDocument={() => setShowNewDocument(true)}
@@ -195,6 +195,6 @@ export function EditorPage() {
<ImageResizeDialog open={showImageResize} onClose={() => setShowImageResize(false)} />
<FillDialog open={fillDialogOpen} onClose={() => setFillDialogOpen(false)} />
<NewDocumentDialog open={showNewDocument} onClose={() => setShowNewDocument(false)} />
</div>
</main>
);
}
+2 -2
View File
@@ -222,7 +222,7 @@ export function LoginPage() {
};
return (
<div className="flex h-screen bg-background">
<main className="flex h-screen bg-background">
<div className="flex-1 flex items-center justify-center p-8">
<div className="w-full max-w-md space-y-8">
<div>
@@ -415,6 +415,6 @@ export function LoginPage() {
</p>
</div>
</div>
</div>
</main>
);
}