Tests
Le projet utilise Vitest pour les tests unitaires.
Lancer les tests
bash
# Tests en mode watch
npm run test
# Tests avec couverture (mode CI)
npm run test:ciStructure
tests/
setup.ts # Mocks globaux
unit/
config/ # Tests de configuration
core/ # Tests permissions
modules/
<module>/ # Tests par module
shared/ # Tests services partagesEcrire un test
typescript
import { describe, it, expect, vi, beforeEach } from 'vitest';
// Mock des dependances du module teste
vi.mock('../../../src/modules/my/repositories/my.repository.js', () => ({
myRepository: {
findByGuild: vi.fn(),
save: vi.fn(),
},
}));
import { myService } from '../../../src/modules/my/services/my.service.js';
import { myRepository } from '../../../src/modules/my/repositories/my.repository.js';
describe('myService', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should process data correctly', async () => {
// Arrange
const mockResult = { id: '1', value: 'TEST' };
vi.mocked(myRepository.save).mockResolvedValue(mockResult);
// Act
const result = await myService.processData({
guildId: 'guild-123',
value: 'test',
});
// Assert
expect(result).toEqual(mockResult);
expect(myRepository.save).toHaveBeenCalledWith({
guildId: 'guild-123',
value: 'TEST',
});
});
});Mocks globaux (setup.ts)
Le fichier tests/setup.ts configure des mocks globaux charges avant chaque test :
env
typescript
vi.mock('../src/config/env.js', () => ({
env: {
DISCORD_TOKEN: 'test-token',
DISCORD_CLIENT_ID: '123456789012345678',
DISCORD_GUILD_ID: '987654321098765432',
DISCORD_LOG_CHANNEL_ID: '111222333444555666',
// ... toutes les variables avec des valeurs de test
},
}));logger
typescript
vi.mock('../src/config/logger.js', () => ({
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn(), fatal: vi.fn(),
child: vi.fn().mockReturnValue(/* meme objet */) },
childLogger: vi.fn().mockReturnValue(/* meme objet */),
}));notifier
typescript
vi.mock('../src/infrastructure/discord/notifier.js', () => ({
notifyAdminChannel: vi.fn().mockResolvedValue(undefined),
notifyModerationChannel: vi.fn().mockResolvedValue(undefined),
}));Ces mocks empechent les tests d'acceder aux services externes (Discord, DB, APIs).
Ce qui est teste vs exclu
Teste (couverture)
- Services (
src/modules/*/services/) - Logique metier pure (calculs XP, aggregation stats, parsers)
- Fonctions utilitaires
- Configuration (constantes)
- Permissions
Exclu de la couverture
| Exclusion | Raison |
|---|---|
src/app/** | Point d'entree, connexion Discord live |
src/core/client.ts | Wiring Discord |
src/shared/db/prisma.ts | Singleton Prisma |
src/config/logger.ts | Singleton Pino |
src/config/env.ts | Validation Zod au demarrage |
src/modules/*/commands/** | Handlers Discord, testes manuellement |
src/modules/*/handlers/** | Evenements Discord gateway |
src/modules/*/jobs/** | Testes via les services qu'ils appellent |
src/modules/*/repositories/** | Requetes Prisma, necessitent une DB |
src/infrastructure/** | Discord notifier, scheduler, HTTP server |
src/shared/types/** | Fichiers de types, pas de runtime |
Seuils de couverture
Configures dans vitest.config.ts :
typescript
thresholds: {
lines: 80,
functions: 80,
branches: 80,
statements: 80,
}Le CI echoue si un seuil n'est pas atteint.
Rapport de couverture
Le rapport est genere dans coverage/ avec les formats text, lcov et html. En CI, il est uploade comme artefact GitHub Actions avec une retention de 7 jours.
