We're planting a tree for every job application! Click here toΒ learn more

How to test your Next.js pages and components with Jest

James Calmus

24 Jun 2021

β€’

5 min read

How to test your Next.js pages and components with Jest
  • JavaScript

Introduction

In my last article, I wrote about setting up a simple Next.js project with Jest, a great JavaScript testing library that is perfect for beginners who have never tested their code before.

Jest itself can be great for testing a wide range of JavaScript files, but when it comes to React – the framework Next.js sits upon – we can use tools that build on the test runner's functionality to target our components by rendering them, something Jest doesn't do out of the box.

Luckily, Jest has an active and passionate community, which means there are a number of incredibly useful tools that can extend Jest's API to allow the test runner to be used for just this purpose.

One such tool is React Testing Library, an open-source tool that I'm going to walk you through setting up and using with your Next.js project.

React Testing Library

Let's start where we left off, with the project we created in the last article. Alternatively, you can grab the code from here.

First we're going to install the packages we need to start testing our components and pages.

Open your terminal, navigate to the project folder and type the following command:

$ yarn add -D @testing-library/jest-dom @testing-library/react

This will install the two Testing Library packages as developer dependencies, i.e. packages that aren't needed for your production site to work.

In this project, we have a single page, index.js, which you can see by running yarn dev in the terminal.

You can visit localhost:3000 in your browser when your terminal shows the following message:

event - compiled successfully

You should see a page appear with the title "Welcome to Next.js!" and four large links.

This is the page we're going to test with our newly-installed package, React Testing Library.

You can close your browser window now and type Ctrl+C into your terminal. This should kill the yarn dev instance. We don't need it to run our tests.

If you've used the template repository I linked to above, you should have a tests folder with a single file in it, my-first-test.test.js. If not, create the folder in your root directory. Inside, we're going to make a new file. Call it my-first-react-test.test.js.

my-first-react-test

Jest, our test runner, has a very specific vocabulary when it comes to writing tests.

Tests can be split up into describe blocks, a defined scope that helps us to identify the feature or component we're testing, and it blocks, a function that encloses a specific test for that feature or component. If that doesn't make a lot of sense to you right now, it will shortly.

Let's write our first describe block.

Type the following into my-first-react-test.test.js:

// my-first-react-test.test.js

describe("Index page", () => {
});

As you can see, the describe block takes two arguments: the first is a string that represents the feature or component we're testing. In this case, that's the index page.

The second argument is a callback function, which encloses the series of tests we're going to run. Let's add one.

Add an it block inside the describe block that looks like the below:

// my-first-react-test.test.js

describe("Index page", () => {
  it("should render", () => {
  });
});

Again, the it block takes two arguments, a description and a callback which will contain the assertions that will determine whether the test will succeed or fail.

You can start to see from simply reading the test above that there is a logic to Jest's vocabulary. We are describing a feature or component and asserting that it should do something.

In this case, we're going to be checking that the index page renders, which is a good initial test for us to write. If that test fails alongside more complex tests when you eventually get to writing them, you know something fundamental has gone wrong with your component, your test runner or your set-up.

Let's add some detail to our test.

Installing React Testing Library gives us access to a render function we can call to, well, render the component we'd like to test. In this case, that's the index page.

First, import a few essentials at the top of the test file:

// my-first-react-test.test.js
import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';
...

We need the first import, jest-dom, to add some extra functionality to Jest. In particular, we're going to be making use of a function called toBeInTheDocument that will help us to assert our component is rendering correctly. This is called a custom matcher.

We're also importing the render function from @testing-library/react which allows us to take control of the testing environment and specify exactly what should be exposed to Jest, and the screen object, which makes finding our rendered component and its children incredibly easy.

Next, let's import the index page so we can test it:

// my-first-react-test.test.js
...
import Index from '../pages/index';
...

Inside the it block, call the render function with the Index page as an argument, just as you would write it to render it in a React component:

// my-first-react-test.test.js
...
describe("Index page", () => {
    it("should render", () => {
        render(<Index />);
    });
});
...

Let's add an expectation.

If you look in the index.js file, you'll see we have a component that looks something like this:

// pages/index.js
export default function Home() {
    return (
        <div className={styles.container}>
            <Head>
            ...
            </Head>
            <main className={styles.main}>
            ...
            </main>
        </div>
    )
}

Our index page is split into two sections, Head and main. The former is a Next.js component that allows you to define the structure of your page's metadata directly in your jsx, and the latter is an HTML tag that defines the main content of your HTML page. Because our test is about the page rendering correctly, we're going to search for the main tag in our test.

Head back to my-first-react-test.test.js and, underneath your render function, create a variable called main that is the result of searching for the role "main" on the screen:

// my-first-react-test.test.js
...
it("should render", () => {
    render(<Index />);
    const main = screen.getByRole("main");
});
...

Now, we want to expect that element to have appeared in our render:

// my-first-react-test.test.js
...
it("should render", () => {
    render(<Index />);
    const main = screen.getByRole("main");
    expect(main).toBeInTheDocument();
});
...

Now, let's test this is all working. In your terminal, type the following command:

$ yarn jest my-first-react-test

You should see a green badge with the word PASS alongside the name of our test. This shows that our page is rendering correctly and our expectation has been met.

If you'd like to prove this is the case, change the expectation to the opposite assertion, that the main element is not in the document, like so:

// my-first-react-test.test.js
...
it("should render", () => {
    render(<Index /);
    const main = screen.getByRole("main");
    expect(main).not.toBeInTheDocument();
});
...

Run the test again, and this time you'll see the word FAIL, in your terminal along with a detailed description of what went wrong. In this case, our output shows that main was in the document, wrapping the body of our page.

Remove the not to enable your test to pass again, and you're now ready to go on and write more complex tests with Jest and Next.js.

Conclusion

The test you've written above is incredibly simple, but it shows us that you can render a React component in a test and expect something of it.

For more detail on the expectations you can make with our setup, I recommend reading the jest-dom docs which has a full list of all of the custom matchers included in it.

I'd also recommend reading the React Testing Library docs which give you more information on how to use the library, and how to use tools like data-testid to expose your components to your tests.

If you'd like the code we produced in this guide, you can find a repository here.

Did you like this article?

James Calmus

See other articles by James

Related jobs

See all

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Related articles

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

β€’

12 Sep 2021

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

β€’

12 Sep 2021

WorksHub

CareersCompaniesSitemapFunctional WorksBlockchain WorksJavaScript WorksAI WorksGolang WorksJava WorksPython WorksRemote Works
hello@works-hub.com

Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ

108 E 16th Street, New York, NY 10003

Subscribe to our newsletter

Join over 111,000 others and get access to exclusive content, job opportunities and more!

Β© 2024 WorksHub

Privacy PolicyDeveloped by WorksHub