Ruby on Rails  

Accessibility-First UI Testing with Axe-Core and Cypress

Web accessibility isn’t just about compliance — it’s about building inclusive applications that everyone can use, regardless of ability.
Unfortunately, accessibility (a11y) is often treated as an afterthought during web development. The good news is Axe-core and Cypress together make accessibility testing simple, automated, and developer-friendly.

This article walks you through how to integrate Axe-core with Cypress to create an accessibility-first testing workflow for modern web applications built with frameworks like Angular, React, or ASP.NET Core with SPA frontends.

1. Why Accessibility Testing Matters

Accessibility ensures your app works for:

  • Screen reader users

  • Keyboard-only navigators

  • Users with visual impairments or cognitive challenges

Ignoring accessibility can:

  • Lead to legal issues (WCAG, ADA non-compliance)

  • Limit your audience reach

  • Harm your brand reputation

With automated tools like Axe-core, developers can detect accessibility violations during CI/CD — before reaching production.

2. Tools Overview

Axe-Core

  • Developed by Deque Systems.

  • JavaScript library that scans for accessibility issues based on WCAG 2.1 standards.

  • Can integrate with browsers, Cypress, Jest, and other test frameworks.

Cypress

  • A modern end-to-end testing framework for frontend applications.

  • Runs tests in the browser, giving instant feedback.

  • Easy to set up for accessibility testing via the cypress-axe plugin.

3. Setting Up Accessibility Testing with Cypress and Axe-Core

Let’s go step-by-step.

Step 1: Install Dependencies

npm install --save-dev cypress @axe-core/webdriverjs cypress-axe

Step 2: Configure Cypress

In your project’s root, ensure you have a cypress.config.js file or cypress/support/e2e.js (depending on version).

Add the following import in your Cypress support file:

// cypress/support/e2e.js or commands.js
import 'cypress-axe';

Step 3: Write an Accessibility Test

Create a test file under cypress/e2e/accessibility.cy.js:

describe('Accessibility Testing with Axe', () => {
  beforeEach(() => {
    cy.visit('http://localhost:4200'); // Replace with your app URL
    cy.injectAxe(); // Injects axe-core script into the page
  });

  it('Should have no detectable accessibility violations on load', () => {
    cy.checkA11y(); // Runs accessibility scan
  });

  it('Should check accessibility only for specific section', () => {
    cy.checkA11y('#main-content'); // Limit scanning to specific DOM element
  });
});

Run it:

npx cypress open

You’ll see accessibility violations reported directly in Cypress’ interactive test runner.

4. Understanding Axe-Core Reports

When violations occur, Axe-core provides:

  • Rule violated (e.g., “Images must have alt text”)

  • Impact level (minor, moderate, serious, critical)

  • Node affected (HTML element causing issue)

  • Help URL (with explanation and fix guidance)

Example console output

Accessibility violation:
Rule: image-alt
Impact: serious
Description: Ensures <img> elements have alternate text or a role of none/presentation.
Help: https://dequeuniversity.com/rules/axe/4.4/image-alt

5. Testing Accessibility Dynamically

You can combine Axe with functional Cypress actions:

it('Should maintain accessibility after form submission', () => {
  cy.get('input[name="email"]').type('[email protected]');
  cy.get('button[type="submit"]').click();
  cy.injectAxe();
  cy.checkA11y();
});

This ensures accessibility remains consistent even after dynamic interactions.

6. Excluding Known or Intentional Violations

Sometimes, you may intentionally skip elements (like hidden modals or non-rendered sections):

cy.checkA11y(
  null,
  {
    exclude: ['.hidden-element', '#test-area']
  }
);

Or limit tests to high-impact issues only:

cy.checkA11y(null, { includedImpacts: ['critical', 'serious'] });

7. Integrating Accessibility Checks into CI/CD

Add your Cypress + Axe tests to your CI pipeline (Jenkins, Azure DevOps, GitHub Actions, etc.):

Example (GitHub Actions)

name: Accessibility Tests
on: [push]
jobs:
  a11y:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install dependencies
        run: npm ci
      - name: Run Cypress a11y tests
        run: npx cypress run --spec "cypress/e2e/accessibility.cy.js"

This ensures every PR or commit maintains accessibility compliance automatically.

8. Example in Angular

If you’re using Angular, here’s a sample scenario:

  • Navigate to /dashboard

  • Check the dashboard’s accessibility

  • Fail if missing alt text or ARIA labels

describe('Angular Dashboard Accessibility', () => {
  beforeEach(() => {
    cy.visit('/dashboard');
    cy.injectAxe();
  });

  it('Dashboard page should be accessible', () => {
    cy.checkA11y('#dashboard-container');
  });
});

9. Benefits of Axe-Core + Cypress Approach

Fast feedback: issues caught during development
Automated compliance: WCAG 2.1 coverage
Developer-friendly: works within Cypress ecosystem
CI/CD integration: maintain continuous accessibility
Improved UX: better experience for all users

10. Conclusion

Accessibility is not optional — it’s essential.
By integrating Axe-core with Cypress, teams can enforce accessibility as part of their development workflow, catching violations early and ensuring a more inclusive web experience.

Whether you’re building a business dashboard, e-commerce portal, or enterprise app, accessibility-first testing empowers you to deliver products that are usable by everyone not just most.