Jest with React

Damaris Göbel
4 min readOct 7, 2021

All Jest related dependencies come installed as a part of the React project created using the npx command npx create-react-app <your app name>.

Jest is a JS test runner that has access to the DOM via jsdom. React Testing Library is a set of helpers that tests React components.

To render snapshots you will need to add this library react-test-renderer to your dependencies.

Just write

npm install react-test-renderer --save-dev

to your terminal. The — save-dev saves the library to dev dependencies.

Let’s build our first todo component:

You can find the code on Github here

// components/todo.jsimport React from 'react'
function Todo({todo}) { const {id, title, completed} = todo const h1 = <h1>{title}</h1> const text = completed ? <strike>{h1}</strike> : h1 return <div data-testid={`todo-${id}`}>{text}</div>}
export default Todo;

We import React and have todo as a props given to the component Todo.

todo as an object has been destructured with the variables id, title and completed. If the todo is completed, it will be crossed out. The div gets a test-id with the todo id.

We import the component Todo in the App component and add an array of arrays which is mapped over the Todo component.

import React from 'react';import Todo from './components/todo/todo';function App() {const todos = [{id: 1, title: 'wash dishes', completed: true},{id: 2, title: 'smile', completed: false},{id: 3, title: 'mop the floor', completed: false},{id: 4, title: 'go grocery shopping', completed: false},{id: 5, title: 'get a haircut', completed: false},{id: 6, title: 'enjoy yourself', completed: false}]return (  <>    {todos.map(todo => {       return (         <Todo todo={todo}/>       )     })    } </>);}export default App;

Create a test file in the Todo folder in your components:

// components/todo.test.jsimport {render, cleanup, screen} from '@testing-library/react'import React from 'react'import Todo from './todo'import renderer from 'react-test-renderer'afterEach(() => {   cleanup()})// first testtest('should render non-completed todo', () => {  const todo = {id: 1, title: 'wash dishes', completed: false}  render(<Todo todo={todo}/>);  const todoElement = screen.getByTestId('todo-1');  expect(todoElement).toBeInTheDocument();  expect(todoElement).toHaveTextContent('wash dishes');  expect(todoElement).not.toContainHTML('<strike>');})
// second test
test('should render completed todo', () => { const todo = {id: 2, title: 'wash car', completed: true} render(<Todo todo={todo}/>); const todoElement = screen.getByTestId('todo-2'); expect(todoElement).toBeInTheDocument(); expect(todoElement).toHaveTextContent('wash car'); expect(todoElement.innerHTML.includes('<strike>')).toBeTruthy();})
// third test
test('matches snapshots', () => { const todo = {id: 1, title: 'wash dishes', completed: false} const tree = renderer.create(<Todo todo={todo} />).toJSON(); // console.log(tree) expect(tree).toMatchSnapshot()})

Let’s explain this code now.

afterEach(fn,timeout)runs a function after each one of the tests in this file completes. cleanup unmounts React trees that were mounted with render.

The test file has 3 tests.

First & second test explained

The first one is to check if the non-completed todos are rendered, have a certain text content and not contain strike in the html.

With todo you give mock data and render it with the Todo component giving in the props from your mock todo.

Queries are the methods that Testing Library gives you to find elements on the page

Testing Library has the following queries to allow you to find elements the same way that users will find them, by their role, label, placeholder, text contents, display value, alt text, title, test ID. If you can’t select an element by the queries, you can use data-testid .

The DOM testing library exports a screen object which has every query that is pre-bound to document.body.

As seen in the code screen is imported from the @testing-library/react

To access the todo element you use the getByTestId with the name you gave in the component for data-testid, here it was `todo-${id}` which could be translated for the first todo element as todo-1 .

If you want to test a value you use the expect function. The expect function is used with a matcher function to assert something about a value.

expect(todoElement).toBeInTheDocument();

Here it is expecting the todoElement to be in the document.

expect(todoElement).toHaveTextContent('wash dishes');

This line is testing if the todoElement contains the text ‘wash dishes’.

expect(todoElement).not.toContainHTML('<strike>');

This line is testing if the todoElement does not contain a strike in the html, as it is completed = false.

Second test is basically the same, only checking if the todoElement contains a strike html tag.

Third test (Snapshot test) explained

First of all, what is a snapshot?

A snapshot test renders a UI component, take a snapshot, then compares it to a reference snapshot file stored in the automatically generated __snapshots__ folder. If the two snapshots don’t match, the test fails. You can update the snapshot or undo the change.

Snapshot testing makes sense if you want to make sure your UI does not change.

You give the test a todo object.

const tree = renderer.create(<Todo todo={todo} />).toJSON();

You use the renderer imported from the library react-test-renderer to generate a serializable value for your React tree. The first time the test runs, Jest generates a snapshot file.

You can also console.log(tree) to see it or look in the generated __snapshot__ folder.

expect(tree).toMatchSnapshot()

This line is the statement that the tree should match the snapshot.

If you need to update your snapshot you press u or just type in the terminal:

jest --updateSnapshot

I hope you learnt sth. new today and got a first impression of testing in react.

Have a look at my repo: https://github.com/damarisGoebel/react-jest

For further reading, have a look at this websites:

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Damaris Göbel
Damaris Göbel

Written by Damaris Göbel

I like to do crazy things with CSS & JavaScript. My brain occasionally runs out of memory so I need to write down my thoughts.

No responses yet

Write a response