# 4.1.1: Frontend React Testing

## Learning Objectives

1. Understand that we can test React Components on our Frontend Application
2. Gain some insight in how to use React Testing Library to test our code
3. Implement programatic tests on a React Component&#x20;

## Introduction

React Testing Library is the suggested testing library for testing React Applications and Components. It contains a set of utilities and API's that enable developers to write tests which simulate user behaviour and interaction with their React Components. Developers can then assert and check if the expected behaviour is executed.&#x20;

Lets try to develop a high-level understanding of how React Testing Library operates:

1. Rendering the Component:
   1. Firstly we will need to render the Component that we want to test using React Testing Library's `render()` method. The `render()` method creates a virtual dom and mounts the component in memory, it will then return the object that contains references to the rendered element.&#x20;
2. Finding Elements:
   1. After you have rendered the component you are able to use the `getBy*()` or `queryBy*()` methods that can be extracted from the React Testing Library. These methods help developers to find specific elements rendered on the Component, they search for Component elements by targeting attributes such as text content or other characteristics.&#x20;
3. Simulate User Interactions:
   1. Once you have successfully selected your elements that your user will interact with you are able to simulate user interactions by calling the `fireEvent()` method, which comes from React Testing Library. We are able to trigger all types of events such as clicks, form submissions and key presses.
4. Assert Results:
   1. To actually check if your components are working in the correct manner, we are able to utilise the `expect()` function from Vitest in this case. With this function we can make assertions concerning the behaviour of the tested Component. We are able to check if the specific element is present, if an event has occurred or if a components state has been updated.

We are able to leverage React Testing Library such that we can test out Components as a user would interact with our application.&#x20;

### Setup

Fork and clone Rocket's [testing-react repo](https://github.com/rocketacademy/react_testing_2024)  to follow along. We have implemented some simple tests within a React environment. Once you have cloned the repository onto your local machine install all of the dependencies with the command

```
npm install
```

Following this you will be able to run React tests by running the command below within the root of the project directory.

```
npm test
```

## Testing React Components

React applications created with the create-react-app contain a basic test that validates the boiler plate code that is provided, it just ensure that the App component loads an contains some text, learn react. We have left this test inside Rocket's testing-react repo.

When developing Frontend applications it is useful to test your component to ensure that your application is rendering the appropriate components, to test if data API's are called onload, or event to check if buttons are firing off the correct functions. To do all of this we can use React Testing Library, it provides a set of utilities that enable developers to test React Components. With this library we are able to simulate how users interact with the application meaning, we are able to write tests that follow user behaviour. These tests ensure that our Components are working as expected within our application.

Here's an example of how to test a button click and the actions that occur after:

{% code title="Button.test.js" lineNumbers="true" %}

```javascript
import { describe, expect, test } from "vitest";
import { screen, render, fireEvent } from "@testing-library/react";
import Button from "../Components/Button";

describe("Button", async () => {
  test("should call onClick when clicked", async () => {
    render(<Button />);

    const button = screen.getByText("Click me");

    expect(screen.getByText("Please click")).toBeInTheDocument();

    await fireEvent.click(button);

    expect(screen.queryByText("Please click above")).not.toBeInTheDocument();

    expect(screen.getByText("Clicked = 1")).toBeInTheDocument();
  });
});
```

{% endcode %}

In the example above we are testing the `Button` Component that has an `onClick` property. The test makes use of the `render` method from React Testing Library, it is used to render the Component. We then select the button with the `getByText` utility function. We are able to check if the correct text is showing on load, by checking if "Please click above" is being rendered. We then use the `fireEvent.click()` method from React Testing Library to simulate a clickEvent, on our rendered Component. This allows us to check the outcome of the click event, in this case, the removal of the string 'Please click above' that is replaced with "Clicked = 1" which is the current count.

It should be noted that if your `Button` Component triggers an action after the click, like calling an API, we are able to apply additional assertions to test that the additional triggers were fired off as expected. You can see how we can achieve this below. &#x20;

{% code title="ButtonComplex.test.js" lineNumbers="true" %}

```javascript
import { describe, expect, test, vi } from "vitest";
import { render, fireEvent, screen } from "@testing-library/react";
import Button from "../Components/ComplexButton";
import axios from "axios";

vi.mock("axios");

describe("Button", () => {

  test("should call onClick and fetch data when clicked", async () => {
  
    render(<Button />);
    
    const button = screen.getByText("Click me");
    
    fireEvent.click(button);
    
    expect(axios.get).toHaveBeenCalledTimes(1);
    
    expect(axios.get).toBeCalledWith(
      "https://pokeapi.co/api/v2/pokemon/geodude"
    );
  });
});
```

{% endcode %}

In the above example we are testing if `Button` Component fire's off an API call. To test if our code is actually calling an API we have to import the `axios` library and mock it using the `vi.mock()` function. Next we render out our `Button` Component, we use the `getByText` method to find the `Button` so that we can fire off a click event, using `fireEvent.click()`. We can then assert that the mocked `axios.get()` has been called  using Jest's `toHaveBeenCalledTimes` moreover we can test that it has been invoked along with its expected argument.&#x20;

When we want to test if an API has been called following a click event witin React Testing Library, we will need to mock the API library, in the case above `axios`. We can then assert that the method has been called with the correct arguments and is actually invoked. This approach means that you can test the functionality of the component without making the API call during tests.&#x20;

### Additional Help

If you would like to explore React Testing Library some more, checkout [this video series](https://www.youtube.com/watch?v=7dTTFW7yACQ)!
