Verwendung mit Puppeteer
Puppeteer ist eine Node.js-Bibliothek, die Chrome/Chromium headless oder mit Oberfläche über das DevTools-Protokoll steuert — Browserautomatisierung und Skripting, oft für Tests verwendet, aber selbst kein Test-Framework. surea11y wird über das Binding @surea11y/puppeteer eingebunden.
$ npm install @surea11y/core @surea11y/puppeteer puppeteer
Puppeteer lädt bei npm install sein eigenes mitgeliefertes Chrome herunter — anders als bei Playwright gibt es keinen separaten Schritt zur Browserinstallation.
const puppeteer = require('puppeteer');const { A11yCoreBuilder } = require('@surea11y/puppeteer');const browser = await puppeteer.launch();const page = await browser.newPage();await page.goto('https://example.com/');const results = await new A11yCoreBuilder({ page }).include('#main') // optional -- call multiple times for multi-region scans.exclude('.cookie-banner') // optional.withWcag('2.2', 'AA') // the rules for WCAG 2.2's A and AA criteria.disableRules(['meta-refresh-no-exceptions']).analyze();console.log(results.checksResults.filter(r => r.outcome === 'fail'));await browser.close();
.withWcag(version, level) wählt nach Konformitätsziel aus: die Regeln für die Erfolgskriterien der Stufen A und AA von WCAG 2.2, nach der Stufe, die jedes Kriterium in dieser Version hat. .withBestPractices() fügt die Regeln hinzu, die kein WCAG-Erfolgskriterium prüfen, etwa region; allein ausgeführt, laufen nur diese.
.withPacks() registriert vor dem Scan ein Pack in der Seite, und .options({ profile }) wählt sein Profil. Ein Pack, das nicht läuft, wird als Scan-Lücke 'pack-skipped' gemeldet, sodass ein Test, der getScanGaps(results) prüft, fehlschlägt, statt ohne das Pack zu bestehen.
Web Components. Eine Komponente, die ihre ElementInternals in einem privaten Feld hält und sich darüber einen Namen, ihre Zustände oder eine Rolle gibt, lässt sich von keinem Skript der Seite auslesen. Standardmäßig stellt der Scan zu einer solchen Komponente eine Frage (cantTell), statt sie zu beurteilen, und eine Rolle, die nur so gesetzt ist, wird gar nicht geprüft. Wenn Sie eine Komponentenbibliothek bauen oder testen, installieren Sie den optionalen Internals-Hook des Bindings, bevor die eigenen Skripte der Seite laufen, und diese Komponenten werden wie jedes andere Bedienelement beurteilt:
const page = await browser.newPage();await A11yCoreBuilder.installInternalsHook(page); // before gotoawait page.goto('https://example.com/');
Rufen Sie ihn vor page.goto() auf. Er läuft über page.evaluateOnNewDocument(), sodass ein Aufruf die Frames und Navigationen der Seite für ihre gesamte Lebensdauer abdeckt, in Chrome und Firefox; ein neuer Tab, den die Seite selbst öffnet, erhält ihn nicht.
Der Hook ist für Test- und Audit-Läufe gedacht: Er legt das, was er aufzeichnet, dort ab, wo jedes Skript der Seite es lesen kann, deshalb ist er optional. Ohne ihn meldet der Scan einmal, wenn er zu solchen Komponenten Fragen gestellt hat. Der Abschnitt der README zum Internals-Hook enthält die Details.
Klick-Handler und Live-Regionen. Seit core 1.14 gibt es zwei weitere optionale Hooks. Die meisten Seiten fügen ihre Klick-Handler per Skript hinzu, wo kein Skript der Seite sie danach auflisten kann. Der Scan sieht daher nicht, dass ein <div role="button"> mit einem Klick-Listener per Tastatur nichts tut; mit dem Listener-Hook ergibt ein solcher Button fail (CLICK_HANDLER_NO_KEY_LISTENER). Der Live-Region-Hook zeichnet auf, was die Live-Regionen der Seite erhalten: Der Scan stellt dann eine Frage zu einer Statusmeldung, die schon mit ihrem Text eingefügt wurde und die Screenreader oft nicht ansagen, und announcements() gibt zurück, was die Seite zur Ansage bereitgestellt hat, damit ein Test prüfen kann, ob eine Aktion den Nutzenden etwas mitgeteilt hat. Installieren Sie sie, bevor die eigenen Skripte der Seite laufen, wie den Internals-Hook:
const page = await browser.newPage();await A11yCoreBuilder.installListenerHook(page); // before gotoawait A11yCoreBuilder.installLiveRegionHook(page);await page.goto('https://example.com/settings');await page.click('#save');const said = await A11yCoreBuilder.announcements(page);// [{ text: 'Saved', politeness: 'polite', ..., selector: '#status' }]
Beide werden wie der Internals-Hook über page.evaluateOnNewDocument() installiert, vor page.goto().
Wie der Internals-Hook sind beide für Test- und Audit-Läufe gedacht: Jedes Skript der Seite kann lesen, was sie aufzeichnen. announcements() ist das, was die Seite zur Ansage bereitgestellt hat, nicht das, was ein Screenreader gesagt hat, und ohne den Live-Region-Hook null. Fehlt einer der beiden Hooks, meldet getScanNotes(), wenn Befunde, die er entschieden hätte, ohne ihn beurteilt wurden. Die Abschnitte der README zum Listener-Hook und zum Live-Region-Hook enthalten die Details.
Dunkler Modus, Smartphone-Breiten und eine Schwelle nach Schweregrad. .conditions([{ colorScheme: 'dark' }, { width: 320 }]) scannt die Seite so, wie sie ist, und dann erneut unter jeder Bedingung, und gibt ein einziges Ergebnis zurück: Das Ergebnis einer Regel ist ihr schlechtestes über alle Scans, und jeder Befund nennt die Bedingungen, unter denen er auftrat. Jede Bedingung ist ein vollständiger Scan, und .frames(true) lässt sich noch nicht damit kombinieren. In Firefox funktionieren Breiten, aber ein Farbschema braucht das DevTools-Protokoll, das Puppeteer nur in Chrome hat; dort lehnt .analyze() daher vor jedem Scan ab. getGatingFailures(results, { failOnSeverity: 'serious' }) gibt die fehlschlagenden Regeln ab diesem Schweregrad zurück, sodass ein Test zuerst bei schwerwiegenden und kritischen Problemen blockiert, während der Rest weiter gemeldet wird; formatFailures() nimmt dieselbe Option.
Fragen mit Tendenz und Prüfschritten. Seit core 1.14 kann ein cantTell-Befund zu fail oder pass tendieren, mit Begründung, und er enthält howToCheck: die Schritte, mit denen eine Person ihn beantwortet. formatFailures() listet die wahrscheinlich nicht erfüllten Fragen direkt nach den Fehlschlägen und gibt mit { howToCheck: true } die Schritte aus. Soll ein Test auch bei wahrscheinlichen Fehlschlägen scheitern, nehmen Sie leaningFailures(results) aus core in die Schwelle auf.
A11yCoreBuilder hat außerdem .wcagLevel(), das die gemeldeten Kriterien auf eine WCAG-Stufe begrenzt, ohne zu ändern, welche Regeln laufen; .includeMode('or'), das die Regeln eines Tags plus die Regeln ausführt, die Sie nennen; .plannedChecks() und .plannedCriteria(), die auflisten, was ein Scan prüfen wird, bevor er läuft, damit eine Auswahl, die nichts ausführt, nicht als Scan ohne Befunde durchgeht; .logger(), das Warnungen zu Scan-Lücken an Ihr eigenes Log schickt; .fetchStyleSheets(false), das .analyze() davon abhält, Stylesheets anderer Origins, die die Seite selbst nicht lesen kann, für die Regeln abzurufen, die das CSS lesen; und getScanNotes(results), das angibt, wie die Seite gescannt wurde. Die README des Bindings beschreibt jede davon.
Siehe auch ein lauffähiges Beispiel im Repository des Pakets.
Als Nächstes: festlegen, welche Regeln laufen, den Scan in die CI einbinden und das vollständige Ergebnisschema ansehen.