diff --git a/packages/cli/src/ui/hooks/useCompletion.integration.test.ts b/packages/cli/src/ui/hooks/useCompletion.integration.test.ts index 43ded9d0..40af5d4f 100644 --- a/packages/cli/src/ui/hooks/useCompletion.integration.test.ts +++ b/packages/cli/src/ui/hooks/useCompletion.integration.test.ts @@ -59,6 +59,31 @@ describe('useCompletion git-aware filtering integration', () => { vi.restoreAllMocks(); }); + it('should filter git-ignored entries from @ completions', async () => { + const globResults = [`${testCwd}/data`, `${testCwd}/dist`]; + vi.mocked(glob).mockResolvedValue(globResults); + + // Mock git ignore service to ignore certain files + mockFileDiscoveryService.shouldGitIgnoreFile.mockImplementation( + (path: string) => path.includes('dist'), + ); + + const { result } = renderHook(() => + useCompletion('@d', testCwd, true, slashCommands, mockConfig), + ); + + // Wait for async operations to complete + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, 150)); // Account for debounce + }); + + expect(result.current.suggestions).toHaveLength(1); + expect(result.current.suggestions).toEqual( + expect.arrayContaining([{ label: 'data', value: 'data' }]), + ); + expect(result.current.showSuggestions).toBe(true); + }); + it('should filter git-ignored directories from @ completions', async () => { // Mock fs.readdir to return both regular and git-ignored directories vi.mocked(fs.readdir).mockResolvedValue([ diff --git a/packages/cli/src/ui/hooks/useCompletion.ts b/packages/cli/src/ui/hooks/useCompletion.ts index 5217e60c..7cbe8a7e 100644 --- a/packages/cli/src/ui/hooks/useCompletion.ts +++ b/packages/cli/src/ui/hooks/useCompletion.ts @@ -306,6 +306,12 @@ export function useCompletion( value: escapePath(relativePath), }; }) + .filter((s) => { + if (fileDiscoveryService) { + return !fileDiscoveryService.shouldGitIgnoreFile(s.label); // relative path + } + return true; + }) .slice(0, maxResults); return suggestions;