Make fileDiscoveryService.test.ts win compatible (#4892)
This commit is contained in:
parent
65aabfede8
commit
4c144e616d
|
@ -4,80 +4,86 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
||||
import type { Mocked } from 'vitest';
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import * as fs from 'fs/promises';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { FileDiscoveryService } from './fileDiscoveryService.js';
|
||||
import { GitIgnoreParser } from '../utils/gitIgnoreParser.js';
|
||||
import * as gitUtils from '../utils/gitUtils.js';
|
||||
|
||||
// Mock the GitIgnoreParser
|
||||
vi.mock('../utils/gitIgnoreParser.js');
|
||||
|
||||
// Mock gitUtils module
|
||||
vi.mock('../utils/gitUtils.js');
|
||||
|
||||
describe('FileDiscoveryService', () => {
|
||||
let service: FileDiscoveryService;
|
||||
let mockGitIgnoreParser: Mocked<GitIgnoreParser>;
|
||||
const mockProjectRoot = '/test/project';
|
||||
let testRootDir: string;
|
||||
let projectRoot: string;
|
||||
|
||||
beforeEach(() => {
|
||||
mockGitIgnoreParser = {
|
||||
initialize: vi.fn(),
|
||||
isIgnored: vi.fn(),
|
||||
loadPatterns: vi.fn(),
|
||||
loadGitRepoPatterns: vi.fn(),
|
||||
} as unknown as Mocked<GitIgnoreParser>;
|
||||
async function createTestFile(filePath: string, content = '') {
|
||||
const fullPath = path.join(projectRoot, filePath);
|
||||
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
||||
await fs.writeFile(fullPath, content);
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
vi.mocked(GitIgnoreParser).mockImplementation(() => mockGitIgnoreParser);
|
||||
vi.mocked(gitUtils.isGitRepository).mockReturnValue(true);
|
||||
vi.mocked(gitUtils.findGitRoot).mockReturnValue('/test/project');
|
||||
vi.clearAllMocks();
|
||||
beforeEach(async () => {
|
||||
testRootDir = await fs.mkdtemp(
|
||||
path.join(os.tmpdir(), 'file-discovery-test-'),
|
||||
);
|
||||
projectRoot = path.join(testRootDir, 'project');
|
||||
await fs.mkdir(projectRoot, { recursive: true });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
afterEach(async () => {
|
||||
await fs.rm(testRootDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
describe('initialization', () => {
|
||||
it('should initialize git ignore parser by default', () => {
|
||||
service = new FileDiscoveryService(mockProjectRoot);
|
||||
expect(GitIgnoreParser).toHaveBeenCalledWith(mockProjectRoot);
|
||||
expect(GitIgnoreParser).toHaveBeenCalledTimes(2);
|
||||
expect(mockGitIgnoreParser.loadGitRepoPatterns).toHaveBeenCalled();
|
||||
expect(mockGitIgnoreParser.loadPatterns).toHaveBeenCalled();
|
||||
it('should initialize git ignore parser by default in a git repo', async () => {
|
||||
await fs.mkdir(path.join(projectRoot, '.git'));
|
||||
await createTestFile('.gitignore', 'node_modules/');
|
||||
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
// Let's check the effect of the parser instead of mocking it.
|
||||
expect(service.shouldGitIgnoreFile('node_modules/foo.js')).toBe(true);
|
||||
expect(service.shouldGitIgnoreFile('src/foo.js')).toBe(false);
|
||||
});
|
||||
|
||||
it('should not initialize git ignore parser when not a git repo', () => {
|
||||
vi.mocked(gitUtils.isGitRepository).mockReturnValue(false);
|
||||
service = new FileDiscoveryService(mockProjectRoot);
|
||||
it('should not load git repo patterns when not in a git repo', async () => {
|
||||
// No .git directory
|
||||
await createTestFile('.gitignore', 'node_modules/');
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
|
||||
expect(GitIgnoreParser).toHaveBeenCalledOnce();
|
||||
expect(mockGitIgnoreParser.loadGitRepoPatterns).not.toHaveBeenCalled();
|
||||
// .gitignore is not loaded in non-git repos
|
||||
expect(service.shouldGitIgnoreFile('node_modules/foo.js')).toBe(false);
|
||||
});
|
||||
|
||||
it('should load .geminiignore patterns even when not in a git repo', async () => {
|
||||
await createTestFile('.geminiignore', 'secrets.txt');
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
|
||||
expect(service.shouldGeminiIgnoreFile('secrets.txt')).toBe(true);
|
||||
expect(service.shouldGeminiIgnoreFile('src/index.js')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('filterFiles', () => {
|
||||
beforeEach(() => {
|
||||
mockGitIgnoreParser.isIgnored.mockImplementation(
|
||||
(path: string) =>
|
||||
path.includes('node_modules') || path.includes('.git'),
|
||||
);
|
||||
service = new FileDiscoveryService(mockProjectRoot);
|
||||
beforeEach(async () => {
|
||||
await fs.mkdir(path.join(projectRoot, '.git'));
|
||||
await createTestFile('.gitignore', 'node_modules/\n.git/\ndist');
|
||||
await createTestFile('.geminiignore', 'logs/');
|
||||
});
|
||||
|
||||
it('should filter out git-ignored files by default', () => {
|
||||
it('should filter out git-ignored and gemini-ignored files by default', () => {
|
||||
const files = [
|
||||
'src/index.ts',
|
||||
'node_modules/package/index.js',
|
||||
'README.md',
|
||||
'.git/config',
|
||||
'dist/bundle.js',
|
||||
];
|
||||
'logs/latest.log',
|
||||
].map((f) => path.join(projectRoot, f));
|
||||
|
||||
const filtered = service.filterFiles(files);
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
|
||||
expect(filtered).toEqual(['src/index.ts', 'README.md', 'dist/bundle.js']);
|
||||
expect(service.filterFiles(files)).toEqual(
|
||||
['src/index.ts', 'README.md'].map((f) => path.join(projectRoot, f)),
|
||||
);
|
||||
});
|
||||
|
||||
it('should not filter files when respectGitIgnore is false', () => {
|
||||
|
@ -85,48 +91,121 @@ describe('FileDiscoveryService', () => {
|
|||
'src/index.ts',
|
||||
'node_modules/package/index.js',
|
||||
'.git/config',
|
||||
];
|
||||
'logs/latest.log',
|
||||
].map((f) => path.join(projectRoot, f));
|
||||
|
||||
const filtered = service.filterFiles(files, { respectGitIgnore: false });
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
|
||||
expect(filtered).toEqual(files);
|
||||
const filtered = service.filterFiles(files, {
|
||||
respectGitIgnore: false,
|
||||
respectGeminiIgnore: true, // still respect this one
|
||||
});
|
||||
|
||||
expect(filtered).toEqual(
|
||||
['src/index.ts', 'node_modules/package/index.js', '.git/config'].map(
|
||||
(f) => path.join(projectRoot, f),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it('should not filter files when respectGeminiIgnore is false', () => {
|
||||
const files = [
|
||||
'src/index.ts',
|
||||
'node_modules/package/index.js',
|
||||
'logs/latest.log',
|
||||
].map((f) => path.join(projectRoot, f));
|
||||
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
|
||||
const filtered = service.filterFiles(files, {
|
||||
respectGitIgnore: true,
|
||||
respectGeminiIgnore: false,
|
||||
});
|
||||
|
||||
expect(filtered).toEqual(
|
||||
['src/index.ts', 'logs/latest.log'].map((f) =>
|
||||
path.join(projectRoot, f),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle empty file list', () => {
|
||||
const filtered = service.filterFiles([]);
|
||||
expect(filtered).toEqual([]);
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
|
||||
expect(service.filterFiles([])).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldGitIgnoreFile', () => {
|
||||
beforeEach(() => {
|
||||
mockGitIgnoreParser.isIgnored.mockImplementation((path: string) =>
|
||||
path.includes('node_modules'),
|
||||
);
|
||||
service = new FileDiscoveryService(mockProjectRoot);
|
||||
describe('shouldGitIgnoreFile & shouldGeminiIgnoreFile', () => {
|
||||
beforeEach(async () => {
|
||||
await fs.mkdir(path.join(projectRoot, '.git'));
|
||||
await createTestFile('.gitignore', 'node_modules/');
|
||||
await createTestFile('.geminiignore', '*.log');
|
||||
});
|
||||
|
||||
it('should return true for git-ignored files', () => {
|
||||
expect(service.shouldGitIgnoreFile('node_modules/package/index.js')).toBe(
|
||||
true,
|
||||
);
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
|
||||
expect(
|
||||
service.shouldGitIgnoreFile(
|
||||
path.join(projectRoot, 'node_modules/package/index.js'),
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for non-ignored files', () => {
|
||||
expect(service.shouldGitIgnoreFile('src/index.ts')).toBe(false);
|
||||
it('should return false for non-git-ignored files', () => {
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
|
||||
expect(
|
||||
service.shouldGitIgnoreFile(path.join(projectRoot, 'src/index.ts')),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true for gemini-ignored files', () => {
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
|
||||
expect(
|
||||
service.shouldGeminiIgnoreFile(path.join(projectRoot, 'debug.log')),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for non-gemini-ignored files', () => {
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
|
||||
expect(
|
||||
service.shouldGeminiIgnoreFile(path.join(projectRoot, 'src/index.ts')),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('edge cases', () => {
|
||||
it('should handle relative project root paths', () => {
|
||||
const relativeService = new FileDiscoveryService('./relative/path');
|
||||
expect(relativeService).toBeInstanceOf(FileDiscoveryService);
|
||||
it('should handle relative project root paths', async () => {
|
||||
await fs.mkdir(path.join(projectRoot, '.git'));
|
||||
await createTestFile('.gitignore', 'ignored.txt');
|
||||
const service = new FileDiscoveryService(
|
||||
path.relative(process.cwd(), projectRoot),
|
||||
);
|
||||
|
||||
expect(
|
||||
service.shouldGitIgnoreFile(path.join(projectRoot, 'ignored.txt')),
|
||||
).toBe(true);
|
||||
expect(
|
||||
service.shouldGitIgnoreFile(path.join(projectRoot, 'not-ignored.txt')),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle filterFiles with undefined options', () => {
|
||||
const files = ['src/index.ts'];
|
||||
const filtered = service.filterFiles(files, undefined);
|
||||
expect(filtered).toEqual(files);
|
||||
it('should handle filterFiles with undefined options', async () => {
|
||||
await fs.mkdir(path.join(projectRoot, '.git'));
|
||||
await createTestFile('.gitignore', 'ignored.txt');
|
||||
const service = new FileDiscoveryService(projectRoot);
|
||||
|
||||
const files = ['src/index.ts', 'ignored.txt'].map((f) =>
|
||||
path.join(projectRoot, f),
|
||||
);
|
||||
|
||||
expect(service.filterFiles(files, undefined)).toEqual([
|
||||
path.join(projectRoot, 'src/index.ts'),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue