// Mocks for dependent agents jest.mock('../src/services/qualimetrie/testAgent', () => ({ __esModule: true, testAgent: jest.fn(), })); jest.mock('../src/services/qualimetrie/lintAgent', () => ({ __esModule: true, lintAgent: jest.fn(), })); jest.mock('../src/services/qualimetrie/securityAgent', () => ({ __esModule: true, securityAgent: jest.fn(), })); jest.mock('../src/services/qualimetrie/bomAgent', () => ({ __esModule: true, bomAgent: jest.fn(), })); import { bomAgent } from '../src/services/qualimetrie/bomAgent'; import { fullAgent } from '../src/services/qualimetrie/fullAgent'; import { lintAgent } from '../src/services/qualimetrie/lintAgent'; import { securityAgent } from '../src/services/qualimetrie/securityAgent'; import { testAgent } from '../src/services/qualimetrie/testAgent'; describe('fullAgent', () => { const mockedTest = testAgent as jest.MockedFunction; const mockedLint = lintAgent as jest.MockedFunction; const mockedSecurity = securityAgent as jest.MockedFunction; const mockedBom = bomAgent as jest.MockedFunction; beforeEach(() => { jest.clearAllMocks(); }); it('generates a full markdown report with correct sections', async () => { // Arrange: mock all agents to return fixed data mockedTest.mockResolvedValue({ success: true, summary: { total: 10, passed: 8, failed: 2, duration: '1.23s' }, metrics: { lines: 55, functions: 65, branches: 75, statements: 85 }, }); mockedLint.mockResolvedValue({ passed: true, metrics: { errors: 1, warnings: 2, files: 0, total: 3, fixable: 0 }, detailPath: '/path/eslint.json', }); mockedSecurity.mockResolvedValue({ total: 1, fixable: 0, bySeverity: { critical: 0, high: 0, moderate: 0, low: 1 }, topPackages: [], detailPath: '', vulnerabilities: [{ id: 'V1', severity: 'low' }], }); mockedBom.mockResolvedValue({ packages: [{ name: 'pkg1', version: '1.0.0', license: 'MIT', risk: 'Low' }] }); // Act const result = await fullAgent(); const report = result.report; // Assert: general structure expect(report).toContain('# Rapport Qualimétrie'); expect(report).toContain('## 1. Tests & Couverture'); // Assert: narrative test summary expect(report).toContain('Les tests ont été exécutés pour un total de **10** tests, dont **8** réussis et **2** échoués, en **1.23s**.'); // Assert: coverage cards expect(report).toContain('Lines covered'); expect(report).toContain('Functions covered'); expect(report).toContain('Branches covered'); expect(report).toContain('Statements covered'); // Assert: pretitle and analysis heading expect(report).toContain('Rapport'); expect(report).toContain('Analyse'); // Since lowest metric is 55 (< 70), expect 'PEUT MIEUX FAIRE' expect(report).toContain('Indicateur de test : PEUT MIEUX FAIRE.'); // Assert: ESLint section expect(report).toContain('## 2. Qualité de code (ESLint)'); expect(report).toContain('- Erreurs: **1**'); expect(report).toContain('- Warnings: **2**'); // Assert: security section expect(report).toContain('## 3. Sécurité (Vulnérabilités)'); expect(report).toContain('V1'); // Assert: BOM section and table output expect(report).toContain('## 4. Bill Of Materials (Licences)'); expect(report).toContain( 'Le tableau ci-dessous présente les 50 premières dépendances du Bill of Materials, avec leur nom, version et licence.' ); expect(report).toContain('pkg1'); expect(report).toContain('1.0.0'); expect(report).toContain('MIT'); expect(report).toContain('Liste complète en pièce jointe de ce document.'); // Assert: coverage visual summary expect(report).toContain('
'); expect(report).toContain('
'); expect(report).toContain('
55%
'); expect(report).toContain('
ceci est les contenu de la card
'); // Assert: coverage chart inclusion expect(report).toContain('
'); expect(report).toMatch(/]+xmlns="http:\/\/www\.w3\.org\/2000\/svg"/); }); it('handles errors in test and lint phases and empty outputs', async () => { mockedTest.mockResolvedValue({ success: false } as any); mockedLint.mockResolvedValue({} as any); mockedSecurity.mockResolvedValue({ vulnerabilities: [] } as any); mockedBom.mockResolvedValue({ packages: [] }); const result = await fullAgent(); const report = result.report; expect(report).toContain( "Erreur lors de l'exécution des tests ou de la collecte de la couverture." ); expect(report).toContain('## 2. Qualité de code (ESLint)'); expect(report).toContain("Erreur lors de l'exécution d'ESLint."); expect(report).toContain('## 3. Sécurité (Vulnérabilités)'); expect(report).toContain('```json'); expect(report).toContain('[]'); expect(report).toContain('## 4. Bill Of Materials (Licences)'); }); it('includes lint summary and detail link when summary is provided', async () => { mockedTest.mockResolvedValue({ success: true, summary: { total: 0, passed: 0, failed: 0, duration: '0s' }, metrics: { lines: 0, functions: 0, branches: 0, statements: 0 }, }); mockedLint.mockResolvedValue({ passed: true, metrics: { errors: 1, warnings: 0, files: 2, total: 1, fixable: 0 }, summary: { topFiles: [ { filePath: 'src/file.ts', total: 1, errors: 1, warnings: 0 }, ], topRules: [{ ruleId: 'r1', count: 5 }], }, detailPath: 'eslint-detail.json', } as any); mockedSecurity.mockResolvedValue({ vulnerabilities: [] } as any); mockedBom.mockResolvedValue({ packages: [] }); const { report } = await fullAgent(); expect(report).toContain('**Top fichiers problématiques**'); expect(report).toContain( '- src/file.ts: 1 problèmes (1 erreurs, 0 avertissements)' ); expect(report).toContain('**Top règles violées**'); expect(report).toContain('- r1: 5 occurrences'); expect(report).toContain('> Rapport complet ESLint: eslint-detail.json'); }); });