// Mock chalk to avoid ESM import issues /* eslint-disable @typescript-eslint/no-explicit-any */ jest.mock('chalk', () => ({ __esModule: true, green: (s: string) => s, red: (s: string) => s, })); // Mock simple-git before importing the module under test jest.mock('simple-git', () => ({ simpleGit: jest.fn(), })); jest.mock('axios'); const axiosModule: any = require('axios'); // Stub POST create_branch axiosModule.post = jest.fn().mockResolvedValue({ data: {} }); import axios from 'axios'; import { simpleGit } from 'simple-git'; import { startTaskAgent } from '../src/services/startTaskAgent'; describe('startTaskAgent', () => { it('should error if repository has uncommitted changes', async () => { const mockStatus = { files: ['file1.txt'] }; // Mock simpleGit to return an object with status() method (simpleGit as jest.Mock).mockReturnValue({ status: jest.fn().mockResolvedValue(mockStatus), }); await expect( startTaskAgent({ id: '42', gitlabToken: 'token' }) ).rejects.toThrow( 'Le dépôt contient des modifications non enregistrées' ); }); it('should create branch with correct naming and default commit message', async () => { // Reset simpleGit mock (simpleGit as jest.Mock).mockClear(); // Prepare mocks for simpleGit methods const mockGit = { status: jest.fn().mockResolvedValue({ files: [] }), getRemotes: jest.fn().mockResolvedValue([{ name: 'origin', refs: { fetch: 'git@host:ns/proj.git', push: 'git@host:ns/proj.git' } }]), fetch: jest.fn().mockResolvedValue(undefined), checkout: jest.fn().mockResolvedValue(undefined), pull: jest.fn().mockResolvedValue(undefined), branch: jest.fn().mockResolvedValue({ all: [] }), checkoutBranch: jest.fn().mockResolvedValue(undefined), add: jest.fn().mockResolvedValue(undefined), commit: jest.fn().mockResolvedValue({ commit: 'abc123' }), push: jest.fn().mockResolvedValue(undefined), }; (simpleGit as jest.Mock).mockReturnValue(mockGit); // Mock axios responses for project and issue (axios.get as jest.Mock) .mockResolvedValueOnce({ data: { id: 123 } }) .mockResolvedValueOnce({ data: { title: 'Implement new payment gateway feature quickly' }, status: 200, headers: { 'content-type': 'application/json' }, }); const result = await startTaskAgent({ id: '42', gitlabToken: 'token' }); expect(result).toEqual({ branch: 'feat/gl-42-implement-new-payment-gateway-feature', commitSha: 'abc123', }); }); it('should checkout existing branch if it already exists', async () => { // Reset simpleGit mock (simpleGit as jest.Mock).mockClear(); // Simulate existing branch with same task ID but different slug const existingBranch = 'feat/gl-42-existing-branch'; // Prepare mocks for simpleGit methods // eslint-disable-next-line @typescript-eslint/no-explicit-any const mockGit = { status: jest.fn().mockResolvedValue({ files: [] }), getRemotes: jest.fn().mockResolvedValue([{ name: 'origin', refs: { fetch: 'git@host:ns/proj.git', push: 'git@host:ns/proj.git' } }]), fetch: jest.fn().mockResolvedValue(undefined), checkout: jest.fn().mockResolvedValue(undefined), pull: jest.fn().mockResolvedValue(undefined), branch: jest.fn().mockResolvedValue({ all: [existingBranch] }), checkoutBranch: jest.fn().mockResolvedValue(undefined), revparse: jest.fn().mockResolvedValue('def456'), add: jest.fn(), commit: jest.fn(), push: jest.fn(), } as any; (simpleGit as jest.Mock).mockReturnValue(mockGit); // Stub axios for project and issue retrieval (axios.get as jest.Mock) .mockResolvedValueOnce({ data: { id: 123 } }) .mockResolvedValueOnce({ data: { title: 'Different title for slug' }, status: 200, headers: { 'content-type': 'application/json' }, }); // Spy on console.warn const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {}); const result = await startTaskAgent({ id: '42', gitlabToken: 'token' }); expect(warnSpy).toHaveBeenCalledWith( expect.stringContaining(`La branche ${existingBranch} existe déjà`) ); expect(mockGit.checkout).toHaveBeenCalledWith(existingBranch); expect(mockGit.checkoutBranch).not.toHaveBeenCalled(); expect(result).toEqual({ branch: existingBranch, commitSha: 'def456' }); warnSpy.mockRestore(); }); });