Skip to content
LatchkeyLatchkey home

jest-axe "Expected the HTML found at $X to have no violations" in CI

jest-axe ran axe-core against your rendered component and toHaveNoViolations() failed because axe returned a non-empty violations array. The message lists each rule id, its impact, and the failing element selector.

What this error means

A Jest test using expect(await axe(container)).toHaveNoViolations() fails with "Expected the HTML found at $(...) to have no violations:" followed by a rule id like color-contrast or image-alt and the offending node.

jest-axe
Expected the HTML found at $('button') to have no violations:

Received:

"Buttons must have discernible text (button-name)"

Fix any of the following:
  Element does not have inner text that is visible to screen readers
  aria-label attribute does not exist or is empty

Diagnose it: did the report reach the service?

Coverage and quality integrations fail in two distinct places: the report was never produced, or it was produced and the upload was rejected. Establish which before touching tokens.

Terminal
# 1. does the report exist and is it non-empty?
ls -la coverage/ && head -5 coverage/lcov.info

# 2. does it reference paths the service can map to the repo?
grep "^SF:" coverage/lcov.info | head -5

# 3. did the upload actually succeed, or just not fail the step?
# most uploaders exit 0 on a rejected upload unless told otherwise

Common causes

The markup has a genuine WCAG violation

axe-core matched one of its rules (missing alt, no accessible name, low contrast) against the DOM your component rendered. It is a real defect, not a flaky test.

A new component or change introduced the violation

The rule passed before because the offending element did not exist. A recent edit added an image, button, or control without its accessible name or attribute.

How to fix it

Read the rule id and apply its documented fix

  1. Note the rule id in parentheses, for example button-name or image-alt.
  2. Apply the "Fix any of the following" remedy axe prints (add inner text, an aria-label, or an alt attribute).
  3. Re-run the test so the violations array is empty.
Component.jsx
// button-name: give the control a discernible name
<button aria-label="Close dialog">
  <svg aria-hidden="true" ... />
</button>

Scope a justified exception, not a blanket disable

If a rule is a confirmed false positive for one node, disable just that rule with a comment explaining why, rather than removing the assertion.

component.test.jsx
const results = await axe(container, {
  rules: { 'color-contrast': { enabled: false } }, // decorative text, see A11Y-123
});

How to prevent it

  • Run jest-axe on every component in the test suite so violations surface at PR time.
  • Fix the underlying WCAG issue rather than disabling rules broadly.
  • Keep axe-core current so rule ids and messages match the docs you follow.

Frequently asked questions

What causes jest-axe "Expected the HTML found at $X to have no violations" in CI?
There are 2 common causes: the markup has a genuine wcag violation and a new component or change introduced the violation. axe-core matched one of its rules (missing alt, no accessible name, low contrast) against the DOM your component rendered.
How do I fix jest-axe "Expected the HTML found at $X to have no violations" in CI?
There are 2 fixes depending on which cause you have: read the rule id and apply its documented fix and scope a justified exception, not a blanket disable. Work through them in order, since the first is the most common.
What does jest-axe "Expected the HTML found at $X to have no violations" in CI actually mean?
A Jest test using expect(await axe(container)).toHaveNoViolations() fails with "Expected the HTML found at $(...) to have no violations:" followed by a rule id like color-contrast or image-alt and the offending node.
How do I stop jest-axe "Expected the HTML found at $X to have no violations" in CI happening again?
Run jest-axe on every component in the test suite so violations surface at PR time. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card