Useful Cheatsheetsusefulcheatsheets.com
Next.js Testing
Chapter 23 · Page 161
Intermediate

Next.js Testing

Test Next.js apps with Jest, React Testing Library, and E2E testing with Playwright or Cypress.

TL;DR

  1. 01Use Jest for unit and integration tests of functions and components.
  2. 02Use React Testing Library to test components from the user perspective.
  3. 03Use Playwright or Cypress for end-to-end testing full user workflows.

Tips

  1. 01Aim for a test pyramid: many unit tests, some integration tests, and a few critical E2E tests to balance speed and confidence.
  2. 02Use Mock Service Worker (MSW) to intercept network requests in integration-style tests, since it mimics real API behavior more closely than manual <code>jest.mock</code> calls.

Warnings

  1. 01Avoid testing implementation details and focus on user behavior, since refactored code will break tests that depend on internal structure.
  2. 02E2E tests that wait on fixed timeouts instead of specific conditions or selectors become flaky, since real network and render timing varies between runs.
Notes
Useful Cheatsheetsusefulcheatsheets.com
Next.js Testing
Chapter 23 · Page 162
Intermediate

Next.js Testing

(continued)

Setup and Jest Basics

  • Next.js doesn't ship a test runner out of the box — install Jest and configure it with the built-in Next.js preset to get started.
    npm install --save-dev jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom
  • Create jest.config.js using the built-in Next.js Jest preset.
    const nextJest = require("next/jest");
    const createJestConfig = nextJest({ dir: "./" });
    module.exports = createJestConfig({ testEnvironment: "jsdom" });
  • Create test files with .test.js or .spec.js extensions.
    // utils.test.js
    import { add } from "./utils";
    it("adds two numbers", () => {
      expect(add(2, 3)).toBe(5);
    });
  • Run tests in watch mode to re-run on file changes.
    npm test -- --watch
  • Use describe to group related tests and it for individual test cases. Jest runs tests in parallel by default.
Notes
Useful Cheatsheetsusefulcheatsheets.com
Next.js Testing
Chapter 23 · Page 163
Intermediate

Next.js Testing

(continued)

Testing Components

  • Tests that check internal state break on every refactor — import React Testing Library to test components the way a user actually sees them.
    import { render, screen } from "@testing-library/react";
    import Button from "./Button";
    
    it("renders a button", () => {
      render(<Button>Click me</Button>);
      const btn = screen.getByRole("button", { name: /click me/i });
      expect(btn).toBeInTheDocument();
    });
  • Query elements using semantic methods like getByRole, getByText.
    screen.getByRole("button", { name: /submit/i });
    screen.getByLabelText("Email");
    screen.getByText("Welcome");
  • Test user interactions with userEvent instead of fireEvent.
    import userEvent from "@testing-library/user-event";
    const user = userEvent.setup();
    await user.click(button);
  • Avoid testing implementation details, focus on what users see and do.
Notes
Useful Cheatsheetsusefulcheatsheets.com
Next.js Testing
Chapter 23 · Page 164
Intermediate

Next.js Testing

(continued)

Testing API Routes

  • No server needed to test an API route — create separate test files that call route handlers directly with mocked request and response objects.
    import { createMocks } from "node-mocks-http";
    import handler from "./api/hello";
    
    it("returns a greeting", async () => {
      const { req, res } = createMocks({
        method: "GET"
      });
      
      await handler(req, res);
      expect(res._getStatusCode()).toBe(200);
      expect(JSON.parse(res._getData())).toHaveProperty("message");
    });
  • Use a library like node-mocks-http to mock request and response.
  • Test different HTTP methods and status codes.
  • Mock dependencies like databases or external APIs.
Notes
Useful Cheatsheetsusefulcheatsheets.com
Next.js Testing
Chapter 23 · Page 165
Intermediate

Next.js Testing

(continued)

Mocking and Fixtures

  • A flaky network call shouldn't fail your test suite — mock external API calls to keep tests fast and isolated.
    jest.mock("./api", () => ({
      fetchUser: jest.fn(() => Promise.resolve({ id: 1, name: "Alice" }))
    }));
  • Use fixtures to provide consistent test data.
    const mockUser = { id: 1, name: "Alice", email: "alice@example.com" };
    
    it("displays user info", () => {
      render(<Profile user={mockUser} />);
      expect(screen.getByText("Alice")).toBeInTheDocument();
    });
  • Mock the App Router navigation module for components using useRouter or usePathname.
    jest.mock("next/navigation", () => ({
      useRouter: jest.fn(() => ({ push: jest.fn(), replace: jest.fn() })),
      usePathname: jest.fn(() => "/"),
      useSearchParams: jest.fn(() => new URLSearchParams())
    }));
  • Mocking prevents external dependencies from slowing tests.
Notes
Useful Cheatsheetsusefulcheatsheets.com
Next.js Testing
Chapter 23 · Page 166
Intermediate

Next.js Testing

(continued)

E2E Testing

  • Unit tests can't catch a broken checkout flow across pages — use Playwright or Cypress for end-to-end testing of full workflows.
    // playwright.spec.ts
    import { test, expect } from "@playwright/test";
    
    test("user can sign up", async ({ page }) => {
      await page.goto("http://localhost:3000");
      await page.fill("input[name=email]", "test@example.com");
      await page.click("button:has-text('Sign Up')");
      await expect(page).toHaveURL("/dashboard");
    });
  • E2E tests run in a real browser and test the entire application.
  • Run E2E tests against a deployed environment before releasing.
  • E2E tests are slower but catch integration issues that unit tests miss.
    npx playwright test
  • Use E2E tests for critical user paths like checkout or login.
Notes
Useful Cheatsheetsusefulcheatsheets.com
Next.js Testing
Chapter 23 · Page 167
Intermediate

Next.js Testing

(FAQ)

FAQ

Install jest, jest-environment-jsdom, @testing-library/react, and @testing-library/jest-dom, then add a jest.config.js using Next.js's built-in preset: const nextJest = require('next/jest'); module.exports = nextJest({ dir: './' })({testEnvironment: 'jsdom'}).

Both work well, but Playwright is generally preferred for new projects due to faster execution, built-in multi-browser support, and better handling of Next.js server components. Cypress has a more mature ecosystem and better real-time debugging.

Import the handler function directly and call it with mocked req/res objects using libraries like node-mocks-http, then assert on res.status() and res.json() values without spinning up a server.

This usually means the element is conditionally rendered or loaded asynchronously—use async queries like findByText or waitFor instead of getByText so the test waits for the DOM to update after data fetching or state changes.

Mock the next/navigation module (App Router) or next/router (Pages Router) using jest.mock: jest.mock('next/navigation', () => ({ useRouter: () => ({ push: jest.fn(), pathname: '/' }) })) at the top of your test file.