test(cli): refactor tests for async render utilities (#23252)

This commit is contained in:
Tommaso Sciortino
2026-03-20 20:08:29 +00:00
committed by GitHub
parent 86a3a913b5
commit 6c78eb7a39
198 changed files with 3592 additions and 4802 deletions
@@ -83,7 +83,7 @@ describe('useAtCompletion', () => {
};
testRootDir = await createTmpDir(structure);
const { result } = renderHook(() =>
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(true, '', mockConfig, testRootDir),
);
@@ -114,7 +114,7 @@ describe('useAtCompletion', () => {
};
testRootDir = await createTmpDir(structure);
const { result } = renderHook(() =>
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(true, 'src/', mockConfig, testRootDir),
);
@@ -137,7 +137,7 @@ describe('useAtCompletion', () => {
};
testRootDir = await createTmpDir(structure);
const { result } = renderHook(() =>
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(true, '', mockConfig, testRootDir),
);
@@ -170,7 +170,7 @@ describe('useAtCompletion', () => {
vi.spyOn(FileSearchFactory, 'create').mockReturnValue(fileSearch);
const { result } = renderHook(() =>
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(
true,
'CrAzYCaSe',
@@ -201,7 +201,7 @@ describe('useAtCompletion', () => {
],
});
const { result } = renderHook(() =>
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(true, 'logs', mockConfig, '/tmp'),
);
@@ -220,24 +220,31 @@ describe('useAtCompletion', () => {
it('should be in a loading state during initial file system crawl', async () => {
testRootDir = await createTmpDir({});
// Mock FileSearch to be slow to catch the loading state
let deferredInit: { resolve: (value?: unknown) => void };
// Mock FileSearch to control when initialization finishes
const mockFileSearch = {
initialize: vi.fn().mockImplementation(async () => {
await new Promise((resolve) => setTimeout(resolve, 50));
}),
initialize: vi.fn().mockImplementation(
() =>
new Promise((resolve) => {
deferredInit = { resolve };
}),
),
search: vi.fn().mockResolvedValue([]),
};
vi.spyOn(FileSearchFactory, 'create').mockReturnValue(
mockFileSearch as unknown as FileSearch,
);
const { result } = renderHook(() =>
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(true, '', mockConfig, testRootDir),
);
// It's initially true because the effect runs synchronously.
await waitFor(() => {
expect(result.current.isLoadingSuggestions).toBe(true);
// It's true because the promise hasn't resolved yet
expect(result.current.isLoadingSuggestions).toBe(true);
// Resolve the initialization
await act(async () => {
deferredInit.resolve();
});
// Wait for the loading to complete.
@@ -250,7 +257,7 @@ describe('useAtCompletion', () => {
const structure: FileSystemStructure = { 'a.txt': '', 'b.txt': '' };
testRootDir = await createTmpDir(structure);
const { result, rerender } = renderHook(
const { result, rerender } = await renderHook(
({ pattern }) =>
useTestHarnessForAtCompletion(true, pattern, mockConfig, testRootDir),
{ initialProps: { pattern: 'a' } },
@@ -294,8 +301,17 @@ describe('useAtCompletion', () => {
await realFileSearch.initialize();
// Mock that returns results immediately but we'll control timing with fake timers
let deferredInit: {
resolve: (value?: unknown) => void;
reject: (e: Error) => void;
};
const mockFileSearch: FileSearch = {
initialize: vi.fn().mockResolvedValue(undefined),
initialize: vi.fn().mockImplementation(
() =>
new Promise((resolve, reject) => {
deferredInit = { resolve, reject };
}),
),
search: vi
.fn()
.mockImplementation(async (pattern, options) =>
@@ -304,12 +320,16 @@ describe('useAtCompletion', () => {
};
vi.spyOn(FileSearchFactory, 'create').mockReturnValue(mockFileSearch);
const { result, rerender } = renderHook(
const { result, rerender } = await renderHook(
({ pattern }) =>
useTestHarnessForAtCompletion(true, pattern, mockConfig, testRootDir),
{ initialProps: { pattern: 'a' } },
);
await act(async () => {
deferredInit.resolve();
});
// Wait for the initial search to complete (using real timers)
await waitFor(() => {
expect(result.current.suggestions.map((s) => s.value)).toEqual([
@@ -355,8 +375,17 @@ describe('useAtCompletion', () => {
testRootDir = await createTmpDir(structure);
const abortSpy = vi.spyOn(AbortController.prototype, 'abort');
let deferredInit: {
resolve: (value?: unknown) => void;
reject: (e: Error) => void;
};
const mockFileSearch: FileSearch = {
initialize: vi.fn().mockResolvedValue(undefined),
initialize: vi.fn().mockImplementation(
() =>
new Promise((resolve, reject) => {
deferredInit = { resolve, reject };
}),
),
search: vi.fn().mockImplementation(async (pattern: string) => {
const delay = pattern === 'a' ? 500 : 50;
await new Promise((resolve) => setTimeout(resolve, delay));
@@ -365,12 +394,16 @@ describe('useAtCompletion', () => {
};
vi.spyOn(FileSearchFactory, 'create').mockReturnValue(mockFileSearch);
const { result, rerender } = renderHook(
const { result, rerender } = await renderHook(
({ pattern }) =>
useTestHarnessForAtCompletion(true, pattern, mockConfig, testRootDir),
{ initialProps: { pattern: 'a' } },
);
await act(async () => {
deferredInit.resolve();
});
// Wait for the hook to be ready (initialization is complete)
await waitFor(() => {
expect(mockFileSearch.search).toHaveBeenCalledWith(
@@ -408,7 +441,7 @@ describe('useAtCompletion', () => {
const structure: FileSystemStructure = { 'a.txt': '' };
testRootDir = await createTmpDir(structure);
const { result, rerender } = renderHook(
const { result, rerender } = await renderHook(
({ enabled }) =>
useTestHarnessForAtCompletion(enabled, 'a', mockConfig, testRootDir),
{ initialProps: { enabled: true } },
@@ -431,21 +464,32 @@ describe('useAtCompletion', () => {
it('should reset the state when disabled after being in an ERROR state', async () => {
testRootDir = await createTmpDir({});
let deferredInit: {
resolve: (value?: unknown) => void;
reject: (e: Error) => void;
};
// Force an error during initialization
const mockFileSearch: FileSearch = {
initialize: vi
.fn()
.mockRejectedValue(new Error('Initialization failed')),
initialize: vi.fn().mockImplementation(
() =>
new Promise((resolve, reject) => {
deferredInit = { resolve, reject };
}),
),
search: vi.fn(),
};
vi.spyOn(FileSearchFactory, 'create').mockReturnValue(mockFileSearch);
const { result, rerender } = renderHook(
const { result, rerender } = await renderHook(
({ enabled }) =>
useTestHarnessForAtCompletion(enabled, '', mockConfig, testRootDir),
{ initialProps: { enabled: true } },
);
await act(async () => {
deferredInit.reject(new Error('Initialization failed'));
});
// Wait for the hook to enter the error state
await waitFor(() => {
expect(result.current.isLoadingSuggestions).toBe(false);
@@ -474,7 +518,7 @@ describe('useAtCompletion', () => {
};
testRootDir = await createTmpDir(structure);
const { result } = renderHook(() =>
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(true, '', mockConfig, testRootDir),
);
@@ -495,7 +539,7 @@ describe('useAtCompletion', () => {
};
testRootDir = await createTmpDir(structure);
const { result } = renderHook(() =>
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(true, '', undefined, testRootDir),
);
@@ -515,7 +559,7 @@ describe('useAtCompletion', () => {
const structure2: FileSystemStructure = { 'file2.txt': '' };
const rootDir2 = await createTmpDir(structure2);
const { result, rerender } = renderHook(
const { result, rerender } = await renderHook(
({ cwd, pattern }) =>
useTestHarnessForAtCompletion(true, pattern, mockConfig, cwd),
{
@@ -574,7 +618,21 @@ describe('useAtCompletion', () => {
getFileFilteringEnableFuzzySearch: () => true,
} as unknown as Config;
const { result } = renderHook(() =>
let deferredInit: { resolve: (value?: unknown) => void };
const mockFileSearch: FileSearch = {
initialize: vi.fn().mockImplementation(
() =>
new Promise((resolve) => {
deferredInit = { resolve };
}),
),
search: vi.fn().mockResolvedValue(['src/', 'file.txt']),
};
vi.spyOn(FileSearchFactory, 'create').mockReturnValue(
mockFileSearch as unknown as FileSearch,
);
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(
true,
'',
@@ -583,6 +641,10 @@ describe('useAtCompletion', () => {
),
);
await act(async () => {
deferredInit.resolve();
});
await waitFor(() => {
expect(result.current.suggestions.length).toBeGreaterThan(0);
});
@@ -619,7 +681,7 @@ describe('useAtCompletion', () => {
}),
} as unknown as Config;
const { result } = renderHook(() =>
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(true, '', multiDirConfig, cwdDir),
);
@@ -656,7 +718,7 @@ describe('useAtCompletion', () => {
}),
} as unknown as Config;
const { result } = renderHook(() =>
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(true, '', dynamicConfig, cwdDir),
);
@@ -695,7 +757,7 @@ describe('useAtCompletion', () => {
}),
} as unknown as Config;
const { result } = renderHook(() =>
const { result } = await renderHook(() =>
useTestHarnessForAtCompletion(true, 'readme', multiDirConfig, dir1),
);