chore: sync gemini-cli v0.1.19

This commit is contained in:
tanzhenxin
2025-08-18 19:55:46 +08:00
244 changed files with 19407 additions and 5030 deletions

View File

@@ -50,6 +50,7 @@ describe('useAtCompletion', () => {
respectGitIgnore: true,
respectGeminiIgnore: true,
})),
getEnableRecursiveFileSearch: () => true,
} as unknown as Config;
vi.clearAllMocks();
});
@@ -113,8 +114,8 @@ describe('useAtCompletion', () => {
expect(result.current.suggestions.map((s) => s.value)).toEqual([
'src/',
'src/components/',
'src/components/Button.tsx',
'src/index.js',
'src/components/Button.tsx',
]);
});
@@ -156,7 +157,7 @@ describe('useAtCompletion', () => {
});
});
it('should NOT show a loading indicator for subsequent searches that complete under 100ms', async () => {
it('should NOT show a loading indicator for subsequent searches that complete under 200ms', async () => {
const structure: FileSystemStructure = { 'a.txt': '', 'b.txt': '' };
testRootDir = await createTmpDir(structure);
@@ -185,7 +186,7 @@ describe('useAtCompletion', () => {
expect(result.current.isLoadingSuggestions).toBe(false);
});
it('should show a loading indicator and clear old suggestions for subsequent searches that take longer than 100ms', async () => {
it('should show a loading indicator and clear old suggestions for subsequent searches that take longer than 200ms', async () => {
const structure: FileSystemStructure = { 'a.txt': '', 'b.txt': '' };
testRootDir = await createTmpDir(structure);
@@ -193,7 +194,7 @@ describe('useAtCompletion', () => {
const originalSearch = FileSearch.prototype.search;
vi.spyOn(FileSearch.prototype, 'search').mockImplementation(
async function (...args) {
await new Promise((resolve) => setTimeout(resolve, 200));
await new Promise((resolve) => setTimeout(resolve, 300));
return originalSearch.apply(this, args);
},
);
@@ -283,6 +284,61 @@ describe('useAtCompletion', () => {
});
});
describe('State Management', () => {
it('should reset the state when disabled after being in a READY state', async () => {
const structure: FileSystemStructure = { 'a.txt': '' };
testRootDir = await createTmpDir(structure);
const { result, rerender } = renderHook(
({ enabled }) =>
useTestHarnessForAtCompletion(enabled, 'a', mockConfig, testRootDir),
{ initialProps: { enabled: true } },
);
// Wait for the hook to be ready and have suggestions
await waitFor(() => {
expect(result.current.suggestions.map((s) => s.value)).toEqual([
'a.txt',
]);
});
// Now, disable the hook
rerender({ enabled: false });
// The suggestions should be cleared immediately because of the RESET action
expect(result.current.suggestions).toEqual([]);
});
it('should reset the state when disabled after being in an ERROR state', async () => {
testRootDir = await createTmpDir({});
// Force an error during initialization
vi.spyOn(FileSearch.prototype, 'initialize').mockRejectedValueOnce(
new Error('Initialization failed'),
);
const { result, rerender } = renderHook(
({ enabled }) =>
useTestHarnessForAtCompletion(enabled, '', mockConfig, testRootDir),
{ initialProps: { enabled: true } },
);
// Wait for the hook to enter the error state
await waitFor(() => {
expect(result.current.isLoadingSuggestions).toBe(false);
});
expect(result.current.suggestions).toEqual([]); // No suggestions on error
// Now, disable the hook
rerender({ enabled: false });
// The state should still be reset (though visually it's the same)
// We can't directly inspect the internal state, but we can ensure it doesn't crash
// and the suggestions remain empty.
expect(result.current.suggestions).toEqual([]);
});
});
describe('Filtering and Configuration', () => {
it('should respect .gitignore files', async () => {
const gitignoreContent = ['dist/', '*.log'].join('\n');
@@ -376,5 +432,42 @@ describe('useAtCompletion', () => {
await cleanupTmpDir(rootDir1);
await cleanupTmpDir(rootDir2);
});
it('should perform a non-recursive search when enableRecursiveFileSearch is false', async () => {
const structure: FileSystemStructure = {
'file.txt': '',
src: {
'index.js': '',
},
};
testRootDir = await createTmpDir(structure);
const nonRecursiveConfig = {
getEnableRecursiveFileSearch: () => false,
getFileFilteringOptions: vi.fn(() => ({
respectGitIgnore: true,
respectGeminiIgnore: true,
})),
} as unknown as Config;
const { result } = renderHook(() =>
useTestHarnessForAtCompletion(
true,
'',
nonRecursiveConfig,
testRootDir,
),
);
await waitFor(() => {
expect(result.current.suggestions.length).toBeGreaterThan(0);
});
// Should only contain top-level items
expect(result.current.suggestions.map((s) => s.value)).toEqual([
'src/',
'file.txt',
]);
});
});
});