Configuración de Jest con Next.js

Jest y React Testing Library se usan frecuentemente juntos para pruebas unitarias (Unit Testing) y pruebas de instantáneas (Snapshot Testing). Esta guía mostrará cómo configurar Jest con Next.js y escribir tus primeras pruebas.

Es bueno saberlo: Dado que los Componentes de Servicio async son nuevos en el ecosistema de React, Jest actualmente no los soporta. Aunque aún puedes ejecutar pruebas unitarias para Componentes de Servicio y Cliente síncronos, recomendamos usar pruebas E2E para componentes async.

Inicio rápido

Puedes usar create-next-app con el ejemplo with-jest de Next.js para comenzar rápidamente:

Terminal
npx create-next-app@latest --example with-jest with-jest-app

Configuración manual

Desde el lanzamiento de Next.js 12, Next.js ahora tiene configuración integrada para Jest.

Para configurar Jest, instala jest y los siguientes paquetes como dependencias de desarrollo:

Terminal
npm install -D jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom
# o
yarn add -D jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom
# o
pnpm install -D jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom

Genera un archivo básico de configuración de Jest ejecutando el siguiente comando:

Terminal
npm init jest@latest
# o
yarn create jest@latest
# o
pnpm create jest@latest

Esto te guiará a través de una serie de preguntas para configurar Jest en tu proyecto, incluyendo la creación automática de un archivo jest.config.ts|js.

Actualiza tu archivo de configuración para usar next/jest. Este transformador tiene todas las opciones de configuración necesarias para que Jest funcione con Next.js:

import type { Config } from 'jest'
import nextJest from 'next/jest.js'

const createJestConfig = nextJest({
  // Proporciona la ruta a tu aplicación Next.js para cargar next.config.js y archivos .env en tu entorno de prueba
  dir: './',
})

// Añade cualquier configuración personalizada para pasar a Jest
const config: Config = {
  coverageProvider: 'v8',
  testEnvironment: 'jsdom',
  // Añade más opciones de configuración antes de ejecutar cada prueba
  // setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}

// createJestConfig se exporta de esta manera para asegurar que next/jest pueda cargar la configuración de Next.js que es asíncrona
export default createJestConfig(config)
const nextJest = require('next/jest')

/** @type {import('jest').Config} */
const createJestConfig = nextJest({
  // Proporciona la ruta a tu aplicación Next.js para cargar next.config.js y archivos .env en tu entorno de prueba
  dir: './',
})

// Añade cualquier configuración personalizada para pasar a Jest
const config = {
  coverageProvider: 'v8',
  testEnvironment: 'jsdom',
  // Añade más opciones de configuración antes de ejecutar cada prueba
  // setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}

// createJestConfig se exporta de esta manera para asegurar que next/jest pueda cargar la configuración de Next.js que es asíncrona
module.exports = createJestConfig(config)

Internamente, next/jest está configurando automáticamente Jest para ti, incluyendo:

  • Configurar transform usando el Next.js Compiler
  • Simulación automática de hojas de estilo (.css, .module.css, y sus variantes scss), importaciones de imágenes y next/font
  • Cargar .env (y todas sus variantes) en process.env
  • Ignorar node_modules de la resolución y transformación de pruebas
  • Ignorar .next de la resolución de pruebas
  • Cargar next.config.js para las banderas que habilitan transformaciones SWC

Es bueno saberlo: Para probar variables de entorno directamente, cárgalas manualmente en un script de configuración separado o en tu archivo jest.config.ts. Para más información, consulta Variables de entorno de prueba.

Opcional: Manejo de importaciones absolutas y alias de módulos

Si tu proyecto usa Alias de módulos, necesitarás configurar Jest para resolver las importaciones haciendo coincidir la opción paths en el archivo jsconfig.json con la opción moduleNameMapper en el archivo jest.config.js. Por ejemplo:

tsconfig.json o jsconfig.json
{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "bundler",
    "baseUrl": "./",
    "paths": {
      "@/components/*": ["components/*"]
    }
  }
}
jest.config.js
moduleNameMapper: {
  // ...
  '^@/components/(.*)$': '<rootDir>/components/$1',
}

Opcional: Extender Jest con comparadores personalizados

@testing-library/jest-dom incluye un conjunto de comparadores personalizados convenientes como .toBeInTheDocument() que facilitan la escritura de pruebas. Puedes importar los comparadores personalizados para cada prueba añadiendo la siguiente opción al archivo de configuración de Jest:

setupFilesAfterEnv: ['<rootDir>/jest.setup.ts']
setupFilesAfterEnv: ['<rootDir>/jest.setup.js']

Luego, dentro de jest.setup.ts, añade la siguiente importación:

import '@testing-library/jest-dom'
import '@testing-library/jest-dom'

Es bueno saberlo:extend-expect fue eliminado en v6.0, así que si estás usando @testing-library/jest-dom antes de la versión 6, necesitarás importar @testing-library/jest-dom/extend-expect en su lugar.

Si necesitas añadir más opciones de configuración antes de cada prueba, puedes añadirlas al archivo jest.setup.js mencionado anteriormente.

Añade un script de prueba a package.json:

Finalmente, añade un script de prueba de Jest a tu archivo package.json:

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "test": "jest",
    "test:watch": "jest --watch"
  }
}

jest --watch volverá a ejecutar las pruebas cuando un archivo cambie. Para más opciones de CLI de Jest, consulta la documentación de Jest.

Creando tu primera prueba:

Tu proyecto ahora está listo para ejecutar pruebas. Crea una carpeta llamada __tests__ en el directorio raíz de tu proyecto.

Por ejemplo, podemos añadir una prueba para verificar si el componente <Page /> renderiza correctamente un encabezado:

import Link from 'next/link'

export default function Home() {
  return (
    <div>
      <h1>Home</h1>
      <Link href="/about">About</Link>
    </div>
  )
}
__tests__/page.test.jsx
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import Page from '../app/page'

describe('Page', () => {
  it('renderiza un encabezado', () => {
    render(<Page />)

    const heading = screen.getByRole('heading', { level: 1 })

    expect(heading).toBeInTheDocument()
  })
})

Opcionalmente, añade una prueba de instantánea (snapshot test) para detectar cambios inesperados en tu componente:

__tests__/snapshot.js
import { render } from '@testing-library/react'
import Page from '../app/page'

it('renderiza la página de inicio sin cambios', () => {
  const { container } = render(<Page />)
  expect(container).toMatchSnapshot()
})

Ejecutando tus pruebas

Luego, ejecuta el siguiente comando para ejecutar tus pruebas:

Terminal
npm run test
# o
yarn test
# o
pnpm test

Recursos adicionales

Para más información, estos recursos pueden ser útiles: