loading...

Accessibility testing in React with jest-axe

bdougieyo profile image Brian Douglas Updated on ・2 min read

After working with React for quite some time, my work with accessibility has sadly always been an afterthought. My approach involves manual testing or running checks through Lighthouse periodically. I am aware this is not perfect and sought to find a better/automated solution.

twitter chatter about dominos accessibility problem

Even pizza websites need accessibility.

Approaching accessibility tooling has never been something I focused on during my tenure as a developer. This recently changed after I completed Kent’s course on testing.

jest-axe

The library introduced in the course is jest-axe. This project is not a size fits all solution and comes with a warning stating, “This project does not guarantee what you build is accessible.” Despite the warning, I have found it successful in making me aware of a11y issues at build/test time through CI automation.

Adding jest-axe is straight forward and requires a few extra lines in your test.

// example 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()
})

During a past crusade to improve test coverage, I began adding these tests to my components and found several missing alt tags and descriptors for my HTML elements. To most developers, this may seem trivial, but for a project that gets contributions from all skill level developers, these reminders are welcomed.

// jext-axe example in src/tests/Header.test.js

import Header from "../components/Header";
import {axe, toHaveNoViolations} from "jest-axe";
expect.extend(toHaveNoViolations);
import {data} from "./mocks";
import {BrowserRouter} from "react-router-dom";

test("container component should have no violations", async () => {
  const {container} = render(
    <BrowserRouter>
      <Header user={data.user} />
    </BrowserRouter>,
  );

const results = await axe(container);
  expect(results).toHaveNoViolations();

  cleanup();
}); 

False Negatives in a11y automation

Primer is the chosen design system for GitHub, and the home to a number of those elements, so many developers, find familiar in their UI. One of those elements is the extensive Octicon library, which I am using throughout my project. My a11y specific tests informed me that these Octicon elements were not accessible, but from conversations with the team, this is intentional. The Octicon names share the same as the elements they are describing (i.e., stars, pull-request, etc.), and it could confuse to hear the detail twice.

A resolution was provided that the preferred user experience is skipping items with alt=null on the Primer components. As mentioned jest-axe is not perfect and can deliver false-negatives; however, I see this as a positive since it created a platform for me to have a conversation about accessibility.

That completes this segment of the Open Sauced journey into a11y, thanks for reading and please share ways you automate your websites and applications to be more accessible in the comments.

Discussion

pic
Editor guide