mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-22 01:37:50 +00:00
Merge tag 'v0.3.0' into chore/sync-gemini-cli-v0.3.0
This commit is contained in:
@@ -9,18 +9,12 @@
|
||||
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
||||
import { renderHook, waitFor, act } from '@testing-library/react';
|
||||
import { useAtCompletion } from './useAtCompletion.js';
|
||||
import {
|
||||
Config,
|
||||
FileSearch,
|
||||
FileSearchFactory,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import {
|
||||
createTmpDir,
|
||||
cleanupTmpDir,
|
||||
FileSystemStructure,
|
||||
} from '@qwen-code/qwen-code-test-utils';
|
||||
import type { Config, FileSearch } from '@qwen-code/qwen-code-core';
|
||||
import { FileSearchFactory } from '@qwen-code/qwen-code-core';
|
||||
import type { FileSystemStructure } from '@qwen-code/qwen-code-test-utils';
|
||||
import { createTmpDir, cleanupTmpDir } from '@qwen-code/qwen-code-test-utils';
|
||||
import { useState } from 'react';
|
||||
import { Suggestion } from '../components/SuggestionsDisplay.js';
|
||||
import type { Suggestion } from '../components/SuggestionsDisplay.js';
|
||||
|
||||
// Test harness to capture the state from the hook's callbacks.
|
||||
function useTestHarnessForAtCompletion(
|
||||
@@ -55,6 +49,7 @@ describe('useAtCompletion', () => {
|
||||
respectGeminiIgnore: true,
|
||||
})),
|
||||
getEnableRecursiveFileSearch: () => true,
|
||||
getFileFilteringDisableFuzzySearch: () => false,
|
||||
} as unknown as Config;
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
@@ -202,15 +197,18 @@ describe('useAtCompletion', () => {
|
||||
cache: false,
|
||||
cacheTtl: 0,
|
||||
enableRecursiveFileSearch: true,
|
||||
disableFuzzySearch: false,
|
||||
});
|
||||
await realFileSearch.initialize();
|
||||
|
||||
// Mock that returns results immediately but we'll control timing with fake timers
|
||||
const mockFileSearch: FileSearch = {
|
||||
initialize: vi.fn().mockResolvedValue(undefined),
|
||||
search: vi.fn().mockImplementation(async (...args) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 300));
|
||||
return realFileSearch.search(...args);
|
||||
}),
|
||||
search: vi
|
||||
.fn()
|
||||
.mockImplementation(async (...args) =>
|
||||
realFileSearch.search(...args),
|
||||
),
|
||||
};
|
||||
vi.spyOn(FileSearchFactory, 'create').mockReturnValue(mockFileSearch);
|
||||
|
||||
@@ -220,33 +218,42 @@ describe('useAtCompletion', () => {
|
||||
{ initialProps: { pattern: 'a' } },
|
||||
);
|
||||
|
||||
// Wait for the initial (slow) search to complete
|
||||
// Wait for the initial search to complete (using real timers)
|
||||
await waitFor(() => {
|
||||
expect(result.current.suggestions.map((s) => s.value)).toEqual([
|
||||
'a.txt',
|
||||
]);
|
||||
});
|
||||
|
||||
// Now, rerender to trigger the second search
|
||||
rerender({ pattern: 'b' });
|
||||
// Now switch to fake timers for precise control of the loading behavior
|
||||
vi.useFakeTimers();
|
||||
|
||||
// Wait for the loading indicator to appear
|
||||
await waitFor(() => {
|
||||
expect(result.current.isLoadingSuggestions).toBe(true);
|
||||
// Trigger the second search
|
||||
act(() => {
|
||||
rerender({ pattern: 'b' });
|
||||
});
|
||||
|
||||
// Suggestions should be cleared while loading
|
||||
// Initially, loading should be false (before 200ms timer)
|
||||
expect(result.current.isLoadingSuggestions).toBe(false);
|
||||
|
||||
// Advance time by exactly 200ms to trigger the loading state
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(200);
|
||||
});
|
||||
|
||||
// Now loading should be true and suggestions should be cleared
|
||||
expect(result.current.isLoadingSuggestions).toBe(true);
|
||||
expect(result.current.suggestions).toEqual([]);
|
||||
|
||||
// Wait for the final (slow) search to complete
|
||||
await waitFor(
|
||||
() => {
|
||||
expect(result.current.suggestions.map((s) => s.value)).toEqual([
|
||||
'b.txt',
|
||||
]);
|
||||
},
|
||||
{ timeout: 1000 },
|
||||
); // Increase timeout for the slow search
|
||||
// Switch back to real timers for the final waitFor
|
||||
vi.useRealTimers();
|
||||
|
||||
// Wait for the search results to be processed
|
||||
await waitFor(() => {
|
||||
expect(result.current.suggestions.map((s) => s.value)).toEqual([
|
||||
'b.txt',
|
||||
]);
|
||||
});
|
||||
|
||||
expect(result.current.isLoadingSuggestions).toBe(false);
|
||||
});
|
||||
@@ -472,6 +479,7 @@ describe('useAtCompletion', () => {
|
||||
respectGitIgnore: true,
|
||||
respectGeminiIgnore: true,
|
||||
})),
|
||||
getFileFilteringDisableFuzzySearch: () => false,
|
||||
} as unknown as Config;
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
|
||||
Reference in New Issue
Block a user