DEV Community

Cover image for Implementing Jest and RTL for beginners (1/3)
Jareth Tan
Jareth Tan

Posted on • Edited on

Implementing Jest and RTL for beginners (1/3)

Table Of Contents

1. Introduction
2. Getting Started
3. Examples and Methods
4. Conclusion

So, for this week's post, we will be looking at Jest.js and React Testing Library. I just recently started learning how to test my code. So likely for the next few posts, I will be documenting the learning and pointers I gathered along the way. It will be pretty basic testing but hopefully the complexity increases as I learn more about testing.

Introduction
So just a little introduction to this topic. I decided to create a simple TicTacToe game using React Library with the intention to implement testing into my simple game app to get exposure to a testing framework.

What is Jest?
Jest is a testing framework which was first build for React applications. It allows developers to run tests on JavaScript and TypeScript code and integrates well with React. It offer functions for test suites, test cases, and assertions which we will get into more later in the post.

What is React Testing Library (RTL)?
React Testing Library is a JavaScript testing utility built specifically to test React components. It is a DOM testing library that handles DOM elements and how they behave in front of real users instead of dealing with instances of rendered React components. The library comes with a set of testing helpers which we will get into later in this post.

So what is the difference between both of them? Can they replace one another?
No they are not a replacement for one another. In fact, we need both to test our component completely.

Getting Started
Fortunately, if we create our React app using create-react-app, Jest and RTL already comes as part of the installation. Once we created our app, there is a file called app.test.js which uses Jest and React Testing Library.

To run the test, open our terminal and run

npm run test // if using npm
Enter fullscreen mode Exit fullscreen mode

or

yarn test // if using yarn
Enter fullscreen mode Exit fullscreen mode

This will initialize the test. The output for a successful and failed test will be shown at the end of the post.

Examples and Methods
In this section, we will reference certain lines of code from the TicTacToe app.

For this post, we will use the Board component to conduct certain tests. Below is the board component which renders a board with nine squares as shown below:

TicTacToe Board

And the JSX for this component are as shown:

  return (
    <div className={classes.container} data-testid="board">
      <span data-testid="playerTurn">Player {select} Turn</span>
      <div className={classes.gridContainer}>
        {arr.map((a, i) => (
          <Square
            key={Math.random()}
            index={i}
            onHandleSelect={onHandleSelect}
            moveName={a}
            disable={disable}
          />
        ))}
      </div>
      {winner ? (
        <h2>
          {winner === "Draw"
            ? "Round Draw. Restart Round."
            : `Player ${winner} is the Winner!`}
        </h2>
      ) : (
        ""
      )}
      <button
        onClick={onHandleReset}
        type="button"
        className={classes.buttonReset}
      >
        reset
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

To start off, we would like to test if the board itself is rendered in the DOM. To begin, we will create a __test__ folder in the folder which houses the Board component and create a test file called Board.test.tsx. like this:

Folder Structure

In Board.test.tsx, import render and cleanup from react test library and also the Board component itself.

import { render, cleanup } from "@testing-library/react";
import Board from "../Board";
Enter fullscreen mode Exit fullscreen mode

Before writing test logic, we need to call the describe method from Jest. describe is used describe our test suite and each test suite can consist of multiple test as shown below

describe(Board, () => {
  test("Board is rendered on screen", () => {
     // our test function comes in here.
  });
  it("Reset button is rendered on screen", () => {
     // ourtest function comes in here.
  });
  // other tests
});
Enter fullscreen mode Exit fullscreen mode

The test method from Jest takes in two argument (test description, test function). Instead of test, the method it can be used as well. Both methods exist to enable the user to make a readable English sentence from our test.

Next, we have to call on the render() method from RTL and insert the component we want to render (in this case it is the Board component). One of the key feature of render() is that we can destructure the rendor method and select different ways to queries the DOM. There are quite a few queries to choose from (for example: byRole, byText, byTitle, etc) and they can be found in RTL official document. For now, we will use getByTestId.

const { getByTestId } = render(<Board />);
Enter fullscreen mode Exit fullscreen mode

From there, we will use getByTestId to search the DOM for the html element with the specified test ID and assign it to a variable.

const renderBoardElement = getByTestId("board");
Enter fullscreen mode Exit fullscreen mode

In this case, the main div in the highest component has the the data-testid prop and can be seen in an abstract from the Board component JSX

  return (
    <div className={classes.container} data-testid="board"> // data-testid *************
      <span data-testid="playerTurn">Player {select} Turn</span>
      <div className={classes.gridContainer}>
        {arr.map((a, i) => ( .....
Enter fullscreen mode Exit fullscreen mode

Then we will use the expect method from Jest and insert the variable in and choose a matcher method to decide the requirement of our test. There are many matchers to choose from and they can be found in Jest official documents. In this case, the matcher we choose will be .toBeInTheDocument()

expect(renderBoardElement).toBeInTheDocument();
Enter fullscreen mode Exit fullscreen mode

Lastly, we will need to use the cleanup method from RTL to clean up the test everytime it finishes executing. The clean up method Unmounts React trees that were mounted with render. The whole testing function for checking the board will be render in the DOM would look something like this:

import { render, cleanup } from "@testing-library/react";
import Board from "../Board";

afterEach(cleanup);

describe(Board, () => {
  test("Board is rendered on screen", () => {
    const { getByTestId } = render(<Board />);
    const renderBoardElement = getByTestId("board");
    expect(renderBoardElement).toBeInTheDocument();
  });
});
Enter fullscreen mode Exit fullscreen mode

If we type npm run test in the terminal and the test is successful, we will see this printout:

Pass Test

This means the div with test-dataId of board was rendered in the DOM.

To generate a fail test, we will change the test-dataId from board to boar and this is what a fail test looks like.

Failed Test

Conclusion
Alright, this is the end of the first part of testing. it is a very basic test to check if the html element are rendered. This is an extremely high level check and there will be many other more in depth to conduct to ensure the test is working correctly. Such as fire-events, number of components rendered, etc. I will document more as I develop my testing skills along the way. If I have any inaccuracies, do tell me as I would love to learn from my mistakes. Apologies for the long intro and for more information on Jest and RTL, refer to the official documentations at:

For Jest: https://jestjs.io/
For React Test Library: https://testing-library.com/docs/react-testing-library/intro/

Top comments (0)