How to test a component in React

Testing means verifying a component displays what we expect without doing it manually.

For example, let's assume that we have a component in React that displays 'Hello world':

jsx
import React from 'react';

const Hello = () => {
    
    return(
        
        <h1>Hello world</h1>
        
    );
    
}

export default Hello;

If we open the browser, we expect to read a blank page with a 'Hello world' title.

Imagine you had 1000 components like this one, each one displaying a different message. Instead of opening 1000 tabs on the browser and verifying each message, you could automate the process by writing tests.

Render and verify

Doing a test means to render and verify. Going back to the previous example:

jsx
// 1. Render <Hello/>

// 2. Verify that the text inside <h1> is 'Hello world'

To do tests, you don't need to install anything, only create the tests.

Let's go back to the previous example and create a new folder /src/Tests and a file called Hello.test.js:

jsx
import React                              from "react";
import { render, unmountComponentAtNode } from "react-dom";
import { act }                            from "react-dom/test-utils";

/* Component to test ------------------------------------------------- */
import Hello                              from './Hello';
/* ------------------------------------------------------------------- */

let container = null;

beforeEach(() => {
    
    container = document.createElement("div");
    document.body.appendChild(container);
    
});

afterEach(() => {
    
    unmountComponentAtNode(container);
    container.remove();
    container = null;
    
});

// 1. Render <Hello/>

// 2. Verify that the text inside <h1> is 'Hello world'

Before each test, we create a container to render a component. After the test is done, we will unmount the component and remove the container.

Now we can render and verify the result:

jsx
it("displays message correctly", () => {
   
    // 1. Render <Hello/>
    act(() => {
        
        render(<Hello/>, container);
        
    });
    
    // 2. Verify that the text inside <h1> is 'Hello world'
    expect(document.querySelector('h1').textContent).toBe('Hello world');
    
});

We are using:

  1. it(): Name of the test
  2. act(): Action to do
  3. expect(): Result expected

So, Hello.test.js would be:

jsx
import React                              from "react";
import { render, unmountComponentAtNode } from "react-dom";
import { act }                            from "react-dom/test-utils";

/* Component to test ------------------------------------------------- */
import Hello                              from './Hello';
/* ------------------------------------------------------------------- */

let container = null;

beforeEach(() => {
    
    container = document.createElement("div");
    document.body.appendChild(container);
    
});

afterEach(() => {
    
    unmountComponentAtNode(container);
    container.remove();
    container = null;
    
});

it("displays message correctly", () => {
   
    // 1. Render <Hello/>
    act(() => {
        
        render(<Hello/>, container);
        
    });
    
    // 2. Verify that the text inside <h1> is 'Hello world'
    expect(document.querySelector('h1').textContent).toBe('Hello world');
    
});

Run a test

Now if run on the Terminal:

terminal
npm test

You'll see that the test passed! You can try to see what would happen if you changed the message expected.

Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.