React Testing with react-testing-library

Antony Budianto
Nov 25, 2018 · 3 min read

Hi, first of all I’d like to thank you for all your support for my React Router Testing with Jest and enzyme article that reached over 100+ fans and 600+ claps! It’s been really meaningful to me and motivated me to write new article about testing.

So this time I’d like to review the recently popular testing library: react-testing-library by Kent C. Dodds.

From its README:

The react-testing-library is a very light-weight solution for testing React components. It provides light utility functions on top of react-dom and react-dom/test-utils, in a way that encourages better testing practices.

I recently used react-testing-library in one of my OSS project (react-save-localstorage) and I think it’s good, simple to use, and works seamlessly with Jest.

Testing simple React component

Let’s say we have a simple component:

import React from 'react'const Hello = ({ name }) => <div>{name}</div>export default Hello

I’d like to test that the name renders correctly, so let’s write the test:

import { render, cleanup } from 'react-testing-library'
import Hello from './Hello'
afterEach(cleanup)describe('Hello', () => {
it('should contains name', () => {
const { getByText } = render(<Hello name="Antony" />)
getByText('Antony')
})
})

Let’s review one by one:

  • cleanup: Unmounts React trees that were mounted with render.
  • render: Render into a container which is appended to document.body
  • getByText will search for all elements that have a text node with textContent matching the given TextMatch

Let’s change name="Antony" into name="Whoops" and you’ll get an error telling that the element cannot be found:

Unable to find an element with the text: Whoops

Testing props change

Testing props change is also simple, you can use rerender utils after rendering once.

import { render, cleanup } from 'react-testing-library'
import Hello from './Hello'
afterEach(cleanup)describe('Hello', () => {
it('should contains name with prop change', () => {
const { getByText, rerender } = render(<Hello name="Antony" />)
getByText('Antony')
rerender(<Hello name="Budi" />)
getByText('Budi')
})
})

Testing events

You can also test events like clicking element using fireEvent util.

import { render, cleanup, fireEvent } from 'react-testing-library'
import Hello from './Hello'
afterEach(cleanup)describe('Hello', () => {
it('should click on text', () => {
const { getByText } = render(<Hello name="Antony" />)
const textEl = getByText('Antony')
fireEvent.click(textEl)
})
})

Testing async rendering

You can also wait for an element to resolve promise and check its output using waitForElement:

import { 
render,
cleanup,
waitForElement
} from 'react-testing-library'
import Hello from './Hello'
afterEach(cleanup)describe('Hello', () => {
it('should contains name', async () => {
const { getByText } = render(<Hello name="Antony" />)
await waitForElement(() => getByText('Antony'))
})
})

Debugging experience

This is one reason why I love react-testing-library, when there’s failed expectation, it’ll print a nice DOM structure so you can debug clearly:

Unable to find an element with the text: Whoops. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.<body>
<div>
<div>
Budi
</div>
</div>
</body>

You can also trigger this manually by calling debug after render:

const { debug } = render(<Hello name="Antony" />)debug()

Okay I think that’s all from me, actually there’s still a lot of APIs to cover but I think it’s a good introduction to react-test-library. I’ll probably update the article if I find some good APIs. I hope it’s useful for you all.

If you like the article, please share with your friends and don’t forget to clap! Look forward for the next article. ❤


P.S. I just started my new YouTube channel, and I’ve posted “Learn React testing in 2 minutes”, please watch, like, share, and subscribe!

Watch “Learn React Testing in 2 minutes” on YouTube

Antony Budianto

Written by

Sr. Software Engineer, Open-source, Writer. Creator at https://youtube.com/antonybudianto

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade