How using Testing Library will help you improve the accessibility of your application
Tags: testing, a11y, react
Published: 2021-02-25 16:07:02


[Testing Library](https://testing-library.com) is a JavaScript testing framework that focuses on testing the way the application is used. Testing Library will also help you avoid testing implementation details and make your tests more maintainable. Testing the way the application is used will give us the confidence that the application is working as intended.

What's also nice about testing-library, is that its recommended queries are designed to work well on accessible elements. This means using Testing Library will also reveal accessibility problems in your application. 

In this article, we'll go through a few examples where Testing Library will reveal accessibility problems in your application.


**While this article uses React components as examples, Testing Library supports many other frameworks and the DOM API works with any environment that provides DOM APIs, such as Jest, Mocha + JSDOM, or a real browser**


## Button 

The first example we'll look at is implementing a button. Here's a naive way of creating a button component.

```js

function Button(props) {
    return (<div className="btn" onClick={props.onClick}>{props.children}</div>);
}

test("button exists", () => {
    render(<Button>Click Me</Button>);
    expect(screen.getByRole("button", {name: /click me/i})).toBeInDocument();
})

```

Here we have a button implemented using a `div` element and when you try to get it using a `getByRole` query in your tests you'll quickly realize it doesn't work.

The test will fail because the query can't find the button. Now, you might just use `getByText` and call it a day. But the problem is, screen readers won't recognize the div-button as a clickable element and the users who depend on them won't be able to use your application at all!

The best way to fix this is to just use the `button` element instead of a `div` element. This will ensure it will be visible to assistive technologies.

If for some reason you still need to use `div` you can add the `role` attribute to the element.

```html
<div className="btn" role="button" onClick={props.onClick}>{props.children}</div>
```

Implementing buttons using divs might seems like a far fetched example but well, it happens 😅

## Modal

As the next example, we will look at implementing a modal. Here's a simple modal implementation.

```js
function Modal({open, title, children}) {
  return (
    <div className="backdrop" style={{display: open ? "block" : "none"}}>
      <div className="modal">
        <h3>{title}</h3>
        <div>
          {children}
        <div>
      </div>
    </div>
  )
}

test("modal has correct title", () => {
    render(<Modal title="Modal title">modal content</Modal>);
    expect(screen.getByRole("dialog", {name: /modal content/i})).toBeInDocument();
})
```

This test will fail to find the dialog, and from the perspective of assistive technologies, the modal might as well not exist. You could get around this issue by querying the div element with the class `modal` but then you would be testing implementation details. What happens when someone decides to change the class name?

Instead, you should make the modal accessible by adding `role`, `aria-modal`, and `aria-labelledby` attributes.

`role` identifies the element as a dialog  
`aria-modal` indicates that the elements under the dialog can't be interacted while the dialog is open  
`aria-labelledby` gives the dialog an accessible name by referencing the element which gives the dialog its title  

```js
<div className="modal"
      role="dialog"
      aria-modal="true"
      aria-labelledby="dialog-title">
  <h3 id="dialog-title">{title}</h3>
  <div>
    {children}
  <div>
</div>
```

## Reach UI

For React developers I recommend using [Reach UI](https://reach.tech/) instead of implementing controls, modals, etc. completely from scratch. It is an accessible foundation for your own components and makes creating accessible design systems easy.

Accessibility is hard to get right and while using Testing Library will help you discover some obvious issues, it's not a replacement for proper accessibility testing. (Edited 25 Feb 8:30 PM EEST) 

## Other resources

[Testing Library](https://testing-library.com/)
[Commong mistakes testing](https://kentcdodds.com/blog/common-testing-mistakes) by Kent C. Dodds
[Common mistakes with React Testing Library](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)  by Kent C. Dodds

<span>Photo by <a href="https://unsplash.com/@untodesign_?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Daniel Ali</a> on <a href="https://unsplash.com/s/photos/accessibility?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span>