Use axe-core or Lighthouse to assert that pages meet accessibility standards. Both tools are available in QA Wolf web flows — axe-core for precise violation gating, Lighthouse for scores and shareable reports.
This recipe covers accessibility spot-checking using axe-core and Lighthouse. For operationalized a11y monitoring — scheduled runs, trend tracking, aggregated reports, and stakeholder dashboards — talk to your QA Wolf team about full-service accessibility testing.
Examples
Gate a release on axe-core violations
await page.addScriptTag({
url: "https://unpkg.com/axe-core@4.8.2/axe.min.js",
});
const violations = await page.evaluate(async () => {
const { violations } = await window.axe.run();
return violations;
});
const critical = violations.filter((x) => x.impact === "critical");
const serious = violations.filter((x) => x.impact === "serious");
expect(critical.length).toBe(0);
expect(serious.length).toBe(0);
Generate a Lighthouse accessibility report
const { lhr } = await playAudit({
page,
thresholds: { accessibility: 90 },
reports: {
formats: { html: true, json: true },
directory: `${process.env.TEAM_STORAGE_DIR}/lighthouse`,
name: `a11y-${Date.now()}`,
},
config: {
extends: "lighthouse:default",
settings: { onlyCategories: ["accessibility"] },
},
});
const a11yScore = Math.round(lhr.categories.accessibility.score * 100);
console.log(`Accessibility score: ${a11yScore}`);
Lighthouse scores accessibility against its own model, which does not map 1:1 to WCAG conformance levels. Use it as a directional score and audit artifact — not as a hard compliance gate.
When to use
- Your app has pages that must meet WCAG standards and you need to catch regressions before they reach production.
- Your team needs a release gate that fails on critical or serious WCAG violations.
- Your team needs a shareable accessibility report for stakeholders or compliance purposes.
- Your team wants to establish a baseline score for a page and track it over time.
Choosing the right approach
| Axe-core | Lighthouse |
|---|
| Best for | CI checks, violation counts, release gating | Scores, formal reports, stakeholder sharing |
| Output | Violation list by severity | Accessibility score + full report |
| Use as a gate | Yes — throw on critical / serious | Not recommended |
| Report artifact | No (console / logs) | Yes — HTML, JSON, PDF |
These two approaches complement each other. Axe-core is precise and gateable; Lighthouse is broad and reportable. For the most complete picture, use both.
Full sample test
import { flow, expect } from "@qawolf/flows/web";
export default flow(
"Accessibility",
{ target: "Web - Chrome", launch: true },
async ({ page, test }) => {
await test("assert no accessibility violations", async () => {
// Arrange
await page.goto("https://your-app.com");
// Act
await page.addScriptTag({
url: "https://unpkg.com/axe-core@4.8.2/axe.min.js",
});
const violations = await page.evaluate(async () => {
const { violations } = await window.axe.run();
return violations;
});
// Assert
const critical = violations.filter((x) => x.impact === "critical");
const serious = violations.filter((x) => x.impact === "serious");
const moderate = violations.filter((x) => x.impact === "moderate");
const minor = violations.filter((x) => x.impact === "minor");
expect(critical.length).toBe(0);
expect(serious.length).toBe(0);
expect(moderate.length).toBe(0);
expect(minor.length).toBe(0);
});
},
);
The full sample gates on all violation levels. Adjust the threshold to match your policy — some teams only gate on critical and serious, particularly when first introducing accessibility testing.