React Testing Library: Tips and Tricks
Tags: frontend, testing, react
Published: 2021-08-20 19:37:14

---
title: "React Testing Library: Tips and Tricks"
published: true
description: Tips for getting started with React Testing Library
author: Sheelah
type: post
canonical_url: https://sheelahb.com/blog/react-testing-library-tips-and-tricks/
cover_image: https://sheelahb.com/static/dcf340f53883e7fd89b341d25af8d562/5d2fb/react-testing-library-tips-and-tricks.jpg
tags:
  - frontend
  - testing
  - react
---


**Update (9/6/22):** This article has been updated to stay in line with current React Testing Library best practices.

Testing front-end web applications has gotten a lot easier! But that doesn't mean it doesn't involve some ramp-up on tooling. In this article I'll provide some tips and tricks for getting started and ramping up quickly with [React Testing Library][1], the most popular tool for React component testing today.

## Getting Started

The [docs][1] are great, so if you're new to the library, you should definitely take a quick look there.

## Deciding on Queries to Use

In order to write tests, you'll use the library to render your component and then write one or more queries to find certain DOM elements on the page. The question you'll have is which query to use! There are [a lot of them][2]. The best practice here is to query for actual visible elements in the DOM, such as querying for buttons with certain text, form inputs, images with certain alt text, etc.

Here's an example of querying for a button with "Read More" text:

```javascript
const button = screen.getByRole("button", { name: /read more/i })
```

These queries can be used to look for certain text elements too! Here's an example of querying for a `h1` heading:

```javascript
const button = screen.getByRole("heading", { level: "h1" })
```

### Role-based Queries

`findByRole` and `getByRole` queries are the ones that you will likely be reaching for the most, and any element listed in this [roles list][3] can be queried for. The bonus of using these roles-based queries is that you're helping to ensure that your components are accessible and available for assistive technology like screen readers!

For the full list of role-based queries available, see the [React testing library docs][4].

### findBy* vs getBy* Queries

So what's the difference between `findBy*` and `getBy*` queries? For any test that involves asynchronous behavior, like checking that a message is rendered after a user clicks on a submit button, `findBy*` queries are the ones to reach for. For tests that don't involve asynchronous behavior, like checking that a heading with certain text is shown when component is rendered, `getBy*` queries work great.

Note that with `findBy*` queries, you'll use `await` to wait for the element you're querying for to be found:

```javascript
const confirmation = await screen.findByRole("heading", { level: "h3" })
```

You can think of `findBy*` queries as a shortcut for running a `getBy*` query followed by an `await waitFor()` call. The following two approaches would accomplish the same thing but you'll see that using `findBy*` is more concise:

```javascript
// Using findByRole() to wait for a toast to appear
const toast = await screen.findByRole("heading", { level: "h3", name: 'Confirmed!' })
expect(toast).toBeDefined() // This is optional since the line above will fail if the toast isn't found

// Using getByRole() to wait for a toast to appear
await waitFor(() => {
  const toast = screen.getByRole("heading", { level: "h3", name: 'Confirmed!' })
  expect(toast).toBeDefined()
}
```

### getBy* vs queryBy* Queries

You'll also notice that there are both `getBy*` queries and `queryBy*` queries. The main difference is that `getBy*` and `findBy*` queries return the actual DOM element matched and throw an error if the element is not found. `queryBy*` queries are similar in that they also return the actual DOM node matched, but they return `null` if no match was found. How do you know which to use? Reach for `getBy*` and `findBy*` queries unless you want to test for an element that may not be present. In that case you'll want to use `queryBy*` queries. An example of a good use case for `queryBy*` queries is when you want to test that an element is not present.

### Querying for Single and Multiple Items

With React Testing Library, you'll notice that there are both `getAllBy*` and `getBy*` queries. When you're just searching for a single element, you'll want to use a `getBy*` or `findBy*` query. For cases where you want to query for multiple items, such as an unordered list of elements, you'll want to use a `getAllBy*` or `findAllBy*` query.

## Debugging Errors or Missing Elements

Sometimes your tests will fail unexpectedly and you'll wonder what is being rendered. Don't worry -- there's a utility for that! Use `screen.debug()` inside your test and you'll then get a full printout of what was rendered. If your component renders a lot of of content and `screen.debug()` output is getting cut off, specify a longer max output length by doing something like `screen.debug(undefined, 50000)` to print 50000 lines. Alternatively, you can print the output for a given DOM element that you queried for with `screen.debug(myElement, 500000)`.

## Testing Hidden Elements

Sometimes you'll want to test a component that is hidden. For example, an element might have `aria-hidden=true` on it if it has surrounding label text. In this case, if you query for the element, you'll find that you don't get any matching element found.

The fix is to include `{ hidden: true }` in your query. Then the library will also include hidden elements in query results.

Example:

```javascript
const buttons = screen.getByRole("button", { hidden: true })
```

See the [documentation on this][5] for more information.

## Testing Click Behaviors

For tests that depend on a user interaction, like a button click, to happen, you'll want to simulate that interaction in your test first. To do this, you can use the [userEvent][6] library:

```javascript
const user = userEvent.setup()

const submitButton = screen.getByRole("button", { name: /sign up/i })
await user.click(submitButton)

const toast = await screen.findByRole("heading", {
  level: "h3",
  name: "Confirmed",
})
expect(toast).toBeDefined()
```

There is also an older utility called [fireEvent][7] that you can use, but using userEvent is preferred since it more closely simulates an actual user interaction.

## More Test Assertion Options

To have access to a wider array of Jest assertion options to use in your tests, I highly recommend installing the [jest-dom][8] library. It works great with React testing library and lets you write some useful assertions without extra legwork. For example, you can test that a link element has a certain `href` attribute like:

```javascript
const link = screen.getByRole("link", { name: "Get Started" })
expect(link).toHaveAttribute("href", "https://example.com")
```

## Query Helpers and Tools

To help with finding an appropriate query, there is a useful Chrome extension that you can try that's called [Testing Playground][9].

To help ensure that you're following all best practices for the library, there's also an [ESLint plugin][10] that's worth installing in your project.

That's all! I'd love to hear what your favorite React Testing Library tip is. Feel free to share in the comments or [find me on Twitter](https://twitter.com/@sheelah_b).


Featured image by [Jörg Angeli](https://unsplash.com/@joerga) via Unsplash

[1]: https://testing-library.com/docs/react-testing-library/intro
[2]: https://testing-library.com/docs/queries/about
[3]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques#roles
[4]: https://testing-library.com/docs/queries/byrole
[5]: https://testing-library.com/docs/queries/byrole/#hidden
[6]: https://testing-library.com/docs/ecosystem-user-event
[7]: https://testing-library.com/docs/dom-testing-library/api-events/#fireevent
[8]: https://github.com/testing-library/jest-dom
[9]: https://chrome.google.com/webstore/detail/testing-playground/hejbmebodbijjdhflfknehhcgaklhano?hl=en
[10]: https://testing-library.com/docs/ecosystem-eslint-plugin-testing-library