Testing React components plays a pivotal role in application development because it helps ensure the individual components and the application work as intended and catches bugs before production.
While unit testing and integration testing are possible in React, we’ll discuss only unit testing in this Answer. There are a few recommended tools for testing components in React, such as Jest and React Testing Library. Jest provides more control over the execution and complexity of tests, whereas React Testing Library is more user-friendly and abstracts the test implementation details away from the user. We’ll be using the React Testing Library for this Answer.
In the first example, let’s render a basic React component using TypeScript to get started and test if it displays the correct text content. The following example has a Hello.tsx
component that renders a name. There’s also a Hello.test.tsx
test file that checks the output of the Hello.tsx
component. Click the “Run” button to start the test.
import React from 'react'; import { render, screen } from '@testing-library/react'; import {Hello} from "./Hello" test('renders a name', () => { render(<Hello name="Mike"/>); const linkElement = screen.getByText(/Hello Mike/i); expect(linkElement).toBeInTheDocument(); });
Hello.tsx
Line 3: We create the Hello
component that takes name
as prop
.
Line 5: We render name
with the string "Hello"
prepended to it.
Hello.test.tsx
Line 2: We import the render
method and the screen
object from the React Testing Library. The render
method is used to render components. The screen
object queries and interacts with the rendered components during testing.
Line 5: We define our test
function and pass a test description as an argument to identify the test. The second argument is the callback function that contains the testing logic.
Line 6: We call the render
function to render the Hello
component with name
set to Mike
provided as the prop
.
Line 7: Then, we use the getByText
method to match any Hello
component is rendered correctly, it should display the text, Hello Mike
, and the getByText
method will extract the DOM element that contains this text content.
Line 8: The expect
method takes the DOM element as an argument, and the toBeInTheDocument()
method is called to check if the DOM element exists in the rendered output.
In the second example, let’s render a form with a username input field and a login button. After entering the username and clicking the login button, the screen should display the text Login Successful
. We’ll test this by creating a Login.tsx
component that renders the form and a Login.test.tsx
test file that tests the functionality of our component. Click the “Run” button to start the test.
import React from 'react'; import { render, screen } from '@testing-library/react'; import {Hello} from "./Hello" test('renders a name', () => { render(<Hello name="Mike"/>); const linkElement = screen.getByText(/Hello Mike/i); expect(linkElement).toBeInTheDocument(); });
Login.tsx
Line 5: We create the isLoggedIn
state variable to check if the user has correctly submitted the form.
Lines 7–9: We create the handleLogin
event handler that toggles the isLoggedIn
state to true
when the form is submitted.
Line 13: We use conditional rendering to display the form when the isLoggedIn
state is false
and display the text Login Successful
when the isLoggedIn
state is true
.
Line 15: We create an input field where the user will enter their username.
Line 16: We create a button and register the handleLogin
method as the onClick
event handler that triggers when the user clicks on it.
Lines 18–19: We set the screen to display the Login Successful
message when the isLoggedIn
state is false
.
Login.test.tx
Line 3: Along with the render
and screen
methods, we also import the fireEvent
object that’s used to simulate user interactions with elements in our tests, such as clicking buttons, typing into input fields, or submitting forms.
Lines 6–7: We use the describe
method to create a test suite to group related test cases. It takes the name of the test suite as the first argument, and the second argument is the callback function that contains the individual test cases within that test suite. We use the it
method to make individual test cases. It takes the name of the test case as the first argument and a callback function with the testing logic as the second argument.
Line 9: We render the Login
component using the render
method.
Line 13: We use the getByPlaceholderText
method to extract the username input element using its placeholder text.
Line 14: We use the change
method of the fireEvent
object to enter a username into the input field. Its first argument is the username input element, whereas the second argument contains the value to be entered in the element.
Line 17: We use the getByText
method to extract the Login
button element. The method takes as an argument the text content of a DOM element to search for.
Line 18: We use the click
method to simulate clicking the Login
button.
Line 21: After submitting the form, we use the getByText
method to extract the DOM element that contains the text Login Successful
.
Line 22: Finally, we call the expect
method that takes the DOM element as an argument, and call the toBeInTheDocument
method to check if the DOM element exists in the rendered output.