40 lines
1.3 KiB
TypeScript
40 lines
1.3 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import AxeBuilder from '@axe-core/playwright';
|
|
|
|
const routes = ['/', '/dashboard', '/focus', '/history', '/routines', '/settings'];
|
|
|
|
for (const route of routes) {
|
|
test(`accessibility: ${route} has no critical violations`, async ({ page }) => {
|
|
await page.goto(route);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const results = await new AxeBuilder({ page })
|
|
.withTags(['wcag2a', 'wcag2aa', 'best-practice'])
|
|
.analyze();
|
|
|
|
const critical = results.violations.filter(
|
|
(v) => v.impact === 'critical' || v.impact === 'serious'
|
|
);
|
|
|
|
if (critical.length > 0) {
|
|
const summary = critical
|
|
.map((v) => `[${v.impact}] ${v.id}: ${v.description} (${v.nodes.length} nodes)`)
|
|
.join('\n');
|
|
console.log(`Accessibility violations on ${route}:\n${summary}`);
|
|
}
|
|
|
|
expect(critical).toHaveLength(0);
|
|
});
|
|
}
|
|
|
|
test('accessibility: focus-visible ring appears on tab navigation', async ({ page }) => {
|
|
await page.goto('/dashboard');
|
|
await page.waitForLoadState('networkidle');
|
|
await page.keyboard.press('Tab');
|
|
await page.keyboard.press('Tab');
|
|
|
|
const focused = page.locator(':focus-visible');
|
|
const count = await focused.count();
|
|
expect(count).toBeGreaterThan(0);
|
|
});
|