Jest - React Testing



In this chapter, we'll learn how to use Jest to test React components. Jest is a powerful testing tool that makes it easy to write tests for JavaScript applications. We will focus on three key areas of React testing:

Jest - React Component Testing

In Jest, testing React components involves rendering them and checking if they display the correct output. This is usually done using the React Testing Library along with Jest.

Installing Required Libraries

Before you start, make sure you have Jest and the React testing library installed:

npm install --save @testing-library/react @testing-library/jest-dom

Testing a React Component

Let's say we have a Greeting component that takes a name prop and displays a greeting.

// Greeting.js
import React from 'react';

const Greeting = ({ name }) => {
    return <h1>Hello, {name}!</h1>;
};

export default Greeting;

To test this component, we render it and check if it correctly displays the greeting message.

// Greeting.test.js
import { render, screen } from '@testing-library/react'; // Importing testing methods
import Greeting from './Greeting'; // Importing the component

test('displays the correct greeting message', () => {
    render(<Greeting name="John" />); // Render component with "John" as prop

    // Check if the greeting is displayed
    expect(screen.getByText(/hello, john!/i)).toBeInTheDocument(); 
});

Jest - Snapshot Testing

Snapshot testing in Jest helps verify that your components don't unexpectedly change. It captures a component's rendered output and saves it. In future tests, Jest compares the current output with the saved snapshot. If there are any differences, Jest will alert you.

Snapshot Testing

Here's how we can use Jest to create a snapshot test for our Greeting component.

// Greeting.test.js
import { render } from '@testing-library/react';
import Greeting from './Greeting';

test('matches the snapshot', () => {
    const { asFragment } = render(<Greeting name="John" />);

    // Compare the rendered output with the snapshot
    expect(asFragment()).toMatchSnapshot();
});

Jest creates a snapshot on the first run and compares it to future outputs. If the output changes, Jest alerts you so you can confirm if the change is intentional.

Jest - Testing React Hooks

React hooks manage state, side effects, and other logic in components. Testing these hooks makes sure they work as expected. With Jest, you can test both custom(user-defined) and built-in hooks like useState and useEffect.

Testing a Custom Hook

Custom hooks in React are used to handle reusable logic. Let's take a look at how to test a simple custom hook that manages a boolean state.

  • Step 1 - Creating the useToggle Hook: The useToggle hook toggles a boolean state (true/false). Here's the implementation:
// useToggle.js
import { useState } from 'react';

const useToggle = () => {
    const [state, setState] = useState(false);
    const toggle = () => setState(!state);
    return { state, toggle };
};

export default useToggle;
  • Step 2 - Testing the useToggle Hook: To test this hook, we'll use renderHook from @testing-library/react-hooks, which allows us to render the hook and check its behavior directly.
  • // useToggle.test.js
    import { renderHook, act } from '@testing-library/react-hooks';
    import useToggle from './useToggle';
    
    test('should toggle the state between true and false', () => {
        const { result } = renderHook(() => useToggle());
    
        // Check the initial state is false
        expect(result.current.state).toBe(false);
    
        // Call the toggle function to change the state
        act(() => result.current.toggle());
    
        // Check if the state changes to true
        expect(result.current.state).toBe(true);
    });
    

    Testing useEffect with Side Effects

    React's useEffect hook is used for side effects like updating the DOM or fetching data. Here, we'll show you how to test a component that uses useEffect to handle such side effects.

    • Step 1 - Create a Count Component: Here, we create a Counter component that uses useState to set the initial count to 0 and includes a button to increase it by 1.
    // Counter.js
    import React, { useState } from 'react';
    
    const Counter = () => {
        const [count, setCount] = useState(0);
    
        return (
            <div>
                <p>Count: {count}</p>
                <button onClick={() => setCount(count + 1)}>Increase</button>
            </div>
        );
    };
    
    export default Counter;
    
  • Step 2 - Write the Test: Now, let's write a test to verify that the count increases when the button is clicked.
  •  // Counter.test.js
    import { render, screen, fireEvent } from '@testing-library/react';
    import Counter from './Counter';
    
    test('counter increments when button is clicked', () => {
        // Render the Counter component
        render(<Counter />);
    
        // Get the button and paragraph elements
        const button = screen.getByText(/increase/i);
        const paragraph = screen.getByText(/count: 0/i);
    
        // Simulate a click on the button
        fireEvent.click(button);
    
        // Check if the count has increased
        expect(paragraph).toHaveTextContent('Count: 1');
    });
    

    This test verifies that when the button is clicked, the count increases from 0 to 1.

    Advertisements