Testing
Guide pour écrire et exécuter des tests dans Wagoo.
Framework de test
Wagoo utilise Vitest pour les tests unitaires et Playwright pour les tests E2E.
Tests unitaires avec Vitest
Écrire un test simple
Créez lib/utils.test.ts :
import { describe, it, expect } from 'vitest'
import { sum, formatDate } from './utils'
describe('Utils', () => {
it('should sum two numbers', () => {
expect(sum(2, 3)).toBe(5)
})
it('should format date', () => {
expect(formatDate(new Date('2024-01-01'))).toBe('01/01/2024')
})
})Lancer les tests
# Lancer tous les tests
pnpm test
# En mode watch (relance au changement)
pnpm test:watch
# Un fichier spécifique
pnpm test lib/utils.test.ts
# Pattern
pnpm test --grep "sum"Tests React avec Vitest
Tester un composant
Créez components/Button.test.tsx :
import { render, screen } from '@testing-library/react'
import { describe, it, expect } from 'vitest'
import Button from './Button'
describe('Button', () => {
it('renders button with text', () => {
render(<Button>Click me</Button>)
expect(screen.getByRole('button')).toHaveTextContent('Click me')
})
it('calls onClick when clicked', async () => {
const handleClick = vi.fn()
render(<Button onClick={handleClick}>Click</Button>)
await user.click(screen.getByRole('button'))
expect(handleClick).toHaveBeenCalled()
})
})Dépendances
pnpm add -D @testing-library/react @testing-library/jest-dom vitest @vitest/uiTests API
Tester une route API
Créez app/api/hello.test.ts :
import { describe, it, expect } from 'vitest'
describe('GET /api/hello', () => {
it('returns hello message', async () => {
const res = await fetch('http://localhost:3000/api/hello')
const data = await res.json()
expect(res.status).toBe(200)
expect(data.message).toBe('Hello')
})
})Tests E2E avec Playwright
Configuration
playwright.config.ts :
import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
testDir: './e2e',
fullyParallel: true,
retries: 1,
use: {
baseURL: 'http://localhost:3000',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
],
webServer: {
command: 'pnpm dev',
port: 3000,
},
})Écrire un test E2E
Créez e2e/auth.spec.ts :
import { test, expect } from '@playwright/test'
test.describe('Authentication', () => {
test('should sign up', async ({ page }) => {
// Aller Ă la page sign up
await page.goto('/auth/sign-up')
// Remplir le formulaire
await page.fill('input[name="email"]', 'test@test.com')
await page.fill('input[name="password"]', 'password123')
// Soumettre
await page.click('button[type="submit"]')
// Vérifier la redirection
await expect(page).toHaveURL('/dashboard')
})
test('should sign in', async ({ page }) => {
// Déjà enregistré, essayer de se connecter
await page.goto('/auth/sign-in')
await page.fill('input[name="email"]', 'test@test.com')
await page.fill('input[name="password"]', 'password123')
await page.click('button[type="submit"]')
await expect(page).toHaveURL('/dashboard')
})
})Lancer les tests E2E
# Lancer tous les tests E2E
pnpm test:e2e
# Mode headed (voir le navigateur)
pnpm test:e2e --headed
# Un navigateur spécifique
pnpm test:e2e --project=chromium
# Mode debug
pnpm test:e2e --debugCoverage (Couverture de code)
Générer le rapport
# Générer la couverture
pnpm test --coverage
# Affiche un rapport
# coverage/
# ├── index.html
# └── coverage.jsonVoir le rapport
# Ouvrir le rapport
open coverage/index.htmlTarget de couverture :
- âś… > 80% fonctions
- âś… > 75% lignes
- âś… > 70% branches
Bonnes pratiques
Tests unitaires
// âś… Bon
it('should validate email format', () => {
expect(isValidEmail('test@test.com')).toBe(true)
expect(isValidEmail('invalid')).toBe(false)
})
// ❌ Mauvais
it('email validation works', () => {
// Trop vague
expect(isValidEmail('test')).toBeDefined()
})Test async
// âś… Bon
it('should fetch data', async () => {
const data = await fetchData()
expect(data).toBeDefined()
})
// ❌ Mauvais
it('should fetch data', (done) => {
fetchData().then(data => {
expect(data).toBeDefined()
done()
})
})Mocking
import { vi } from 'vitest'
it('should call API', async () => {
const mockFetch = vi.fn().mockResolvedValue({
json: () => ({ id: 1 })
})
// Test avec mock
const result = await fetchData(mockFetch)
expect(result.id).toBe(1)
expect(mockFetch).toHaveBeenCalled()
})Dépannage
Tests ne trouvent pas les modules
# Reconstruire
pnpm test --clearCache
# Regénérer Prisma
pnpm prisma generateTests trop lents
Solutions :
// Ne pas faire de vraies requĂŞtes
// Mocker les dépendances
vi.mock('./api')
// Paralléliser
pnpm test --parallel
// Skip les tests lents
it.skip('slow test', () => {
// ...
})Erreur “fetch is not defined”
Ajouter Ă vitest.config.ts :
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
environment: 'node',
globals: true,
}
})CI/CD - GitHub Actions
Fichier .github/workflows/test.yml :
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'pnpm'
- run: pnpm install
- run: pnpm test
- run: pnpm test:e2eProchaines étapes
→ Code Standards → Contributing
Last updated on