Skip to content
Latchkey

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.

playwright
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

  1. Await a load state or a key selector before analyze().
  2. Read the rule ids in violations and apply each WCAG fix.
  3. Re-run the test so violations is empty.
a11y.spec.ts
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.

a11y.spec.ts
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.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →