Skip to content

Accessibility Testing with Cypress

Automated accessibility testing catches a meaningful subset of accessibility issues directly inside your existing Cypress suite. This lesson covers cypress-axe, the most widely used tool for this in the Cypress ecosystem.

cypress-axe: Automated Accessibility Scanning

cypress-axe integrates the axe-core accessibility engine into Cypress, letting you scan a page (or a specific element) for a wide range of automatically detectable accessibility violations: missing alt text, insufficient color contrast, missing form labels, and more.

import 'cypress-axe';

it('has no detectable accessibility violations on the homepage', () => {
  cy.visit('/');
  cy.injectAxe();
  cy.checkA11y();
});

cy.injectAxe() loads the axe-core engine into the page; cy.checkA11y() runs the scan and fails the test if violations are found.

cypress-axe Syntax

cy.injectAxe()
cy.checkA11y()
cy.checkA11y(context, options)
cy.checkA11y(null, { rules: { 'color-contrast': { enabled: false } } })
  • cy.injectAxe() must run after cy.visit(), since it injects the engine into the loaded page.
  • context scopes the scan to a specific selector instead of the whole page.
  • options can disable specific rules, useful for known, tracked exceptions.
  • Violations are reported with severity, affected elements, and a link to relevant guidance.

Accessibility Testing Cheat Sheet

Common patterns for adding automated accessibility checks to a Cypress suite.

Goal Approach
Scan a full page cy.injectAxe(); cy.checkA11y();
Scan just one section cy.checkA11y('[data-cy="checkout-form"]')
Ignore a specific known rule { rules: { 'rule-id': { enabled: false } } }
Check only serious/critical violations Filter results by impact in a custom callback
Run on every page in a suite Add cy.checkA11y() to a shared afterEach or helper

What Automated Accessibility Testing Can (and Can't) Catch

Automated tools like axe-core reliably catch structural and programmatic issues: missing labels, poor contrast ratios, invalid ARIA usage, missing alt text. They cannot evaluate genuinely subjective or contextual concerns, like whether alt text is meaningfully descriptive, or whether a keyboard navigation order truly makes logical sense to a real user.

  • Automated tools catch roughly a third to half of common accessibility issues, not all of them.
  • Manual testing (screen readers, keyboard-only navigation) remains necessary for full coverage.
  • Automated checks are best treated as a fast, continuous safety net, not a complete accessibility audit.

Integrating Accessibility Checks into Existing Tests

Rather than writing entirely separate accessibility-only tests, adding cy.checkA11y() calls at key points within existing E2E tests (after visiting a page, after opening a modal) gets broad coverage with minimal extra test-writing effort.

it('opens the checkout modal accessibly', () => {
  cy.visit('/cart');
  cy.injectAxe();
  cy.checkA11y();
  cy.get('[data-cy="checkout"]').click();
  cy.checkA11y('[data-cy="checkout-modal"]');
});

Common Mistakes

  • Treating a passing automated accessibility scan as proof the page is fully accessible.
  • Calling cy.injectAxe() before cy.visit(), or on a page that hasn't fully loaded yet.
  • Disabling rules broadly to silence noise instead of fixing or specifically, deliberately excepting real issues.
  • Never testing dynamic UI states (modals, dropdowns, error messages) for accessibility, only static initial page loads.

Key Takeaways

  • cypress-axe integrates axe-core automated accessibility scanning directly into Cypress tests.
  • Automated scans catch a meaningful, but incomplete, subset of real accessibility issues.
  • Manual testing with screen readers and keyboard navigation remains necessary for full coverage.
  • Adding cy.checkA11y() calls into existing E2E tests is more efficient than separate accessibility-only tests.

Pro Tip

Add cy.checkA11y() right after any cy.visit() or major UI state change (opening a modal, submitting a form) in your existing E2E tests rather than writing a whole separate accessibility test suite, this gets broad, continuous coverage almost for free.