summaryrefslogtreecommitdiff
path: root/packages/core/src
diff options
context:
space:
mode:
authorTommaso Sciortino <[email protected]>2025-07-25 14:30:15 -0700
committerGitHub <[email protected]>2025-07-25 21:30:15 +0000
commit4c144e616d43071c8672890cc579c9d5cdde706f (patch)
treee6f0ef30dbf7f748f6621e66884a7d672030915c /packages/core/src
parent65aabfede8b7f842fa37abf1ac36afe4b4881e50 (diff)
Make fileDiscoveryService.test.ts win compatible (#4892)
Diffstat (limited to 'packages/core/src')
-rw-r--r--packages/core/src/services/fileDiscoveryService.test.ts219
1 files changed, 149 insertions, 70 deletions
diff --git a/packages/core/src/services/fileDiscoveryService.test.ts b/packages/core/src/services/fileDiscoveryService.test.ts
index d7530cd6..f8a03f62 100644
--- a/packages/core/src/services/fileDiscoveryService.test.ts
+++ b/packages/core/src/services/fileDiscoveryService.test.ts
@@ -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 service = new FileDiscoveryService(projectRoot);
- const filtered = service.filterFiles(files, { respectGitIgnore: false });
+ const filtered = service.filterFiles(files, {
+ respectGitIgnore: false,
+ respectGeminiIgnore: true, // still respect this one
+ });
- expect(filtered).toEqual(files);
+ 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'),
+ ]);
});
});
});