cypress-axe

repository·master·Indexed 20 days ago

https://github.com/component-driven/cypress-axe

A Cypress plugin that integrates axe-core to perform automated accessibility testing within Cypress test suites. It provides custom commands including cy.injectAxe() to load the axe-core runtime, cy.configureAxe() for global settings, and cy.checkA11y() to run accessibility checks against the document or a specific context with support for custom violation callbacks and retry logic.

Tokens
2.2K
Snippets
10
Records
10
Agent score
21%

What's inside cypress-axe

  1. Install cypress-axe

    master

    To use cypress-axe for accessibility testing in Cypress, follow these steps based on your Cypress version:

    For Cypress v10 and above

    1. Install the latest versions of axe-core, cypress, and cypress-axe:
      npm install --save-dev axe-core cypress cypress-axe
    2. Include the commands in cypress/support/e2e.js:
      import 'cypress-axe'

    For Cypress v9 and below

    1. Install cypress-axe 0.x.x and your specific Cypress version (e.g., v9.6.0):
      npm install --save-dev axe-core cypress@9.6.0 cypress-axe@0.14.0
    2. Include the commands in cypress/support/index.js:
      import 'cypress-axe'

    Note on Logging

    It is recommended to add a Cypress task to log accessibility messages to the terminal during execution.

    npm install --save-dev axe-core cypress cypress-axe
  2. Configure TypeScript for cypress-axe

    master

    If you are using TypeScript, add cypress-axe to the types array in your tsconfig.json file to enable type support for the custom commands.

    {
      "compilerOptions": {
        "baseUrl": "./",
        "target": "es5",
        "lib": ["esnext", "dom"],
        "types": ["cypress", "cypress-axe"]
      },
      "include": ["."]
    }
  3. Implement custom violation logging with violationCallback

    master

    You can use the violationCallback argument in cy.checkA11y to perform custom actions, such as logging violations to the terminal using cy.task.

    // 1. In your Cypress plugins file (e.g., cypress.config.js or similar)
    module.exports = (on, config) => {
      on('task', {
        log(message) {
          console.log(message)
          return null
        },
        table(message) {
          console.table(message)
          return null
        }
      })
    }
    
    // 2. In your spec file
    function terminalLog(violations) {
      cy.task(
        'log',
        `${violations.length} accessibility violation${
          violations.length === 1 ? '' : 's'
        } ${violations.length === 1 ? 'was' : 'were'} detected`
      )
      const violationData = violations.map(
        ({ id, impact, description, nodes }) => ({
          id,
          impact,
          description,
          nodes: nodes.length
        })
      )
      cy.task('table', violationData)
    }
    
    // 3. In your test
    it('Logs violations to the terminal', () => {
      cy.checkA11y(null, null, terminalLog)
    })
  4. Run accessibility checks with cy.checkA11y

    master

    The cy.checkA11y() command runs axe-core against the document (or a specific context) at the moment it is called. This allows you to test accessibility after user interactions like clicks or page loads.

    Parameters

    1. context (optional): Defines the scope of analysis (e.g., a CSS selector, ID, or class name). Pass null to analyze the entire document.
    2. options (optional): A set of options passed to rules or checks. Unlike cy.configureAxe, these are temporary for this specific call.
      • includedImpacts: An array of strings ('minor', 'moderate', 'serious', or 'critical') to filter violations by impact level.
      • retries: An integer specifying how many times to retry the check if initial findings are detected. Useful for dynamic content.
      • interval: An integer (milliseconds) to wait between retries. Defaults to 1000.
      • Other keys accepted by axe.run's options argument.
    3. violationCallback (optional): A function that receives the violations, allowing for custom side-effects like terminal logging.
    4. skipFailures (optional): A boolean (defaults to false). If true, the test will not fail on violations; it will only log them to the console. This is useful for introducing accessibility testing into legacy applications.
    // Example: Check only critical impact violations
    cy.checkA11y(null, {
      includedImpacts: ['critical']
    })
    
    // Example: Retry check for dynamic content
    cy.checkA11y(null, {
      retries: 3,
      interval: 100
    })
    
    // Example: Log violations without failing the test
    cy.checkA11y(null, null, null, true)
  5. Configure aXe settings with cy.configureAxe

    master

    Use cy.configureAxe() to define the format of the JSON structure passed to the axe.run callback. This is useful for adding new rules or configuring branding, reporters, checks, and locales. This configuration is permanent for the duration of the test session.

    cy.configureAxe({
      branding: {
        brand: String,
        application: String
      },
      reporter: 'option',
      checks: [Object],
      rules: [Object],
      locale: Object
    })
  6. Inject axe-core with cy.injectAxe

    master

    The cy.injectAxe() command injects the axe-core runtime into the page under test.

    Requirements:

    • You must run this after cy.visit() and before cy.checkA11y().
    • It can be called within a test or in a beforeEach block.

    Options:

    • injectOptions: An object that can include axeCorePath (string) to specify the file path from which axe-core will be injected. If not provided, it attempts to resolve axe-core/axe.min.js via require.resolve or defaults to node_modules/axe-core/axe.min.js.
    beforeEach(() => {
      cy.visit('http://localhost:9000')
      cy.injectAxe({ axeCorePath: '<path-to-axe-core>' })
    })
  7. Configure axe-core settings with cy.configureAxe()

    master

    Use cy.configureAxe(configurationOptions) to apply configuration settings to the injected axe-core instance. This allows you to customize how accessibility rules are applied globally within your test session.

    cy.configureAxe({
      rules: {
        'color-contrast': { enabled: false }
      }
    });
  8. Inject axe-core into the browser with cy.injectAxe()

    master

    Use cy.injectAxe() to load the axe-core library into the Cypress browser window. This is a prerequisite before calling cy.configureAxe() or cy.checkA11y().

    By default, it attempts to resolve the path to axe-core/axe.min.js using require.resolve or a standard node_modules path. You can provide a custom path via the axeCorePath option.

    cy.injectAxe({ axeCorePath: 'path/to/your/axe.min.js' });
  9. Configure checkA11y behavior via Options interface

    master

    The Options interface extends axe.RunOptions and adds Cypress-specific controls for retrying checks.

    Properties:

    • includedImpacts (optional): An array of strings (e.g., ['critical', 'serious']) used to filter the results. Only violations with an impact matching these values will be returned/asserted.
    • interval (optional): The delay in milliseconds to wait between retries if violations are found. Defaults to 1000.
    • retries (optional): The number of times to re-run the accessibility check if violations are detected. Defaults to 0.
    • ...axeOptions: Any valid property from axe.RunOptions is also accepted.
    export interface Options extends axe.RunOptions {
    	includedImpacts?: string[];
    	interval?: number;
    	retries?: number;
    }
  10. Configure injectAxe behavior via InjectOptions interface

    master

    The InjectOptions interface allows you to specify the location of the axe-core source file.

    Properties:

    • axeCorePath (optional): A string representing the file path to the axe.min.js file used for injection.
    export interface InjectOptions {
    	axeCorePath?: string;
    }