28 lines
1.3 KiB
JavaScript
28 lines
1.3 KiB
JavaScript
// Automated accessibility scan of the AUTHENTICATED app (QA_PLAN B14). Companion
|
|
// to a11y.spec.js (public pages). Runs axe-core on the main in-app pages using the
|
|
// logged-in state from auth.setup, and fails on critical/serious WCAG violations
|
|
// so contrast/label/role regressions are caught every cycle.
|
|
const { test, expect } = require('@playwright/test');
|
|
const AxeBuilder = require('@axe-core/playwright').default;
|
|
const { STORAGE_STATE } = require('./constants');
|
|
|
|
test.use({ storageState: STORAGE_STATE });
|
|
|
|
const PAGES = ['/', '/bills', '/summary', '/spending', '/analytics', '/categories', '/snowball'];
|
|
|
|
for (const path of PAGES) {
|
|
test(`no critical/serious a11y violations on ${path}`, async ({ page }) => {
|
|
await page.goto(path);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const results = await new AxeBuilder({ page }).withTags(['wcag2a', 'wcag2aa']).analyze();
|
|
const blocking = results.violations.filter((v) => v.impact === 'critical' || v.impact === 'serious');
|
|
const summary = blocking
|
|
.map((v) => `- [${v.impact}] ${v.id}: ${v.help} (${v.nodes.length})\n ${v.nodes.map((n) => (n.html || '').slice(0, 140)).join('\n ')}`)
|
|
.join('\n');
|
|
if (blocking.length) console.log(`[a11y] ${path}\n${summary}\n`);
|
|
|
|
expect.soft(blocking, `axe critical/serious on ${path}:\n${summary}`).toEqual([]);
|
|
});
|
|
}
|