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

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

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

  • Версии Cypress ниже 13.6.3 не поддерживают TypeScript версии 5 с moduleResolution:"bundler". Однако эта проблема была исправлена в Cypress версии 13.6.3 и выше. cypress v13.6.3

Быстрый старт

Вы можете использовать create-next-app с примером with-cypress, чтобы быстро начать работу.

Терминал
npx create-next-app@latest --example with-cypress with-cypress-app

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

Для ручной настройки 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 в первый раз, чтобы открыть тестовый набор Cypress:

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

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

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

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

import { defineConfig } from 'cypress'

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

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

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

app/page.js
import Link from 'next/link'

export default function Page() {
  return (
    <div>
      <h1>Home</h1>
      <Link href="/about">About</Link>
    </div>
  )
}
app/about/page.js
import Link from 'next/link'

export default function Page() {
  return (
    <div>
      <h1>About</h1>
      <Link href="/">Home</Link>
    </div>
  )
}

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

cypress/e2e/app.cy.js
describe('Navigation', () => {
  it('should navigate to the about page', () => {
    // Начинаем с главной страницы
    cy.visit('http://localhost:3000/')

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

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

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

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

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

Запустите npm run build && npm run start для сборки Next.js-приложения, затем в другом окне терминала запустите npm run cypress:open, чтобы начать работу с Cypress и запустить набор 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 имеет следующую конфигурацию:

import { defineConfig } from 'cypress'

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

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

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

cypress/component/about.cy.tsx
import Page from '../../app/page'

describe('<Page />', () => {
  it('should render and display expected content', () => {
    // Монтируем React-компонент для главной страницы
    cy.mount(<Page />)

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

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

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

  • Cypress в настоящее время не поддерживает компонентное тестирование для асинхронных серверных компонентов (Server Components). Мы рекомендуем использовать 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 и непрерывной интеграции из этих ресурсов: