/ opencodehub / tests / unit / git.test.ts
Swadhin Biswas chore(release): production-grade security & reliability hardening · 6/4/2026
739ba78
96 lines · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { initRepository, isRepoEmpty, getGit } from '@/lib/git';
import * as fs from 'fs';
import { simpleGit } from 'simple-git';

// Mock simple-git
vi.mock('simple-git', () => {
    const mGit = {
        init: vi.fn(),
        addConfig: vi.fn(),
        add: vi.fn(),
        commit: vi.fn(),
        branch: vi.fn(),
        addRemote: vi.fn(),
        push: vi.fn(),
        raw: vi.fn(),
        env: vi.fn(),
    };
    return {
        simpleGit: vi.fn(() => mGit),
    };
});

// Mock fs
vi.mock('fs', async () => {
    return {
        existsSync: vi.fn(),
        mkdirSync: vi.fn(),
        rmSync: vi.fn(),
        readdirSync: vi.fn(() => []),
    };
});

// Mock fs/promises
vi.mock('fs/promises', async () => {
    return {
        writeFile: vi.fn(),
        mkdir: vi.fn(),
        rm: vi.fn(),
        unlink: vi.fn(),
    };
});

// Mock child_process for hooks
vi.mock('child_process', () => ({
    spawn: vi.fn(),
}));

describe('Git Library', () => {
    beforeEach(() => {
        vi.clearAllMocks();
    });

    describe('initRepository', () => {
        it('should initialize a bare repository', async () => {
            const repoPath = '/tmp/test-repo.git';
            // We rely on real path.dirname, so no need to mock it.
            // But we need to mock existSync behavior
            (fs.existsSync as any).mockReturnValue(false); // Parent dir doesn't exist

            await initRepository(repoPath, { repoName: 'Test Repo', skipHooks: true });

            expect(fs.mkdirSync).toHaveBeenCalledWith('/tmp', { recursive: true });
            expect(fs.mkdirSync).toHaveBeenCalledWith(repoPath, { recursive: true });
            expect(simpleGit).toHaveBeenCalledWith(expect.objectContaining({ baseDir: repoPath }));

            const git = simpleGit({ baseDir: repoPath });
            expect(git.init).toHaveBeenCalledWith(true);
        });
    });

    describe('isRepoEmpty', () => {
        it('should return true if rev-parse HEAD fails', async () => {
            const repoPath = '/tmp/empty-repo.git';
            (simpleGit as any).mockReturnValue({
                env: vi.fn(),
                raw: vi.fn().mockRejectedValue(new Error('ambiguous argument')),
            } as any);

            const isEmpty = await isRepoEmpty(repoPath);
            expect(isEmpty).toBe(true);
        });

        it('should return false if rev-parse HEAD succeeds', async () => {
            const repoPath = '/tmp/full-repo.git';
            (simpleGit as any).mockReturnValue({
                env: vi.fn(),
                raw: vi.fn().mockResolvedValue('hash'),
            } as any);

            const isEmpty = await isRepoEmpty(repoPath);
            expect(isEmpty).toBe(false);
        });
    });
});