# Ejecuta pruebas de Next.js en un contenedor


## Prerrequisitos

Completa todas las secciones anteriores de esta guía, comenzando con [Contenerizar una aplicación Next.js](/guides/nextjs/run-tests/containerize/).

## Descripción general

Las pruebas son una parte crítica del proceso de desarrollo. In esta sección, aprenderás a:

- Ejecutar pruebas unitarias usando Vitest (o Jest) dentro de un contenedor Docker.
- Ejecutar lint (por ejemplo, ESLint) dentro de un contenedor Docker.
- Usar Docker Compose para ejecutar pruebas y lint en un entorno aislado y reproducible.

El [proyecto de ejemplo](https://github.com/kristiyan-velkov/docker-nextjs-sample) utiliza [Vitest](https://vitest.dev/) con [Testing Library](https://testing-library.com/) para pruebas de componentes. Puedes usar la misma configuración o seguir la configuración alternativa de Jest más adelante.

---

## Ejecutar pruebas durante el desarrollo

El [proyecto de ejemplo](https://github.com/kristiyan-velkov/docker-nextjs-sample) ya incluye lint (ESLint) y pruebas de ejemplo (Vitest, `app/page.test.tsx`). Si estás usando la aplicación de ejemplo, puedes pasar directamente al **Paso 3: Actualizar compose.yaml** y ejecutar las pruebas o lint con los comandos a continuación. Si estás usando tu propio proyecto, sigue los pasos de instalación y configuración para agregar los paquetes y scripts.

El ejemplo incluye un archivo de prueba en:

```text
app/page.test.tsx
```

Este archivo utiliza Vitest y React Testing Library para verificar el comportamiento de los componentes de la página.

### Paso 1: Instalar Vitest y React Testing Library (proyectos personalizados)

Si estás usando un proyecto personalizado y aún no has agregado las herramientas de prueba necesarias, instálalas ejecutando:

```console
$ npm install --save-dev vitest @vitejs/plugin-react @testing-library/react @testing-library/dom jsdom
```

Luego, actualiza la sección de scripts de tu archivo `package.json` para incluir:

```json
"scripts": {
  "test": "vitest",
  "test:run": "vitest run"
}
```

Para lint, agrega un script `lint` (y opcionalmente `lint:fix`). Por ejemplo, con [ESLint](https://eslint.org/):

```json
"scripts": {
  "test": "vitest",
  "test:run": "vitest run",
  "lint": "eslint .",
  "lint:fix": "eslint . --fix"
}
```

El proyecto de ejemplo utiliza `eslint` and `eslint-config-next` para Next.js. Instálalos en un proyecto personalizado con:

```console
$ npm install --save-dev eslint eslint-config-next @eslint/eslintrc
```

Crea un archivo de configuración de ESLint (por ejemplo, `eslint.config.cjs`) en la raíz de tu proyecto con las reglas de Next.js y los ignores globales:

```js
const { defineConfig, globalIgnores } = require("eslint/config");
const { FlatCompat } = require("@eslint/eslintrc");

const compat = new FlatCompat({ baseDirectory: __dirname });

module.exports = defineConfig([
  ...compat.extends(
    "eslint-config-next/core-web-vitals",
    "eslint-config-next/typescript"
  ),
  globalIgnores([
    ".next/**",
    "out/**",
    "build/**",
    "next-env.d.ts",
    "node_modules/**",
    "eslint.config.cjs",
  ]),
]);
```

---

### Paso 2: Configurar Vitest (proyectos personalizados)

Si estás usando un proyecto personalizado, crea un archivo `vitest.config.ts` en la raíz de tu proyecto (que coincida con el del [proyecto de ejemplo](https://github.com/kristiyan-velkov/docker-nextjs-sample)):

```ts
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  test: {
    environment: "jsdom",
    setupFiles: "./vitest.setup.ts",
    globals: true,
  },
});
```

Crea un archivo `vitest.setup.ts` en la raíz de tu proyecto:

```ts
import "@testing-library/jest-dom/vitest";
```

> [!NOTE]
> Vitest funciona muy bien con Next.js y ofrece una ejecución rápida y soporte para ESM. Para más detalles, consulta la [documentación de pruebas de Next.js](https://nextjs.org/docs/app/building-your-application/testing) y las [docs de Vitest](https://vitest.dev/).

### Paso 3: Actualizar compose.yaml

Agrega los servicios `nextjs-test` y `nextjs-lint` a tu archivo `compose.yaml`. En el proyecto de ejemplo, estos servicios utilizan el perfil `tools` para que no se inicien con un `docker compose up` normal. Ambos reutilizan `Dockerfile.dev` y ejecutan el comando de prueba o lint:

```yaml
services:
  nextjs-prod-standalone:
    build:
      context: .
      dockerfile: Dockerfile
    image: nextjs-sample:prod
    container_name: nextjs-sample-prod
    ports:
      - "3000:3000"

  nextjs-dev:
    build:
      context: .
      dockerfile: Dockerfile.dev
    image: nextjs-sample:dev
    container_name: nextjs-sample-dev
    ports:
      - "3000:3000"
    environment:
      - WATCHPACK_POLLING=true
    develop:
      watch:
        - action: sync
          path: .
          target: /app
          ignore:
            - node_modules/
            - .next/
        - action: rebuild
          path: package.json

  nextjs-test:
    build:
      context: .
      dockerfile: Dockerfile.dev
    image: nextjs-sample:dev
    container_name: nextjs-sample-test
    command:
      [
        "sh",
        "-c",
        "if [ -f package-lock.json ]; then npm run test:run 2>/dev/null || npm run test -- --run; elif [ -f yarn.lock ]; then yarn test:run 2>/dev/null || yarn test --run; elif [ -f pnpm-lock.yaml ]; then pnpm run test:run; else npm run test -- --run; fi",
      ]
    profiles:
      - tools

  nextjs-lint:
    build:
      context: .
      dockerfile: Dockerfile.dev
    image: nextjs-sample:dev
    container_name: nextjs-sample-lint
    command:
      [
        "sh",
        "-c",
        "if [ -f package-lock.json ]; then npm run lint; elif [ -f yarn.lock ]; then yarn lint; elif [ -f pnpm-lock.yaml ]; then pnpm lint; else npm run lint; fi",
      ]
    profiles:
      - tools
```

Los servicios `nextjs-test` y `nextjs-lint` reutilizan el mismo `Dockerfile.dev` utilizado para el [desarrollo](/guides/nextjs/run-tests/develop/) y sobrescriben el comando predeterminado para ejecutar las pruebas o lint. La directiva `profiles: [tools]` significa que estos servicios solo se ejecutan cuando usas la opción `--profile tools`.

Después de completar los pasos anteriores, el directorio de tu proyecto debería contener:

```text
├── docker-nextjs-sample/
│ ├── Dockerfile
│ ├── Dockerfile.dev
│ ├── .dockerignore
│ ├── compose.yaml
│ ├── vitest.config.ts
│ ├── vitest.setup.ts
│ ├── next.config.ts
│ └── README.Docker.md
```

### Paso 4: Ejecutar las pruebas

Para ejecutar tu suite de pruebas dentro del contenedor, ejecuta desde la raíz de tu proyecto:

```console
$ docker compose --profile tools run --rm nextjs-test
```

Este comando hará lo siguiente:
- Iniciará el servicio `nextjs-test` (debido a `--profile tools`).
- Ejecutará tu script de prueba (`test:run` o `test -- --run`) en el mismo entorno de desarrollo.
- Eliminará el contenedor después de que se completen las pruebas ([`docker compose run --rm`](/reference/cli/docker/compose/run/)).

> [!NOTE]
> Para obtener más información sobre los comandos y perfiles de Compose, consulta la [referencia de CLI de Compose](/reference/cli/docker/compose/).

### Paso 5: Ejecutar lint en el contenedor

Para ejecutar tu linter (por ejemplo, ESLint) dentro del contenedor, usa el servicio `nextjs-lint` con el mismo perfil `tools`:

```console
$ docker compose --profile tools run --rm nextjs-lint
```

Este comando hará lo siguiente:
- Iniciará el servicio `nextjs-lint` (debido a `--profile tools`).
- Ejecutará tu script de lint (`npm run lint`, `yarn lint` o `pnpm lint` dependiendo de tu archivo de bloqueo) en el mismo entorno de desarrollo.
- Eliminará el contenedor una vez completado el lint.

Asegúrate de que tu `package.json` incluya un script `lint`. El proyecto de ejemplo ya tiene `"lint": "eslint ."` y `"lint:fix": "eslint . --fix"`; para un proyecto personalizado, agrega lo mismo e instala `eslint` y `eslint-config-next` si es necesario.

---

## Resumen

En esta sección, aprendiste a ejecutar pruebas unitarias para tu aplicación Next.js dentro de un contenedor Docker usando Vitest y Docker Compose.

Lo que lograste:
- Instalaste y configuraste Vitest y React Testing Library para probar componentes de Next.js.
- Creaste los servicios `nextjs-test` and `nextjs-lint` en `compose.yaml` (con el perfil `tools`) para aislar la ejecución de pruebas y lint.
- Reutilizaste el `Dockerfile.dev` de desarrollo para asegurar la consistencia entre los entornos de dev, test y lint.
- Ejecutaste pruebas dentro del contenedor usando `docker compose --profile tools run --rm nextjs-test`.
- Ejecutaste lint dentro del contenedor usando `docker compose --profile tools run --rm nextjs-lint`.
- Garantizaste pruebas y análisis de código (linting) confiables y repetibles en todos los entornos sin depender de la configuración de la máquina local.

---

## Recursos relacionados

Explora las referencias oficiales y las mejores prácticas para perfeccionar tu flujo de trabajo de pruebas con Docker:

- [Referencia de Dockerfile](/reference/dockerfile/) – Conoce todas las instrucciones y la sintaxis de Dockerfile.
- [Mejores prácticas para escribir Dockerfiles](/develop/develop-images/dockerfile_best-practices/) – Escribe Dockerfiles eficientes, fáciles de mantener y seguros.
- [Referencia del archivo de Compose](/compose/compose-file/) – Conoce la sintaxis completa y las opciones disponibles para configurar servicios en `compose.yaml`.  
- [Referencia de CLI de `docker compose run`](/reference/cli/docker/compose/run/) – Ejecuta comandos puntuales en un contenedor de servicio.
- [Documentación de pruebas de Next.js](https://nextjs.org/docs/app/building-your-application/testing) – Guía oficial de pruebas de Next.js.

---

## Próximos pasos

A continuación, aprenderás cómo configurar un flujo de trabajo (pipeline) de CI/CD utilizando GitHub Actions para construir y probar automáticamente tu aplicación Next.js en un entorno contenerizado. Esto asegura que tu código sea validado en cada push (empuje) o pull request (solicitud de extracción), manteniendo la consistencia y fiabilidad en todo tu flujo de trabajo de desarrollo.

