25

Testing React with Jest & React Testing Library

 5 years ago
source link: https://www.tuicool.com/articles/NzMNbeV
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Learn how we can test our components and React Hooks to have better quality code within our applications, improving code reuse and removing errors.

In this article, we're going to learn about tests in React, how we can use the Jest library to test our components and write the right tests to make sure it's all working the way we expect. Also, we're going to learn more about the React Testing Library, which is a library that can help us write better tests, with some exceptional functions and methods, that guarantee us that our code is well-tested and safe.

Testing?

Does this scenario sound familiar? You learned JavaScript, created your first functions and objects, then you started to learn React, created your first React components, learned about patterns and created some real-world apps examples to release to the world and learn more. Your code isn't the best code out there, you don't care about having good code readability, don't have a lot of code reuse in your applications, you repeat a lot of logic within your application, and don't write any tests to test your components and state logic to see if it's all working as expected. You don't know for sure if your functions and components are returning and rendering the exact data that you want, but, for you, it's all perfect.

For a long time, tests in development were hidden and neglected. We didn't care about testing when talking about building huge applications that require better code patterns. We were too busy thinking about new ways to create the same thing using something new, and didn't care about testing our code. But now, tests are more and more important, and are play an important role in our applications, making sure that everything is working fine.

When we're starting to program, we don't care about tests at first, but then when we're at some level of development we must start to care and think about it. Especially when we want to start to contribute to open source, or when we're going to start in a new position at a company, we must (and even sometimes we're forced to) learn to start testing our code to make sure that everything is working fine.

A lot of people think that testing code is a waste of time and that we shouldn't be doing tests, but they're wrong or they don't understand how tests can improve our code and our projects. Tests are a vital part of our application. With testing, we can guarantee that our code is working well and isn't causing any problems. There are many benefits of testing. Maintaining good tests in your applications means that your code is exactly the way you want, and you won't have any unexpected errors or side-effects when running your application.

Getting Started

To test a real application here, we're going to test a task app! It's called Cactus, and it's a basic task app built using React Hooks. If you don't know exactlyhow Hooks workyet, you can also learn more about it just looking at the code. All you need to do to start the project is clone it, install and run it.

This is the link to the repo, so all you need to do is clone it, and install it using yarn :

yarn install
yarn start

Or, if you use npm:

npm install
npm start

Now the application should be running fine for you at localhost:3000 , and as you can see it's a pretty simple task app. You can add a to-do and then delete a task if you want it, not too fancy, but it's the core idea of any task app! Now, we're going to learn more about Jest so we can start to write our tests.

Jest

Whether you're a beginner or you've been working with React for some time now, you may have heard of Jest. Jest is a JavaScript testing framework , which helps us to write tests and see if it's all working fine in our applications. Jest is not limited to React, so you can use it in any JavaScript project that you want, with any libraries or frameworks like Vue or Angular, but in React it's the most used testing framework. So now, let's see how Jest tests work and how we can benefit from them in our code by writing our first test.

Let's write a simple test here just to see it how Jest works. So now let's create a simple file inside our cloned project called fullName.test.js . Inside this fullName.test.js we're going to create a function called fullName , which is going to look like this:

const fullName = (firstName, lastName) => `Hey ${firstName} ${lastName}, this is your first test using Jest!`;

Well, pretty basic, this function is just taking the firstName and the lastName passed and return a string to us as a result. So now, let's test this function to see if it's going to work the way we want. Below the function, let's put the following code:

describe('Testing the fullName function', () => {
  // ...
});

The describe function here creates a test suite. It's a good way to test because with it you can create one test suite for each part of your code as functions, components, objects, modules, etc. So, since in this example we're going to test a specific function, we're going to create a specific test suite for it. Inside that describe function, we're going to pass a string to define what we're testing and a callback function. Inside that callback function, we're going to create another function, this time called it :

describe('Testing the fullName function', () => {
  it('Should return the full name', () => {
  });
});

The it function is where we're going to write our tests, and you should pass a string as the first argument. This string should be a description of what are you testing exactly. You want your code to be legible so others can understand it, so for a cleaner and more legible code, you should describe shortly what are you testing. In our example, we're going to test if the function is returning the full name that we expect, so we pass that specific string. The it function also takes a callback function, and inside that callback function, we're going to write our test.

Remember, the it function is where we're going to write our tests, and each describe function can have as many functions as you want. The describe function's just to create a test suite and help us organize our test code.

Now, let's write our test. First, we're going to write what we're expecting as a result. I'm going create a const called result ; this const is going to be a string, with the exact data that we're to be expecting as a result. I'm going to pass my name as arguments, so the const result should look like this:

const result = `Hey Leonardo Maldonado, this is your first test using Jest!`;

Now, we're going to use the expect function which is imported from Jest. This function allows us to use matchers. Basically, matchers are functions that allow us to test values in different ways. If you want to see all matchers available, you can click here .

Our expect function is going to look like this:

expect(fullName("Leonardo", "Maldonado")).toBe(result);

We're passing our fullName function inside of it, and passing my name as arguments. After the expect , we use the toBe matcher, which is going to test if the result of the fullName function matches the const result that we created.

Now, let's run our test and see the result, all we need to do is give a yarn test or an npm test and our test should pass!

FnIZvee.png!web

Our test passes, as you can see, and it's working pretty well! Now, let's learn more about what React Testing Library is and how it can help us to test our React components.

Testing React Components

To test our React components, we're going to use a library called React Testing Library, which is a React DOM testing utilities library focused on good practices. The project is already using it so you don't need to install.

Now, we're going to start to write our React component tests. I defined some goals and tests that we're going to write, to see if everything is working fine. To test our application, I thought of some obvious test that should be written and it'll help us understand how to use them in real-world applications. These are the tests that we're going to write:

  • Test if we're getting the correct value on input: After typing something on the input we should get a correct value.
  • Test if it's adding a task when you click the button: After typing something on the input and clicking on the button, it should add the task to the tasks state.
  • Test if it's deleting a task when you click on the X icon: Should delete the task after you click on the X icon.

Test 1: Correct Value on Input

Now, let's write our first test. Go to our components folder and inside our AddTask folder, we're going to create a file called AddTask.test.js , which is going to contain all of our tests for this component.

Inside that file, let's write our first test. We're going to test if it's rendering our component correctly. First, let's import some things that we're going to need:

import React from 'react';
import { render, fireEvent } from 'react-testing-library';
import AddTask from './AddTask';

Our test is going to be a simple test using the render function that we imported from react-testing-library. It's going to look like this:

it('renders the AddTask', () => {
  const { getByText } = render(</>)
  const button = getByText('Add')
  expect(button.innerHTML).toBe('Add')
});

Let's write another test for this component. This time we're going to test if we're getting the exact value of input expected. Our test is going to look like this:

it('Get value of the input', () => {
  const { getByTestId } = render(</>)
  const input = getByTestId('input');
  fireEvent.change(input, { target: { value: 'task' } });
  expect(input.value).toBe('task')
})

In this test, we're using the fireEvent function which is a function provided by the react-testing-library to simulate a DOM event. In this case particularly, we're simulating a change on the value of the input.

Test 2: Adding a Task on Button Click

Let's write our last test for this component, but first we need to know some things. This project is using React Hooks, which is a new way to manage state in React. To test Hooks, we're going to use a library called react-hooks-testing-library , which is a library to help us test our React Hooks and see if everything is working fine.

Now, we're going to export some things from the react-hooks-testing-library:

import { renderHook, act } from "react-hooks-testing-library";

And import our useTasks Custom Hook to our test file:

import useTasks from '../../hooks/useTasks';

Now let's write our test. It's going to be a pretty simple test. We're going to test if it's adding a new task every time we call the addTask function. Our test is going to look like this:

it('Should add a Task after clicking the Add button', () => {
  const { result } = renderHook(() => useTasks());
  expect(result.current.tasks.length).toBe(0);
  act(() => result.current.addTask());
  expect(result.current.tasks.length).toBe(1);
})

We used the renderHook function from the react-hooks-testing-library to render our Custom Hook, and then we tested some things: the length of the tasks should be 0 , then after we called the addTask , it should be 1 . Pretty simple and readable, even someone who is starting with React Hooks and tests can totally understand what's going on.

Now, let's write the tests for the Task component. Inside our Task folder, we're going to create a file called Task.test.js and start to write our tests.

First, we're going to write a test to check if it's rendering everything ok, so it's going to look like this:

describe('Task', () => {
  it('renders the Task', () => {
    const props = { text: "A simple task", index: 1, deleteTask: jest.fn() };
    render(<Task {...props} />)
  });
})

Test 3: Deleting a Task with X Icon

Now, for our last test for this Task file, we're going to test if it's deleting a task after we call the deleteTask function. Like we did before, we're going to import some things from the react-hooks-testing-library:

import { renderHook, act } from "react-hooks-testing-library";

Now, let's import our useTasks Custom Hook to our test file:

import useTasks from '../../hooks/useTasks';

This test is going to be pretty similar to the previous one, but this time we're going to use the addTask to add a task, and then we're going to call the deleteTask to delete this task, so our test is going to look like this:

it('Should delete a Task after clicking the X button', () => {
  const { result } = renderHook(() => useTasks());
  expect(result.current.tasks.length).toBe(0);
  act(() => result.current.addTask());
  expect(result.current.tasks.length).toBe(1);
  act(() => result.current.deleteTask());
  expect(result.current.tasks.length).toBe(0);
})

Now that we tested our Hooks, we're going to write the tests for the Tasks component. Inside our Tasks folder, we're going to create a file called Tasks.test.js . In this component, we're going to write just one single test.

We're going to test if it's rendering a list of tasks. So, our test will look like this:

it('Renders the Tasks ', () => {
  const tasks = [{ text: "A simple task", deleteTask: jest.fn() }];
  const { getAllByTestId } = render(<Tasks tasks={tasks} />)
  const task = getAllByTestId('task').map(li => li.textContent);
  const fakeTasks = tasks.map(task => task.text);
  expect(task).toEqual(fakeTasks);
})

And we're done! We tested our useTasks Custom Hook using the react-testing-library, and now we won't get any errors when using our application and we left our code safer. In this example we only wrote three tests. We could have written a lot more to cover a lot more of our application.

You should start to test your code now because, with it, you guarantee that your code is safer, you're free of errors in production, and your code readability is improved, as you'll need to write better code to write the right tests for it. Don't panic and start to test everything in your application because sometimes it doesn't make any sense to test. You should test the critical parts of your applications, imagining some real cases that might occur with your users.

Conclusion

In this article, we've seen how to write tests using Jest and also how to test components using the React Testing Library. Also, we learned about how we can test our Custom Hooks using the react-hooks-testing-library. We've seen how to test our React components using the react-testing-library and its functions as the fireEvent or the render, and how to test our React Hooks properly.

Thank you for reading, see you at the next article!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK