Tests
Exemples
Apprenez à configurer Next.js avec des outils de test couramment utilisés : Cypress, Playwright et Jest avec React Testing Library.
Cypress
Cypress est un exécuteur de tests utilisé pour les tests End-to-End (E2E) et les tests de composants.
Démarrage rapide
Vous pouvez utiliser create-next-app
avec l'exemple with-cypress pour commencer rapidement.
npx create-next-app@latest --example with-cypress with-cypress-app
Configuration manuelle
Pour commencer avec Cypress, installez le package cypress
:
npm install --save-dev cypress
Ajoutez Cypress au champ scripts
du package.json
:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"cypress:open": "cypress open"
}
}
Exécutez Cypress pour la première fois pour générer des exemples utilisant leur structure de dossiers recommandée :
npm run cypress:open
Vous pouvez parcourir les exemples générés et la section Writing Your First Test de la documentation Cypress pour vous familiariser avec Cypress.
Dois-je utiliser des tests E2E ou des tests de composants ?
La documentation Cypress contient un guide sur la différence entre ces deux types de tests et quand il est approprié d'utiliser chacun.
Création de votre premier test E2E Cypress
Supposons les deux pages Next.js suivantes :
import Link from 'next/link'
export default function Home() {
return (
<nav>
<h1>Page d'accueil</h1>
<Link href="/about">À propos</Link>
</nav>
)
}
export default function About() {
return (
<div>
<h1>Page À propos</h1>
<Link href="/">Page d'accueil</Link>
</div>
)
}
Ajoutez un test pour vérifier que votre navigation fonctionne correctement :
describe('Navigation', () => {
it('should navigate to the about page', () => {
// Commencez depuis la page d'index
cy.visit('http://localhost:3000/')
// Trouvez un lien avec un attribut href contenant "about" et cliquez dessus
cy.get('a[href*="about"]').click()
// La nouvelle URL devrait inclure "/about"
cy.url().should('include', '/about')
// La nouvelle page devrait contenir un h1 avec "About page"
cy.get('h1').contains('About Page')
})
})
Vous pouvez utiliser cy.visit("/")
au lieu de cy.visit("http://localhost:3000/")
si vous ajoutez baseUrl: 'http://localhost:3000'
au fichier de configuration cypress.config.js
.
Création de votre premier test de composant Cypress
Les tests de composants construisent et montent un composant spécifique sans avoir à bundler toute votre application ou à lancer un serveur. Cela permet des tests plus performants qui fournissent toujours un retour visuel et la même API utilisée pour les tests E2E Cypress.
Bon à savoir : Comme les tests de composants ne lancent pas un serveur Next.js, les fonctionnalités comme
<Image />
etgetServerSideProps
qui dépendent d'un serveur disponible ne fonctionneront pas par défaut. Consultez la documentation Cypress Next.js pour des exemples de mise en œuvre de ces fonctionnalités dans les tests de composants.
Supposant les mêmes composants que dans la section précédente, ajoutez un test pour valider qu'un composant rend le résultat attendu :
import AboutPage from './about.js'
describe('<AboutPage />', () => {
it('should render and display expected content', () => {
// Montez le composant React pour la page À propos
cy.mount(<AboutPage />)
// La nouvelle page devrait contenir un h1 avec "About page"
cy.get('h1').contains('About Page')
// Validez qu'un lien avec l'URL attendue est présent
// *Suivre* le lien est mieux adapté à un test E2E
cy.get('a[href="/"]').should('be.visible')
})
})
Exécution de vos tests Cypress
Tests E2E
Comme les tests E2E Cypress testent une véritable application Next.js, ils nécessitent que le serveur Next.js soit en cours d'exécution avant de démarrer Cypress. Nous recommandons d'exécuter vos tests contre votre code de production pour mieux ressembler au comportement de votre application.
Exécutez npm run build
et npm run start
, puis exécutez npm run cypress -- --e2e
dans une autre fenêtre de terminal pour démarrer Cypress et exécuter votre suite de tests E2E.
Bon à savoir : Alternativement, vous pouvez installer le package
start-server-and-test
et l'ajouter au champscripts
dupackage.json
:"test": "start-server-and-test start http://localhost:3000 cypress"
pour démarrer le serveur de production Next.js conjointement avec Cypress. N'oubliez pas de reconstruire votre application après de nouveaux changements.
Tests de composants
Exécutez npm run cypress -- --component
pour démarrer Cypress et exécuter votre suite de tests de composants.
Préparation pour l'intégration continue (CI)
Vous aurez remarqué que l'exécution de Cypress jusqu'à présent a ouvert un navigateur interactif, ce qui n'est pas idéal pour les environnements CI. Vous pouvez également exécuter Cypress en mode headless en utilisant la commande cypress run
:
{
"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"
}
}
Vous pouvez en apprendre plus sur Cypress et l'intégration continue à partir de ces ressources :
- Documentation Cypress sur l'intégration continue
- Guide Cypress GitHub Actions
- Action GitHub officielle Cypress
- Discord Cypress
Playwright
Playwright est un framework de test qui vous permet d'automatiser Chromium, Firefox et WebKit avec une seule API. Vous pouvez l'utiliser pour écrire des tests End-to-End (E2E) et des tests d'intégration sur toutes les plateformes.
Démarrage rapide
Le moyen le plus rapide de commencer est d'utiliser create-next-app
avec l'exemple with-playwright. Cela créera un projet Next.js complet avec Playwright déjà configuré.
npx create-next-app@latest --example with-playwright with-playwright-app
Configuration manuelle
Vous pouvez également utiliser npm init playwright
pour ajouter Playwright à un projet NPM
existant.
Pour commencer manuellement avec Playwright, installez le package @playwright/test
:
npm install --save-dev @playwright/test
Ajoutez Playwright au champ scripts
du package.json
:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"test:e2e": "playwright test"
}
}
Création de votre premier test End-to-End Playwright
Supposant les deux pages Next.js suivantes :
import Link from 'next/link'
export default function Home() {
return (
<nav>
<Link href="/about">À propos</Link>
</nav>
)
}
export default function About() {
return (
<div>
<h1>Page À propos</h1>
</div>
)
}
Ajoutez un test pour vérifier que votre navigation fonctionne correctement :
import { test, expect } from '@playwright/test'
test('should navigate to the about page', async ({ page }) => {
// Commencez depuis la page d'index (baseURL est défini via webServer dans playwright.config.ts)
await page.goto('http://localhost:3000/')
// Trouvez un élément avec le texte 'About Page' et cliquez dessus
await page.click('text=About')
// La nouvelle URL devrait être "/about" (baseURL est utilisé ici)
await expect(page).toHaveURL('http://localhost:3000/about')
// La nouvelle page devrait contenir un h1 avec "About Page"
await expect(page.locator('h1')).toContainText('About Page')
})
import { test, expect } from '@playwright/test'
test('should navigate to the about page', async ({ page }) => {
// Commencez depuis la page d'index (baseURL est défini via webServer dans playwright.config.ts)
await page.goto('http://localhost:3000/')
// Trouvez un élément avec le texte 'About Page' et cliquez dessus
await page.click('text=About')
// La nouvelle URL devrait être "/about" (baseURL est utilisé ici)
await expect(page).toHaveURL('http://localhost:3000/about')
// La nouvelle page devrait contenir un h1 avec "About Page"
await expect(page.locator('h1')).toContainText('About Page')
})
Vous pouvez utiliser page.goto("/")
au lieu de page.goto("http://localhost:3000/")
, si vous ajoutez "baseURL": "http://localhost:3000"
au fichier de configuration playwright.config.ts
.
Exécution de vos tests Playwright
Comme Playwright teste une véritable application Next.js, il nécessite que le serveur Next.js soit en cours d'exécution avant de démarrer Playwright. Il est recommandé d'exécuter vos tests contre votre code de production pour mieux ressembler au comportement de votre application.
Exécutez npm run build
et npm run start
, puis exécutez npm run test:e2e
dans une autre fenêtre de terminal pour exécuter les tests Playwright.
Bon à savoir : Alternativement, vous pouvez utiliser la fonctionnalité
webServer
pour laisser Playwright démarrer le serveur de développement et attendre qu'il soit complètement disponible.
Exécution de Playwright en intégration continue (CI)
Playwright exécutera par défaut vos tests en mode headless. Pour installer toutes les dépendances Playwright, exécutez npx playwright install-deps
.
Vous pouvez en apprendre plus sur Playwright et l'intégration continue à partir de ces ressources :
- Premiers pas avec Playwright
- Utiliser un serveur de développement
- Playwright sur votre fournisseur CI
- Discord Playwright
Jest et React Testing Library
Jest et React Testing Library sont fréquemment utilisés ensemble pour les tests unitaires. Il existe trois façons de commencer à utiliser Jest dans votre application Next.js :
- En utilisant un de nos exemples de démarrage rapide
- Avec le compilateur Rust Next.js
- Avec Babel
Les sections suivantes expliqueront comment configurer Jest avec chacune de ces options :
Démarrage rapide
Vous pouvez utiliser create-next-app
avec l'exemple with-jest pour commencer rapidement avec Jest et React Testing Library :
npx create-next-app@latest --example with-jest with-jest-app
Configuration de Jest (avec le compilateur Rust)
Depuis la sortie de Next.js 12, Next.js dispose désormais d'une configuration intégrée pour Jest.
Pour configurer Jest, installez jest
, jest-environment-jsdom
, @testing-library/react
, @testing-library/jest-dom
:
npm install --save-dev jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom
Créez un fichier jest.config.mjs
à la racine de votre projet et ajoutez-y ce qui suit :
import nextJest from 'next/jest.js'
const createJestConfig = nextJest({
// Fournissez le chemin vers votre application Next.js pour charger next.config.js et les fichiers .env dans votre environnement de test
dir: './',
})
// Ajoutez toute configuration personnalisée à passer à Jest
/** @type {import('jest').Config} */
const config = {
// Ajoutez plus d'options de configuration avant chaque exécution de test
// setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testEnvironment: 'jest-environment-jsdom',
}
// createJestConfig est exporté de cette manière pour s'assurer que next/jest peut charger la configuration Next.js qui est asynchrone
export default createJestConfig(config)
Sous le capot, next/jest
configure automatiquement Jest pour vous, notamment :
- La configuration de
transform
en utilisant SWC - Le mock automatique des feuilles de style (
.css
,.module.css
, et leurs variantes scss), des imports d'images et denext/font
- Le chargement de
.env
(et toutes ses variantes) dansprocess.env
- L'ignorance de
node_modules
pour la résolution et les transformations des tests - L'ignorance de
.next
pour la résolution des tests - Le chargement de
next.config.js
pour les flags activant les transformations SWC
Bon à savoir : Pour tester directement les variables d'environnement, chargez-les manuellement dans un script de configuration séparé ou dans votre fichier
jest.config.js
. Pour plus d'informations, consultez Variables d'environnement de test.
Configuration de Jest (avec Babel)
Si vous choisissez de ne pas utiliser le Compilateur Rust, vous devrez configurer Jest manuellement et installer babel-jest
et identity-obj-proxy
en plus des packages mentionnés précédemment.
Voici les options recommandées pour configurer Jest avec Next.js :
module.exports = {
collectCoverage: true,
// sur Node 14.x, le fournisseur de couverture v8 offre une bonne vitesse et un rapport plus ou moins correct
coverageProvider: 'v8',
collectCoverageFrom: [
'**/*.{js,jsx,ts,tsx}',
'!**/*.d.ts',
'!**/node_modules/**',
'!<rootDir>/out/**',
'!<rootDir>/.next/**',
'!<rootDir>/*.config.js',
'!<rootDir>/coverage/**',
],
moduleNameMapper: {
// Gérer les imports CSS (avec modules CSS)
// https://jestjs.io/docs/webpack#mocking-css-modules
'^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
// Gérer les imports CSS (sans modules CSS)
'^.+\\.(css|sass|scss)$': '<rootDir>/__mocks__/styleMock.js',
// Gérer les imports d'images
// https://jestjs.io/docs/webpack#handling-static-assets
'^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp|svg)$/i': `<rootDir>/__mocks__/fileMock.js`,
// Gérer les alias de modules
'^@/components/(.*)$': '<rootDir>/components/$1',
},
// Ajouter plus d'options de configuration avant chaque exécution de test
// setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/'],
testEnvironment: 'jsdom',
transform: {
// Utiliser babel-jest pour transpiler les tests avec le preset next/babel
// https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
'^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }],
},
transformIgnorePatterns: [
'/node_modules/',
'^.+\\.module\\.(css|sass|scss)$',
],
}
Vous pouvez en apprendre davantage sur chaque option de configuration dans la documentation de Jest.
Gestion des feuilles de style et des imports d'images
Les feuilles de style et les images ne sont pas utilisées dans les tests, mais leur importation peut causer des erreurs, il faut donc les simuler. Créez les fichiers de simulation référencés dans la configuration ci-dessus - fileMock.js
et styleMock.js
- dans un répertoire __mocks__
:
module.exports = {
src: '/img.jpg',
height: 24,
width: 24,
blurDataURL: 'data:image/png;base64,imagedata',
}
module.exports = {}
Pour plus d'informations sur la gestion des ressources statiques, veuillez consulter la documentation de Jest.
Optionnel : Étendre Jest avec des matchers personnalisés
@testing-library/jest-dom
inclut un ensemble de matchers personnalisés pratiques comme .toBeInTheDocument()
, facilitant l'écriture des tests. Vous pouvez importer ces matchers pour chaque test en ajoutant l'option suivante au fichier de configuration Jest :
setupFilesAfterEnv: ['<rootDir>/jest.setup.js']
Puis, dans jest.setup.js
, ajoutez l'import suivant :
import '@testing-library/jest-dom'
extend-expect
a été supprimé dans lav6.0
, donc si vous utilisez@testing-library/jest-dom
avant la version 6, vous devrez importer@testing-library/jest-dom/extend-expect
à la place.
Si vous avez besoin d'ajouter plus d'options de configuration avant chaque test, il est courant de les ajouter dans le fichier jest.setup.js
ci-dessus.
Optionnel : Imports absolus et alias de modules
Si votre projet utilise des alias de modules, vous devrez configurer Jest pour résoudre les imports en faisant correspondre l'option paths
dans le fichier jsconfig.json
avec l'option moduleNameMapper
dans le fichier jest.config.js
. Par exemple :
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "node",
"baseUrl": "./",
"paths": {
"@/components/*": ["components/*"]
}
}
}
moduleNameMapper: {
'^@/components/(.*)$': '<rootDir>/components/$1',
}
Création de vos tests :
Ajouter un script de test à package.json
Ajoutez l'exécutable Jest en mode watch aux scripts du package.json
:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"test": "jest --watch"
}
}
jest --watch
relancera les tests lorsqu'un fichier est modifié. Pour plus d'options CLI de Jest, veuillez consulter la documentation de Jest.
Créez vos premiers tests
Votre projet est maintenant prêt à exécuter des tests. Suivez la convention de Jest en ajoutant des tests dans le dossier __tests__
à la racine de votre projet.
Par exemple, nous pouvons ajouter un test pour vérifier si le composant <Home />
affiche correctement un titre :
import { render, screen } from '@testing-library/react'
import Home from '../pages/index'
import '@testing-library/jest-dom'
describe('Home', () => {
it('renders a heading', () => {
render(<Home />)
const heading = screen.getByRole('heading', {
name: /welcome to next\.js!/i,
})
expect(heading).toBeInTheDocument()
})
})
Optionnellement, ajoutez un test de snapshot pour suivre les changements inattendus dans votre composant <Home />
:
import { render } from '@testing-library/react'
import Home from '../pages/index'
it('renders homepage unchanged', () => {
const { container } = render(<Home />)
expect(container).toMatchSnapshot()
})
Bon à savoir : Les fichiers de test ne doivent pas être inclus dans le routeur Pages car tous les fichiers à l'intérieur du routeur Pages sont considérés comme des routes.
Exécution de votre suite de tests
Exécutez npm run test
pour lancer votre suite de tests. Après que vos tests passent ou échouent, vous verrez une liste de commandes interactives de Jest qui seront utiles lorsque vous ajouterez plus de tests.
Pour approfondir, ces ressources pourraient vous être utiles :
- Documentation de Jest
- Documentation de React Testing Library
- Testing Playground - utilisez les bonnes pratiques de test pour faire correspondre les éléments.
Packages et exemples de la communauté
La communauté Next.js a créé des packages et des articles qui pourraient vous être utiles :
- next-router-mock pour Storybook.
- Test Preview Vercel Deploys with Cypress par Gleb Bahmutov.
Pour plus d'informations sur ce qu'il faut lire ensuite, nous recommandons :
- pages/basic-features/environment-variables#test-environment-variables