Skip to content

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:ci

Structure

tests/
  setup.ts              # Mocks globaux
  unit/
    config/             # Tests de configuration
    core/               # Tests permissions
    modules/
      <module>/         # Tests par module
    shared/             # Tests services partages

Ecrire 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

ExclusionRaison
src/app/**Point d'entree, connexion Discord live
src/core/client.tsWiring Discord
src/shared/db/prisma.tsSingleton Prisma
src/config/logger.tsSingleton Pino
src/config/env.tsValidation 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.