Utilisation avec Playwright
Playwright est un framework de tests de bout en bout multinavigateur de Microsoft, qui pilote de vrais moteurs Chromium, Firefox et WebKit depuis Node.js. surea11y s’y intègre via le binding @surea11y/playwright.
$ npm install @surea11y/core @surea11y/playwright playwright$ npx playwright install chromium
La seconde commande est importante : chaque test lance un vrai navigateur, et npm install seul ne le télécharge pas.
const { chromium } = require('playwright');const { A11yCoreBuilder } = require('@surea11y/playwright');const browser = await chromium.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) sélectionne par cible de conformité : les règles des critères de niveau A et AA de WCAG 2.2, selon le niveau de chaque critère dans cette version. .withBestPractices() ajoute les règles qui ne vérifient aucun critère WCAG, comme region ; seule, elle n’exécute que celles-ci.
.withPacks() enregistre un pack dans la page avant l’analyse, et .options({ profile }) choisit son profil. Un pack qui ne s’exécute pas est signalé comme une lacune d’analyse 'pack-skipped', si bien qu’un test qui vérifie getScanGaps(results) échoue au lieu de passer sans lui.
Fonctionne avec les trois moteurs de Playwright, pas seulement Chromium : vérifié par de vraies exécutions sous Firefox et WebKit.
Composants web. Un composant qui garde ses ElementInternals dans un champ privé, et se donne un nom, ses états ou un rôle par ce biais, ne peut être relu par aucun script de la page. Par défaut, l’analyse pose donc une question sur ce composant (cantTell) au lieu de le juger, et un rôle donné uniquement ainsi n’est pas vérifié du tout. Si vous construisez ou testez une bibliothèque de composants, installez le hook d’internals facultatif du binding avant que les scripts de la page elle-même ne s’exécutent, et ces composants sont jugés comme n’importe quel autre contrôle :
const context = await browser.newContext();await A11yCoreBuilder.installInternalsHook(context); // before any page navigatesconst page = await context.newPage();await page.goto('https://example.com/');
Appelez-le avant page.goto(), sur la page ou sur son contexte de navigateur. Il s’exécute via addInitScript() : un seul appel couvre chaque frame et chaque navigation de la page, ou de chaque page qu’ouvre le contexte, dans Chromium, Firefox et WebKit. Avec @playwright/test, appelez-le dans un beforeEach sur la fixture context.
Le hook est destiné aux exécutions de test et d’audit : il garde ce qu’il enregistre là où n’importe quel script de la page peut le lire, c’est pourquoi il est facultatif. Sans lui, l’analyse le signale une fois lorsqu’elle a posé une question sur de tels composants. La section du README sur le hook d’internals donne les détails.
Gestionnaires de clic et régions live. Depuis core 1.14, il existe deux autres hooks facultatifs. La plupart des pages ajoutent leurs gestionnaires de clic depuis un script, où aucun script de la page ne peut les lister ensuite, si bien que l’analyse ne voit pas qu’un <div role="button"> doté d’un écouteur de clic ne fait rien au clavier ; avec le hook d’écouteurs, ce bouton échoue (CLICK_HANDLER_NO_KEY_LISTENER). Le hook de régions live enregistre ce que reçoivent les régions live de la page : l’analyse pose alors une question sur un message d’état ajouté avec son texte déjà dedans, que les lecteurs d’écran n’annoncent souvent pas, et announcements() renvoie ce que la page a mis à disposition pour être annoncé, afin qu’un test vérifie qu’une action a bien informé l’utilisateur. Installez-les avant que les scripts de la page elle-même ne s’exécutent, comme le hook d’internals :
const context = await browser.newContext();await A11yCoreBuilder.installListenerHook(context); // before any page navigatesawait A11yCoreBuilder.installLiveRegionHook(context);const page = await context.newPage();await page.goto('https://example.com/settings');await page.getByRole('button', { name: 'Save' }).click();const said = await A11yCoreBuilder.announcements(page);// [{ text: 'Saved', politeness: 'polite', ..., selector: '#status' }]
Tous deux s’installent comme le hook d’internals, sur la page ou sur son contexte de navigateur, avant qu’elle ne navigue. Avec @playwright/test, installez-les dans un beforeEach sur la fixture context.
Comme le hook d’internals, tous deux sont destinés aux exécutions de test et d’audit : n’importe quel script de la page peut lire ce qu’ils enregistrent. announcements() est ce que la page a mis à disposition pour être annoncé, pas ce qu’un lecteur d’écran a dit, et vaut null sans le hook de régions live. Sans l’un ou l’autre hook, getScanNotes() signale quand des constats que ce hook aurait tranchés ont été jugés sans lui. Les sections du README sur le hook d’écouteurs et le hook de régions live donnent les détails.
Mode sombre, largeurs de téléphone et seuil de gravité. .conditions([{ colorScheme: 'dark' }, { width: 320 }]) analyse la page telle qu’elle est, puis à nouveau sous chaque condition, et renvoie un seul résultat : le résultat d’une règle est le pire de toutes les analyses, et chaque constat indique les conditions sous lesquelles il a été vu. Chaque condition est une analyse complète, et .frames(true) ne peut pas encore s’y combiner. Cela fonctionne dans Chromium, Firefox et WebKit. getGatingFailures(results, { failOnSeverity: 'serious' }) renvoie les règles en échec à cette gravité ou au-dessus, pour qu’un test bloque d’abord les problèmes graves et critiques pendant que les autres restent signalés ; formatFailures() accepte la même option.
Des questions qui penchent, avec des étapes. Depuis core 1.14, un constat cantTell peut pencher vers fail ou pass, en disant pourquoi, et porte howToCheck, les étapes qu’une personne suit pour y répondre. formatFailures() liste les échecs probables juste après les échecs, et affiche les étapes avec { howToCheck: true }. Pour qu’un test échoue aussi sur les échecs probables, ajoutez leaningFailures(results) de core au seuil.
A11yCoreBuilder a aussi .wcagLevel(), qui limite les critères rapportés à un niveau WCAG sans changer les règles exécutées ; .includeMode('or'), qui exécute les règles d’une étiquette plus les règles que vous nommez ; .plannedChecks() et .plannedCriteria(), qui listent ce qu’une analyse vérifiera avant qu’elle ne s’exécute, pour qu’une sélection qui n’exécute rien ne passe pas pour une analyse sans échec ; .logger(), qui envoie les avertissements de lacunes d’analyse à votre propre journal ; .fetchStyleSheets(false), qui empêche .analyze() de récupérer les feuilles de style d’autres origines que la page ne peut pas lire elle-même, pour les règles qui lisent le CSS ; et getScanNotes(results), qui indique comment la page a été analysée. Le README du binding les décrit chacun.
Voir aussi un exemple exécutable dans le dépôt du paquet.
Ensuite : choisir les règles à exécuter, intégrer l’analyse à la CI et consulter le schéma complet du résultat.