We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies.

We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies. Less

We use cookies and other tracking technologies... More

Login or register
to apply for this job!

Login or register
to save this job!

Login or register
to save interesting jobs!

Login or register
to get access to all your job applications!

Login or register to start contributing with an article!

Login or register
to see more jobs from this company!

Login or register
to boost this post!

Show some love to the author of this blog by giving their post some rocket fuel ๐Ÿš€.

Login or register to search for your ideal job!

Login or register to start working on this issue!

Engineers who find a new job through WorksHub average a 15% increase in salary ๐Ÿš€

Blog hero image

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

James Calmus 28 January, 2021 | 5 min read

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.

Author's avatar
James Calmus
JavaScript developer at Digital Theatre.
    angular
    javascript
    CSS
    node.js
    Design
    Sketch
    Ionic

Related Issues

cosmos / gaia
  • Open
  • 0
  • 0
  • Intermediate
  • Go
cosmos / gaia
  • Open
  • 0
  • 0
  • Intermediate
  • Go
cosmos / ibc
  • Open
  • 0
  • 0
  • Intermediate
  • TeX
cosmos / ibc
cosmos / ibc
  • Open
  • 0
  • 0
  • Intermediate
  • TeX
WorksHub / client
  • Started
  • 0
  • 28
  • Intermediate
  • Clojure
  • $150
viebel / klipse-clj
viebel / klipse-clj
  • Started
  • 0
  • 4
  • Intermediate
  • Clojure
viebel / klipse
  • Started
  • 0
  • 1
  • Intermediate
  • Clojure
viebel / klipse
  • 1
  • 0
  • Intermediate
  • Clojure

Get hired!

Sign up now and apply for roles at companies that interest you.

Engineers who find a new job through WorksHub average a 15% increase in salary.

Start with GitHubStart with Stack OverflowStart with Email