Q14 of 24 · Accessibility

How do you integrate axe-core into a Playwright or Cypress test suite?

AccessibilityMidaccessibilityaxe-coreplaywrightcypressci-cdautomationtesting

Short answer

Short answer: Install @axe-core/playwright or cypress-axe, navigate to a page, inject axe, and run an accessibility scan. Assert zero violations at the AA ruleset. Use this as a regression net in CI — it catches structural regressions, not a full audit.

Detail

Playwright integration:

import { checkA11y } from '@axe-core/playwright';

test('checkout page has no axe violations', async ({ page }) => {
  await page.goto('/checkout');
  const results = await checkA11y(page, undefined, {
    runOnly: { type: 'tag', values: ['wcag2a', 'wcag2aa', 'wcag21aa'] },
  });
  expect(results.violations).toHaveLength(0);
});

Cypress integration:

import 'cypress-axe';

it('has no axe violations', () => {
  cy.visit('/checkout');
  cy.injectAxe();
  cy.checkA11y(null, { includedImpacts: ['critical', 'serious'] });
});

Configuration decisions:

  • Ruleset: target wcag2a, wcag2aa, wcag21aa — the rules that map to WCAG 2.x A/AA conformance.
  • Known failures: if you have existing violations you can't fix immediately, configure an explicit ignore list with a ticket reference rather than silencing the entire scan. Use axe's disableRules or Cypress axe's skipFailures with a comment.
  • Scope: scan the full page OR a specific component. Component-scoped scans are more precise and fail less frequently due to third-party content.

What this catches vs misses: it catches missing labels, contrast failures, obvious ARIA misuse. It misses keyboard interaction quality, screen reader announcements, reading order, and meaning. Add it to your CI regression suite — don't mistake it for a complete accessibility programme.

// EXAMPLE

a11y.spec.ts

import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';

test('login page passes axe AA scan', async ({ page }) => {
  await page.goto('/login');

  const results = await new AxeBuilder({ page })
    .withTags(['wcag2a', 'wcag2aa', 'wcag21aa'])
    .analyze();

  expect(results.violations).toEqual([]);
});

// WHAT INTERVIEWERS LOOK FOR

Can write the integration code without prompting. Selects the correct WCAG tags. Knows how to handle known violations without silencing the scan entirely.