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 affects the way unit tests for Next.js apps are written: isolated tests targeting different parts 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
andgetStaticProps
) providing the expectedcontext
object -
mocking
NextRouter
object with relevant current route data (path
,params
,querystring
...) when the tested page makes use of Next'sLink
,useRouter
orwithRouter
- 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.
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 popular article by Kent C. Dodds to name one 🔗.
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 tested 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 Next.js glue:
- resolving provided routes into the matching page component
- calling Next.js data fetching methods (
getServerSideProps
,getInitialProps
orgetStaticProps
) - set up the expected mocked
next/router
provider - wrapping page with custom
_app
/_document
component - instantiating page component with the expected props
- Emulate client side navigation via
Link
,router.push
,router.replace
I put together this logic in next-page-tester, an utility library which enables approaching tests like:
import { screen, fireEvent } from '@testing-library/react';
import { getPage } from 'next-page-tester';
describe('Blog page', () => {
it('renders blog page', async () => {
const { render } = await getPage({
route: '/blog/1',
});
render();
expect(screen.getByText('Blog')).toBeInTheDocument();
fireEvent.click(screen.getByText('Link'));
await screen.findByText('Linked page');
});
});
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. Hop over to next-page-tester
GitHub page to see how it works or lend hand :).
Top comments (6)
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...
nice! man
Amazing stuff buddy, I was looking for something like that :) Any chance you need a hand with the project? I'd like to contribute :)
Hi Maciek! We definitely encourage and support external contributions. We wouldn't be able to follow Next.js evolution without the help of next-page-tester's users.
You're welcome on board.
This looks like a great approach. Very excited to give it a go.
This is really great, I had been struggling with aforementioned issues when I discovered this!