summaryrefslogtreecommitdiff
path: root/packages/core/src/services/fileDiscoveryService.test.ts
blob: d7530cd69b7b2fe0984af2d56ef358da1b547247 (plain)
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
import type { Mocked } from 'vitest';
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';

  beforeEach(() => {
    mockGitIgnoreParser = {
      initialize: vi.fn(),
      isIgnored: vi.fn(),
      loadPatterns: vi.fn(),
      loadGitRepoPatterns: vi.fn(),
    } as unknown as Mocked<GitIgnoreParser>;

    vi.mocked(GitIgnoreParser).mockImplementation(() => mockGitIgnoreParser);
    vi.mocked(gitUtils.isGitRepository).mockReturnValue(true);
    vi.mocked(gitUtils.findGitRoot).mockReturnValue('/test/project');
    vi.clearAllMocks();
  });

  afterEach(() => {
    vi.restoreAllMocks();
  });

  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 not initialize git ignore parser when not a git repo', () => {
      vi.mocked(gitUtils.isGitRepository).mockReturnValue(false);
      service = new FileDiscoveryService(mockProjectRoot);

      expect(GitIgnoreParser).toHaveBeenCalledOnce();
      expect(mockGitIgnoreParser.loadGitRepoPatterns).not.toHaveBeenCalled();
    });
  });

  describe('filterFiles', () => {
    beforeEach(() => {
      mockGitIgnoreParser.isIgnored.mockImplementation(
        (path: string) =>
          path.includes('node_modules') || path.includes('.git'),
      );
      service = new FileDiscoveryService(mockProjectRoot);
    });

    it('should filter out git-ignored files by default', () => {
      const files = [
        'src/index.ts',
        'node_modules/package/index.js',
        'README.md',
        '.git/config',
        'dist/bundle.js',
      ];

      const filtered = service.filterFiles(files);

      expect(filtered).toEqual(['src/index.ts', 'README.md', 'dist/bundle.js']);
    });

    it('should not filter files when respectGitIgnore is false', () => {
      const files = [
        'src/index.ts',
        'node_modules/package/index.js',
        '.git/config',
      ];

      const filtered = service.filterFiles(files, { respectGitIgnore: false });

      expect(filtered).toEqual(files);
    });

    it('should handle empty file list', () => {
      const filtered = service.filterFiles([]);
      expect(filtered).toEqual([]);
    });
  });

  describe('shouldGitIgnoreFile', () => {
    beforeEach(() => {
      mockGitIgnoreParser.isIgnored.mockImplementation((path: string) =>
        path.includes('node_modules'),
      );
      service = new FileDiscoveryService(mockProjectRoot);
    });

    it('should return true for git-ignored files', () => {
      expect(service.shouldGitIgnoreFile('node_modules/package/index.js')).toBe(
        true,
      );
    });

    it('should return false for non-ignored files', () => {
      expect(service.shouldGitIgnoreFile('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 filterFiles with undefined options', () => {
      const files = ['src/index.ts'];
      const filtered = service.filterFiles(files, undefined);
      expect(filtered).toEqual(files);
    });
  });
});