Testing Next.js 14 and Supabase

Friends, I have to be honest, I hate writing tests.

Not because it's hard, but because it's tedious and yes, we've got AI tools to help with that now, blah blah blah, but it doesn't stop the time-sink that is getting the testing frameworks up and running, and then update hell when something breaks due to a framework or package update. Infuriatingly fragile AF.

For reasons, I upgraded Next.js 12 to 14. I don't want to get into it, but suffice it to say, I tried 13 at the time and I didn't have the energy to deal with things being bleeding edge and not stable. Things look a bit more solid now, but unfortunately, on top of the cruft that goes with a framework upgrade, when I moved up to 14 and the app router, my tests stopped working. Woe.

vitest

I was getting next/headers cookieStore errors when instantiating a server-side Supabase client in tests. Adding this to vitest.setup.ts fixed it:

Loading...
vi.mock("next/headers", async (importOriginal) => { return { cookies: () => { return { get: (name: string) => { return { value: "cookie", }; }, }; }, }; });

Route handlers

I was manually mocking NextApiRequest and didn't seem to work with NextRequest. But I found a thing that literally Just Works(TM) (after a relatively small amount of finagling) for testing route handlers: next-test-api-route-handler. So dreamy.

The documentation is pretty thorough, but these are the two things I specifically needed:

Test dynamic routes:

Loading...
dynamic: 'force-dynamic', // /api/segment/[slug] url: '/api/segment/slug', paramsPatcher(params) { params.slug = 'test-slug'; },

Add an authorisation header:

Loading...
requestPatcher(request) { request.headers.set('authorization', 'Bearer token'); },

Throw in msw for remote calls and you're off to the races.

Published May 29, 2024