Development
Tests
Guide complet des tests pour Company Manager.
Tests
Guide complet pour tester les applications Company Manager.
Configuration
Vitest
// vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'jsdom',
setupFiles: ['./src/test/setup.ts'],
coverage: {
reporter: ['text', 'json', 'html'],
},
},
});Setup
// src/test/setup.ts
import '@testing-library/jest-dom';
import { vi } from 'vitest';
// Mock des variables d'environnement
vi.mock('process.env', () => ({
NEXT_PUBLIC_API_URL: 'http://localhost:3000',
}));
// Nettoyage après chaque test
afterEach(() => {
vi.clearAllMocks();
});Tests Unitaires
Composants React
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from './Button';
describe('Button', () => {
it('should render correctly', () => {
render(<Button>Click me</Button>);
expect(screen.getByText('Click me')).toBeInTheDocument();
});
it('should handle click events', () => {
const onClick = vi.fn();
render(<Button onClick={onClick}>Click me</Button>);
fireEvent.click(screen.getByText('Click me'));
expect(onClick).toHaveBeenCalled();
});
});Hooks
import { renderHook, act } from '@testing-library/react';
import { useCounter } from './useCounter';
describe('useCounter', () => {
it('should increment counter', () => {
const { result } = renderHook(() => useCounter());
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
});Services
import { UserService } from './UserService';
describe('UserService', () => {
let service: UserService;
beforeEach(() => {
service = new UserService();
});
it('should fetch user by id', async () => {
const user = await service.getUser('123');
expect(user).toEqual(expect.objectContaining({
id: '123',
name: expect.any(String),
}));
});
});Tests d'Intégration
API Routes
import { createMocks } from 'node-mocks-http';
import { handler } from './api/users';
describe('Users API', () => {
it('should create user', async () => {
const { req, res } = createMocks({
method: 'POST',
body: {
name: 'John Doe',
email: 'john@example.com',
},
});
await handler(req, res);
expect(res._getStatusCode()).toBe(201);
expect(JSON.parse(res._getData())).toEqual(
expect.objectContaining({
id: expect.any(String),
})
);
});
});Base de Données
import { prisma } from '@/lib/prisma';
describe('Database Integration', () => {
beforeEach(async () => {
await prisma.user.deleteMany();
});
it('should create and retrieve user', async () => {
const user = await prisma.user.create({
data: {
email: 'test@example.com',
name: 'Test User',
},
});
const found = await prisma.user.findUnique({
where: { id: user.id },
});
expect(found).toEqual(user);
});
});Tests E2E
Playwright
import { test, expect } from '@playwright/test';
test('user flow', async ({ page }) => {
// Login
await page.goto('/login');
await page.fill('[name=email]', 'user@example.com');
await page.fill('[name=password]', 'password');
await page.click('button[type=submit]');
// Navigation
await expect(page).toHaveURL('/dashboard');
// Interaction
await page.click('[data-testid=create-button]');
await page.fill('[name=title]', 'New Item');
await page.click('button[type=submit]');
// Verification
await expect(page.locator('h1')).toContainText('New Item');
});Mocks
API Mocks
import { rest } from 'msw';
import { setupServer } from 'msw/node';
const server = setupServer(
rest.get('/api/users', (req, res, ctx) => {
return res(
ctx.json([
{ id: '1', name: 'John' },
{ id: '2', name: 'Jane' },
])
);
})
);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());Component Mocks
vi.mock('@/components/Chart', () => ({
Chart: () => <div data-testid="mocked-chart" />,
}));Couverture de Tests
Configuration
// vitest.config.ts
export default defineConfig({
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
exclude: [
'node_modules/',
'test/',
'**/*.d.ts',
],
},
},
});Scripts
{
"scripts": {
"test": "vitest",
"test:coverage": "vitest run --coverage",
"test:ui": "vitest --ui",
"test:e2e": "playwright test"
}
}Bonnes Pratiques
-
Organisation
- Un fichier de test par module
- Nommage clair et descriptif
- Structure AAA (Arrange, Act, Assert)
-
Performance
- Isolation des tests
- Nettoyage après chaque test
- Utilisation de mocks appropriés
-
Maintenabilité
- Tests lisibles et maintenables
- Éviter la duplication de code
- Documentation des cas complexes