Skip to Content
Wagoo SaaS 1.0.25 is released 🎉
08 DevelopmentTestingTesting

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/ui

Tests 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 --debug

Coverage (Couverture de code)

Générer le rapport

# Générer la couverture pnpm test --coverage # Affiche un rapport # coverage/ # ├── index.html # └── coverage.json

Voir le rapport

# Ouvrir le rapport open coverage/index.html

Target 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 generate

Tests 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:e2e

Prochaines étapes

→ Code Standards → Contributing

Last updated on