As much as I enjoy creating DOM nodes and appending them to the body
, that
seems like boilerplate that could live in an abstraction. And it is! Among other
things, that’s what React Testing Library does.
React Testing Library is the React implementation of the DOM Testing Library (there’s also a React Native Testing Library and many others). Testing Library comes with a ton of really useful features which we’ll be using throughout this workshop, but for now, we’ll just start out with cleaning up some of this boilerplate.
Here’s a simple example of how to use this:
import {render, fireEvent, screen} from '@testing-library/react'test('it works', () => {const {container} = render(<Example />)// container is the div that your component has been mounted onto.const input = container.querySelector('input')fireEvent.mouseEnter(input) // fires a mouseEnter event on the inputscreen.debug() // logs the current state of the DOM (with syntax highlighting!)})
Notice the lack of cleanup
functionality. That’s thanks to
@testing-library/react
’s
auto-cleanup feature
Another automatic feature of React Testing Library is its handling of
React’s act
function. If
you’ve ever seen a warning about something not being wrapped in act
, that’s
what we’re talking about. As mentioned in the React docs, React Testing Library
is recommended for avoiding the issues act
is warning you about. You can learn
more about this from my blog post
Fix the “not wrapped in act(…)” warning.
In this exercise, we’re going to remove some of our boilerplate that React Testing Library does for us. The emoji should guide you pretty well on this one so I’ll let you have at it!
Testing Library also has a suite of assertions that can be installed with Jest.
They’re already added to this project, so you can switch from Jest’s built-in
assertions to more specific assertions which will give you better error
messages. So go ahead and swap the expect(message.textContent).toBe(...)
assertions with toHaveTextContent
from
@testing-library/jest-dom
.
After the instruction, if you want to remember what you’ve just learned, then fill out the elaboration and feedback form:
import * as React from 'react'import {render, fireEvent} from '@testing-library/react'import Counter from '../../components/counter'test('counter increments and decrements when the buttons are clicked', () => {const {container} = render(<Counter />)const [decrement, increment] = container.querySelectorAll('button')const message = container.firstChild.querySelector('div')expect(message).toHaveTextContent('Current count: 0')fireEvent.click(increment)expect(message).toHaveTextContent('Current count: 1')fireEvent.click(decrement)expect(message).toHaveTextContent('Current count: 0')})
Quick Links
Legal Stuff
Social Media