/jest-axe

Custom Jest matcher for aXe for testing accessibility ♿️🃏

Primary LanguageJavaScriptMIT LicenseMIT

jest-axe

Greenkeeper badge npm version Build Status JavaScript Style Guide

Custom Jest matcher for aXe for testing accessibility

⚠️✋ This project does not guarantee what you build is accessible.

The GDS Accessibility team found that only ~30% of issues are found by automated testing.

Tools like aXe are similar to code linters such as eslint or sass-lint: they can find common issues but cannot guarantee what you build works for users.

You'll also need to:

Installation:

npm install --save-dev jest-axe

Usage:

const { axe, toHaveNoViolations } = require('jest-axe')

expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage', async () => {
  const render = () => '<img src="#"/>'

  // pass anything that outputs html to axe
  const html = render()

  expect(await axe(html)).toHaveNoViolations()
})

Screenshot of the resulting output from the usage example

Note, you can also require 'jest-axe/extend-expect' which will call expect.extend for you. This is especially helpful when using the jest setupTestFrameworkScriptFile configuration.

With React

const { axe, toHaveNoViolations } = require('jest-axe')

expect.extend(toHaveNoViolations)

const React = require('react')
const ReactDOMServer = require('react-dom/server')

it('should demonstrate this matcher`s usage with react', async () => {
  const html = ReactDOMServer.renderToString(
    <img src='#' />
  )

  const results = await axe(html)

  expect(results).toHaveNoViolations()
})

Note, if you're using react-testing-library you should be using cleanup.

Axe configuration

The axe function allows options to be set with the same options as documented in axe-core:

const { axe, toHaveNoViolations } = require('jest-axe')

expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with a custom config', async () => {
  const render = () => `
    <div>
      <img src="#"/>
    </div>
  `

  // pass anything that outputs html to axe
  const html = render()

  const results = await axe(html, {
    rules: {
      // for demonstration only, don't disable rules that need fixing.
      'image-alt': { enabled: false }
    }
  })

  expect(results).toHaveNoViolations()
})

Setting global configuration

If you find yourself repeating the same options multiple times, you can export a version of the axe function with defaults set.

Note: You can still pass additional options to this new instance; they will be merged with the defaults.

This could be done in Jest's setup step

// Global helper file (axe-helper.js)
const { configureAxe } = require('jest-axe')

const axe = configureAxe({
  rules: {
    // for demonstration only, don't disable rules that need fixing.
    'image-alt': { enabled: false }
  }
})

module.exports = axe
// Individual test file (test.js)
const { toHaveNoViolations } = require('jest-axe')
const axe = require('./axe-helper.js')

expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with a default config', async () => {
  const render = () => `
    <div>
      <img src="#"/>
    </div>
  `

  // pass anything that outputs html to axe
  const html = render()

  expect(await axe(html)).toHaveNoViolations()
})

Thanks

  • Jest for the great test runner that allows extending matchers.
  • aXe for the wonderful axe-core that makes it so easy to do this.
  • Government Digital Service for making coding in the open the default.
  • jest-image-snapshot for inspiration on README and repo setup