Write Tests with Axe DevTools Cypress

This page is not available in the language you requested. You have been redirected to the English version of the page.
Link to this page copied to clipboard

Writing accessibility tests with Axe DevTools for Web in Cypress

Not for use with personal data

Producing accessibility scan results with Axe DevTools can be as easy as one line of code. These results can be consumed raw, used in conjunction with an assertion library, or used to create accessibility reports.

note

@axe-devtools/cypress supports Cypress 4 through 13. These instructions describe the project layout introduced in Cypress 10.0. If you are still on Cypress 9 or earlier, put your specs in cypress/integration, register the plugin in cypress/plugins/index.js, and add the import to cypress/support/index.js instead.

Prerequisites

In order to test pages with Axe DevTools, you first need it installed in your project. If you haven’t completed this step yet, view the installation guide.

Project Structure

.
├── package.json
├── cypress.config.js
├── cypress
│   ├── e2e
│   │   └── test.cy.js
│   └── support
│       └── e2e.js
└── results
    └── broken-workshop.json

Cypress 10.0 replaced the cypress.json configuration file with cypress.config.js (or cypress.config.ts), renamed the cypress/integration spec directory to cypress/e2e, renamed cypress/support/index.js to cypress/support/e2e.js, and removed the cypress/plugins directory in favor of the setupNodeEvents function in the configuration file. Spec files use the .cy.js suffix rather than .spec.js.

The results directory holds the JSON scan results written by your tests. Cypress creates it on the first write, so you don't need to add it yourself.

Setup

The following is required to use Axe DevTools Cypress.

Include the following line in cypress/support/e2e.js:

import '@axe-devtools/cypress';

Within the cypress.config.js file, you will need to add the following:

const { defineConfig } = require('cypress');
const axeDevtoolsCypressPlugin = require("@axe-devtools/cypress/dist/plugin");

module.exports = defineConfig({
   e2e: {
     setupNodeEvents(on, config) {
       axeDevtoolsCypressPlugin(on);
       return config;
     }
   }
 });

Complete Sample File

Call cy.axeAnalyze() and cy.getAxeResults() inside each it() block, and use a unique filename for each test to avoid overwriting results from other tests.

Add this code to the test.cy.js file in the e2e directory:

describe('Axe DevTools Cypress', () => {
  it('Scans the home page for accessibility issues', () => {
    // Visit the page to test
    cy.visit('https://broken-workshop.dequelabs.com')
    // Run an accessibility scan on the current page
    cy.axeAnalyze()
    // Write results to a uniquely named file; use a different name for each test to avoid overwriting
    cy.getAxeResults().then(results => {
      cy.writeFile('./results/broken-workshop.json', results)
    })
  })
})

Run Your Tests

Add scripts to your package.json so you can run the suite headlessly in CI or open the Cypress app while you write tests:

{
  "scripts": {
    "test": "cypress run",
    "test:open": "cypress open"
  }
}

Run all specs in cypress/e2e headlessly with npm test, or open the interactive Cypress app with npm run test:open. To run a single spec, pass the --spec flag: npx cypress run --spec cypress/e2e/test.cy.js.

Cross-Origin and Sandboxed Iframes

cy.axeAnalyze() injects axe-core into the page under test and into each iframe it can reach. Iframes that Cypress cannot inject into, including cross-origin iframes and iframes carrying a sandbox attribute, are skipped: the scan continues and reports results for the rest of the page rather than failing the test. Content inside a skipped iframe is not analyzed, so test those pages directly in their own specs if you need coverage of them.