loading...
Cover image for DOM testing Next.js applications

DOM testing Next.js applications

toomuchdesign profile image Andrea Carraro Updated on ・4 min read

This article analyses the current status of DOM tests in Next.js and presents a utility library (next-page-tester) to get back DOM integration tests alongside Next.js apps.

The missing tile

Next.js comes with an outstanding tool belt out of the box, providing any web project with great dev experience and productivity since day one.

The value provided by Next.js is truly priceless, but there's a missing tile: DOM integration testing (React Testing Library or Enzyme tests, to put it simple) is quite uneffective and fragmented when it comes to Next.js.

Let's see why.

Why

An average Next.js project is made of disconnected pieces which are glued together by Next.js internals on next dev or next build.

This means less boilerplate code 👍but also no explicit relations among separate parts 😔. In other words: only Next.js knows how to put your application together.

This is reflected in how unit tests are written Next.js apps: separate tests for each single part of the application and optimistically mocking what's in-between.

Let's be more explicit. This involves:

  • testing individual page components providing the expected server-side generated props
  • testing pages' data fetching methods (getServerSideProps and getStaticProps) providing the expected context object
  • mocking NextRouter object wit relevant current route data (path, params, querystring...) when the tested page makes use of Next's Link, useRouter or withRouter
  • hoping that page file names are 100% correct, since Next.js relies on those to configure file system routing
  • rendering custom App and Document components, if the case

All this is feasible but, where are the times when we could write integration tests by rendering the whole components tree in Node.js with JSDOM?

Write tests. Not too many. Mostly integration.

Alt Text

https://twitter.com/rauchg/status/807626710350839808

Since business logic is spread among different disconnected places (and the fact that Next.js runs a web server), the currently suggested way of testing Next.js applications consists of running e2e tests against a fully fledged instance of the app.

With the rise of tools like Cypress and Test Café, e2e tester lives became significantly easier but, as everything in life, there's no silver bullet™ and browser tests make no exception. It'd be cool to be able to grab the right tool for the right task.

The internet is packed with resources documenting the trade-offs of different testing strategies. It's mostly a matter of cost, speed and determinism. This is a notorious article by Kent C. Dodds to name one 🔗.

Alt Text

DOM Integration tests for Next.js

Ideally, a promising integration testing routine might consist of testing Next.js apps by route: given a route path, I receive the matching page element ready to be rendered with any DOM testing library:

const Page = getNextJsPage('/blog/1');
render(Page);

In order to get to such testing routine we need to replicate part of of Next.js glue:

  • resolving provided routes into the matching page component
  • calling Next.js data fetching methods (getServerSideProps, getInitialProps or getStaticProps)
  • set up the expected mocked next/router provider
  • wrapping page with custom _app component
  • instantiating page component with the expected props

I put together this logic in next-page-tester, an utility library which enables approaching tests like:

import { render, screen } from '@testing-library/react';
import { getPage } from 'next-page-tester';

describe('Blog page', () => {
  it('renders blog page', async () => {
    const Page = await getPage({
      route: '/blog/1',
      pagesDirectory: process.cwd() + '/src/pages',
    });

    render(Page);
    expect(screen.getByText('Blog')).toBeInTheDocument();
  });
});

next-page-tester is available on NPM and aims to make DOM integration tests first class citizens in Next.js.

It's written in Typescript, fully tested and open to receive any feedback from curious Next.js users.

Posted on by:

toomuchdesign profile

Andrea Carraro

@toomuchdesign

Front-end engineer @uala. Previously @XING_de @MosaicoonSpa. Human.

Discussion

pic
Editor guide
 

Thanks for the article, testing Next.js applications is not a subject that is often talked about. I added your article in the latest Next.js News: twitter.com/vvoyer/status/13182876...