Reader small image

You're reading from  Learn React with TypeScript - Second Edition

Product typeBook
Published inMar 2023
Reading LevelBeginner
PublisherPackt
ISBN-139781804614204
Edition2nd Edition
Languages
Tools
Right arrow
Author (1)
Carl Rippon
Carl Rippon
author image
Carl Rippon

Carl Rippon has been in the software industry for over 20 years developing a complex lines of business applications in various sectors. He has spent the last 8 years building single-page applications using a wide range of JavaScript technologies including Angular, ReactJS, and TypeScript. Carl has also written over 100 blog posts on various technologies.
Read more about Carl Rippon

Right arrow

Unit Testing with Jest and React Testing Library

In this chapter, we learn how to use Jest and React Testing Library, two popular automated testing tools that can be used together in React applications. We will create tests on the checklist component we created in Chapter 11, Reusable Components.

We will start by focusing on Jest and using it to test simple functions, learning about Jest’s common matcher functions for writing expectations, and how to execute tests to check whether they pass.

We will then move on to learning about component testing using React Testing Library. We’ll understand the different query types and variants and how they help us create robust tests.

After that, we will learn the most accurate way to simulate user interactions using a React Testing Library companion package. We will use this to create tests for items being checked in the checklist component.

At the end of the chapter, we will learn how to determine which code is covered...

Technical requirements

We will use the following technologies in this chapter:

We will start with a modified version of the code we finished in the last chapter. The modified code contains logic extracted into pure functions, which will be ideal to use in the first tests we write. This code can be found online at https://github.com/PacktPublishing/Learn-React-with-TypeScript-2nd-Edition/tree/main/Chapter12/start.

Carry out the following steps to download this to your local computer:

  1. Go to https://download-directory.github.io/ in a browser.
  2. In the textbox on the web page, enter the following URL: https://github.com/PacktPublishing/Learn-React-with-TypeScript-2nd-Edition/tree/main/Chapter12/start.
  3. Press the Enter key. A ZIP file containing the start folder will now be downloaded.
  4. Extract the ZIP...

Testing pure functions

In this section, we will start by understanding the fundamental parts of a Jest test. Then, we will put this into practice by implementing tests on a pure function in the checklist component.

A pure function has a consistent output value for a given set of parameter values. These functions depend only on the function parameters and nothing outside the function, and also don’t change any argument values passed into them. So, pure functions are nice for learning how to write tests because there are no tricky side effects to deal with.

In this section, we will also cover how to test exceptions, which is useful for testing type assertion functions. Finally, at the end of this section, we will learn how to run the tests in a test suite.

Understanding a Jest test

Jest is preinstalled in a Create React App project and configured to look for tests in files with particular extensions. These file extensions are .test.ts for tests on pure functions...

Testing components

Testing components is important because this is what the user interacts with. Having automated tests on components gives us confidence that the app is working correctly and helps prevent regressions when we change code.

In this section, we will learn how to test components with Jest and React Testing Library. Then, we will create some tests on the checklist component we developed in the last chapter.

Understanding React Testing Library

React Testing Library is a popular companion library for testing React components. It provides functions to render components and then select internal elements. Those internal elements can then be checked using special matchers provided by another companion library called jest-dom.

A basic component test

Here’s an example of a component test:

test('should render heading when content specified', () => {
  render(<Heading>Some heading</Heading>);
  const heading =...

Simulating user interactions

So far, our tests have simply rendered the checklist component with various props set. Users can interact with the checklist component by checking and unchecking items. In this section, we will first learn how to simulate user interactions in tests. We will then use this knowledge to test whether list items are checked when clicked and that onCheckedIdsChange is raised.

Understanding fireEvent and user-event

React Testing Library has a fireEvent function that can raise events on DOM elements. The following example raises a click event on a Save button:

render(<button>Save</button>);
fireEvent.click(screen.getByText('Save'));

This is okay, but what if logic was implemented using a mousedown event rather than click? The test would then need to be as follows:

render(<button>Save</button>);
fireEvent.mouseDown(screen.getByText('Save'));

Fortunately, there is an alternative approach to performing...

Getting code coverage

Code coverage is how we refer to how much of our app code is covered by unit tests. As we write our unit tests, we’ll have a fair idea of what code is covered and not covered, but as the app grows and time passes, we’ll lose track of this.

In this section, we’ll learn how to use Jest’s code coverage option so that we don’t have to keep what is covered in our heads. We will use the code coverage option to determine the code coverage on the checklist component and understand all the different statistics in the report. We will use the code coverage report to find some uncovered code in our checklist component. We will then extend the tests on the checklist component to achieve full code coverage.

Running code coverage

To get code coverage, we run the test command with a --coverage option. We also include a --watchAll=false option that tells Jest not to run in watch mode. So, run the following command in a terminal...

Summary

In this chapter, we created tests on a checklist component using Jest and React Testing Library. In addition, we learned about common Jest matchers in Jest’s core package and useful matchers for component testing in a companion package called jest-dom.

We used Jest’s test runner and used options to run certain tests. This is particularly useful on large code bases.

We learned about the wide variety of queries available in React Testing Library to select elements in different ways. We used the getByText query extensively in the checklist tests. We also created a test ID on list item checkboxes so that the getByTestId query could be used to select them uniquely.

We learned that the user-event package is an excellent way of simulating user interactions that are decoupled from the implementation. We used this to simulate a user clicking a list item checkbox.

We learned how to produce code coverage reports and understood all the statistics in the report...

Questions

Answer the following questions to check what you have learned in this chapter:

  1. We have written some tests for a HomePage component and placed them in a file called HomePage.tests.tsx. However, the tests aren’t run when the npm test command is executed—not even when the a key is pressed to run all the tests. What do you think the problem might be?
  2. Why doesn’t the following expectation pass? How could this be resolved?
    expect({ name: 'Bob' }).toBe({ name: 'Bob' });
  3. Which matcher can be used to check that a variable isn’t null?
  4. Here’s an expectation that checks whether a Save button is disabled:
    expect(
      screen.getByText('Save').hasAttribute('disabled')
    ).toBe(true);

The expectation passes as expected, but is there a different matcher that can be used to simplify this?

  1. Write a test for the getNewCheckedIds function we used in this chapter. The test should check...

Answers

  1. The problem is that the file extension is tests.tsx rather than test.tsx.
  2. The toBe matcher should only be used for checking primitive values such as numbers and strings—this is an object. The toStrictEqual matcher should be used to check objects because it checks the values of all its properties instead of the object reference:
    expect({ name: 'Bob' }).toStrictEqual({ name: 'Bob' });
  3. The not and toBeNull matchers can be combined to check a variable isn’t null:
    expect(something).not.toBeNull();
  4. The toBeDisabled matcher can be used from jest-dom:
    expect(screen.getByText('Save')).toBeDisabled();
  5. Here’s a test:
    test('should remove id when already in checked ids', () => {
      const result = getNewCheckedIds([1, 2, 3], 2);
      expect(result).toStrictEqual([1, 3]);
    });
  6. The findBy query type requires awaiting because it is asynchronous:
    expect(await screen.findByText('Save')).toBeInTheDocument...
lock icon
The rest of the chapter is locked
You have been reading a chapter from
Learn React with TypeScript - Second Edition
Published in: Mar 2023Publisher: PacktISBN-13: 9781804614204
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Carl Rippon

Carl Rippon has been in the software industry for over 20 years developing a complex lines of business applications in various sectors. He has spent the last 8 years building single-page applications using a wide range of JavaScript technologies including Angular, ReactJS, and TypeScript. Carl has also written over 100 blog posts on various technologies.
Read more about Carl Rippon