import { jest, expect, describe, beforeEach, it } from '@jest/globals' import { checkoutRepo } from '../checkout' import { getCurrentContext } from '../context' // Mock dependencies jest.mock('../utils') jest.mock('../context') jest.mock('fs', () => ({ existsSync: jest.fn(), mkdirSync: jest.fn(), rmSync: jest.fn(), writeFileSync: jest.fn(), })) const mockedGetCurrentContext = getCurrentContext as jest.MockedFunction describe('checkoutRepo', () => { const mockContext = { repo: { owner: 'test-org', repo: 'test-repo' }, probotContext: { payload: { installation: { id: 12345 }, pull_request: { head: { ref: 'feature-branch', sha: 'abc123' }, }, }, octokit: { auth: jest.fn().mockResolvedValue({ token: 'test-token' } as any), }, }, workingDir: '/tmp/test', } beforeEach(() => { jest.clearAllMocks() mockedGetCurrentContext.mockReturnValue(mockContext as any) }) it('should throw error if context is not available', async () => { mockedGetCurrentContext.mockReturnValue(undefined) await expect(checkoutRepo('/tmp/test')).rejects.toThrow('No context available for checkout') }) it('should throw error if git is not found', async () => { const { prixExec } = await import('../utils') ;(prixExec as jest.MockedFunction).mockImplementation(() => { throw new Error('git not found') }) await expect(checkoutRepo('/tmp/test')).rejects.toThrow('git command not found') }) it('should throw error if installation ID is missing', async () => { const ctxWithoutInstallation = { ...mockContext, probotContext: { ...mockContext.probotContext, payload: { installation: null, pull_request: { head: { ref: '', sha: '' } } }, }, } mockedGetCurrentContext.mockReturnValue(ctxWithoutInstallation as any) const { prixExec } = await import('../utils') ;(prixExec as jest.MockedFunction).mockReturnValue('git version 2.30.0') await expect(checkoutRepo('/tmp/test')).rejects.toThrow('Installation ID not found') }) it('should successfully clone repository', async () => { const { prixExec } = await import('../utils') const mockedPrixExec = prixExec as jest.MockedFunction mockedPrixExec.mockReturnValue(undefined as any) const { existsSync, mkdirSync, rmSync } = await import('fs') ;(existsSync as jest.MockedFunction).mockReturnValue(false) const result = await checkoutRepo('/tmp/test-repo') expect(result).toBe('/tmp/test-repo') expect(mockedPrixExec).toHaveBeenCalledWith(expect.stringContaining('git clone'), expect.any(Object)) expect(mockedPrixExec).toHaveBeenCalledWith(expect.stringContaining('git config user.name'), expect.any(Object)) }) it('should use sparse checkout when files are specified', async () => { const { prixExec } = await import('../utils') const mockedPrixExec = prixExec as jest.MockedFunction mockedPrixExec.mockReturnValue(undefined as any) const { existsSync, mkdirSync, rmSync, writeFileSync } = await import('fs') ;(existsSync as jest.MockedFunction).mockReturnValue(false) await checkoutRepo('/tmp/test-repo', { sparse: true, files: ['src/index.ts'] }) expect(mockedPrixExec).toHaveBeenCalledWith(expect.stringContaining('sparse-checkout'), expect.any(Object)) }) it('should clean up existing directory before clone', async () => { const { prixExec } = await import('../utils') const mockedPrixExec = prixExec as jest.MockedFunction mockedPrixExec.mockReturnValue(undefined as any) const { existsSync, rmSync, mkdirSync } = await import('fs') ;(existsSync as jest.MockedFunction).mockReturnValue(true) await checkoutRepo('/tmp/test-repo') expect(rmSync).toHaveBeenCalledWith('/tmp/test-repo', { recursive: true, force: true }) }) })