Procédures de test

Une analyse tranche ce que les règles peuvent trancher. Le reste d’une évaluation revient à une personne : les questions qu’une analyse laisse ouvertes (cantTell), et les parties d’un critère qu’aucune règle ne teste. Depuis @surea11y/core 1.15.0, core indique aussi comment faire cette partie : une procédure de test pour chaque facette de chaque critère WCAG qu’évaluent ses règles, et des bonnes pratiques, avec les étapes, les outils nécessaires, et ce qui réussit et ce qui échoue, en anglais, français, allemand, espagnol et japonais. C’est le même texte que celui d’où vient le « Comment vérifier » d’un constat : les vérifications manuelles d’une équipe et ses analyses disent donc la même chose.

Utilisez-les sans aucune analyse, pour un audit manuel ; à côté d’une analyse, pour ce qu’elle laisse à une personne ; ou pour expliquer un critère dont les règles n’ont rien trouvé mais ne couvrent pas tout. Comme les étapes d’un constat, les procédures sont une aide, pas une partie de l’identité d’un constat : leur formulation peut s’améliorer dans n’importe quelle version.

Les voir

Ces deux pages sont la sortie de core lui-même pour WCAG 2.2 niveaux A et AA, régénérée à chaque version que suit ce site, et s’ouvrent depuis le disque sans rien charger d’ailleurs :

  • La référence : comment évaluer chaque critère, facette par facette, sous les principes et les règles des WCAG.
  • La liste de travail : chaque vérification une seule fois, avec un résultat (Non vérifié, Conforme, Non conforme, Non applicable) et des remarques à noter, conservés dans votre navigateur et téléchargeables en JSON ou en CSV.

Les deux pages sont soumises aux propres règles de core, dans jsdom et dans Chromium, en mode clair et sombre, avec le profil WCAG 2.2 AA : un lien d’évitement, un niveau de titre à la fois, des régions nommées, de vraies listes et de vrais fieldsets, un focus visible, rien qui ne repose sur la seule couleur, un thème à couleurs forcées respecté, la largeur d’un téléphone, et une mise en page imprimable.

Ce qu’est une procédure

Un critère a des facettes, les objectifs de test qu’une personne vérifie pour l’évaluer. Une facette qu’une règle tranche est full, une dont les règles tranchent une partie est partial, et une que seule une personne peut juger est manual. Une facette a une procédure générale : les étapes qu’une personne suit sur une page entière, dans un navigateur avec ses outils de développement, un clavier et, quand c’est important, un lecteur d’écran ; puis ce qu’elle constate si cela réussit et si cela échoue, en nommant le critère non respecté ; et les outils nécessaires en plus d’un navigateur :

OutilCe que c’est
keyboardUn clavier
pointerUne souris ou un autre dispositif de pointage
screen-readerUn lecteur d’écran
zoomLe zoom du navigateur
contrast-themeUn thème à contraste élevé (couleurs forcées)
devtoolsLes outils de développement du navigateur
  • Une facette de technologie est un test qu’une règle fait sur un type d’élément (un <img> a un attribut alt). Elle n’a pas de procédure propre : coveredBy nomme la facette plus large dont la procédure l’évalue, pour qu’une liste de contrôle indique ce que fait une personne, une seule fois.
  • Une variante est la question plus étroite qu’une règle pose sur un élément : les étapes que son constat non tranché affiche dans howToCheck. Un constat affiche toujours sa variante, jamais le texte général, et les deux ne se contredisent jamais. Chaque code de raison qu’une règle de core peut rapporter en cantTell se trouve sous exactement une facette.
  • Ce qu’aucun critère n’exige est tenu à part, sous best-practice, pour que les procédures d’un critère ne présentent jamais un conseil comme un échec.

Quels critères ont des procédures

Chaque critère qu’une règle de core évalue, entièrement, en partie ou en cantTell, a une procédure pour chaque facette, y compris les facettes qu’aucune règle ne vérifie, puisqu’une personne en a besoin pour terminer ce que l’analyse a commencé : 36 des 87 critères des WCAG 2.2 aux niveaux A, AA et AAA et 4.1.1 (retiré en 2.2), avec 170 facettes, 56 procédures propres et 114 facettes de technologie couvertes par l’une d’elles. Un tel critère est complete. Les 51 autres critères, qu’aucune règle n’évalue (1.2.3 Audiodescription ou version de remplacement pour un média temporel, par exemple), sont listés avec leurs facettes et sans procédure : comment les évaluer à la main sort du champ de core. Les bonnes pratiques en ont une pour chacune de leurs 13 facettes : landmarks, contenu dans les landmarks, titres, balisage des tableaux, rôles ARIA, ordre du focus, touches d’accès rapide, liens d’évitement, noms et libellés, zoom, noms répétés, nouvelles fenêtres et téléchargements, et réduction des animations.

Les lire

FonctionCe qu’elle donne
proceduresFor(requirement, options)Une exigence : un critère WCAG ('1.4.12'), 'best-practice', ou une exigence d’un pack.
listProcedures(options)Toutes les exigences d’une norme, dans leur ordre, avec les groupes où elle les range (les principes et les règles des WCAG).
procedureChecklist(options)Ce qu’une personne fait pour évaluer la norme, une seule fois chaque chose : un élément par procédure générale.
renderProcedures(input, options)N’importe lequel des trois sous forme de page HTML autonome, ou de Markdown.
relatedRequirements(requirement, options)Entre les WCAG et la norme d’un pack : les exigences qui reprennent un critère ou s’y rattachent, et l’inverse.
procedureLanguages(options)Les langues dans lesquelles on peut lire les procédures d’une norme, complètes ou non, pour un sélecteur de langue.

Dans Node, elles viennent de @surea11y/core, qui lit les dictionnaires sur le disque. Du code qui s’exécute dans un navigateur importe les mêmes depuis @surea11y/core/procedures, avec un suffixe From (proceduresFrom, listProceduresFrom, procedureChecklistFrom, renderProceduresFrom, procedureLanguagesFrom), et passe les dictionnaires qu’il importe depuis @surea11y/core/procedures/<locale> : il n’a besoin d’aucun système de fichiers et n’atteint aucune des règles.

const { proceduresFor } = require('@surea11y/core');
 
proceduresFor('1.4.12', { locale: 'fr' });
// { standard: 'wcag', id: '1.4.12', title: 'Espacement du texte', level: 'AA', complete: true,
// rules: ['avoid-inline-spacing', 'text-spacing-content-loss'], facets: [ … ] }
import { proceduresFrom } from '@surea11y/core/procedures';
import en from '@surea11y/core/procedures/en';
import fr from '@surea11y/core/procedures/fr';
 
proceduresFrom({ en, fr }, '1.4.12', { locale: 'fr' });

Chaque facette porte son label, son automation, les rules qui la revendiquent, ses tools, sa procedure ({ steps, passWhen, failWhen }, ou null pour une facette de technologie, avec coveredBy) et ses variants, chacune exactement le howToCheck du constat de cette règle pour ce code. Un texte dans une autre langue que celle lue (le titre propre d’une version antérieure des WCAG, comme « Parsing » de la 2.1 pour 4.1.1, ou un texte absent d’une langue) indique laquelle, pour qu’un outil puisse le marquer avec lang, comme le demande le critère WCAG 3.1.2. Le fichier PROCEDURES.md de core sur GitHub décrit la structure complète.

Les lister

const { listProcedures } = require('@surea11y/core');
 
listProcedures(); // WCAG 2.2, every level
listProcedures({ version: '2.1', levels: ['A', 'AA'] }); // WCAG 2.1 A and AA
listProcedures({ standard: 'best-practice' });
listProcedures({ levels: ['A', 'AA'], automation: ['manual', 'partial'] }); // what a scan leaves
OptionEffet
standard'wcag' (par défaut), 'best-practice', ou la norme d’un pack, par sa clé ou son nom.
versionCelle des WCAG ('2.0', '2.1', '2.2', par défaut), ou celle de la norme du pack.
levelsWCAG uniquement : 'A', 'AA', 'AAA' ou une liste de niveaux ; tous les niveaux par défaut.
localeUn tag ('fr-CA' lit fr-ca, puis fr) ou une liste, la plus souhaitée en premier ; l’anglais pour tout texte absent d’une langue.
toolsUniquement les facettes dont la procédure demande l’un de ces outils ('screen-reader').
automationUniquement les facettes que les règles tranchent entièrement, en partie ou pas du tout : ['manual', 'partial'] correspond à ce qu’une analyse laisse à une personne.
rulesUniquement les facettes que revendique l’une de ces règles ('img-alt-present').
packsLes packs dont lire la norme ou les règles.
profileLe profil d’un pack qui nomme une loi : seules les exigences que cette loi demande, avec la loi nommée dans l’en-tête de la liste (core 1.16.0, expérimental ; voir Packs).

Les critères des WCAG sont ceux que contient la version, à ses niveaux : les versions 2.0 et 2.1 listent 4.1.1 comme critère de niveau A intitulé « Analyse syntaxique », la 2.2 non. Avec plusieurs filtres, une facette doit correspondre à chacun ; le complete d’une exigence reste le sien.

Une liste de contrôle

procedureChecklist prend les mêmes options et donne ce qu’une personne fait pour évaluer la norme, une seule fois chaque chose : un élément par procédure générale, avec dans covers les facettes de technologie qu’il évalue aussi, et dans rules les règles qui l’appuient.

const { procedureChecklist } = require('@surea11y/core');
 
procedureChecklist({ levels: ['A', 'AA'] }).items[0];
// {
// key: '1.1.1/text-alternative-mechanism',
// label: 'Non-text content that conveys something has a text alternative',
// automation: 'partial',
// wcag: '1.1.1',
// requirements: ['1.1.1'],
// covers: ['img-alt-attr-present', 'role-img-text-alternative-present', …],
// rules: ['img-alt-present', …],
// tools: [{ id: 'devtools', label: "The browser's developer tools" }],
// procedure: { steps: ['…'], passWhen: '…', failWhen: '… which fails WCAG 1.1.1.' }
// }

Pages et listes de travail

renderProcedures transforme ce que donnent listProcedures, procedureChecklist ou proceduresFor en un document qu’une personne lit ou parcourt pas à pas : une page HTML autonome, qui s’ouvre depuis le disque sans serveur, réseau, police ni script venus d’ailleurs, ou du Markdown. Les mêmes données et options donnent toujours la même page.

const { listProcedures, procedureChecklist, renderProcedures } = require('@surea11y/core');
const fs = require('node:fs');
 
// A reference: how to assess every WCAG 2.2 A and AA criterion.
fs.writeFileSync('wcag-22-aa.html', renderProcedures(listProcedures({ levels: ['A', 'AA'] })));
 
// A worksheet: each check once, with a result and notes to record.
fs.writeFileSync('wcag-22-aa-checklist.html', renderProcedures(procedureChecklist({ levels: ['A', 'AA'] })));
 
// The same in Markdown, for a repository or a wiki.
fs.writeFileSync('wcag-22-aa.md', renderProcedures(listProcedures({ levels: ['A', 'AA'] }), { format: 'markdown' }));
OptionEffet
format'html' (par défaut) ou 'markdown'.
localeLa langue des mots propres à la page ; par défaut, celle dans laquelle les procédures ont été lues.
titleLe titre et l’intitulé de la page ; par défaut, un titre qui nomme la norme (« WCAG 2.2 : liste de vérification manuelle »).
variantstrue ajoute, sous chaque facette d’une liste, les étapes qu’indique pour elle le constat non tranché d’une analyse, dans un bloc repliable fermé.
recordfalse retire d’une page de liste de contrôle ses résultats et son script.
beforefalse retire « Avant de commencer », les habitudes qui rendent un résultat fiable.
fragmenttrue donne le contenu seul, sans document, style ni script, à insérer dans une page à vous.
packsLes packs avec lesquels les procédures ont été lues.

La page d’une liste est une référence pour la norme : son titre et sa portée, ce que signifient ses résultats (les bonnes pratiques ne comptent pour aucune conformité, le niveau AAA est indicatif), « Avant de commencer », une table des matières, et chaque exigence avec ses facettes : ce que chacune vérifie, quelle part en tranchent les règles, les outils, les étapes, ce qui réussit et ce qui échoue, et les règles qui la testent.

La page d’une liste de contrôle est une liste de travail. Sous chaque élément, une personne note un résultat et des remarques ; la page compte les résultats dans un message d’état qu’annonce un lecteur d’écran, les conserve dans le navigateur (localStorage, avec pour clé la norme, la version et le titre), et les télécharge en JSON, avec le résultat de chaque exigence agrégé à partir de ses éléments, ou en CSV, qu’un tableur ouvre avec ses accents. Une exigence échoue quand l’un de ses éléments échoue, est open quand l’un n’est pas encore vérifié, est notApplicable quand aucun ne s’applique, et réussit sinon.

{
"title": "WCAG 2.2: manual checklist",
"standard": "wcag",
"version": "2.2",
"items": [
{
"key": "1.1.1/text-alternative-mechanism",
"requirements": ["1.1.1"],
"outcome": "fail",
"notes": "The logo has no alt."
}
],
"requirements": [{ "id": "1.1.1", "outcome": "fail" }]
}

Les mots propres à une page existent dans chaque langue que fournit core, tout comme les procédures, les libellés des facettes et les principes, règles et critères des WCAG, avec les noms que leur donne la traduction publiée des WCAG dans chaque langue. Ce qui est dans une autre langue que celle de la page est marqué comme tel, pour qu’un lecteur d’écran lise chaque partie dans sa langue. fragment: true donne le contenu seul, dans une <div class="surea11y-procedures"> avec ses titres à partir de h1, pour un site de documentation qui apporte ses propres styles.

Depuis la CLI

@surea11y/cli 1.5.0 écrit les mêmes pages sans code : surea11y procedures sans analyse, et --manual-checks à côté d’une analyse, pour les vérifications qu’elle laisse à une personne.

# How to assess every WCAG 2.2 A and AA criterion, or a worksheet for a manual audit
$ surea11y procedures --wcag-level AA -o wcag-22-aa.html
$ surea11y procedures --wcag-level AA --checklist --title "Audit: example.com" -o audit.html
# The checks a scan leaves to a person, as a worksheet next to its report
$ surea11y scan https://example.com/ --wcag 2.2 --html report.html --manual-checks manual-checks.html

Dans le rapport HTML

Le rapport HTML a une section « Ce qui reste à vérifier par une personne » : chaque exigence de la norme analysée qui a une vérification qu’aucune règle ne tranche entièrement, avec à côté son résultat dans l’analyse et, repliées en dessous, ces vérifications avec leurs étapes. Une exigence dont toutes les règles réussissent n’est satisfaite que si ses vérifications réussissent aussi, et le rapport le dit. renderHtmlReport(result, { manualChecks: false }) retire la section.

Usages

Un audit manuel, sans analyse. Une personne chargée de l’audit parcourt la liste de travail de la norme visée, note chaque résultat et chaque remarque, et télécharge le JSON pour le rapport :

const checklist = procedureChecklist({ version: '2.2', levels: ['A', 'AA'] });
fs.writeFileSync('audit-worksheet.html', renderProcedures(checklist, { title: 'Accessibility audit: example.com' }));

Une pièce jointe d’une exécution de tests. Un test Playwright qui analyse une page peut joindre les vérifications que ses règles ne tranchent pas, pour qu’elles figurent à côté de l’analyse dans le rapport de tests :

test('home page', async ({ page }, testInfo) => {
// ... scan the page ...
const left = procedureChecklist({ levels: ['A', 'AA'], automation: ['manual', 'partial'] });
await testInfo.attach('manual-checks.html', {
body: renderProcedures(left, { record: false }),
contentType: 'text/html'
});
});

Une séance avec une personne qui utilise un lecteur d’écran. Uniquement ce qui demande un lecteur d’écran, pour une séance avec quelqu’un qui en utilise un tous les jours :

const sr = listProcedures({ levels: ['A', 'AA'], tools: 'screen-reader' });
fs.writeFileSync('screen-reader-session.html', renderProcedures(sr, { title: 'Screen reader session' }));

Documentation. Un fichier Markdown par norme dans un site de documentation ou un dépôt, régénéré à chaque mise à jour de core, pour qu’une équipe lise les mêmes procédures que celles qu’utilisent ses outils. Un critère, là où il le faut : un outil qui affiche un constat peut montrer comment évaluer tout son critère, avec renderProcedures(proceduresFor('1.4.12', { locale: 'de' }), { fragment: true }).

La norme d’un pack

La norme d’un pack peut indiquer comment une personne évalue ses propres exigences, et chaque fonction ci-dessus la lit quand on lui donne les packs : avec ses propres numéros et groupes, dans sa propre langue quand elle en déclare une. Une exigence qui reprend un critère WCAG prend les procédures de ce critère, lues comme celles de l’exigence (« ce qui ne respecte pas EN 301 549 9.1.4.3 »). Depuis core 1.16.0, une facette liste aussi les règles de core que la correspondance de la norme envoie vers ce qu’elle évalue (mappedRules, et le mappedRules d’un point de la liste de contrôle), si bien qu’une exigence ou un test que seules les règles de core vérifient ne paraît pas non vérifié.

const en301549 = require('@surea11y/pack-en301549');
 
proceduresFor('9.1.4.3', { packs: [en301549], standard: 'en301549', version: 'V4.1.1', locale: 'fr' });
relatedRequirements('1.4.3', { packs: [en301549] });
// [{ standard: 'EN 301 549', id: '9.1.4.3', version: 'V4.1.1', relation: 'restates', … }]
 
const options = { packs: [en301549], standard: 'en301549', version: 'V4.1.1', locale: 'fr' };
fs.writeFileSync('en-301-549.html', renderProcedures(procedureChecklist(options), { packs: [en301549] }));

Le pack EN 301 549 1.2.0 fournit des procédures pour chaque clause du chapitre 9 dont une règle de core évalue le critère, en cinq langues, et le pack WAI-ARIA fournit une liste de contrôle pour chacune de ses exigences, avec la liste complète des rôles, états et valeurs valides. Un pack qui ne fournit pas de procédures ne change rien : celles des WCAG sont les mêmes avec lui que sans lui.