feat(a11y): add skip link for improved navigation accessibility

This commit is contained in:
fitse-yotor
2026-08-21 12:34:00 +03:00
parent e74ef1c672
commit 8f6ebdafb1
11 changed files with 114 additions and 5 deletions

View File

@@ -98,3 +98,42 @@ for (const app of APPS) {
await expect(button).toHaveScreenshot(`${app.name}-focus-ring.png`);
});
}
/**
* The skip link, on a real app shell.
*
* Not on the gallery route: the point of a skip link is bypassing the nav, and
* the gallery has none. The login page is the shell-less public route both apps
* share, so this uses the landing route instead — it carries the chrome without
* needing a session.
*
* A skip link is invisible until focused, which means a broken one and a
* working one look identical in every screenshot. Only a focus test separates
* them.
*/
test.describe('skip link', () => {
for (const app of APPS) {
test(`${app.name} — reveals on focus and targets main`, async ({ page }) => {
await page.goto(`${app.url}/`, { waitUntil: 'networkidle' });
const link = page.locator('.ema-skip-link');
if ((await link.count()) === 0) {
// The public landing route does not mount the app shell in every app;
// skipping is honest here, where asserting absence would be wrong.
test.skip(true, 'landing route does not mount the app shell');
return;
}
// Off-screen until focused...
await expect(link).not.toBeInViewport();
await page.keyboard.press('Tab');
await expect(link).toBeFocused();
await expect(link).toBeInViewport();
// ...and it must point at something that exists.
const href = await link.getAttribute('href');
expect(href).toBe('#ema-main-content');
});
}
});