@a11y-pulse/audit-runner
v0.5.0
Published
Simple example tool that runs all A11y Pulse accessibility audits
Maintainers
Readme
@a11y-pulse/audit-runner
A simple command line interface that runs axe-core and all A11y Pulse audits against a single page. Results are reported in the axe-core format.
This package also exists as a reference for your own audit pipeline. If you would like to explore the code, a good starting point is src/run-audits.ts.
Install
npm install @a11y-pulse/audit-runnerBy default this package runs audits using Puppeteer. If you would like to use Playwright, you will need to install it with npm install playwright-core && npx playwright-core install.
CLI
npx @a11y-pulse/audit-runner https://who.likesdogs.nz/Launches headless Chromium at a 1280x800 viewport, loads the URL, runs every audit, and writes the combined axe-core report to stdout as JSON. Pipe it wherever you like:
npx @a11y-pulse/audit-runner https://who.likesdogs.nz/ | jq '.violations[].id'For a readable summary of just the failed audits, use --format simple:
npx @a11y-pulse/audit-runner https://who.likesdogs.nz/ --format simpleEach failed audit is listed with its impact, a description, the selector and HTML of up to five failing elements, and a link to more help. Colours are used when stdout is a terminal.
Write either format to a file with --output. Missing parent directories are created:
npx @a11y-pulse/audit-runner https://who.likesdogs.nz/ --output reports/likesdogs.jsonWhile it runs, a spinner on stderr shows the current step (loading the page, waiting for network idle, running axe-core, and so on). The spinner only appears when stderr is a terminal, so CI logs and redirected output stay clean.
--engine playwright drives the page with Playwright rather than Puppeteer, and --browser then picks the engine to launch:
npx @a11y-pulse/audit-runner https://who.likesdogs.nz/ --engine playwright --browser webkit| Option | Values | Default |
| --- | --- | --- |
| -o, --output | A file path | stdout |
| --format | json, simple | json |
| --engine | puppeteer, playwright | puppeteer |
| --browser | chromium, firefox, webkit | chromium |
--browser requires --engine playwright. Firefox and WebKit tab in their own order and apply their own :focus-visible heuristics, so results will not match Chromium's element for element.
The exit code reports whether the run itself succeeded, not whether the page passed: a page with violations still exits 0. A bad URL or a crashed browser exits 1, with the message on stderr.
Browser support
| Adaptor | Browser | Supported | | --- | --- | --- | | Puppeteer | Chrome | Yes | | Playwright | Chromium | Yes | | Playwright | WebKit | No. The keyboard-driven audits it runs are unsupported on WebKit, which does not move focus to links when Tab is pressed. | | Playwright | Firefox | Partial. Reflow, text spacing, skip link and context change match Chromium; focus appearance and focus not obscured differ in the cases noted in their own READMEs. |
runAllAudits
import { runAllAudits } from "@a11y-pulse/audit-runner";
import { PuppeteerAdaptor } from "@a11y-pulse/browser-adaptor/puppeteer";
import { PuppeteerAdaptor as ReflowAdaptor } from "@a11y-pulse/reflow-audit/puppeteer";
import { PuppeteerAdaptor as TextSpacingAdaptor } from "@a11y-pulse/text-spacing-audit/puppeteer";
import puppeteer from "puppeteer";
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://who.likesdogs.nz/");
const results = await runAllAudits({
browser: new PuppeteerAdaptor(page),
reflow: new ReflowAdaptor(page),
textSpacing: new TextSpacingAdaptor(page),
});
console.log(results.violations.map((audit) => audit.id));
// ['color-contrast', 'focus-appearance', 'reflow']
await browser.close();runAllAudits(adaptors, options?) takes one adaptor per audit interface, all three wrapping the same already-loaded page. Swap in the PlaywrightAdaptor from each of those subpaths to run the same audits under Playwright; nothing else changes.
options takes each audit's own options object under its key, all optional. axe is passed straight to axe.run(), and onProgress is called with a short description of each step as it starts:
const results = await runAllAudits(adaptors, {
axe: { runOnly: ["wcag2a", "wcag2aa"] },
focusAppearance: { elementLimit: 50, skipStyleCheck: true },
reflow: { screenshotLimit: 3 },
});Results
The return value is in the shape of axe-core's results object. The A11y Pulse audit results included with the following audit IDs:
| Audit | id |
| --- | --- |
| Focus appearance (WCAG 2.4.7) | focus-appearance |
| Focus not obscured (WCAG 2.4.11) | focus-not-obscured |
| Context change on focus (WCAG 3.2.1) | context-change-on-focus |
| Skip link activation (WCAG 2.4.1) | skip-link-activation |
| Reflow (WCAG 1.4.10) | reflow |
| Text spacing (WCAG 1.4.12) | text-spacing |
JSON output
Audit evidence is attached to the node it belongs to, as a single axe-core check under any, carrying PNG bytes as raw Uint8Arrays. toJson is a thin JSON.stringify wrapper that encodes those as base64:
{
"url": "https://who.likesdogs.nz/",
"violations": [
{
"id": "reflow",
"help": "Content must reflow without two-dimensional scrolling",
"impact": "serious",
"tags": ["wcag21aa", "wcag1410", "cat.structure"],
"nodes": [
{
"target": ["#wide"],
"html": "<div id=\"wide\">",
"failureSummary": "Element is overflowing the viewport by 580px…",
"any": [
{
"id": "reflow-evidence",
"impact": "serious",
"message": "Element overflows the 320px reflow viewport",
"data": { "screenshot": "iVBORw0KGgoAAAANSUhEUg…" }
}
],
"all": [],
"none": []
}
]
}
]
}Releasing
Releases are managed in the A11y-Pulse/audits monorepo with Changesets. Publishing uses npm trusted publishing (OIDC). There is no long-lived NPM_TOKEN.
Ship a change
- Open a PR against
mainthat includes a changeset (npx changeset) naming@a11y-pulse/audit-runner. - After merge, the Release workflow opens a Version PR. Merging that PR publishes this package to npm and tags
@a11y-pulse/audit-runner@<version>.
Trusted Publisher on npm must stay configured for:
| Field | Value |
| --- | --- |
| Organization or user | A11y-Pulse |
| Repository | audits |
| Workflow filename | release.yml |
License
MIT. Use it however you like, including in commercial and competing products.
The audit packages in this repository are licensed separately, under the PolyForm Shield License 1.0.0.
