Accessibility Testing in React with jest-axe

Orkhan Huseynli
4 min readJul 16, 2020

Introduction

Accessibility in web applications is to make your web app accessible to as many people as possible, in spite of their physical, cognitive and visual abilities. Making your web apps accessible just requires you to follow some set of simple rules like using semantic HTML, using good color contrast on your pages, making your pages mobile friendly etc. In this article we will see how you can test your React components’ accessibility with a library called jest-axe.

Setting up React project

First, let’s begin with creating your React application and setting up tests. If you are already using React, this must not be new to you. To create a React app we’ll use create-react-app cli:

$ npx create-react-app accessibility-test

After, the application has been created, cd into your app and start your favorite text editor. In my case, it’s VS Code:

$ cd accessibility-test && code .

Adding jest-axe

To use jest-axe, run yarn add jest-axe --dev to install it and add it to development dependencies. If you prefer working with TypeScript, you’ll also need to install @types/jest-axe module.

Go to setupTests.js file inside src directory. In this file you’ll see this line along with some comments:

import '@testing-library/jest-dom/extend-expect';

As comments explain, in this line react-testing-library adds some custom matchers to jest. This allows you to do assertions like expect(element).toHaveTextContent(/react/i). This means, we can also extend expect command and add new matchers to it. We’re going to do it now. Add these lines to setupTests.js file:

import { toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);

As you see we just imported toHaveNoViolations matcher from jest-axe and extended expect command with it. So, your setupTests.js file will look something like this:

// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom/extend-expect';
import { toHaveNoViolations } from 'jest-axe';

expect.extend(toHaveNoViolations);

Now that we finished setting up our tests, let’s write our component and test its accessibility.

Writing a form component

For simplicity purposes, I’ll write a simple form component with two inaccessible fields. Create a SimpleForm.js file and create a simple form like this:

import React from 'react';

export default function SimpleForm() {
return (
<div>
<h5>First name</h5>
<input name="firstName" type="text" placeholder="Enter your first name" />
<h5>Gender</h5>
Male <input type="radio" name="gender" value="Male" />
Female <input type="radio" name="gender" value="Female" />
</div>
);
}

As you see, it’s not an accessible form; it’s not wrapped by <form> tag and <input/> elements does not have associated labels. So, let’s write a test for this component:

import React from 'react';
import { render } from '@testing-library/react';
import { axe } from 'jest-axe';

import SimpleForm from './SimpleForm';

describe('The <SimpleForm/> component', () => {
it('should not fail any accessibility tests', async () => {
const { container } = render(<SimpleForm />);
expect(await axe(container)).toHaveNoViolations();
});
});

If you have written tests before you’ll get it immediately. We just render <SimpleForm/> component, get it’s container, test it with axe and expect it to have no violations.

To run the tests, open terminal and run yarn test src/SimpleForm.test.js command. The tests will fail as no form element has an associated label. The test results will look something like this:

SimpleForm accessibility tests are failing

To fix the form to pass accessibility tests, just wrap inputs around a <form> element and add associated labels to <input/> elements:

import React from 'react';

export default function SimpleForm() {
return (
<form>
<label htmlFor="firstName">First name</label>
<input
id="firstName"
name="firstName"
type="text"
placeholder="Enter your first name"
/>
<h5>Gender</h5>
<label>
Male <input type="radio" name="gender" value="Male" />
</label>
<label>
Female <input type="radio" name="gender" value="Female" />
</label>
</form>
);
}

As the form accessibility issues are fixed, let’s run tests again and see the results:

SimpleForm.js accessibility tests are passing

Conclusion

Note that as jest-axe library states, these tests does not guarantee that your application is 100% accessible since it only analyzes your markup and finds issues.

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

Thanks for reading. I hope this article was helpful for you. If you find any issues in the article, do not hesitate to write some comments. 😊

--

--