Настройка Cypress с Next.js

Cypress — это инструмент для запуска сквозных (E2E) и компонентных тестов. На этой странице вы узнаете, как настроить Cypress с Next.js и написать первые тесты.

Предупреждение:

  • Для компонентного тестирования Cypress в настоящее время не поддерживает Next.js версии 14 и async серверные компоненты. Эти проблемы отслеживаются. Пока компонентное тестирование работает с Next.js версии 13, а для async серверных компонентов рекомендуется использовать E2E-тестирование.
  • Cypress в настоящее время не поддерживает TypeScript версии 5 с moduleResolution:"bundler". Эта проблема отслеживается.

Ручная настройка

Для ручной настройки Cypress установите cypress как dev-зависимость:

Терминал
npm install -D cypress
# или
yarn add -D cypress
# или
pnpm install -D cypress

Добавьте команду open Cypress в поле scripts файла package.json:

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "cypress:open": "cypress open"
  }
}

Запустите Cypress впервые, чтобы открыть интерфейс тестирования:

Терминал
npm run cypress:open

Вы можете выбрать настройку E2E-тестирования и/или компонентного тестирования. При выборе любого из этих вариантов автоматически создадутся файл cypress.config.js и папка cypress в вашем проекте.

Создание первого E2E-теста в Cypress

Убедитесь, что ваш файл cypress.config.js содержит следующую конфигурацию:

cypress.config.ts
import { defineConfig } from 'cypress'

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {},
  },
})
cypress.config.js
const { defineConfig } = require('cypress')

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {},
  },
})

Затем создайте два новых файла Next.js:

pages/index.js
import Link from 'next/link'

export default function Home() {
  return (
    <div>
      <h1>Главная</h1>
      <Link href="/about">О нас</Link>
    </div>
  )
}
pages/about.js
import Link from 'next/link'

export default function About() {
  return (
    <div>
      <h1>О нас</h1>
      <Link href="/">Главная</Link>
    </div>
  )
}

Добавьте тест для проверки работы навигации:

cypress/e2e/app.cy.js
describe('Навигация', () => {
  it('должна переходить на страницу "О нас"', () => {
    // Начинаем с главной страницы
    cy.visit('http://localhost:3000/')

    // Находим ссылку с атрибутом href, содержащим "about", и кликаем по ней
    cy.get('a[href*="about"]').click()

    // Новый URL должен содержать "/about"
    cy.url().should('include', '/about')

    // Новая страница должна содержать заголовок h1 с текстом "О нас"
    cy.get('h1').contains('О нас')
  })
})

Запуск E2E-тестов

Cypress имитирует действия пользователя в вашем приложении, что требует запущенного сервера Next.js. Рекомендуется запускать тесты против production-сборки, чтобы поведение максимально соответствовало реальному.

Выполните npm run build && npm run start для сборки Next.js-приложения, затем в другом терминале запустите npm run cypress:open, чтобы начать E2E-тестирование.

Полезно знать:

  • Вы можете использовать cy.visit("/") вместо cy.visit("http://localhost:3000/"), добавив baseUrl: 'http://localhost:3000' в файл конфигурации cypress.config.js.
  • Альтернативно, можно установить пакет start-server-and-test для одновременного запуска production-сервера Next.js и Cypress. После установки добавьте "test": "start-server-and-test start http://localhost:3000 cypress" в поле scripts файла package.json. Не забудьте пересобрать приложение после внесения изменений.

Создание первого компонентного теста в Cypress

Компонентные тесты собирают и монтируют конкретный компонент без необходимости сборки всего приложения или запуска сервера.

Выберите Component Testing в приложении Cypress, затем выберите Next.js как фронтенд-фреймворк. В проекте создастся папка cypress/component, а файл cypress.config.js обновится для поддержки компонентного тестирования.

Убедитесь, что ваш файл cypress.config.js содержит следующую конфигурацию:

cypress.config.ts
import { defineConfig } from 'cypress'

export default defineConfig({
  component: {
    devServer: {
      framework: 'next',
      bundler: 'webpack',
    },
  },
})
cypress.config.js
const { defineConfig } = require('cypress')

module.exports = defineConfig({
  component: {
    devServer: {
      framework: 'next',
      bundler: 'webpack',
    },
  },
})

Используя те же компоненты из предыдущего раздела, добавьте тест для проверки их отображения:

cypress/component/about.cy.js
import AboutPage from '../../pages/about'

describe('<AboutPage />', () => {
  it('должен отображаться и показывать ожидаемый контент', () => {
    // Монтируем React-компонент страницы "О нас"
    cy.mount(<AboutPage />)

    // Страница должна содержать заголовок h1 с текстом "О нас"
    cy.get('h1').contains('О нас')

    // Проверяем видимость ссылки с ожидаемым URL
    // *Переход* по ссылке лучше тестировать в E2E-тестах
    cy.get('a[href="/"]').should('be.visible')
  })
})

Полезно знать:

  • Cypress пока не поддерживает компонентное тестирование для async серверных компонентов. Рекомендуется использовать E2E-тестирование.
  • Поскольку компонентные тесты не требуют сервера Next.js, такие функции, как <Image />, зависящие от сервера, могут не работать "из коробки".

Запуск компонентных тестов

Выполните npm run cypress:open в терминале, чтобы запустить Cypress и компонентные тесты.

Непрерывная интеграция (CI)

Помимо интерактивного тестирования, вы можете запускать Cypress в headless-режиме с помощью команды cypress run, что лучше подходит для CI-сред:

package.json
{
  "scripts": {
    //...
    "e2e": "start-server-and-test dev http://localhost:3000 \"cypress open --e2e\"",
    "e2e:headless": "start-server-and-test dev http://localhost:3000 \"cypress run --e2e\"",
    "component": "cypress open --component",
    "component:headless": "cypress run --component"
  }
}

Дополнительные ресурсы по Cypress и непрерывной интеграции: