Playwright + axe AxeBuilder analyze() violations in CI
The @axe-core/playwright AxeBuilder(...).analyze() call returned a results object whose violations array is not empty, so expect(results.violations).toEqual([]) fails. Each entry names the rule id and the affected nodes.
What this error means
A Playwright test asserting an empty violations array fails, and the diff shows objects with id values like color-contrast or landmark-one-main plus the failing selectors.
Error: expect(received).toEqual(expected)
- Expected - 0
+ Received + 1
+ Array [
+ Object { "id": "color-contrast", "impact": "serious", "nodes": [...] },
+ ]Common causes
The scanned page has real violations
analyze() ran axe-core against the live page and returned the rules that failed, exactly like a browser axe run.
The scan ran before navigation or hydration completed
Calling analyze() before the page reached a stable state can scan incomplete DOM; wait for load state or a selector first.
How to fix it
Wait for a stable page, then fix each rule
- Await a load state or a key selector before analyze().
- Read the rule ids in
violationsand apply each WCAG fix. - Re-run the test so violations is empty.
await page.goto('/');
await page.waitForLoadState('networkidle');
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);Scope or disable one rule with justification
Restrict the scan with withTags or disableRules for a documented false positive, rather than dropping the assertion.
const results = await new AxeBuilder({ page })
.disableRules(['color-contrast']) // decorative, tracked in A11Y-45
.analyze();How to prevent it
- Wait for a stable load state before analyze().
- Assert an empty violations array on key pages in the suite.
- Document any disabled rule with a tracking reference.