mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-06 19:31:15 -07:00
test(cli): refactor tests for async render utilities (#23252)
This commit is contained in:
committed by
GitHub
parent
86a3a913b5
commit
6c78eb7a39
@@ -87,7 +87,7 @@ describe('ScrollProvider Drag', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -190,7 +190,7 @@ describe('ScrollProvider Drag', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -253,7 +253,7 @@ describe('ScrollProvider Drag', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -291,7 +291,7 @@ describe('ScrollProvider Drag', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -329,7 +329,7 @@ describe('ScrollProvider Drag', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -397,7 +397,7 @@ describe('ScrollProvider Drag', () => {
|
||||
);
|
||||
TestScrollableWithScrollTo.displayName = 'TestScrollableWithScrollTo';
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollableWithScrollTo
|
||||
id="test-scrollable-scrollto"
|
||||
|
||||
@@ -82,7 +82,7 @@ describe('ScrollProvider', () => {
|
||||
});
|
||||
|
||||
describe('Event Handling Status', () => {
|
||||
it('returns true when scroll event is handled', () => {
|
||||
it('returns true when scroll event is handled', async () => {
|
||||
const scrollBy = vi.fn();
|
||||
const getScrollState = vi.fn(() => ({
|
||||
scrollTop: 0,
|
||||
@@ -90,7 +90,7 @@ describe('ScrollProvider', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -119,7 +119,7 @@ describe('ScrollProvider', () => {
|
||||
expect(handled).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when scroll event is ignored (cannot scroll further)', () => {
|
||||
it('returns false when scroll event is ignored (cannot scroll further)', async () => {
|
||||
const scrollBy = vi.fn();
|
||||
// Already at bottom
|
||||
const getScrollState = vi.fn(() => ({
|
||||
@@ -128,7 +128,7 @@ describe('ScrollProvider', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -167,7 +167,7 @@ describe('ScrollProvider', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -211,7 +211,7 @@ describe('ScrollProvider', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -244,7 +244,7 @@ describe('ScrollProvider', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -289,7 +289,7 @@ describe('ScrollProvider', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -347,7 +347,7 @@ describe('ScrollProvider', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -408,7 +408,7 @@ describe('ScrollProvider', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
@@ -470,7 +470,7 @@ describe('ScrollProvider', () => {
|
||||
innerHeight: 10,
|
||||
}));
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ScrollProvider>
|
||||
<TestScrollable
|
||||
id="test-scrollable"
|
||||
|
||||
@@ -54,12 +54,12 @@ const TestHarness = ({
|
||||
};
|
||||
|
||||
describe('SessionStatsContext', () => {
|
||||
it('should provide the correct initial state', () => {
|
||||
it('should provide the correct initial state', async () => {
|
||||
const contextRef: MutableRefObject<
|
||||
ReturnType<typeof useSessionStats> | undefined
|
||||
> = { current: undefined };
|
||||
|
||||
const { unmount } = render(
|
||||
const { unmount } = await render(
|
||||
<SessionStatsProvider>
|
||||
<TestHarness contextRef={contextRef} />
|
||||
</SessionStatsProvider>,
|
||||
@@ -73,12 +73,12 @@ describe('SessionStatsContext', () => {
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should update metrics when the uiTelemetryService emits an update', () => {
|
||||
it('should update metrics when the uiTelemetryService emits an update', async () => {
|
||||
const contextRef: MutableRefObject<
|
||||
ReturnType<typeof useSessionStats> | undefined
|
||||
> = { current: undefined };
|
||||
|
||||
const { unmount } = render(
|
||||
const { unmount } = await render(
|
||||
<SessionStatsProvider>
|
||||
<TestHarness contextRef={contextRef} />
|
||||
</SessionStatsProvider>,
|
||||
@@ -149,7 +149,7 @@ describe('SessionStatsContext', () => {
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should not update metrics if the data is the same', () => {
|
||||
it('should not update metrics if the data is the same', async () => {
|
||||
const contextRef: MutableRefObject<
|
||||
ReturnType<typeof useSessionStats> | undefined
|
||||
> = { current: undefined };
|
||||
@@ -161,7 +161,7 @@ describe('SessionStatsContext', () => {
|
||||
return null;
|
||||
};
|
||||
|
||||
const { unmount } = render(
|
||||
const { unmount } = await render(
|
||||
<SessionStatsProvider>
|
||||
<CountingTestHarness />
|
||||
</SessionStatsProvider>,
|
||||
@@ -239,12 +239,12 @@ describe('SessionStatsContext', () => {
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should update session ID and reset stats when the uiTelemetryService emits a clear event', () => {
|
||||
it('should update session ID and reset stats when the uiTelemetryService emits a clear event', async () => {
|
||||
const contextRef: MutableRefObject<
|
||||
ReturnType<typeof useSessionStats> | undefined
|
||||
> = { current: undefined };
|
||||
|
||||
const { unmount } = render(
|
||||
const { unmount } = await render(
|
||||
<SessionStatsProvider>
|
||||
<TestHarness contextRef={contextRef} />
|
||||
</SessionStatsProvider>,
|
||||
@@ -267,12 +267,12 @@ describe('SessionStatsContext', () => {
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should throw an error when useSessionStats is used outside of a provider', () => {
|
||||
it('should throw an error when useSessionStats is used outside of a provider', async () => {
|
||||
const onError = vi.fn();
|
||||
// Suppress console.error from React for this test
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const { unmount } = render(
|
||||
const { unmount } = await render(
|
||||
<ErrorBoundary onError={onError}>
|
||||
<TestHarness contextRef={{ current: undefined }} />
|
||||
</ErrorBoundary>,
|
||||
|
||||
@@ -90,15 +90,15 @@ describe('SettingsContext', () => {
|
||||
</SettingsContext.Provider>
|
||||
);
|
||||
|
||||
it('should provide the correct initial state', () => {
|
||||
const { result } = renderHook(() => useSettingsStore(), { wrapper });
|
||||
it('should provide the correct initial state', async () => {
|
||||
const { result } = await renderHook(() => useSettingsStore(), { wrapper });
|
||||
|
||||
expect(result.current.settings.merged).toEqual(mockSnapshot.merged);
|
||||
expect(result.current.settings.isTrusted).toBe(true);
|
||||
});
|
||||
|
||||
it('should allow accessing settings for a specific scope', () => {
|
||||
const { result } = renderHook(() => useSettingsStore(), { wrapper });
|
||||
it('should allow accessing settings for a specific scope', async () => {
|
||||
const { result } = await renderHook(() => useSettingsStore(), { wrapper });
|
||||
|
||||
const userSettings = result.current.settings.forScope(SettingScope.User);
|
||||
expect(userSettings).toBe(mockSnapshot.user);
|
||||
@@ -109,8 +109,8 @@ describe('SettingsContext', () => {
|
||||
expect(workspaceSettings).toBe(mockSnapshot.workspace);
|
||||
});
|
||||
|
||||
it('should trigger re-renders when settings change (external event)', () => {
|
||||
const { result } = renderHook(() => useSettingsStore(), { wrapper });
|
||||
it('should trigger re-renders when settings change (external event)', async () => {
|
||||
const { result } = await renderHook(() => useSettingsStore(), { wrapper });
|
||||
|
||||
expect(result.current.settings.merged.ui?.theme).toBe('default-theme');
|
||||
|
||||
@@ -130,8 +130,8 @@ describe('SettingsContext', () => {
|
||||
expect(result.current.settings.merged.ui?.theme).toBe('new-theme');
|
||||
});
|
||||
|
||||
it('should call store.setValue when setSetting is called', () => {
|
||||
const { result } = renderHook(() => useSettingsStore(), { wrapper });
|
||||
it('should call store.setValue when setSetting is called', async () => {
|
||||
const { result } = await renderHook(() => useSettingsStore(), { wrapper });
|
||||
|
||||
act(() => {
|
||||
result.current.setSetting(SettingScope.User, 'ui.theme', 'dark');
|
||||
@@ -144,12 +144,12 @@ describe('SettingsContext', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error if used outside provider', () => {
|
||||
it('should throw error if used outside provider', async () => {
|
||||
const onError = vi.fn();
|
||||
// Suppress console.error (React logs error boundary info)
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
render(
|
||||
await render(
|
||||
<ErrorBoundary onError={onError}>
|
||||
<TestHarness />
|
||||
</ErrorBoundary>,
|
||||
|
||||
@@ -51,12 +51,11 @@ const TestComponent = ({ onColor }: { onColor: (c: string) => void }) => {
|
||||
describe('TerminalContext', () => {
|
||||
it('should parse OSC 11 response', async () => {
|
||||
const handleColor = vi.fn();
|
||||
const { waitUntilReady, unmount } = render(
|
||||
const { waitUntilReady, unmount } = await render(
|
||||
<TerminalProvider>
|
||||
<TestComponent onColor={handleColor} />
|
||||
</TerminalProvider>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
await act(async () => {
|
||||
mockStdin.emit('data', '\x1b]11;rgb:ffff/ffff/ffff\x1b\\');
|
||||
@@ -71,12 +70,11 @@ describe('TerminalContext', () => {
|
||||
|
||||
it('should handle partial chunks', async () => {
|
||||
const handleColor = vi.fn();
|
||||
const { waitUntilReady, unmount } = render(
|
||||
const { waitUntilReady, unmount } = await render(
|
||||
<TerminalProvider>
|
||||
<TestComponent onColor={handleColor} />
|
||||
</TerminalProvider>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
await act(async () => {
|
||||
mockStdin.emit('data', '\x1b]11;rgb:0000/');
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import { act } from 'react';
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { renderHook } from '../../test-utils/render.js';
|
||||
import { waitFor } from '../../test-utils/async.js';
|
||||
import { ToolActionsProvider, useToolActions } from './ToolActionsContext.js';
|
||||
import {
|
||||
type Config,
|
||||
@@ -81,7 +80,7 @@ describe('ToolActionsContext', () => {
|
||||
);
|
||||
|
||||
it('publishes to MessageBus for tools with correlationId', async () => {
|
||||
const { result } = renderHook(() => useToolActions(), { wrapper });
|
||||
const { result } = await renderHook(() => useToolActions(), { wrapper });
|
||||
|
||||
await result.current.confirm(
|
||||
'modern-call',
|
||||
@@ -99,7 +98,7 @@ describe('ToolActionsContext', () => {
|
||||
});
|
||||
|
||||
it('handles cancel by calling confirm with Cancel outcome', async () => {
|
||||
const { result } = renderHook(() => useToolActions(), { wrapper });
|
||||
const { result } = await renderHook(() => useToolActions(), { wrapper });
|
||||
|
||||
await result.current.cancel('modern-call');
|
||||
|
||||
@@ -112,20 +111,26 @@ describe('ToolActionsContext', () => {
|
||||
});
|
||||
|
||||
it('resolves IDE diffs for edit tools when in IDE mode', async () => {
|
||||
let deferredIdeClient: { resolve: (c: IdeClient) => void };
|
||||
const mockIdeClient = {
|
||||
isDiffingEnabled: vi.fn().mockReturnValue(true),
|
||||
resolveDiffFromCli: vi.fn(),
|
||||
addStatusChangeListener: vi.fn(),
|
||||
removeStatusChangeListener: vi.fn(),
|
||||
} as unknown as IdeClient;
|
||||
vi.mocked(IdeClient.getInstance).mockResolvedValue(mockIdeClient);
|
||||
|
||||
vi.mocked(IdeClient.getInstance).mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
deferredIdeClient = { resolve };
|
||||
}),
|
||||
);
|
||||
vi.mocked(mockConfig.getIdeMode).mockReturnValue(true);
|
||||
|
||||
const { result } = renderHook(() => useToolActions(), { wrapper });
|
||||
const { result } = await renderHook(() => useToolActions(), { wrapper });
|
||||
|
||||
// Wait for IdeClient initialization in useEffect
|
||||
await act(async () => {
|
||||
await waitFor(() => expect(IdeClient.getInstance).toHaveBeenCalled());
|
||||
// Give React a chance to update state
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
deferredIdeClient.resolve(mockIdeClient);
|
||||
});
|
||||
|
||||
await result.current.confirm(
|
||||
@@ -146,6 +151,8 @@ describe('ToolActionsContext', () => {
|
||||
|
||||
it('updates isDiffingEnabled when IdeClient status changes', async () => {
|
||||
let statusListener: () => void = () => {};
|
||||
let deferredIdeClient: { resolve: (c: IdeClient) => void };
|
||||
|
||||
const mockIdeClient = {
|
||||
isDiffingEnabled: vi.fn().mockReturnValue(false),
|
||||
addStatusChangeListener: vi.fn().mockImplementation((listener) => {
|
||||
@@ -154,15 +161,18 @@ describe('ToolActionsContext', () => {
|
||||
removeStatusChangeListener: vi.fn(),
|
||||
} as unknown as IdeClient;
|
||||
|
||||
vi.mocked(IdeClient.getInstance).mockResolvedValue(mockIdeClient);
|
||||
vi.mocked(IdeClient.getInstance).mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
deferredIdeClient = { resolve };
|
||||
}),
|
||||
);
|
||||
vi.mocked(mockConfig.getIdeMode).mockReturnValue(true);
|
||||
|
||||
const { result } = renderHook(() => useToolActions(), { wrapper });
|
||||
const { result } = await renderHook(() => useToolActions(), { wrapper });
|
||||
|
||||
// Wait for initialization
|
||||
await act(async () => {
|
||||
await waitFor(() => expect(IdeClient.getInstance).toHaveBeenCalled());
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
deferredIdeClient.resolve(mockIdeClient);
|
||||
});
|
||||
|
||||
expect(result.current.isDiffingEnabled).toBe(false);
|
||||
@@ -202,7 +212,7 @@ describe('ToolActionsContext', () => {
|
||||
} as unknown as SerializableConfirmationDetails,
|
||||
};
|
||||
|
||||
const { result } = renderHook(() => useToolActions(), {
|
||||
const { result } = await renderHook(() => useToolActions(), {
|
||||
wrapper: ({ children }) => (
|
||||
<ToolActionsProvider config={mockConfig} toolCalls={[legacyTool]}>
|
||||
{children}
|
||||
|
||||
Reference in New Issue
Block a user