In this blog, we will consider how we can test React components using Jest and some of its best practices.
Setting up Jest
To use Jest for testing React components, we need to install Jest with the below command:
For additional information related to Jest setup, refer Getting Started with Jest.
Starting with the unit tests
Before writing tests, let's look at the component we are testing.
In the below code, we have a Search Input and are fetching the blogs from an API call and showing them in the UI. The App.js file contains a label, Search Input field, and useFetch hook, which we will use to fetch the content of the blog posts. The code is below:
We will be testing 3 things with this React component.
- Testing React component in the loading state
- Testing user interaction
- Testing for failed requests
Now let's look at how to write unit tests for the above App.js component.
Testing React component in a loading state
First, we will test for the loading state. We are mocking the return value from the 'useFetch' Hooks in the below code. Then we are rendering the App and expect to see the 'Loading Posts' text which will look like below.
You can run the tests with the command ```npm test -- App.test.js``` and see the results if it passes.
Testing user interaction
To simulate user interaction, like clicking or typing, we will use fireEvent methods, and test the output.
Here, we are testing the component by entering the text ‘second’ in the search field and validating that only the post related to it shows up.
Testing for failed requests
We are testing a scenario when the API fails to fetch the posts. It will throw some error messages.
Now the above-tested component is just one of the examples which we have shown in this blog. Let's consider multiple real-world scenarios that we can use, such as:
Login Page Testing
Let's say you have a login page for your application. You can use React Testing Library to simulate user input and test the login functionality. For example, you can use fireEvent.change to change the value of the email and password inputs and fireEvent.click to simulate the click of the login button. You can then use 'Expect' to verify that the correct action was taken, such as a redirect to the dashboard page or an error message if the login credentials were incorrect.
Shopping Cart Testing
If you have a shopping cart feature on your website, you can use React Testing Library to test the functionality of adding and removing items from the cart. You can simulate user actions, such as clicking on the "Add to Cart" button or removing an item from the cart, and then checking that the cart has been updated correctly. For example, you can use getByText to find the cart total and check that it is updated correctly.
Form Validation Testing
Another real-world scenario is testing form validation. You can use React Testing Library to simulate user input and verify that the form validation rules are working correctly. For example, you can simulate user input using fireEvent.change to change the value of a form input and then check that the correct error message is displayed if the input value is invalid. You can also verify that the form cannot be submitted when there are validation errors present.
API Request Testing
If your application makes API requests, you can use React Testing Library to simulate user input and verify that the correct data is displayed in the UI based on the mocked API responses.
These are just a few examples of applying Jest and React Testing Library to real-world scenarios. The possibilities are endless, and you can use these tools to test almost any aspect of your application. Let's look at some of the best practices.
Use Snapshot Testing sparingly
Snapshot testing is a useful tool for detecting unexpected changes in your UI. However, relying too heavily on snapshot testing can lead to brittle tests that break easily. Instead, focus on testing the behavior of your components and use snapshot testing sparingly.
Use Mocks and Spies
Mocks and spies can help you isolate your components from their dependencies, making your tests more reliable. Jest provides a powerful mocking system to create mocks and spies for components.
Use Continuous Integration
Continuous integration (CI) means automatically building and testing your code whenever changes are made. CI can help catch errors early and ensure your tests always pass. In 2023, using a CI system is becoming increasingly common, and it's highly recommended to integrate it into your testing process.
Test the behavior, not the implementation
Instead of testing specific functions or components, focus on testing the behavior and functionality of your app. It makes tests more reliable and less likely to break when you make changes.
Keep tests simple and focused
Write small, focused tests that only test one thing at a time. It makes it easier to debug failures and maintain your tests over time.
Use beforeEach() and afterEach()
Use these functions to set up and clean up test data. It can help prevent test data from interfering with other tests.
Use waitFor() for asynchronous code
Use waitFor() to wait for asynchronous code to finish before continuing with your tests. It helps prevent false negatives and flaky tests.
Use screen object to access the DOM
Use the screen object from React Testing Library to access the DOM elements rendered by your components. It provides a more reliable way to test your components than testing implementation details.
Use fireEvent to simulate user actions
Use fireEvent to simulate user actions, such as clicking or typing. It makes it easy to test the behavior of your components in response to user interactions.
Keep your tests up to date
As you make changes to your app, make sure to update your tests accordingly. It helps ensure that your tests remain accurate and reliable over time.
Testing React components using Jest and React Testing Library are essential to building high-quality software applications. We have discussed how to set up Jest and write some tests to check the rendering, user interactions, failed API requests, and behavior of a React component. These tools can help us write comprehensive tests for React components and ensure they work as expected.