GdzieWjade/scripts/axe.mjs

42 lines
2.2 KiB
JavaScript

// Automated a11y scan (axe-core, WCAG 2.2 AA rules) of the main views. Run against `pnpm preview`.
import { readFile } from 'node:fs/promises';
import { chromium } from 'playwright-core';
const axeSrc = await readFile('node_modules/axe-core/axe.min.js', 'utf8');
const URL = process.env.URL ?? 'http://localhost:4173/';
const browser = await chromium.launch();
// VIEWPORT=390x844 runs the same scan with a phone-sized (touch) viewport
const [vw, vh] = (process.env.VIEWPORT ?? '1280x900').split('x').map(Number);
const page = await browser.newPage({ viewport: { width: vw, height: vh }, isMobile: vw < 700, hasTouch: vw < 700, locale: 'pl-PL' });
let bad = 0;
async function scan(name) {
await page.addScriptTag({ content: axeSrc });
const r = await page.evaluate(() => axe.run(document, { runOnly: { type: 'tag', values: ['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa', 'best-practice'] } }));
console.log(`${name}: ${r.violations.length} violation(s)`);
for (const v of r.violations) { bad++; console.log(` [${v.impact}] ${v.id}: ${v.help} — ${v.nodes.length} node(s), e.g. ${v.nodes[0].target.join(' ')}`); }
}
await page.goto(URL, { waitUntil: 'networkidle' });
await scan('login');
await page.click('text=Zaloguj jako Maria Wiśniewska');
await page.waitForSelector('[role=tablist]');
for (const [tab, name] of [['Zgłoszenia', 'dashboard: reports'], ['Przejścia', 'dashboard: crossings'], ['Jakość', 'dashboard: quality'], ['Eksport', 'dashboard: export']]) {
await page.click(`[role=tab]:has-text("${tab}")`);
await scan(name);
}
await page.click('nav >> text=Miejsca');
await page.waitForSelector('#q');
await scan('places');
await page.fill('#q', 'Sukiennice');
await page.click('button[id^=place-]');
await page.waitForSelector('text=Szczegóły dostępności');
await scan('place detail');
await page.click('nav >> text=Trasa');
await page.click('text=Sukiennice → Zamek Królewski na Wawelu');
await page.waitForSelector('text=Opis trasy tekstem');
await scan('route');
await page.click('nav >> text=Profil');
await page.waitForSelector('#st1');
await scan('profile + settings');
await page.click('nav >> text=Dane');
await scan('about');
await browser.close();
process.exitCode = bad ? 1 : 0;