Tutorials on React Testing Library

Learn about React Testing Library from fellow newline community members!

  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL
  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL

How to Test Your First React Hook Using Testing Library

In previous posts we learned: In this post, we're going to write tests for a custom React hook. We're going to create a custom hook that will uppercase a given text string. This hook will be connected to an input and whenever a user changes the input value this hook will automatically uppercase the value. Let's write the hook. Create a file called useUppercase.ts In this file, we create a custom hook function useUppercase() . It accepts a string as an initial argument. We transform this string using .toUpperCase() and then store the result value in a local state. Also, we create a function update() . This function will be a part of the public API. With this function, components will be able to update the current value. Finally, we use useEffect() to re-render the hook if the initialValue gets changed. This, for example, happens when the component gets new props and passes the new initial value to the hook. In this case, we need to update the local state with the new value from the component. Now, let's test the hook! To test hooks, we're going to use React Hooks Testing Library . It gives us utilities for testing hooks without even rendering a single component. Let's install it: Now, we create a file useUppercase.test.ts . In this file, we import our hook and describe our first test: The first thing we want to test is that the hook returns a given initial value in the upper case. With React Hooks Testing Library, we don't need to render a whole component, instead, we render the hook itself with a special function called renderHook() : The renderHook() function returns an object with the result field. We can access the current render result with the current field. It contains the object our hook returns. We can use autosuggestions to select a field to test against: The coolest feature is readability. We don't need to create extra infrastructure code to test hooks in isolation. It just works! Another thing we want to test is that when we call update with a new string, the hook's value updates. Let's write another test: The current render result contains a reference to our update() method, so we can use it to simulate a change. Notice that we need to use act() . It is required for the hook to update the values inside of it. According to the documentation : The last thing to cover is a case when the hook gets a new initialValue . In this case, we need to update its values and re-render the component that is using them. In this test, we access not only the result but also the rerender() method. This method renders the hook with another initial value. Also, this time we use props to pass initial values. They help us to keep the code shorter and more readable. In general, we pass the initialProps object to options of the render() method. When we need to re-render the hook, we can pass updated values for this object. The library infers the type of the object so we can use autosuggestions here as well:

Thumbnail Image of Tutorial How to Test Your First React Hook Using Testing Library

How to Write Your First Component Test in React + TypeScript App

In the previous post , we created a unit test for a function. In this post, we're going to create a unit test for a component using @testing-library/react . Since we're using Create React App the React Testing Library is already installed in our dependencies. If you don't have it, install the package using: We will create a Greetings component with the greetings text inside and a button for sending friendly waves 😊 Let's create and review a component first: This component takes a name and an onSendWaves function as props. The name will be rendered in the greetings text, and the callback function will be called whenever the button is pressed. The button can be hidden if the callback function is not provided. We need to test 3 things here: Let's start with the first one. For the first test, let's check if the greetings text is rendered correctly. Let's break the test code down a bit. In describe and it we explain the assumption we want to test as we did in the previous post . Then, we use the render method from the @testing-library/react package. This method renders the component provided in arguments and appends it to the body of the document. Once we're rendered the component we can use the screen object to get access to the render result. It provides a set of queries for us to find the required element. If you saw tests with RTL before, you might have seen this: We use getByText query to find an element that contains the given text. Notice that React Testing Library doesn't focus on the component implementation. We don't explicitly define where to look for that text, instead, we tell what to find and RTL will try to find it for us. Finally, we check that the required element is indeed in the document. We can select elements not only by the text they contain. In fact, there are quite a few ways to query elements . Let's review a couple of types of queries : Another cool (and a bit confusing at first) feature is the query type. Until now we only saw a getBy query. It searches for a single element and returns it if found and throws an error if didn't find. There are also other types of queries for different types of searches : The queryBy and queryAllBy are usually used to make sure that elements are not in the document. The findBy and findAllBy are used to search for elements that are not available at first render. It is hard to pick a query at first, that's why there is a priority guideline in the docs and the cheatsheet to help us. Now, let's test that when the onSendWaves is provided the button gets rendered: Here, we use getByRole query because we need to find a single button element. React Testing Library has the fireEvent object that can help with simulating browser events, however, it is more convenient to use the user-event library since it provides more advanced simulation of browser interactions. Let's install it with: Now let's test that when the button is pressed it fires the callback: First of all, we use jest.fn method to create a mock function . This mock will help us to test how many times and with what arguments this function has been called. On the last line, we check that the mock instance ( onSendWavesMock ) is called at least once with a given text. Another text will result in the failing test. To click the button we use the userEvent object from React Testing Library. It provides most common actions like click, input changes, and so on. In our case, we need to test the click action, so we use the click method and pass the element that should be pressed. In the next post, we will test react hooks with @testing-library/react-hook .

I got a job offer, thanks in a big part to your teaching. They sent a test as part of the interview process, and this was a huge help to implement my own Node server.

This has been a really good investment!

Advance your career with newline Pro.

Only $30 per month for unlimited access to over 60+ books, guides and courses!

Learn More

Testing a Create React App TypeScript Project with Jest and React Testing Library

Building single-page React applications has never been easier. With a single command, Create React App (CRA) scaffolds an entire React application with development/build tools, such as Babel and Jest, automatically configured and integrated into the project. Getting started requires no additional configuration. Plus, it eliminates the need to maintain an entire build process, which can require lots of work and is very prone to error. However, the default template of Create React App does not include support for TypeScript, which has gained much traction in recent years. Below, I'm going to show you: To generate a new CRA project with TypeScript, provide the --template option to create-react-app and specify typescript as the template. Once the process is complete, view the project in an IDE (such as VSCode). Take note of the few differences between this template and the default template. Of course, TypeScript can be added to an existing CRA project by reproducing the above modifications. Replicating these steps on each new CRA project would be quite tedious and would waste valuable time that could be put towards designing/building your application. The CRA typescript template instantly did all this work for us. CRA templates simply offer conveniences that cannot be overlooked. Run the CRA application. You should see the following in your browser at localhost:3000 . Inside of src/App.test.tsx , there is a single unit test. ( src/App.test.tsx ) Run tests by executing the test NPM script: The test checks whether the "Learn React" link is rendered to the page. The React Testing Library ( @testing-library/react ) provides APIs for testing React components: Now, let's write several additional tests for the CRA TypeScript template project. To test if the React logo is rendered, use the getByAltText method, a semantic query method used for finding elements that support the alt attribute (such as <img /> ). This test should automatically pass. To test if the prompt to the user ("Edit src/App.tsx and save to reload") is rendered, use the getByText method. When you run the tests, you will notice that this test fails. This test fails because the query method encounters elements with parts of their text content wrapped in other elements such as <strong /> , <em /> , etc. Example : As the error message mentions, this issue can be resolved by passing a custom function as the text matcher argument to the getByText method. The function is executed on each node that's rendered to the page. When the function evaluates to true for a node, then that node will be returned as a matching node. On the contrary, when the function evaluates to false for a node, then that node will be ignored. This function accepts two arguments: Running the tests once more, all the tests pass. Experiment! Try out other queries and methods provided by the React Testing Library. The code for this post can found here . If you want to learn more about testing TypeScript + React with Jest and React Testing Library, then check out Fullstack React with TypeScript :

Thumbnail Image of Tutorial Testing a Create React App TypeScript Project with Jest and React Testing Library