Categories
Code Quality Jest React Unit Testing

Unit Testing for React: A Comprehensive Introduction

Reading Time: 15 minutes

Are you tired of debugging your React app and fixing bugs that could have been caught earlier? Unit testing is the solution! With unit testing, you can ensure that your code works as intended, and catch issues early on. In this blog post, we’ll explore different ways to get started with unit testing a React app using Jest.

Jest is a JavaScript testing framework developed by Facebook. It is widely used in the React community and provides an easy-to-use interface for writing tests. Let’s explore some examples of how you can get started with Jest in your React app.

  1. Setting up Jest in a React app

First, you need to set up Jest in your React app. You can do this by installing Jest as a dev dependency in your project:

npm install --save-dev jest

Once installed, create a jest.config.js file in the root of your project:

module.exports = {
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
};

This sets up the Jest environment and includes the @testing-library/jest-dom package, which provides additional matchers for testing React components.

  1. Writing your first unit test

Now that Jest is set up in your project, it’s time to write your first unit test. Let’s say you have a simple component that displays a greeting message:

function Greeting(props) {
  return <h1>Hello, {props.name}!</h1>;
}

To test this component, create a Greeting.test.js file and write your first test:

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

test('renders greeting message', () => {
  const { getByText } = render(<Greeting name="John" />);
  const greetingElement = getByText(/Hello, John!/i);
  expect(greetingElement).toBeInTheDocument();
});

In this test, we render the Greeting component with a name prop of “John”. We then use getByText from the @testing-library/react package to find the element that contains the greeting message. Finally, we use expect to assert that the greeting element is in the document.

  1. Testing component behavior

In addition to testing component rendering, you can also test component behavior. Let’s say you have a simple counter component that increments a count when a button is clicked:

function Counter() {
  const [count, setCount] = useState(0);

  const handleIncrement = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleIncrement}>Increment</button>
    </div>
  );
}

To test the behavior of this component, create a Counter.test.js file and write your test:

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

test('increments count when button is clicked', () => {
  const { getByText } = render(<Counter />);
  const countElement = getByText(/Count: 0/i);
  const incrementButton = getByText(/Increment/i);

  fireEvent.click(incrementButton);

  expect(countElement).toHaveTextContent('Count: 1');
});

In this test, we render the Counter component and find the elements that contain the count and increment button. We then use fireEvent.click to simulate a click on the increment button. Finally, we use expect to assert that the count element has been updated to display a count of 1.

  1. Testing asynchronous code

What about components that fetch data from an API? Jest provides an easy way to test asynchronous code using async and await. Let’s say you have a component that fetches a list of users from an API:

function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    async function fetchUsers() {
      const response = await fetch('https://jsonplaceholder.typicode.com/users');
      const data = await response.json();
      setUsers(data);
    }

    fetchUsers();
  }, []);

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

To test this component, create a UserList.test.js file and write your test:

import React from 'react';
import { render, waitFor } from '@testing-library/react';
import UserList from './UserList';

test('displays list of users', async () => {
  const { getByText } = render(<UserList />);
  await waitFor(() => getByText(/Leanne Graham/i));
  expect(getByText(/Leanne Graham/i)).toBeInTheDocument();
});

In this test, we render the UserList component and use waitFor from the @testing-library/react package to wait for the list of users to be fetched and rendered. We then use expect to assert that the name “Leanne Graham” is in the document.

  1. Mocking dependencies

What if your component depends on an external library or API? Jest provides a way to mock these dependencies in your tests. Let’s say you have a component that depends on the axios library to fetch data:

import axios from 'axios';

function TodoList() {
  const [todos, setTodos] = useState([]);

  useEffect(() => {
    async function fetchTodos() {
      const response = await axios.get('https://jsonplaceholder.typicode.com/todos');
      setTodos(response.data);
    }

    fetchTodos();
  }, []);

  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

To test this component, create a TodoList.test.js file and mock the axios library:

import React from 'react';
import { render } from '@testing-library/react';
import axios from 'axios';
import TodoList from './TodoList';

jest.mock('axios');

test('displays list of todos', async () => {
  const mockData = [
    { id: 1, title: 'Todo 1' },
    { id: 2, title: 'Todo 2' },
  ];

  axios.get.mockResolvedValue({ data: mockData });

  const { getByText } = render(<TodoList />);
  expect(getByText(/Todo 1/i)).toBeInTheDocument();
  expect(getByText(/Todo 2/i)).toBeInTheDocument();
});

In this test, we used jest.mock to mock the axios library. We then create some mock data and use axios.get.mockResolvedValue to mock the response from the API. Finally, we render the TodoList component and use expect to assert that the mock data is in the document.

Unit testing your React app with Jest is essential in ensuring your code works as intended and catching issues early on. By following these examples, you’ll be well on your way to writing effective and efficient unit tests for your React components.

Here are more examples from the basic to intermediate level, this should cover most of the scenarios one would encounter in day-to-day development tasks –

Example 1. Simplest Component

Let’s create a simple component and write a test for it. Create a new file MyComponent.jsx in your src folder and add the following code:

import React from 'react';

function MyComponent({ name }) {
  return (
    <div>
      <h1>Hello, {name}!</h1>
    </div>
  );
}

export default MyComponent;

Now, let’s write a test for this component. Create a new file MyComponent.test.jsx in the same directory and add the following code:

import React from 'react';
import { render } from '@testing-library/react';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
  it('renders the name prop', () => {
    const { getByText } = render(<MyComponent name="John" />);
    expect(getByText('Hello, John!')).toBeInTheDocument();
  });
});

Let’s go over what we just did.

We imported render from @testing-library/react to render our component in a test environment. We also imported our component, MyComponent.

We used the describe function to group our tests together. In this case, we only have one test, so we only need one it function.

In our test, we render our component with a name prop of “John”. We use the getByText function from @testing-library/react to check if the text “Hello, John!” is present in the rendered component.

Finally, we use the expect function to check if our assertion is true.

Example 2. Testing Component State

Let’s create a component that manages state, and test its behavior when the state changes. Create a new file Counter.jsx in your src folder and add the following code:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}

export default Counter;

This is a simple component that displays a counter and a button. When the button is clicked, the counter increments by one.

Now let’s write a test for this component. Create a new file Counter.test.jsx in the same directory and add the following code:

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

describe('Counter', () => {
  it('increments the counter on button click', () => {
    const { getByText } = render(<Counter />);
    const button = getByText('Click me');
    fireEvent.click(button);
    expect(getByText('You clicked 1 times')).toBeInTheDocument();
    fireEvent.click(button);
    expect(getByText('You clicked 2 times')).toBeInTheDocument();
  });
});


Let’s break down this test. We render our `Counter` component using `render` from `@testing-library/react`. We then use `getByText` to get a reference to the button element. We simulate a click event on the button using `fireEvent.click`. We then use `getByText` to check if the text “You clicked 1 times” is present in the rendered component. We simulate another click event on the button and check if the text “You clicked 2 times” is present. ## Testing component props Let’s create a component that takes props and test its behavior with different props. Create a new file `Greeting.jsx` in your `src` folder and add the following code:

import React from 'react';

function Greeting({ name }) {
  return (
    <div>
      <p>Hello, {name}!</p>
    </div>
  );
}

export default Greeting;

This is a simple component that displays a greeting message with the given name prop.

Now let’s write a test for this component. Create a new file Greeting.test.jsx in the same directory and add the following code:

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

describe('Greeting', () => {
  it('renders the name prop', () => {
    const { getByText } = render(<Greeting name="John" />);
    expect(getByText('Hello, John!')).toBeInTheDocument();
  });

  it('renders "World" if no name prop is passed', () => {
    const { getByText } = render(<Greeting />);
    expect(getByText('Hello, World!')).toBeInTheDocument();
  });
});

In this test, we have two test cases.

The first test case checks if the component renders the name prop correctly. We render the component with a name prop of “John” and check if the text “Hello, John!” is present in the rendered component.

The second test case checks if the component renders the default message “Hello, World!” if no name prop is passed. We render the component without any props and check if the text “Hello, World!” is present in the rendered component.

Example 3. Testing Component Events

Let’s create a component that fires an event and test its behavior when the event is triggered. Create a new file Form.jsx in your src folder and add the following code:

import React, { useState } from 'react';

function Form() {
  const [inputValue, setInputValue] = useState('');

  const handleSubmit = (event) => {
    event.preventDefault();
    alert(`You submitted: ${inputValue}`);
  };

  const handleChange = (event) => {
    setInputValue(event.target.value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name:
        <input type="text" value={inputValue} onChange={handleChange} />
      </label>
      <button type="submit">Submit</button>
    </form>
  );
}

export default Form;

This is a simple form component that takes input from the user and shows an alert when the form is submitted.

Now let’s write a test for this component. Create a new file Form.test.jsx in the same directory and add the following code:

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

describe('Form', () => {
  it('shows an alert when the form is submitted', () => {
  const { getByLabelText, getByText } = render(<Form />);
  const input = getByLabelText('Name:');
  const submitButton = getByText('Submit');
  fireEvent.change(input, { target: { value: 'John' } });
  fireEvent.click(submitButton);

  expect(window.alert).toHaveBeenCalledWith('You submitted: John');
  });
});


In this test, we render the `Form` component and get references to the input and submit button using `getByLabelText` and `getByText`. We simulate a change event on the input field with `fireEvent.change` and pass an object that contains the value we want to set for the input. We then simulate a click event on the submit button using `fireEvent.click`. Finally, we check if the `window.alert` method was called with the expected message “You submitted: John”. Note that we have to mock the `window.alert` method using `jest.spyOn` before running this test.

Example 4. Testing a Component with a Third-party Library

To test a component that uses react-data-grid, you can create a test file called Table.test.jsx and add the following code:

import React from 'react';
import { render } from '@testing-library/react';
import ReactDataGrid from 'react-data-grid';
import Table from './Table';

describe('Table', () => {
  it('renders a grid with data', () => {
    const data = [
      { id: 1, name: 'John', age: 25 },
      { id: 2, name: 'Jane', age: 30 },
      { id: 3, name: 'Bob', age: 40 },
    ];
    const columns = [
      { key: 'id', name: 'ID' },
      { key: 'name', name: 'Name' },
      { key: 'age', name: 'Age' },
    ];

    const { container } = render(<Table data={data} columns={columns} />);
    const grid = container.querySelector('.react-grid-Grid');

    expect(grid).toBeInTheDocument();
    expect(grid).toHaveClass('react-grid-Grid');
    expect(grid).toHaveAttribute('role', 'grid');
    expect(grid).toHaveAttribute('aria-rowcount', '4'); // 3 data rows + 1 header row
  });

  it('displays the correct data in the grid', () => {
    const data = [
      { id: 1, name: 'John', age: 25 },
      { id: 2, name: 'Jane', age: 30 },
      { id: 3, name: 'Bob', age: 40 },
    ];
    const columns = [
      { key: 'id', name: 'ID' },
      { key: 'name', name: 'Name' },
      { key: 'age', name: 'Age' },
    ];

    const { getAllByRole } = render(<Table data={data} columns={columns} />);
    const rows = getAllByRole('row');

    expect(rows.length).toBe(4); // 3 data rows + 1 header row

    // Check header row
    const headerRow = rows[0];
    const headerCells = headerRow.querySelectorAll('[role="columnheader"]');

    expect(headerCells.length).toBe(3);
    expect(headerCells[0]).toHaveTextContent('ID');
    expect(headerCells[1]).toHaveTextContent('Name');
    expect(headerCells[2]).toHaveTextContent('Age');

    // Check data rows
    const dataRows = rows.slice(1);
    const firstDataRowCells = dataRows[0].querySelectorAll('[role="gridcell"]');

    expect(firstDataRowCells.length).toBe(3);
    expect(firstDataRowCells[0]).toHaveTextContent('1');
    expect(firstDataRowCells[1]).toHaveTextContent('John');
    expect(firstDataRowCells[2]).toHaveTextContent('25');
  });
});

In this test file, we create two tests: one to check if the Table component renders a grid with the correct attributes and one to check if the grid displays the correct data.

To render the Table component, we pass in some sample data and column definitions as props. We then use the render function from the @testing-library/react package to get a reference to the container that holds the rendered component.

Example 5. Testing a Component with Uses a Service

Let’s say you have a component called PostsList which displays a list of blog posts fetched from a backend API. The component uses a service called postService to fetch the data from the backend.

To test the PostsList component, you can create a test file called PostsList.test.jsx and add the following code:

import React from 'react';
import { render, waitFor } from '@testing-library/react';
import PostsList from './PostsList';
import postService from './postService';

jest.mock('./postService');

describe('PostsList', () => {
  it('displays a list of blog posts', async () => {
    const mockPosts = [
      { id: 1, title: 'First Post', body: 'This is the first post' },
      { id: 2, title: 'Second Post', body: 'This is the second post' },
      { id: 3, title: 'Third Post', body: 'This is the third post' },
    ];
    postService.getPosts.mockResolvedValue(mockPosts);

    const { getByText } = render(<PostsList />);
    const firstPostTitle = await waitFor(() => getByText('First Post'));

    expect(firstPostTitle).toBeInTheDocument();
    expect(getByText('Second Post')).toBeInTheDocument();
    expect(getByText('Third Post')).toBeInTheDocument();
  });

  it('displays an error message if the posts fail to load', async () => {
    const errorMessage = 'Failed to load posts';
    postService.getPosts.mockRejectedValue(new Error(errorMessage));

    const { getByText } = render(<PostsList />);
    const error = await waitFor(() => getByText(errorMessage));

    expect(error).toBeInTheDocument();
  });
});

In this test file, we create two tests: one to check if the PostsList component displays a list of blog posts fetched from the backend, and one to check if the component displays an error message if the posts fail to load.

To mock the postService module, we use the jest.mock function to replace the module with a mock implementation. In this case, we mock the getPosts function to return a mock array of blog posts.

In the first test, we render the PostsList component and wait for the posts to load using the waitFor function from @testing-library/react. We then check if the component renders the expected post titles using the getByText function from @testing-library/react.

In the second test, we mock the getPosts function to throw an error, simulating a failed API call. We then render the PostsList component and wait for the error message to appear using the waitFor function. We then check if the error message is displayed using the getByText function.

Example 6. Testing a component that renders different templates based on conditions.

Here’s an example of a component that renders different components based on a condition and uses the react-render-plugin library for testing:

import React from 'react';
import { renderPlugin } from 'react-render-plugin';

const ComponentWithConditionalRendering = ({ type }) => {
  if (type === 'A') {
    return <ComponentA />;
  } else if (type === 'B') {
    return <ComponentB />;
  } else {
    return <ComponentC />;
  }
};

const ComponentA = () => {
  return <div>Component A</div>;
};

const ComponentB = () => {
  return <div>Component B</div>;
};

const ComponentC = () => {
  return <div>Component C</div>;
};

describe('ComponentWithConditionalRendering', () => {
  it('should render ComponentA when type is A', () => {
    const { getByText } = renderPlugin(
      <ComponentWithConditionalRendering type="A" />
    );
    expect(getByText('Component A')).toBeInTheDocument();
  });

  it('should render ComponentB when type is B', () => {
    const { getByText } = renderPlugin(
      <ComponentWithConditionalRendering type="B" />
    );
    expect(getByText('Component B')).toBeInTheDocument();
  });

  it('should render ComponentC when type is neither A nor B', () => {
    const { getByText } = renderPlugin(
      <ComponentWithConditionalRendering type="C" />
    );
    expect(getByText('Component C')).toBeInTheDocument();
  });
});

In this example, the ComponentWithConditionalRendering component takes a type prop and renders different components based on the value of the type prop. We are using the react-render-plugin library to test this component.

In our tests, we render the ComponentWithConditionalRendering component with different type props and check that the correct component is rendered based on the value of the type prop. We use the getByText method from react-render-plugin to check that the correct component is rendered based on its text content.

Note that in this example, we only have three possible types (A, B, or any other value), but this approach can be extended to handle more complex conditions and multiple components.

Example 7. Testing a .tsx component using react-testing-library

Here’s another example of a React component that renders different components based on different conditions and is tested using react-testing-library:

import React from 'react';
import { render } from 'react-testing-library';
import { LibraryComponent } from 'library';

const ComponentToTest = () => {
  const [isConditionMet, setIsConditionMet] = React.useState(false);

  return (
    <div>
      {isConditionMet ? (
        <div>Rendered when condition is true</div>
      ) : (
        <div>Rendered when condition is false</div>
      )}
      <button onClick={() => setIsConditionMet(!isConditionMet)}>
        Toggle Condition
      </button>
      <LibraryComponent />
    </div>
  );
};

describe('ComponentToTest', () => {
  it('renders the component from the library', () => {
    const { getByTestId } = render(<ComponentToTest />);
    expect(getByTestId('library-component')).toBeInTheDocument();
  });

  it('renders "Rendered when condition is false" when condition is false', () => {
    const { getByText } = render(<ComponentToTest />);
    expect(getByText('Rendered when condition is false')).toBeInTheDocument();
  });

  it('renders "Rendered when condition is true" when condition is true', () => {
    const { getByText, getByRole } = render(<ComponentToTest />);
    const toggleButton = getByRole('button');
    toggleButton.click();
    expect(getByText('Rendered when condition is true')).toBeInTheDocument();
  });
});

In this example, the ComponentToTest renders a button to toggle the isConditionMet state between true and false, and conditionally renders different components based on that state. The react-testing-library is used to render the component and make assertions about the rendered output in the test cases.

Example 8. An example of a test for a component that makes an API call using Axios and checks the HTTP status and response:

import React from 'react';
import axios from 'axios';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';

jest.mock('axios');

describe('MyComponent', () => {
  it('should display the data fetched from the API', async () => {
    const data = { id: 1, name: 'John Doe' };
    const response = { data, status: 200 };
    axios.get.mockResolvedValue(response);

    render(<MyComponent />);

    const idElement = await screen.findByText(`ID: ${data.id}`);
    const nameElement = await screen.findByText(`Name: ${data.name}`);

    expect(idElement).toBeInTheDocument();
    expect(nameElement).toBeInTheDocument();
    expect(axios.get).toHaveBeenCalledTimes(1);
    expect(axios.get).toHaveBeenCalledWith('https://example.com/api/data');
  });

  it('should display an error message if the API call fails', async () => {
    const error = new Error('API call failed');
    axios.get.mockRejectedValue(error);

    render(<MyComponent />);

    const errorElement = await screen.findByText('Error: API call failed');

    expect(errorElement).toBeInTheDocument();
    expect(axios.get).toHaveBeenCalledTimes(1);
    expect(axios.get).toHaveBeenCalledWith('https://example.com/api/data');
  });

  it('should display a loading message while the API call is in progress', async () => {
    axios.get.mockImplementation(() => new Promise(() => {}));

    render(<MyComponent />);

    const loadingElement = await screen.findByText('Loading...');

    expect(loadingElement).toBeInTheDocument();
    expect(axios.get).toHaveBeenCalledTimes(1);
    expect(axios.get).toHaveBeenCalledWith('https://example.com/api/data');
  });

  it('should handle a 404 response status', async () => {
    const errorResponse = {
      response: {
        status: 404,
        data: { message: 'Resource not found' }
      }
    };
    axios.get.mockRejectedValue(errorResponse);

    render(<MyComponent />);

    const errorElement = await screen.findByText('Error: Resource not found');

    expect(errorElement).toBeInTheDocument();
    expect(axios.get).toHaveBeenCalledTimes(1);
    expect(axios.get).toHaveBeenCalledWith('https://example.com/api/data');
  });

  it('should handle a 500 response status', async () => {
    const errorResponse = {
      response: {
        status: 500,
        data: { message: 'Internal server error' }
      }
    };
    axios.get.mockRejectedValue(errorResponse);

    render(<MyComponent />);

    const errorElement = await screen.findByText('Error: Internal server error');

    expect(errorElement).toBeInTheDocument();
    expect(axios.get).toHaveBeenCalledTimes(1);
    expect(axios.get).toHaveBeenCalledWith('https://example.com/api/data');
  });
});

In this example, we are testing a component called MyComponent that makes an API call using Axios. We are using Jest to mock the Axios library and simulate different API responses (successful, failed, 404, 500).


Now that you have all commonly used examples, it shouldn’t be too challenging to get started. However, if you’re wondering what are the common tests one should write for a component, here’s a cheat sheet

When testing a component, there are several types of tests you can write to ensure that it works as expected. Here are some common types of tests you should write for a component:

  1. Rendering test: This type of test checks if the component renders correctly. You can use functions from testing libraries like @testing-library/react to test if the component renders with the expected text, elements, and styles.
import React from 'react';
import { render } from '@testing-library/react';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
  it('renders with the expected text', () => {
    const { getByText } = render(<MyComponent text="Hello world" />);
    const textElement = getByText('Hello world');
    expect(textElement).toBeInTheDocument();
  });
});

In this example, we render the MyComponent component with a prop called text set to “Hello world”. We then use the getByText function from @testing-library/react to get the text element and check if it is in the document using the toBeInTheDocument function.

  1. Props test: This type of test checks if the component behaves correctly when receiving different props. You can use functions from testing libraries like @testing-library/react to test if the component renders correctly with different props.
import React from 'react';
import { render } from '@testing-library/react';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
  it('renders with the expected text', () => {
    const { getByText } = render(<MyComponent text="Hello world" />);
    const textElement = getByText('Hello world');
    expect(textElement).toBeInTheDocument();
  });

  it('renders with the default text if no text prop is provided', () => {
    const { getByText } = render(<MyComponent />);
    const textElement = getByText('Default text');
    expect(textElement).toBeInTheDocument();
  });
});

In this example, we add another test that checks if the MyComponent component renders with the default text if no text prop is provided.

  1. State test: This type of test checks if the component behaves correctly when its state changes. You can use functions from testing libraries like @testing-library/react to simulate user interactions and check if the component updates its state correctly.
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
  it('renders with the expected text', () => {
    const { getByText } = render(<MyComponent text="Hello world" />);
    const textElement = getByText('Hello world');
    expect(textElement).toBeInTheDocument();
  });

  it('updates the text when the button is clicked', () => {
    const { getByText } = render(<MyComponent text="Hello world" />);
    const buttonElement = getByText('Click me');
    fireEvent.click(buttonElement);
    const textElement = getByText('New text');
    expect(textElement).toBeInTheDocument();
  });
});

In this example, we add another test that checks if the MyComponent component updates its text when the button is clicked. We use the fireEvent.click function from @testing-library/react to simulate a user click on the button and then check if the text element is updated to “New text”.

  1. Lifecycle test: This type of test checks if the component behaves correctly during its lifecycle. You can use functions from testing libraries like jest to test if the component calls certain lifecycle methods at the right time.
import React from "react";
import { render } from "@testing-library/react";
import MyComponent from "./MyComponent";

describe("MyComponent", () => {
  it("renders with the expected text", () => {
    const { getByText } = render(<MyComponent text="Hello world" />);
    const textElement = getByText("Hello world");
    expect(textElement).toBeInTheDocument();
  });

  it("updates the text when the button is clicked", () => {
    const { getByText } = render(<MyComponent text="Hello world" />);
    const buttonElement = getByText("Click me");
    fireEvent.click(buttonElement);
    const textElement = getByText("New text");
    expect(textElement).toBeInTheDocument();
  });

  it("calls the componentDidMount method", () => {
    const componentDidMountSpy = jest.spyOn(
      MyComponent.prototype,
      "componentDidMount"
    );
    render(<MyComponent text="Hello world" />);
    expect(componentDidMountSpy).toHaveBeenCalled();
  });
});

In this example, we add another test that checks if the `MyComponent` component calls the `componentDidMount` method when it is mounted. We use the `jest.spyOn` function to spy on the `componentDidMount` method and then check if it has been called using the `toHaveBeenCalled` matcher. By writing these tests, you can ensure that your component works as expected and catches any bugs or unexpected behavior early on in the development process.

Another common test for a component is to test its interactions with external services or APIs. For example, if your component fetches data from a backend API, you can write a test to check if it correctly handles the response and displays the data.

Here’s an example:

import React from 'react';
import { render, waitFor } from '@testing-library/react';
import axios from 'axios';
import MyComponent from './MyComponent';

jest.mock('axios');

describe('MyComponent', () => {
  it('renders with data from the backend API', async () => {
    const responseData = {
      id: 1,
      name: 'John Doe',
      email: 'johndoe@example.com',
    };
    axios.get.mockResolvedValue({ data: responseData });
    const { getByText } = render(<MyComponent />);
    await waitFor(() => {
      const nameElement = getByText('Name: John Doe');
      const emailElement = getByText('Email: johndoe@example.com');
      expect(nameElement).toBeInTheDocument();
      expect(emailElement).toBeInTheDocument();
    });
  });
});

In this example, we use the jest.mock function to mock the axios library, which is used to make HTTP requests. We then use the mockResolvedValue method to set the response data for the mocked API request.

We then render the MyComponent component and use the waitFor function to wait for the API request to complete and for the component to render the data. We then use the getByText function to find elements in the component that contain the expected data and use the toBeInTheDocument matcher to check if they are present in the component.

By writing tests like these, you can ensure that your component works correctly with external services and APIs, and catches any errors or unexpected behavior early on in the development process.

Leave a Reply

Your email address will not be published. Required fields are marked *