Custom Jest matcher for aXe for testing accessibility
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:
- test your interface with the assistive technologies that real users use (see also WebAIM's survey results).
- include people with disabilities in user research.
npm install --save-dev jest-axeconst { 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()
})Note, you can also require
'jest-axe/extend-expect'which will callexpect.extendfor you. This is especially helpful when using the jestsetupTestFrameworkScriptFileconfiguration.
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-libraryyou should be usingcleanup.
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()
})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()
})- 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.
- GOV.UK Publishing Frontend team who published the basis of the aXe reporter
- jest-image-snapshot for inspiration on README and repo setup
