DEV Community

Cover image for How using Testing Library will help you improve the accessibility of your application
Juhana Jauhiainen
Juhana Jauhiainen

Posted on • Originally published at

How using Testing Library will help you improve the accessibility of your application

Testing Library 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


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

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();

Enter fullscreen mode Exit fullscreen mode

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.

<div className="btn" role="button" onClick={props.onClick}>{props.children}</div>
Enter fullscreen mode Exit fullscreen mode

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


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

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

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

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

<div className="modal"
  <h3 id="dialog-title">{title}</h3>
Enter fullscreen mode Exit fullscreen mode

Reach UI

For React developers I recommend using Reach UI 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
Commong mistakes testing by Kent C. Dodds
Common mistakes with React Testing Library by Kent C. Dodds

Photo by Daniel Ali on Unsplash

Top comments (2)

stereobooster profile image

Be aware that manual testing is still needed for a11y. For example, in your code button has role, but doesn't have tabIndex, which means that users which don't use mouse can't focus the button and trigger an action

juhanakristian profile image
Juhana Jauhiainen • Edited

You're absolutely right 👍 This is no replacement for proper a11y testing but will uncover some issues.