gitDiffHandle.test.tsā¢6.41 kB
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { getGitDiffs, getStagedDiff, getWorkTreeDiff } from '../../../src/core/git/gitDiffHandle.js';
import { logger } from '../../../src/shared/logger.js';
import { createMockConfig } from '../../testing/testUtils.js';
vi.mock('../../../src/shared/logger');
describe('gitDiffHandle', () => {
beforeEach(() => {
vi.resetAllMocks();
});
describe('getWorkTreeDiff', () => {
test('should return diffs when directory is a git repository', async () => {
const mockDiff = 'diff --git a/file.txt b/file.txt\n+new line';
const mockIsGitRepository = vi.fn().mockResolvedValue(true);
const mockExecGitDiff = vi.fn().mockResolvedValue(mockDiff);
const result = await getWorkTreeDiff('/test/dir', {
execGitDiff: mockExecGitDiff,
isGitRepository: mockIsGitRepository,
});
expect(result).toBe(mockDiff);
expect(mockIsGitRepository).toHaveBeenCalledWith('/test/dir');
expect(mockExecGitDiff).toHaveBeenCalledWith('/test/dir', []);
});
test('should return empty string when directory is not a git repository', async () => {
const mockIsGitRepository = vi.fn().mockResolvedValue(false);
const mockExecGitDiff = vi.fn();
const result = await getWorkTreeDiff('/test/dir', {
execGitDiff: mockExecGitDiff,
isGitRepository: mockIsGitRepository,
});
expect(result).toBe('');
expect(mockIsGitRepository).toHaveBeenCalledWith('/test/dir');
expect(mockExecGitDiff).not.toHaveBeenCalled();
});
test('should return empty string when git diff command fails', async () => {
const mockIsGitRepository = vi.fn().mockResolvedValue(true);
const mockExecGitDiff = vi.fn().mockRejectedValue(new Error('Failed to get diff'));
const result = await getWorkTreeDiff('/test/dir', {
execGitDiff: mockExecGitDiff,
isGitRepository: mockIsGitRepository,
});
expect(result).toBe('');
expect(mockIsGitRepository).toHaveBeenCalledWith('/test/dir');
expect(mockExecGitDiff).toHaveBeenCalledWith('/test/dir', []);
expect(logger.trace).toHaveBeenCalledWith('Failed to get git diff:', 'Failed to get diff');
});
});
describe('getStagedDiff', () => {
test('should return staged diffs when directory is a git repository', async () => {
const mockDiff = 'diff --git a/staged.txt b/staged.txt\n+staged content';
const mockIsGitRepository = vi.fn().mockResolvedValue(true);
const mockExecGitDiff = vi.fn().mockResolvedValue(mockDiff);
const result = await getStagedDiff('/test/dir', {
execGitDiff: mockExecGitDiff,
isGitRepository: mockIsGitRepository,
});
expect(result).toBe(mockDiff);
expect(mockIsGitRepository).toHaveBeenCalledWith('/test/dir');
expect(mockExecGitDiff).toHaveBeenCalledWith('/test/dir', ['--cached']);
});
});
describe('getGitDiffs', () => {
test('should return git diffs when includeDiffs is enabled', async () => {
const mockWorkTreeDiff = 'diff --git a/file.txt b/file.txt\n+new line';
const mockStagedDiff = 'diff --git a/staged.txt b/staged.txt\n+staged content';
const mockGetWorkTreeDiff = vi.fn().mockResolvedValue(mockWorkTreeDiff);
const mockGetStagedDiff = vi.fn().mockResolvedValue(mockStagedDiff);
const mockConfig = createMockConfig({
cwd: '/test/repo',
output: {
git: {
includeDiffs: true,
},
},
});
const result = await getGitDiffs(['/test/repo'], mockConfig, {
getWorkTreeDiff: mockGetWorkTreeDiff,
getStagedDiff: mockGetStagedDiff,
});
expect(result).toEqual({
workTreeDiffContent: mockWorkTreeDiff,
stagedDiffContent: mockStagedDiff,
});
expect(mockGetWorkTreeDiff).toHaveBeenCalledWith('/test/repo');
expect(mockGetStagedDiff).toHaveBeenCalledWith('/test/repo');
});
test('should return undefined when includeDiffs is disabled', async () => {
const mockGetWorkTreeDiff = vi.fn();
const mockGetStagedDiff = vi.fn();
const mockConfig = createMockConfig({
cwd: '/test/repo',
output: {
git: {
includeDiffs: false,
},
},
});
const result = await getGitDiffs(['/test/repo'], mockConfig, {
getWorkTreeDiff: mockGetWorkTreeDiff,
getStagedDiff: mockGetStagedDiff,
});
expect(result).toBeUndefined();
expect(mockGetWorkTreeDiff).not.toHaveBeenCalled();
expect(mockGetStagedDiff).not.toHaveBeenCalled();
});
test('should use cwd when rootDirs is empty', async () => {
const mockWorkTreeDiff = 'diff content';
const mockStagedDiff = '';
const mockGetWorkTreeDiff = vi.fn().mockResolvedValue(mockWorkTreeDiff);
const mockGetStagedDiff = vi.fn().mockResolvedValue(mockStagedDiff);
const mockConfig = createMockConfig({
cwd: '/fallback/dir',
output: {
git: {
includeDiffs: true,
},
},
});
const result = await getGitDiffs([], mockConfig, {
getWorkTreeDiff: mockGetWorkTreeDiff,
getStagedDiff: mockGetStagedDiff,
});
expect(result).toEqual({
workTreeDiffContent: mockWorkTreeDiff,
stagedDiffContent: mockStagedDiff,
});
// createMockConfig sets cwd to the actual working directory, so we check the actual config value
expect(mockGetWorkTreeDiff).toHaveBeenCalledWith(mockConfig.cwd);
expect(mockGetStagedDiff).toHaveBeenCalledWith(mockConfig.cwd);
});
test('should throw error when diff operations fail', async () => {
const mockGetWorkTreeDiff = vi.fn().mockRejectedValue(new Error('Failed to get diff'));
const mockGetStagedDiff = vi.fn();
const mockConfig = createMockConfig({
cwd: '/test/repo',
output: {
git: {
includeDiffs: true,
},
},
});
await expect(
getGitDiffs(['/test/repo'], mockConfig, {
getWorkTreeDiff: mockGetWorkTreeDiff,
getStagedDiff: mockGetStagedDiff,
}),
).rejects.toThrow('Failed to get git diffs: Failed to get diff');
expect(mockGetWorkTreeDiff).toHaveBeenCalledWith('/test/repo');
});
});
});