Skip to content
Latchkey

Storybook a11y addon violations gating the test-runner in CI

When the test-runner is wired to run axe via @storybook/addon-a11y, accessibility violations become test failures. The job fails with the axe rule id and the element that violated it, gating the merge on a11y.

What this error means

The runner fails a story with an axe result like "Expected 0 accessibility violations but found N", naming rules such as color-contrast or button-name.

test-runner
Expected the page to have no accessibility violations but found 1:
  color-contrast: Elements must meet minimum color contrast ratio thresholds
  Element: <button class="btn-ghost">Save</button>

Common causes

A real accessibility violation in the component

axe found a genuine issue (low contrast, missing accessible name) that the runner is set to fail on.

A rule that needs configuration for your design system

A rule flags an intended pattern; it should be tuned in the a11y config rather than left as a spurious failure.

How to fix it

Fix the violation in the component

  1. Read the axe rule id and the offending element.
  2. Fix the markup (contrast, label, role) so the rule passes.
  3. Re-run the runner to confirm zero violations.

Tune axe rules in the test-runner hook

Configure which rules run per story via the a11y parameters and the runner's postVisit hook, disabling only rules that do not apply.

.storybook/test-runner.ts
// .storybook/test-runner.ts
import { injectAxe, checkA11y } from 'axe-playwright';
export default {
  async postVisit(page) {
    await injectAxe(page);
    await checkA11y(page, '#storybook-root');
  },
};

How to prevent it

  • Fix real a11y violations rather than globally disabling axe.
  • Configure rule exceptions narrowly in a11y parameters.
  • Run the a11y checks locally before pushing.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →