refactor(cli): integrate real config loading into async test utils (#23040)

This commit is contained in:
Tommaso Sciortino 2026-03-19 17:05:33 +00:00 committed by GitHub
parent 7de0616229
commit 23264ced9a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
103 changed files with 1806 additions and 1541 deletions

View file

@ -29,7 +29,7 @@ describe('Model Steering Integration', () => {
configOverrides: { modelSteering: true },
});
await rig.initialize();
rig.render();
await rig.render();
await rig.waitForIdle();
rig.setToolPolicy('list_directory', PolicyDecision.ASK_USER);

View file

@ -5,7 +5,6 @@
*/
import { describe, it, afterEach, expect } from 'vitest';
import { act } from 'react';
import { AppRig } from './AppRig.js';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
@ -31,7 +30,7 @@ describe('AppRig', () => {
configOverrides: { modelSteering: true },
});
await rig.initialize();
rig.render();
await rig.render();
await rig.waitForIdle();
// Set breakpoints on the canonical tool names
@ -69,12 +68,7 @@ describe('AppRig', () => {
);
rig = new AppRig({ fakeResponsesPath });
await rig.initialize();
await act(async () => {
rig!.render();
// Allow async initializations (like banners) to settle within the act boundary
await new Promise((resolve) => setTimeout(resolve, 0));
});
await rig.render();
// Wait for initial render
await rig.waitForIdle();

View file

@ -11,7 +11,7 @@ import os from 'node:os';
import path from 'node:path';
import fs from 'node:fs';
import { AppContainer } from '../ui/AppContainer.js';
import { renderWithProviders } from './render.js';
import { renderWithProviders, type RenderInstance } from './render.js';
import {
makeFakeConfig,
type Config,
@ -155,7 +155,7 @@ export interface PendingConfirmation {
}
export class AppRig {
private renderResult: ReturnType<typeof renderWithProviders> | undefined;
private renderResult: RenderInstance | undefined;
private config: Config | undefined;
private settings: LoadedSettings | undefined;
private testDir: string;
@ -393,12 +393,12 @@ export class AppRig {
return isAnyToolActive || isAwaitingConfirmation;
}
render() {
async render() {
if (!this.config || !this.settings)
throw new Error('AppRig not initialized');
act(() => {
this.renderResult = renderWithProviders(
await act(async () => {
this.renderResult = await renderWithProviders(
<AppContainer
config={this.config!}
version="test-version"

View file

@ -16,8 +16,6 @@ import { vi } from 'vitest';
import stripAnsi from 'strip-ansi';
import type React from 'react';
import { act, useState } from 'react';
import os from 'node:os';
import path from 'node:path';
import type { LoadedSettings } from '../config/settings.js';
import { KeypressProvider } from '../ui/contexts/KeypressContext.js';
import { SettingsContext } from '../ui/contexts/SettingsContext.js';
@ -44,7 +42,7 @@ import {
type OverflowState,
} from '../ui/contexts/OverflowContext.js';
import { makeFakeConfig, type Config } from '@google/gemini-cli-core';
import { type Config } from '@google/gemini-cli-core';
import { FakePersistentState } from './persistentStateFake.js';
import { AppContext, type AppState } from '../ui/contexts/AppContext.js';
import { createMockSettings } from './settings.js';
@ -53,6 +51,7 @@ import { themeManager, DEFAULT_THEME } from '../ui/themes/theme-manager.js';
import { DefaultLight } from '../ui/themes/builtin/light/default-light.js';
import { pickDefaultThemeName } from '../ui/themes/theme.js';
import { generateSvgForTerminal } from './svg.js';
import { loadCliConfig, type CliArgs } from '../config/config.js';
export const persistentStateMock = new FakePersistentState();
@ -66,7 +65,9 @@ if (process.env['NODE_ENV'] === 'test') {
}
vi.mock('../utils/persistentState.js', () => ({
persistentState: persistentStateMock,
get persistentState() {
return persistentStateMock;
},
}));
vi.mock('../ui/utils/terminalUtils.js', () => ({
@ -486,50 +487,6 @@ export const simulateClick = async (
});
};
let mockConfigInternal: Config | undefined;
const getMockConfigInternal = (): Config => {
if (!mockConfigInternal) {
mockConfigInternal = makeFakeConfig({
targetDir: os.tmpdir(),
enableEventDrivenScheduler: true,
});
}
return mockConfigInternal;
};
const configProxy = new Proxy({} as Config, {
get(_target, prop) {
if (prop === 'getTargetDir') {
return () =>
path.join(
path.parse(process.cwd()).root,
'Users',
'test',
'project',
'foo',
'bar',
'and',
'some',
'more',
'directories',
'to',
'make',
'it',
'long',
);
}
if (prop === 'getUseBackgroundColor') {
return () => true;
}
const internal = getMockConfigInternal();
if (prop in internal) {
return internal[prop as keyof typeof internal];
}
throw new Error(`mockConfig does not have property ${String(prop)}`);
},
});
export const mockSettings = createMockSettings();
// A minimal mock UIState to satisfy the context provider.
@ -639,7 +596,7 @@ const ContextCapture: React.FC<{ children: React.ReactNode }> = ({
return <>{children}</>;
};
export const renderWithProviders = (
export const renderWithProviders = async (
component: React.ReactElement,
{
shellFocus = true,
@ -647,8 +604,7 @@ export const renderWithProviders = (
uiState: providedUiState,
width,
mouseEventsEnabled = false,
config = configProxy as unknown as Config,
config,
uiActions,
persistentState,
appState = mockAppState,
@ -666,13 +622,15 @@ export const renderWithProviders = (
};
appState?: AppState;
} = {},
): RenderInstance & {
simulateClick: (
col: number,
row: number,
button?: 0 | 1 | 2,
) => Promise<void>;
} => {
): Promise<
RenderInstance & {
simulateClick: (
col: number,
row: number,
button?: 0 | 1 | 2,
) => Promise<void>;
}
> => {
const baseState: UIState = new Proxy(
{ ...baseMockUiState, ...providedUiState },
{
@ -701,8 +659,15 @@ export const renderWithProviders = (
persistentStateMock.mockClear();
const terminalWidth = width ?? baseState.terminalWidth;
const finalSettings = settings;
const finalConfig = config;
if (!config) {
config = await loadCliConfig(
settings.merged,
'random-session-id',
{} as unknown as CliArgs,
{ cwd: '/' },
);
}
const mainAreaWidth = terminalWidth;
@ -732,8 +697,8 @@ export const renderWithProviders = (
const wrapWithProviders = (comp: React.ReactElement) => (
<AppContext.Provider value={appState}>
<ConfigContext.Provider value={finalConfig}>
<SettingsContext.Provider value={finalSettings}>
<ConfigContext.Provider value={config}>
<SettingsContext.Provider value={settings}>
<UIStateContext.Provider value={finalUiState}>
<VimModeProvider>
<ShellFocusContext.Provider value={shellFocus}>
@ -744,7 +709,7 @@ export const renderWithProviders = (
<UIActionsContext.Provider value={finalUIActions}>
<OverflowProvider>
<ToolActionsProvider
config={finalConfig}
config={config}
toolCalls={allToolCalls}
>
<AskUserActionsProvider
@ -863,7 +828,7 @@ export function renderHook<Result, Props>(
return { result, rerender, unmount, waitUntilReady, generateSvg };
}
export function renderHookWithProviders<Result, Props>(
export async function renderHookWithProviders<Result, Props>(
renderCallback: (props: Props) => Result,
options: {
initialProps?: Props;
@ -876,13 +841,13 @@ export function renderHookWithProviders<Result, Props>(
mouseEventsEnabled?: boolean;
config?: Config;
} = {},
): {
): Promise<{
result: { current: Result };
rerender: (props?: Props) => void;
unmount: () => void;
waitUntilReady: () => Promise<void>;
generateSvg: () => string;
} {
}> {
const result = { current: undefined as unknown as Result };
let setPropsFn: ((props: Props) => void) | undefined;
@ -901,8 +866,8 @@ export function renderHookWithProviders<Result, Props>(
let renderResult: ReturnType<typeof render>;
act(() => {
renderResult = renderWithProviders(
await act(async () => {
renderResult = await renderWithProviders(
<Wrapper>
{}
<TestComponent initialProps={options.initialProps as Props} />

View file

@ -94,11 +94,10 @@ describe('App', () => {
};
it('should render main content and composer when not quitting', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<App />,
{
uiState: mockUIState,
config: makeFakeConfig({ useAlternateBuffer: false }),
settings: createMockSettings({ ui: { useAlternateBuffer: false } }),
},
);
@ -116,11 +115,10 @@ describe('App', () => {
quittingMessages: [{ id: 1, type: 'user', text: 'test' }],
} as UIState;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<App />,
{
uiState: quittingUIState,
config: makeFakeConfig({ useAlternateBuffer: false }),
settings: createMockSettings({ ui: { useAlternateBuffer: false } }),
},
);
@ -138,11 +136,10 @@ describe('App', () => {
pendingHistoryItems: [{ type: 'user', text: 'pending item' }],
} as UIState;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<App />,
{
uiState: quittingUIState,
config: makeFakeConfig({ useAlternateBuffer: true }),
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
},
);
@ -159,11 +156,10 @@ describe('App', () => {
dialogsVisible: true,
} as UIState;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<App />,
{
uiState: dialogUIState,
config: makeFakeConfig({ useAlternateBuffer: true }),
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
},
);
@ -187,11 +183,10 @@ describe('App', () => {
[stateKey]: true,
} as UIState;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<App />,
{
uiState,
config: makeFakeConfig({ useAlternateBuffer: true }),
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
},
);
@ -205,11 +200,10 @@ describe('App', () => {
it('should render ScreenReaderAppLayout when screen reader is enabled', async () => {
(useIsScreenReaderEnabled as Mock).mockReturnValue(true);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<App />,
{
uiState: mockUIState,
config: makeFakeConfig({ useAlternateBuffer: true }),
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
},
);
@ -225,11 +219,10 @@ describe('App', () => {
it('should render DefaultAppLayout when screen reader is not enabled', async () => {
(useIsScreenReaderEnabled as Mock).mockReturnValue(false);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<App />,
{
uiState: mockUIState,
config: makeFakeConfig({ useAlternateBuffer: true }),
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
},
);
@ -281,7 +274,7 @@ describe('App', () => {
vi.spyOn(configWithExperiment, 'isTrustedFolder').mockReturnValue(true);
vi.spyOn(configWithExperiment, 'getIdeMode').mockReturnValue(false);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<App />,
{
uiState: stateWithConfirmingTool,
@ -302,11 +295,10 @@ describe('App', () => {
describe('Snapshots', () => {
it('renders default layout correctly', async () => {
(useIsScreenReaderEnabled as Mock).mockReturnValue(false);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<App />,
{
uiState: mockUIState,
config: makeFakeConfig({ useAlternateBuffer: true }),
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
},
);
@ -317,11 +309,10 @@ describe('App', () => {
it('renders screen reader layout correctly', async () => {
(useIsScreenReaderEnabled as Mock).mockReturnValue(true);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<App />,
{
uiState: mockUIState,
config: makeFakeConfig({ useAlternateBuffer: true }),
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
},
);
@ -335,11 +326,10 @@ describe('App', () => {
...mockUIState,
dialogsVisible: true,
} as UIState;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<App />,
{
uiState: dialogUIState,
config: makeFakeConfig({ useAlternateBuffer: true }),
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
},
);

View file

@ -53,7 +53,7 @@ describe('IdeIntegrationNudge', () => {
});
it('renders correctly with default options', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<IdeIntegrationNudge {...defaultProps} />,
);
await waitUntilReady();
@ -68,7 +68,7 @@ describe('IdeIntegrationNudge', () => {
it('handles "Yes" selection', async () => {
const onComplete = vi.fn();
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<IdeIntegrationNudge {...defaultProps} onComplete={onComplete} />,
);
@ -89,7 +89,7 @@ describe('IdeIntegrationNudge', () => {
it('handles "No" selection', async () => {
const onComplete = vi.fn();
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<IdeIntegrationNudge {...defaultProps} onComplete={onComplete} />,
);
@ -115,7 +115,7 @@ describe('IdeIntegrationNudge', () => {
it('handles "Dismiss" selection', async () => {
const onComplete = vi.fn();
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<IdeIntegrationNudge {...defaultProps} onComplete={onComplete} />,
);
@ -146,7 +146,7 @@ describe('IdeIntegrationNudge', () => {
it('handles Escape key press', async () => {
const onComplete = vi.fn();
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<IdeIntegrationNudge {...defaultProps} onComplete={onComplete} />,
);
@ -173,9 +173,10 @@ describe('IdeIntegrationNudge', () => {
vi.stubEnv('GEMINI_CLI_IDE_WORKSPACE_PATH', '/tmp');
const onComplete = vi.fn();
const { lastFrame, stdin, waitUntilReady, unmount } = renderWithProviders(
<IdeIntegrationNudge {...defaultProps} onComplete={onComplete} />,
);
const { lastFrame, stdin, waitUntilReady, unmount } =
await renderWithProviders(
<IdeIntegrationNudge {...defaultProps} onComplete={onComplete} />,
);
await waitUntilReady();

View file

@ -143,7 +143,7 @@ describe('AuthDialog', () => {
for (const [key, value] of Object.entries(env)) {
vi.stubEnv(key, value as string);
}
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -161,7 +161,7 @@ describe('AuthDialog', () => {
it('filters auth types when enforcedType is set', async () => {
props.settings.merged.security.auth.enforcedType = AuthType.USE_GEMINI;
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -173,7 +173,7 @@ describe('AuthDialog', () => {
it('sets initial index to 0 when enforcedType is set', async () => {
props.settings.merged.security.auth.enforcedType = AuthType.USE_GEMINI;
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -213,7 +213,7 @@ describe('AuthDialog', () => {
},
])('selects initial auth type $desc', async ({ setup, expected }) => {
setup();
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -226,7 +226,7 @@ describe('AuthDialog', () => {
describe('handleAuthSelect', () => {
it('calls onAuthError if validation fails', async () => {
mockedValidateAuthMethod.mockReturnValue('Invalid method');
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -245,7 +245,7 @@ describe('AuthDialog', () => {
it('sets auth context with requiresRestart: true for LOGIN_WITH_GOOGLE', async () => {
mockedValidateAuthMethod.mockReturnValue(null);
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -261,7 +261,7 @@ describe('AuthDialog', () => {
it('sets auth context with empty object for other auth types', async () => {
mockedValidateAuthMethod.mockReturnValue(null);
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -278,7 +278,7 @@ describe('AuthDialog', () => {
vi.stubEnv('GEMINI_API_KEY', 'test-key-from-env');
// props.settings.merged.security.auth.selectedType is undefined here, simulating initial setup
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -297,7 +297,7 @@ describe('AuthDialog', () => {
vi.stubEnv('GEMINI_API_KEY', ''); // Empty string
// props.settings.merged.security.auth.selectedType is undefined here
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -316,7 +316,7 @@ describe('AuthDialog', () => {
// process.env['GEMINI_API_KEY'] is not set
// props.settings.merged.security.auth.selectedType is undefined here, simulating initial setup
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -337,7 +337,7 @@ describe('AuthDialog', () => {
props.settings.merged.security.auth.selectedType =
AuthType.LOGIN_WITH_GOOGLE;
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -360,7 +360,7 @@ describe('AuthDialog', () => {
vi.mocked(props.config.isBrowserLaunchSuppressed).mockReturnValue(true);
mockedValidateAuthMethod.mockReturnValue(null);
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -383,7 +383,7 @@ describe('AuthDialog', () => {
it('displays authError when provided', async () => {
props.authError = 'Something went wrong';
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -429,7 +429,7 @@ describe('AuthDialog', () => {
},
])('$desc', async ({ setup, expectations }) => {
setup();
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -442,7 +442,7 @@ describe('AuthDialog', () => {
describe('Snapshots', () => {
it('renders correctly with default props', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -452,7 +452,7 @@ describe('AuthDialog', () => {
it('renders correctly with auth error', async () => {
props.authError = 'Something went wrong';
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();
@ -462,7 +462,7 @@ describe('AuthDialog', () => {
it('renders correctly with enforced auth type', async () => {
props.settings.merged.security.auth.enforcedType = AuthType.USE_GEMINI;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AuthDialog {...props} />,
);
await waitUntilReady();

View file

@ -73,7 +73,7 @@ describe('BannedAccountDialog', () => {
});
it('renders the suspension message from accountSuspensionInfo', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<BannedAccountDialog
accountSuspensionInfo={DEFAULT_SUSPENSION_INFO}
onExit={onExit}
@ -89,7 +89,7 @@ describe('BannedAccountDialog', () => {
});
it('renders menu options with appeal link text from response', async () => {
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<BannedAccountDialog
accountSuspensionInfo={DEFAULT_SUSPENSION_INFO}
onExit={onExit}
@ -109,7 +109,7 @@ describe('BannedAccountDialog', () => {
const infoWithoutUrl: AccountSuspensionInfo = {
message: 'Account suspended.',
};
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<BannedAccountDialog
accountSuspensionInfo={infoWithoutUrl}
onExit={onExit}
@ -129,7 +129,7 @@ describe('BannedAccountDialog', () => {
message: 'Account suspended.',
appealUrl: 'https://example.com/appeal',
};
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<BannedAccountDialog
accountSuspensionInfo={infoWithoutLinkText}
onExit={onExit}
@ -143,7 +143,7 @@ describe('BannedAccountDialog', () => {
});
it('opens browser when appeal option is selected', async () => {
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<BannedAccountDialog
accountSuspensionInfo={DEFAULT_SUSPENSION_INFO}
onExit={onExit}
@ -162,7 +162,7 @@ describe('BannedAccountDialog', () => {
it('shows URL when browser cannot be launched', async () => {
mockedShouldLaunchBrowser.mockReturnValue(false);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<BannedAccountDialog
accountSuspensionInfo={DEFAULT_SUSPENSION_INFO}
onExit={onExit}
@ -180,7 +180,7 @@ describe('BannedAccountDialog', () => {
});
it('calls onExit when "Exit" is selected', async () => {
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<BannedAccountDialog
accountSuspensionInfo={DEFAULT_SUSPENSION_INFO}
onExit={onExit}
@ -196,7 +196,7 @@ describe('BannedAccountDialog', () => {
});
it('calls onChangeAuth when "Change authentication" is selected', async () => {
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<BannedAccountDialog
accountSuspensionInfo={DEFAULT_SUSPENSION_INFO}
onExit={onExit}
@ -212,7 +212,7 @@ describe('BannedAccountDialog', () => {
});
it('exits on escape key', async () => {
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<BannedAccountDialog
accountSuspensionInfo={DEFAULT_SUSPENSION_INFO}
onExit={onExit}
@ -227,7 +227,7 @@ describe('BannedAccountDialog', () => {
});
it('renders snapshot correctly', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<BannedAccountDialog
accountSuspensionInfo={DEFAULT_SUSPENSION_INFO}
onExit={onExit}

View file

@ -25,7 +25,7 @@ describe('AboutBox', () => {
};
it('renders with required props', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AboutBox {...defaultProps} />,
);
await waitUntilReady();
@ -46,7 +46,7 @@ describe('AboutBox', () => {
['tier', 'Enterprise', 'Tier'],
])('renders optional prop %s', async (prop, value, label) => {
const props = { ...defaultProps, [prop]: value };
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AboutBox {...props} />,
);
await waitUntilReady();
@ -58,7 +58,7 @@ describe('AboutBox', () => {
it('renders Auth Method with email when userEmail is provided', async () => {
const props = { ...defaultProps, userEmail: 'test@example.com' };
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AboutBox {...props} />,
);
await waitUntilReady();
@ -69,7 +69,7 @@ describe('AboutBox', () => {
it('renders Auth Method correctly when not oauth', async () => {
const props = { ...defaultProps, selectedAuthType: 'api-key' };
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AboutBox {...props} />,
);
await waitUntilReady();

View file

@ -17,7 +17,7 @@ describe('AdminSettingsChangedDialog', () => {
});
it('renders correctly', async () => {
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AdminSettingsChangedDialog />,
);
await waitUntilReady();
@ -25,7 +25,7 @@ describe('AdminSettingsChangedDialog', () => {
});
it('restarts on "r" key press', async () => {
const { stdin, waitUntilReady } = renderWithProviders(
const { stdin, waitUntilReady } = await renderWithProviders(
<AdminSettingsChangedDialog />,
{
uiActions: {
@ -43,7 +43,7 @@ describe('AdminSettingsChangedDialog', () => {
});
it.each(['r', 'R'])('restarts on "%s" key press', async (key) => {
const { stdin, waitUntilReady } = renderWithProviders(
const { stdin, waitUntilReady } = await renderWithProviders(
<AdminSettingsChangedDialog />,
{
uiActions: {

View file

@ -115,7 +115,7 @@ describe('AgentConfigDialog', () => {
settings: LoadedSettings,
definition: AgentDefinition = createMockAgentDefinition(),
) => {
const result = renderWithProviders(
const result = await renderWithProviders(
<AgentConfigDialog
agentName="test-agent"
displayName="Test Agent"
@ -323,7 +323,7 @@ describe('AgentConfigDialog', () => {
const settings = createMockSettings();
// Agent config has about 6 base items + 2 per tool
// Render with very small height (20)
const { lastFrame, unmount } = renderWithProviders(
const { lastFrame, unmount } = await renderWithProviders(
<AgentConfigDialog
agentName="test-agent"
displayName="Test Agent"

View file

@ -108,7 +108,7 @@ describe('AlternateBufferQuittingDisplay', () => {
it('renders with active and pending tool messages', async () => {
persistentStateMock.setData({ tipsShown: 0 });
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AlternateBufferQuittingDisplay />,
{
uiState: {
@ -125,7 +125,7 @@ describe('AlternateBufferQuittingDisplay', () => {
it('renders with empty history and no pending items', async () => {
persistentStateMock.setData({ tipsShown: 0 });
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AlternateBufferQuittingDisplay />,
{
uiState: {
@ -142,7 +142,7 @@ describe('AlternateBufferQuittingDisplay', () => {
it('renders with history but no pending items', async () => {
persistentStateMock.setData({ tipsShown: 0 });
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AlternateBufferQuittingDisplay />,
{
uiState: {
@ -159,7 +159,7 @@ describe('AlternateBufferQuittingDisplay', () => {
it('renders with pending items but no history', async () => {
persistentStateMock.setData({ tipsShown: 0 });
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AlternateBufferQuittingDisplay />,
{
uiState: {
@ -195,7 +195,7 @@ describe('AlternateBufferQuittingDisplay', () => {
],
},
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AlternateBufferQuittingDisplay />,
{
uiState: {
@ -220,7 +220,7 @@ describe('AlternateBufferQuittingDisplay', () => {
{ id: 1, type: 'user', text: 'Hello Gemini' },
{ id: 2, type: 'gemini', text: 'Hello User!' },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AlternateBufferQuittingDisplay />,
{
uiState: {

View file

@ -10,7 +10,6 @@ import {
} from '../../test-utils/render.js';
import { AppHeader } from './AppHeader.js';
import { describe, it, expect, vi } from 'vitest';
import { makeFakeConfig } from '@google/gemini-cli-core';
import crypto from 'node:crypto';
vi.mock('../utils/terminalSetup.js', () => ({
@ -19,7 +18,6 @@ vi.mock('../utils/terminalSetup.js', () => ({
describe('<AppHeader />', () => {
it('should render the banner with default text', async () => {
const mockConfig = makeFakeConfig();
const uiState = {
history: [],
bannerData: {
@ -29,10 +27,9 @@ describe('<AppHeader />', () => {
bannerVisible: true,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AppHeader version="1.0.0" />,
{
config: mockConfig,
uiState,
},
);
@ -44,7 +41,6 @@ describe('<AppHeader />', () => {
});
it('should render the banner with warning text', async () => {
const mockConfig = makeFakeConfig();
const uiState = {
history: [],
bannerData: {
@ -54,10 +50,9 @@ describe('<AppHeader />', () => {
bannerVisible: true,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AppHeader version="1.0.0" />,
{
config: mockConfig,
uiState,
},
);
@ -69,7 +64,6 @@ describe('<AppHeader />', () => {
});
it('should not render the banner when no flags are set', async () => {
const mockConfig = makeFakeConfig();
const uiState = {
history: [],
bannerData: {
@ -78,10 +72,9 @@ describe('<AppHeader />', () => {
},
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AppHeader version="1.0.0" />,
{
config: mockConfig,
uiState,
},
);
@ -93,7 +86,6 @@ describe('<AppHeader />', () => {
});
it('should not render the default banner if shown count is 5 or more', async () => {
const mockConfig = makeFakeConfig();
const uiState = {
history: [],
bannerData: {
@ -111,10 +103,9 @@ describe('<AppHeader />', () => {
},
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AppHeader version="1.0.0" />,
{
config: mockConfig,
uiState,
},
);
@ -126,7 +117,6 @@ describe('<AppHeader />', () => {
});
it('should increment the version count when default banner is displayed', async () => {
const mockConfig = makeFakeConfig();
const uiState = {
history: [],
bannerData: {
@ -139,10 +129,9 @@ describe('<AppHeader />', () => {
// and interfering with the expected persistentState.set call.
persistentStateMock.setData({ tipsShown: 10 });
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<AppHeader version="1.0.0" />,
{
config: mockConfig,
uiState,
},
);
@ -161,7 +150,6 @@ describe('<AppHeader />', () => {
});
it('should render banner text with unescaped newlines', async () => {
const mockConfig = makeFakeConfig();
const uiState = {
history: [],
bannerData: {
@ -171,10 +159,9 @@ describe('<AppHeader />', () => {
bannerVisible: true,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AppHeader version="1.0.0" />,
{
config: mockConfig,
uiState,
},
);
@ -185,7 +172,6 @@ describe('<AppHeader />', () => {
});
it('should render Tips when tipsShown is less than 10', async () => {
const mockConfig = makeFakeConfig();
const uiState = {
history: [],
bannerData: {
@ -197,10 +183,9 @@ describe('<AppHeader />', () => {
persistentStateMock.setData({ tipsShown: 5 });
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AppHeader version="1.0.0" />,
{
config: mockConfig,
uiState,
},
);
@ -212,7 +197,6 @@ describe('<AppHeader />', () => {
});
it('should NOT render Tips when tipsShown is 10 or more', async () => {
const mockConfig = makeFakeConfig();
const uiState = {
bannerData: {
defaultText: '',
@ -222,10 +206,9 @@ describe('<AppHeader />', () => {
persistentStateMock.setData({ tipsShown: 10 });
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<AppHeader version="1.0.0" />,
{
config: mockConfig,
uiState,
},
);
@ -238,7 +221,6 @@ describe('<AppHeader />', () => {
it('should show tips until they have been shown 10 times (persistence flow)', async () => {
persistentStateMock.setData({ tipsShown: 9 });
const mockConfig = makeFakeConfig();
const uiState = {
history: [],
bannerData: {
@ -249,8 +231,7 @@ describe('<AppHeader />', () => {
};
// First session
const session1 = renderWithProviders(<AppHeader version="1.0.0" />, {
config: mockConfig,
const session1 = await renderWithProviders(<AppHeader version="1.0.0" />, {
uiState,
});
await session1.waitUntilReady();
@ -260,9 +241,10 @@ describe('<AppHeader />', () => {
session1.unmount();
// Second session - state is persisted in the fake
const session2 = renderWithProviders(<AppHeader version="1.0.0" />, {
config: mockConfig,
});
const session2 = await renderWithProviders(
<AppHeader version="1.0.0" />,
{},
);
await session2.waitUntilReady();
expect(session2.lastFrame()).not.toContain('Tips');

View file

@ -32,7 +32,7 @@ describe('AppHeader Icon Rendering', () => {
it('renders the default icon in standard terminals', async () => {
vi.mocked(isAppleTerminal).mockReturnValue(false);
const result = renderWithProviders(<AppHeader version="1.0.0" />);
const result = await renderWithProviders(<AppHeader version="1.0.0" />);
await result.waitUntilReady();
await expect(result).toMatchSvgSnapshot();
@ -41,7 +41,7 @@ describe('AppHeader Icon Rendering', () => {
it('renders the symmetric icon in Apple Terminal', async () => {
vi.mocked(isAppleTerminal).mockReturnValue(true);
const result = renderWithProviders(<AppHeader version="1.0.0" />);
const result = await renderWithProviders(<AppHeader version="1.0.0" />);
await result.waitUntilReady();
await expect(result).toMatchSvgSnapshot();

View file

@ -48,7 +48,7 @@ describe('AskUserDialog', () => {
];
it('renders question and options', async () => {
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={authQuestion}
onSubmit={vi.fn()}
@ -140,7 +140,7 @@ describe('AskUserDialog', () => {
])('Submission: $name', ({ name, questions, actions, expectedSubmit }) => {
it(`submits correct values for ${name}`, async () => {
const onSubmit = vi.fn();
const { stdin } = renderWithProviders(
const { stdin } = await renderWithProviders(
<AskUserDialog
questions={questions}
onSubmit={onSubmit}
@ -172,7 +172,7 @@ describe('AskUserDialog', () => {
},
] as Question[];
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={questions}
onSubmit={vi.fn()}
@ -196,7 +196,7 @@ describe('AskUserDialog', () => {
it('handles custom option in single select with inline typing', async () => {
const onSubmit = vi.fn();
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={authQuestion}
onSubmit={onSubmit}
@ -245,7 +245,7 @@ describe('AskUserDialog', () => {
];
const onSubmit = vi.fn();
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={authQuestionWithOther}
onSubmit={onSubmit}
@ -307,7 +307,7 @@ describe('AskUserDialog', () => {
},
];
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={questions}
onSubmit={vi.fn()}
@ -341,7 +341,7 @@ describe('AskUserDialog', () => {
);
it('navigates to custom option when typing unbound characters (Type-to-Jump)', async () => {
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={authQuestion}
onSubmit={vi.fn()}
@ -397,7 +397,7 @@ describe('AskUserDialog', () => {
},
];
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={multiQuestions}
onSubmit={vi.fn()}
@ -412,7 +412,7 @@ describe('AskUserDialog', () => {
});
it('hides progress header for single question', async () => {
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={authQuestion}
onSubmit={vi.fn()}
@ -427,7 +427,7 @@ describe('AskUserDialog', () => {
});
it('shows keyboard hints', async () => {
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={authQuestion}
onSubmit={vi.fn()}
@ -461,7 +461,7 @@ describe('AskUserDialog', () => {
},
];
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={multiQuestions}
onSubmit={vi.fn()}
@ -508,7 +508,7 @@ describe('AskUserDialog', () => {
];
const onSubmit = vi.fn();
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={multiQuestions}
onSubmit={onSubmit}
@ -582,7 +582,7 @@ describe('AskUserDialog', () => {
},
];
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={multiQuestions}
onSubmit={vi.fn()}
@ -614,7 +614,7 @@ describe('AskUserDialog', () => {
},
];
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={multiQuestions}
onSubmit={vi.fn()}
@ -664,7 +664,7 @@ describe('AskUserDialog', () => {
},
];
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={multiQuestions}
onSubmit={vi.fn()}
@ -703,7 +703,7 @@ describe('AskUserDialog', () => {
];
const onSubmit = vi.fn();
const { stdin } = renderWithProviders(
const { stdin } = await renderWithProviders(
<AskUserDialog
questions={multiQuestions}
onSubmit={onSubmit}
@ -736,7 +736,7 @@ describe('AskUserDialog', () => {
},
];
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={textQuestion}
onSubmit={vi.fn()}
@ -759,7 +759,7 @@ describe('AskUserDialog', () => {
},
];
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={textQuestion}
onSubmit={vi.fn()}
@ -782,7 +782,7 @@ describe('AskUserDialog', () => {
},
];
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={textQuestion}
onSubmit={vi.fn()}
@ -820,7 +820,7 @@ describe('AskUserDialog', () => {
},
];
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={textQuestion}
onSubmit={vi.fn()}
@ -853,7 +853,7 @@ describe('AskUserDialog', () => {
},
];
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={mixedQuestions}
onSubmit={vi.fn()}
@ -903,7 +903,7 @@ describe('AskUserDialog', () => {
];
const onSubmit = vi.fn();
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={mixedQuestions}
onSubmit={onSubmit}
@ -959,7 +959,7 @@ describe('AskUserDialog', () => {
];
const onSubmit = vi.fn();
const { stdin } = renderWithProviders(
const { stdin } = await renderWithProviders(
<AskUserDialog
questions={textQuestion}
onSubmit={onSubmit}
@ -986,7 +986,7 @@ describe('AskUserDialog', () => {
];
const onCancel = vi.fn();
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={textQuestion}
onSubmit={vi.fn()}
@ -1036,7 +1036,7 @@ describe('AskUserDialog', () => {
},
];
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={multiQuestions}
onSubmit={vi.fn()}
@ -1102,7 +1102,7 @@ describe('AskUserDialog', () => {
];
const onSubmit = vi.fn();
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={multiQuestions}
onSubmit={onSubmit}
@ -1154,7 +1154,7 @@ describe('AskUserDialog', () => {
},
];
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={questions}
onSubmit={vi.fn()}
@ -1184,7 +1184,7 @@ describe('AskUserDialog', () => {
},
];
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={questions}
onSubmit={vi.fn()}
@ -1217,7 +1217,7 @@ describe('AskUserDialog', () => {
},
];
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={questions}
onSubmit={vi.fn()}
@ -1248,7 +1248,7 @@ describe('AskUserDialog', () => {
},
];
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={questions}
onSubmit={vi.fn()}
@ -1287,7 +1287,7 @@ describe('AskUserDialog', () => {
availableTerminalHeight: 5, // Small height to force scroll arrows
} as UIState;
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<UIStateContext.Provider value={mockUIState}>
<AskUserDialog
questions={questions}
@ -1326,7 +1326,7 @@ describe('AskUserDialog', () => {
availableTerminalHeight: 5,
} as UIState;
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<UIStateContext.Provider value={mockUIState}>
<AskUserDialog
questions={questions}
@ -1365,7 +1365,7 @@ describe('AskUserDialog', () => {
},
];
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={questions}
onSubmit={vi.fn()}
@ -1399,7 +1399,7 @@ describe('AskUserDialog', () => {
},
];
const { stdin, lastFrame, waitUntilReady } = renderWithProviders(
const { stdin, lastFrame, waitUntilReady } = await renderWithProviders(
<AskUserDialog
questions={questions}
onSubmit={vi.fn()}
@ -1432,7 +1432,7 @@ describe('AskUserDialog', () => {
];
const onSubmit = vi.fn();
const { stdin } = renderWithProviders(
const { stdin } = await renderWithProviders(
<AskUserDialog
questions={questions}
onSubmit={onSubmit}

View file

@ -14,7 +14,7 @@ describe('Banner', () => {
['info mode', false, 'Info Message'],
['multi-line warning', true, 'Title Line\\nBody Line 1\\nBody Line 2'],
])('renders in %s', async (_, isWarning, text) => {
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<Banner bannerText={text} isWarning={isWarning} width={80} />,
);
await renderResult.waitUntilReady();
@ -24,7 +24,7 @@ describe('Banner', () => {
it('handles newlines in text', async () => {
const text = 'Line 1\\nLine 2';
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<Banner bannerText={text} isWarning={false} width={80} />,
);
await renderResult.waitUntilReady();

View file

@ -30,7 +30,7 @@ describe('Key Bubbling Regression', () => {
];
it('does not navigate when pressing "j" or "k" in a focused text input', async () => {
const { stdin, lastFrame } = renderWithProviders(
const { stdin, lastFrame } = await renderWithProviders(
<AskUserDialog
questions={choiceQuestion}
onSubmit={vi.fn()}

View file

@ -17,7 +17,9 @@ describe('<CliSpinner />', () => {
it('should increment debugNumAnimatedComponents on mount and decrement on unmount', async () => {
expect(debugState.debugNumAnimatedComponents).toBe(0);
const { waitUntilReady, unmount } = renderWithProviders(<CliSpinner />);
const { waitUntilReady, unmount } = await renderWithProviders(
<CliSpinner />,
);
await waitUntilReady();
expect(debugState.debugNumAnimatedComponents).toBe(1);
unmount();
@ -26,7 +28,7 @@ describe('<CliSpinner />', () => {
it('should not render when showSpinner is false', async () => {
const settings = createMockSettings({ ui: { showSpinner: false } });
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<CliSpinner />,
{ settings },
);

View file

@ -96,7 +96,7 @@ describe('ColorsDisplay', () => {
it('renders correctly', async () => {
const mockTheme = themeManager.getActiveTheme();
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ColorsDisplay activeTheme={mockTheme} />,
);
await waitUntilReady();

View file

@ -43,7 +43,7 @@ describe('ConfigInitDisplay', () => {
});
it('renders initial state', async () => {
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<ConfigInitDisplay />,
);
await waitUntilReady();
@ -59,7 +59,7 @@ describe('ConfigInitDisplay', () => {
return coreEvents;
});
const { lastFrame } = renderWithProviders(<ConfigInitDisplay />);
const { lastFrame } = await renderWithProviders(<ConfigInitDisplay />);
// Wait for listener to be registered
await waitFor(() => {
@ -97,7 +97,7 @@ describe('ConfigInitDisplay', () => {
return coreEvents;
});
const { lastFrame } = renderWithProviders(<ConfigInitDisplay />);
const { lastFrame } = await renderWithProviders(<ConfigInitDisplay />);
await waitFor(() => {
if (!listener) throw new Error('Listener not registered yet');
@ -133,7 +133,7 @@ describe('ConfigInitDisplay', () => {
return coreEvents;
});
const { lastFrame } = renderWithProviders(<ConfigInitDisplay />);
const { lastFrame } = await renderWithProviders(<ConfigInitDisplay />);
await waitFor(() => {
if (!listener) throw new Error('Listener not registered yet');

View file

@ -19,7 +19,7 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
describe('ContextUsageDisplay', () => {
it('renders correct percentage used', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ContextUsageDisplay
promptTokenCount={5000}
model="gemini-pro"
@ -33,7 +33,7 @@ describe('ContextUsageDisplay', () => {
});
it('renders correctly when usage is 0%', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ContextUsageDisplay
promptTokenCount={0}
model="gemini-pro"
@ -47,7 +47,7 @@ describe('ContextUsageDisplay', () => {
});
it('renders abbreviated label when terminal width is small', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ContextUsageDisplay
promptTokenCount={2000}
model="gemini-pro"
@ -63,7 +63,7 @@ describe('ContextUsageDisplay', () => {
});
it('renders 80% correctly', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ContextUsageDisplay
promptTokenCount={8000}
model="gemini-pro"
@ -77,7 +77,7 @@ describe('ContextUsageDisplay', () => {
});
it('renders 100% when full', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ContextUsageDisplay
promptTokenCount={10000}
model="gemini-pro"

View file

@ -30,7 +30,7 @@ vi.mock('./shared/ScrollableList.js', () => ({
describe('DetailedMessagesDisplay', () => {
it('renders nothing when messages are empty', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<DetailedMessagesDisplay
messages={[]}
maxHeight={10}
@ -54,7 +54,7 @@ describe('DetailedMessagesDisplay', () => {
{ type: 'debug', content: 'Debug message', count: 1 },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<DetailedMessagesDisplay
messages={messages}
maxHeight={20}
@ -77,7 +77,7 @@ describe('DetailedMessagesDisplay', () => {
{ type: 'error', content: 'Error message', count: 1 },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<DetailedMessagesDisplay
messages={messages}
maxHeight={20}
@ -98,7 +98,7 @@ describe('DetailedMessagesDisplay', () => {
{ type: 'error', content: 'Error message', count: 1 },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<DetailedMessagesDisplay
messages={messages}
maxHeight={20}
@ -119,7 +119,7 @@ describe('DetailedMessagesDisplay', () => {
{ type: 'log', content: 'Repeated message', count: 5 },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<DetailedMessagesDisplay
messages={messages}
maxHeight={10}

View file

@ -104,7 +104,7 @@ describe('DialogManager', () => {
};
it('renders nothing by default', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<DialogManager {...defaultProps} />,
{ uiState: baseUiState as Partial<UIState> as UIState },
);
@ -197,7 +197,7 @@ describe('DialogManager', () => {
it.each(testCases)(
'renders %s when state is %o',
async (uiStateOverride, expectedComponent) => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<DialogManager {...defaultProps} />,
{
uiState: {

View file

@ -51,11 +51,11 @@ describe('EditorSettingsDialog', () => {
vi.clearAllMocks();
});
const renderWithProvider = (ui: React.ReactElement) =>
const renderWithProvider = async (ui: React.ReactElement) =>
renderWithProviders(ui);
it('renders correctly', async () => {
const { lastFrame, waitUntilReady } = renderWithProvider(
const { lastFrame, waitUntilReady } = await renderWithProvider(
<EditorSettingsDialog
onSelect={vi.fn()}
settings={mockSettings}
@ -68,7 +68,7 @@ describe('EditorSettingsDialog', () => {
it('calls onSelect when an editor is selected', async () => {
const onSelect = vi.fn();
const { lastFrame, waitUntilReady } = renderWithProvider(
const { lastFrame, waitUntilReady } = await renderWithProvider(
<EditorSettingsDialog
onSelect={onSelect}
settings={mockSettings}
@ -81,7 +81,7 @@ describe('EditorSettingsDialog', () => {
});
it('switches focus between editor and scope sections on Tab', async () => {
const { lastFrame, stdin, waitUntilReady } = renderWithProvider(
const { lastFrame, stdin, waitUntilReady } = await renderWithProvider(
<EditorSettingsDialog
onSelect={vi.fn()}
settings={mockSettings}
@ -127,7 +127,7 @@ describe('EditorSettingsDialog', () => {
it('calls onExit when Escape is pressed', async () => {
const onExit = vi.fn();
const { stdin, waitUntilReady } = renderWithProvider(
const { stdin, waitUntilReady } = await renderWithProvider(
<EditorSettingsDialog
onSelect={vi.fn()}
settings={mockSettings}
@ -162,7 +162,7 @@ describe('EditorSettingsDialog', () => {
},
} as unknown as LoadedSettings;
const { lastFrame, waitUntilReady } = renderWithProvider(
const { lastFrame, waitUntilReady } = await renderWithProvider(
<EditorSettingsDialog
onSelect={vi.fn()}
settings={settingsWithOtherScope}

View file

@ -30,7 +30,7 @@ describe('EmptyWalletDialog', () => {
describe('rendering', () => {
it('should match snapshot with fallback available', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<EmptyWalletDialog
failedModel="gemini-2.5-pro"
fallbackModel="gemini-3-flash-preview"
@ -45,7 +45,7 @@ describe('EmptyWalletDialog', () => {
});
it('should match snapshot without fallback', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<EmptyWalletDialog
failedModel="gemini-2.5-pro"
onChoice={mockOnChoice}
@ -58,7 +58,7 @@ describe('EmptyWalletDialog', () => {
});
it('should display the model name and usage limit message', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<EmptyWalletDialog
failedModel="gemini-2.5-pro"
onChoice={mockOnChoice}
@ -73,7 +73,7 @@ describe('EmptyWalletDialog', () => {
});
it('should display purchase prompt and credits update notice', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<EmptyWalletDialog
failedModel="gemini-2.5-pro"
onChoice={mockOnChoice}
@ -90,7 +90,7 @@ describe('EmptyWalletDialog', () => {
});
it('should display reset time when provided', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<EmptyWalletDialog
failedModel="gemini-2.5-pro"
resetTime="3:45 PM"
@ -106,7 +106,7 @@ describe('EmptyWalletDialog', () => {
});
it('should not display reset time when not provided', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<EmptyWalletDialog
failedModel="gemini-2.5-pro"
onChoice={mockOnChoice}
@ -120,7 +120,7 @@ describe('EmptyWalletDialog', () => {
});
it('should display slash command hints', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<EmptyWalletDialog
failedModel="gemini-2.5-pro"
onChoice={mockOnChoice}
@ -139,7 +139,7 @@ describe('EmptyWalletDialog', () => {
describe('onChoice handling', () => {
it('should call onGetCredits and onChoice when get_credits is selected', async () => {
// get_credits is the first item, so just press Enter
const { unmount, stdin, waitUntilReady } = renderWithProviders(
const { unmount, stdin, waitUntilReady } = await renderWithProviders(
<EmptyWalletDialog
failedModel="gemini-2.5-pro"
onChoice={mockOnChoice}
@ -158,7 +158,7 @@ describe('EmptyWalletDialog', () => {
});
it('should call onChoice without onGetCredits when onGetCredits is not provided', async () => {
const { unmount, stdin, waitUntilReady } = renderWithProviders(
const { unmount, stdin, waitUntilReady } = await renderWithProviders(
<EmptyWalletDialog
failedModel="gemini-2.5-pro"
onChoice={mockOnChoice}
@ -177,7 +177,7 @@ describe('EmptyWalletDialog', () => {
it('should call onChoice with use_fallback when selected', async () => {
// With fallback: items are [get_credits, use_fallback, stop]
// use_fallback is the second item: Down + Enter
const { unmount, stdin, waitUntilReady } = renderWithProviders(
const { unmount, stdin, waitUntilReady } = await renderWithProviders(
<EmptyWalletDialog
failedModel="gemini-2.5-pro"
fallbackModel="gemini-3-flash-preview"
@ -198,7 +198,7 @@ describe('EmptyWalletDialog', () => {
it('should call onChoice with stop when selected', async () => {
// Without fallback: items are [get_credits, stop]
// stop is the second item: Down + Enter
const { unmount, stdin, waitUntilReady } = renderWithProviders(
const { unmount, stdin, waitUntilReady } = await renderWithProviders(
<EmptyWalletDialog
failedModel="gemini-2.5-pro"
onChoice={mockOnChoice}

View file

@ -139,7 +139,7 @@ Implement a comprehensive authentication system with multiple providers.
vi.restoreAllMocks();
});
const renderDialog = (options?: { useAlternateBuffer?: boolean }) => {
const renderDialog = async (options?: { useAlternateBuffer?: boolean }) => {
const useAlternateBuffer = options?.useAlternateBuffer ?? true;
return renderWithProviders(
<ExitPlanModeDialog
@ -176,7 +176,9 @@ Implement a comprehensive authentication system with multiple providers.
'useAlternateBuffer: $useAlternateBuffer',
({ useAlternateBuffer }) => {
it('renders correctly with plan content', async () => {
const { lastFrame } = renderDialog({ useAlternateBuffer });
const { lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
// Advance timers to pass the debounce period
await act(async () => {
@ -199,7 +201,9 @@ Implement a comprehensive authentication system with multiple providers.
});
it('calls onApprove with AUTO_EDIT when first option is selected', async () => {
const { stdin, lastFrame } = renderDialog({ useAlternateBuffer });
const { stdin, lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();
@ -217,7 +221,9 @@ Implement a comprehensive authentication system with multiple providers.
});
it('calls onApprove with DEFAULT when second option is selected', async () => {
const { stdin, lastFrame } = renderDialog({ useAlternateBuffer });
const { stdin, lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();
@ -236,7 +242,9 @@ Implement a comprehensive authentication system with multiple providers.
});
it('calls onFeedback when feedback is typed and submitted', async () => {
const { stdin, lastFrame } = renderDialog({ useAlternateBuffer });
const { stdin, lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();
@ -267,7 +275,9 @@ Implement a comprehensive authentication system with multiple providers.
});
it('calls onCancel when Esc is pressed', async () => {
const { stdin, lastFrame } = renderDialog({ useAlternateBuffer });
const { stdin, lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();
@ -293,7 +303,9 @@ Implement a comprehensive authentication system with multiple providers.
error: 'File not found',
});
const { lastFrame } = renderDialog({ useAlternateBuffer });
const { lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();
@ -309,7 +321,9 @@ Implement a comprehensive authentication system with multiple providers.
it('displays error state when plan file is empty', async () => {
vi.mocked(validatePlanContent).mockResolvedValue('Plan file is empty.');
const { lastFrame } = renderDialog({ useAlternateBuffer });
const { lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();
@ -328,7 +342,9 @@ Implement a comprehensive authentication system with multiple providers.
returnDisplay: 'Read file',
});
const { lastFrame } = renderDialog({ useAlternateBuffer });
const { lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();
@ -344,7 +360,9 @@ Implement a comprehensive authentication system with multiple providers.
});
it('allows number key quick selection', async () => {
const { stdin, lastFrame } = renderDialog({ useAlternateBuffer });
const { stdin, lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();
@ -363,7 +381,9 @@ Implement a comprehensive authentication system with multiple providers.
});
it('clears feedback text when Ctrl+C is pressed while editing', async () => {
const { stdin, lastFrame } = renderDialog({ useAlternateBuffer });
const { stdin, lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();
@ -420,7 +440,7 @@ Implement a comprehensive authentication system with multiple providers.
return <>{children}</>;
};
const { stdin, lastFrame } = renderWithProviders(
const { stdin, lastFrame } = await renderWithProviders(
<BubbleListener>
<ExitPlanModeDialog
planPath={mockPlanFullPath}
@ -491,7 +511,9 @@ Implement a comprehensive authentication system with multiple providers.
});
it('does not submit empty feedback when Enter is pressed', async () => {
const { stdin, lastFrame } = renderDialog({ useAlternateBuffer });
const { stdin, lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();
@ -518,7 +540,9 @@ Implement a comprehensive authentication system with multiple providers.
});
it('allows arrow navigation while typing feedback to change selection', async () => {
const { stdin, lastFrame } = renderDialog({ useAlternateBuffer });
const { stdin, lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();
@ -550,7 +574,9 @@ Implement a comprehensive authentication system with multiple providers.
});
it('automatically submits feedback when Ctrl+X is used to edit the plan', async () => {
const { stdin, lastFrame } = renderDialog({ useAlternateBuffer });
const { stdin, lastFrame } = await act(async () =>
renderDialog({ useAlternateBuffer }),
);
await act(async () => {
vi.runAllTimers();

View file

@ -48,7 +48,7 @@ describe('FolderTrustDialog', () => {
});
it('should render the dialog with title and description', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<FolderTrustDialog onSelect={vi.fn()} />,
);
await waitUntilReady();
@ -72,7 +72,7 @@ describe('FolderTrustDialog', () => {
discoveryErrors: [],
securityWarnings: [],
};
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<FolderTrustDialog
onSelect={vi.fn()}
discoveryResults={discoveryResults}
@ -103,7 +103,7 @@ describe('FolderTrustDialog', () => {
discoveryErrors: [],
securityWarnings: [],
};
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<FolderTrustDialog
onSelect={vi.fn()}
discoveryResults={discoveryResults}
@ -135,7 +135,7 @@ describe('FolderTrustDialog', () => {
discoveryErrors: [],
securityWarnings: [],
};
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<FolderTrustDialog
onSelect={vi.fn()}
discoveryResults={discoveryResults}
@ -165,7 +165,7 @@ describe('FolderTrustDialog', () => {
securityWarnings: [],
};
const { lastFrame, unmount } = renderWithProviders(
const { lastFrame, unmount } = await renderWithProviders(
<FolderTrustDialog
onSelect={vi.fn()}
discoveryResults={discoveryResults}
@ -192,7 +192,7 @@ describe('FolderTrustDialog', () => {
// because it's handled in AppContainer.
// But we can re-render with constrainHeight: false.
const { lastFrame: lastFrameExpanded, unmount: unmountExpanded } =
renderWithProviders(
await renderWithProviders(
<FolderTrustDialog
onSelect={vi.fn()}
discoveryResults={discoveryResults}
@ -217,9 +217,10 @@ describe('FolderTrustDialog', () => {
it('should display exit message and call process.exit and not call onSelect when escape is pressed', async () => {
const onSelect = vi.fn();
const { lastFrame, stdin, waitUntilReady, unmount } = renderWithProviders(
<FolderTrustDialog onSelect={onSelect} isRestarting={false} />,
);
const { lastFrame, stdin, waitUntilReady, unmount } =
await renderWithProviders(
<FolderTrustDialog onSelect={onSelect} isRestarting={false} />,
);
await waitUntilReady();
await act(async () => {
@ -245,7 +246,7 @@ describe('FolderTrustDialog', () => {
});
it('should display restart message when isRestarting is true', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<FolderTrustDialog onSelect={vi.fn()} isRestarting={true} />,
);
await waitUntilReady();
@ -259,7 +260,7 @@ describe('FolderTrustDialog', () => {
const relaunchApp = vi
.spyOn(processUtils, 'relaunchApp')
.mockResolvedValue(undefined);
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<FolderTrustDialog onSelect={vi.fn()} isRestarting={true} />,
);
await waitUntilReady();
@ -274,7 +275,7 @@ describe('FolderTrustDialog', () => {
const relaunchApp = vi
.spyOn(processUtils, 'relaunchApp')
.mockResolvedValue(undefined);
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<FolderTrustDialog onSelect={vi.fn()} isRestarting={true} />,
);
await waitUntilReady();
@ -288,7 +289,7 @@ describe('FolderTrustDialog', () => {
});
it('should not call process.exit when "r" is pressed and isRestarting is false', async () => {
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<FolderTrustDialog onSelect={vi.fn()} isRestarting={false} />,
);
await waitUntilReady();
@ -307,7 +308,7 @@ describe('FolderTrustDialog', () => {
describe('directory display', () => {
it('should correctly display the folder name for a nested directory', async () => {
mockedCwd.mockReturnValue('/home/user/project');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<FolderTrustDialog onSelect={vi.fn()} />,
);
await waitUntilReady();
@ -317,7 +318,7 @@ describe('FolderTrustDialog', () => {
it('should correctly display the parent folder name for a nested directory', async () => {
mockedCwd.mockReturnValue('/home/user/project');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<FolderTrustDialog onSelect={vi.fn()} />,
);
await waitUntilReady();
@ -327,7 +328,7 @@ describe('FolderTrustDialog', () => {
it('should correctly display an empty parent folder name for a directory directly under root', async () => {
mockedCwd.mockReturnValue('/project');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<FolderTrustDialog onSelect={vi.fn()} />,
);
await waitUntilReady();
@ -347,7 +348,7 @@ describe('FolderTrustDialog', () => {
discoveryErrors: [],
securityWarnings: [],
};
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<FolderTrustDialog
onSelect={vi.fn()}
discoveryResults={discoveryResults}
@ -385,7 +386,7 @@ describe('FolderTrustDialog', () => {
discoveryErrors: [],
securityWarnings: ['Dangerous setting detected!'],
};
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<FolderTrustDialog
onSelect={vi.fn()}
discoveryResults={discoveryResults}
@ -409,7 +410,7 @@ describe('FolderTrustDialog', () => {
discoveryErrors: ['Failed to load custom commands'],
securityWarnings: [],
};
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<FolderTrustDialog
onSelect={vi.fn()}
discoveryResults={discoveryResults}
@ -433,7 +434,7 @@ describe('FolderTrustDialog', () => {
discoveryErrors: [],
securityWarnings: [],
};
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<FolderTrustDialog
onSelect={vi.fn()}
discoveryResults={discoveryResults}
@ -469,7 +470,7 @@ describe('FolderTrustDialog', () => {
securityWarnings: [`${ansiRed}warning-with-ansi${ansiReset}`],
};
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<FolderTrustDialog
onSelect={vi.fn()}
discoveryResults={discoveryResults}

View file

@ -8,6 +8,7 @@ import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
import { renderWithProviders } from '../../test-utils/render.js';
import { Footer } from './Footer.js';
import { createMockSettings } from '../../test-utils/settings.js';
import { type Config } from '@google/gemini-cli-core';
import path from 'node:path';
// Normalize paths to POSIX slashes for stable cross-platform snapshots.
@ -16,7 +17,11 @@ const normalizeFrame = (frame: string | undefined) => {
return frame.replace(/\\/g, '/');
};
let mockIsDevelopment = false;
const { mocks } = vi.hoisted(() => ({
mocks: {
isDevelopment: false,
},
}));
vi.mock('../../utils/installationInfo.js', async (importOriginal) => {
const original =
@ -24,7 +29,7 @@ vi.mock('../../utils/installationInfo.js', async (importOriginal) => {
return {
...original,
get isDevelopment() {
return mockIsDevelopment;
return mocks.isDevelopment;
},
};
});
@ -45,11 +50,34 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
const defaultProps = {
model: 'gemini-pro',
targetDir:
'/Users/test/project/foo/bar/and/some/more/directories/to/make/it/long',
targetDir: path.join(
path.parse(process.cwd()).root,
'Users',
'test',
'project',
'foo',
'bar',
'and',
'some',
'more',
'directories',
'to',
'make',
'it',
'long',
),
branchName: 'main',
};
const mockConfig = {
getTargetDir: () => defaultProps.targetDir,
getDebugMode: () => false,
getModel: () => defaultProps.model,
getIdeMode: () => false,
isTrustedFolder: () => true,
getExtensionRegistryURI: () => undefined,
} as unknown as Config;
const mockSessionStats = {
sessionId: 'test-session-id',
sessionStartTime: new Date(),
@ -110,9 +138,10 @@ describe('<Footer />', () => {
});
it('renders the component', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
branchName: defaultProps.branchName,
@ -127,9 +156,10 @@ describe('<Footer />', () => {
describe('path display', () => {
it('should display a shortened path on a narrow terminal', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 79,
uiState: { sessionStats: mockSessionStats },
},
@ -143,9 +173,10 @@ describe('<Footer />', () => {
});
it('should use wide layout at 80 columns', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 80,
uiState: { sessionStats: mockSessionStats },
},
@ -158,9 +189,10 @@ describe('<Footer />', () => {
});
it('should not truncate high-priority items on narrow terminals (regression)', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 60,
uiState: {
sessionStats: mockSessionStats,
@ -190,9 +222,10 @@ describe('<Footer />', () => {
});
it('displays the branch name when provided', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
branchName: defaultProps.branchName,
@ -206,9 +239,10 @@ describe('<Footer />', () => {
});
it('does not display the branch name when not provided', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: { branchName: undefined, sessionStats: mockSessionStats },
},
@ -219,9 +253,10 @@ describe('<Footer />', () => {
});
it('displays the model name and context percentage', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
currentModel: defaultProps.model,
@ -246,9 +281,10 @@ describe('<Footer />', () => {
});
it('displays the usage indicator when usage is low', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
sessionStats: mockSessionStats,
@ -274,9 +310,10 @@ describe('<Footer />', () => {
});
it('hides the usage indicator when usage is not near limit', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
sessionStats: mockSessionStats,
@ -302,9 +339,10 @@ describe('<Footer />', () => {
});
it('displays "Limit reached" message when remaining is 0', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
sessionStats: mockSessionStats,
@ -330,9 +368,10 @@ describe('<Footer />', () => {
});
it('displays the model name and abbreviated context used label on narrow terminals', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 99,
uiState: { sessionStats: mockSessionStats },
settings: createMockSettings({
@ -353,9 +392,10 @@ describe('<Footer />', () => {
describe('sandbox and trust info', () => {
it('should display untrusted when isTrustedFolder is false', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: { isTrustedFolder: false, sessionStats: mockSessionStats },
},
@ -367,9 +407,10 @@ describe('<Footer />', () => {
it('should display custom sandbox info when SANDBOX env is set', async () => {
vi.stubEnv('SANDBOX', 'gemini-cli-test-sandbox');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
isTrustedFolder: undefined,
@ -386,9 +427,10 @@ describe('<Footer />', () => {
it('should display macOS Seatbelt info when SANDBOX is sandbox-exec', async () => {
vi.stubEnv('SANDBOX', 'sandbox-exec');
vi.stubEnv('SEATBELT_PROFILE', 'test-profile');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: { isTrustedFolder: true, sessionStats: mockSessionStats },
},
@ -402,9 +444,10 @@ describe('<Footer />', () => {
it('should display "no sandbox" when SANDBOX is not set and folder is trusted', async () => {
// Clear any SANDBOX env var that might be set.
vi.stubEnv('SANDBOX', '');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: { isTrustedFolder: true, sessionStats: mockSessionStats },
},
@ -417,9 +460,10 @@ describe('<Footer />', () => {
it('should prioritize untrusted message over sandbox info', async () => {
vi.stubEnv('SANDBOX', 'gemini-cli-test-sandbox');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: { isTrustedFolder: false, sessionStats: mockSessionStats },
},
@ -434,9 +478,10 @@ describe('<Footer />', () => {
describe('footer configuration filtering (golden snapshots)', () => {
it('renders complete footer with all sections visible (baseline)', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: { sessionStats: mockSessionStats },
settings: createMockSettings({
@ -456,7 +501,7 @@ describe('<Footer />', () => {
});
it('renders footer with all optional sections hidden (minimal footer)', async () => {
const { lastFrame, unmount } = renderWithProviders(<Footer />, {
const { lastFrame, unmount } = await renderWithProviders(<Footer />, {
width: 120,
uiState: { sessionStats: mockSessionStats },
settings: createMockSettings({
@ -478,9 +523,10 @@ describe('<Footer />', () => {
});
it('renders footer with only model info hidden (partial filtering)', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: { sessionStats: mockSessionStats },
settings: createMockSettings({
@ -500,9 +546,10 @@ describe('<Footer />', () => {
});
it('renders footer with CWD and model info hidden to test alignment (only sandbox visible)', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: { sessionStats: mockSessionStats },
settings: createMockSettings({
@ -524,9 +571,10 @@ describe('<Footer />', () => {
});
it('hides the context percentage when hideContextPercentage is true', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: { sessionStats: mockSessionStats },
settings: createMockSettings({
@ -544,9 +592,10 @@ describe('<Footer />', () => {
unmount();
});
it('shows the context percentage when hideContextPercentage is false', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: { sessionStats: mockSessionStats },
settings: createMockSettings({
@ -564,9 +613,10 @@ describe('<Footer />', () => {
unmount();
});
it('renders complete footer in narrow terminal (baseline narrow)', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 79,
uiState: { sessionStats: mockSessionStats },
settings: createMockSettings({
@ -588,7 +638,7 @@ describe('<Footer />', () => {
describe('Footer Token Formatting', () => {
const renderWithTokens = async (tokens: number) => {
const result = renderWithProviders(<Footer />, {
const result = await renderWithProviders(<Footer />, {
width: 120,
uiState: {
sessionStats: {
@ -656,17 +706,18 @@ describe('<Footer />', () => {
describe('error summary visibility', () => {
beforeEach(() => {
mockIsDevelopment = false;
mocks.isDevelopment = false;
});
afterEach(() => {
mockIsDevelopment = false;
mocks.isDevelopment = false;
});
it('hides error summary in low verbosity mode out of dev mode', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
sessionStats: mockSessionStats,
@ -682,10 +733,11 @@ describe('<Footer />', () => {
});
it('shows error summary in low verbosity mode in dev mode', async () => {
mockIsDevelopment = true;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
mocks.isDevelopment = true;
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
sessionStats: mockSessionStats,
@ -702,9 +754,10 @@ describe('<Footer />', () => {
});
it('shows error summary in full verbosity mode', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
sessionStats: mockSessionStats,
@ -723,9 +776,10 @@ describe('<Footer />', () => {
describe('Footer Custom Items', () => {
it('renders items in the specified order', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
currentModel: 'gemini-pro',
@ -750,9 +804,10 @@ describe('<Footer />', () => {
});
it('renders multiple items with proper alignment', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
sessionStats: mockSessionStats,
@ -786,7 +841,7 @@ describe('<Footer />', () => {
});
it('handles empty items array', async () => {
const { lastFrame, unmount } = renderWithProviders(<Footer />, {
const { lastFrame, unmount } = await renderWithProviders(<Footer />, {
width: 120,
uiState: { sessionStats: mockSessionStats },
settings: createMockSettings({
@ -807,9 +862,10 @@ describe('<Footer />', () => {
});
it('does not render items that are conditionally hidden', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
sessionStats: mockSessionStats,
@ -837,9 +893,10 @@ describe('<Footer />', () => {
describe('fallback mode display', () => {
it('should display Flash model when in fallback mode, not the configured Pro model', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
sessionStats: mockSessionStats,
@ -856,9 +913,10 @@ describe('<Footer />', () => {
});
it('should display Pro model when NOT in fallback mode', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
config: mockConfig,
width: 120,
uiState: {
sessionStats: mockSessionStats,

View file

@ -25,7 +25,7 @@ describe('<FooterConfigDialog />', () => {
it('renders correctly with default settings', async () => {
const settings = createMockSettings();
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<FooterConfigDialog onClose={mockOnClose} />,
{ settings },
);
@ -37,7 +37,7 @@ describe('<FooterConfigDialog />', () => {
it('toggles an item when enter is pressed', async () => {
const settings = createMockSettings();
const { lastFrame, stdin, waitUntilReady } = renderWithProviders(
const { lastFrame, stdin, waitUntilReady } = await renderWithProviders(
<FooterConfigDialog onClose={mockOnClose} />,
{ settings },
);
@ -62,7 +62,7 @@ describe('<FooterConfigDialog />', () => {
it('reorders items with arrow keys', async () => {
const settings = createMockSettings();
const { lastFrame, stdin, waitUntilReady } = renderWithProviders(
const { lastFrame, stdin, waitUntilReady } = await renderWithProviders(
<FooterConfigDialog onClose={mockOnClose} />,
{ settings },
);
@ -93,7 +93,7 @@ describe('<FooterConfigDialog />', () => {
it('closes on Esc', async () => {
const settings = createMockSettings();
const { stdin, waitUntilReady } = renderWithProviders(
const { stdin, waitUntilReady } = await renderWithProviders(
<FooterConfigDialog onClose={mockOnClose} />,
{ settings },
);
@ -110,7 +110,7 @@ describe('<FooterConfigDialog />', () => {
it('highlights the active item in the preview', async () => {
const settings = createMockSettings();
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<FooterConfigDialog onClose={mockOnClose} />,
{ settings },
);
@ -148,7 +148,7 @@ describe('<FooterConfigDialog />', () => {
it('shows an empty preview when all items are deselected', async () => {
const settings = createMockSettings();
const { lastFrame, stdin, waitUntilReady } = renderWithProviders(
const { lastFrame, stdin, waitUntilReady } = await renderWithProviders(
<FooterConfigDialog onClose={mockOnClose} />,
{ settings },
);
@ -178,7 +178,7 @@ describe('<FooterConfigDialog />', () => {
it('moves item correctly after trying to move up at the top', async () => {
const settings = createMockSettings();
const { lastFrame, stdin, waitUntilReady } = renderWithProviders(
const { lastFrame, stdin, waitUntilReady } = await renderWithProviders(
<FooterConfigDialog onClose={mockOnClose} />,
{ settings },
);
@ -217,7 +217,7 @@ describe('<FooterConfigDialog />', () => {
it('updates the preview when Show footer labels is toggled off', async () => {
const settings = createMockSettings();
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<FooterConfigDialog onClose={mockOnClose} />,
{ settings },
);

View file

@ -72,7 +72,7 @@ useSessionStatsMock.mockReturnValue({
describe('Gradient Crash Regression Tests', () => {
it('<Header /> should not crash when theme.ui.gradient is empty', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Header version="1.0.0" nightly={false} />,
{
width: 120,
@ -84,7 +84,7 @@ describe('Gradient Crash Regression Tests', () => {
});
it('<ModelDialog /> should not crash when theme.ui.gradient is empty', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ModelDialog onClose={async () => {}} />,
{
width: 120,
@ -96,7 +96,7 @@ describe('Gradient Crash Regression Tests', () => {
});
it('<Banner /> should not crash when theme.ui.gradient is empty', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Banner bannerText="Test Banner" isWarning={false} width={80} />,
{
width: 120,
@ -108,7 +108,7 @@ describe('Gradient Crash Regression Tests', () => {
});
it('<Footer /> should not crash when theme.ui.gradient has only one color (or empty) and nightly is true', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Footer />,
{
width: 120,
@ -127,7 +127,7 @@ describe('Gradient Crash Regression Tests', () => {
});
it('<StatsDisplay /> should not crash when theme.ui.gradient is empty', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<StatsDisplay duration="1s" title="My Stats" />,
{
width: 120,

View file

@ -39,7 +39,7 @@ describe('<HistoryItemDisplay />', () => {
type: MessageType.USER,
text: 'Hello',
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HistoryItemDisplay {...baseItem} item={item} />,
);
await waitUntilReady();
@ -53,7 +53,7 @@ describe('<HistoryItemDisplay />', () => {
type: 'hint',
text: 'Try using ripgrep first',
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HistoryItemDisplay {...baseItem} item={item} />,
);
await waitUntilReady();
@ -67,7 +67,7 @@ describe('<HistoryItemDisplay />', () => {
type: MessageType.USER,
text: '/theme',
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HistoryItemDisplay {...baseItem} item={item} />,
);
await waitUntilReady();
@ -83,7 +83,7 @@ describe('<HistoryItemDisplay />', () => {
type: MessageType.INFO,
text: '⚡ Line 1\n⚡ Line 2\n⚡ Line 3',
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HistoryItemDisplay {...baseItem} item={item} />,
{
config: makeFakeConfig({ useAlternateBuffer }),
@ -114,7 +114,7 @@ describe('<HistoryItemDisplay />', () => {
},
],
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HistoryItemDisplay {...baseItem} item={item} />,
);
await waitUntilReady();
@ -128,7 +128,7 @@ describe('<HistoryItemDisplay />', () => {
type: MessageType.STATS,
duration: '1s',
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<SessionStatsProvider>
<HistoryItemDisplay {...baseItem} item={item} />
</SessionStatsProvider>,
@ -150,7 +150,7 @@ describe('<HistoryItemDisplay />', () => {
gcpProject: 'test-project',
ideClient: 'test-ide',
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HistoryItemDisplay {...baseItem} item={item} />,
);
await waitUntilReady();
@ -163,7 +163,7 @@ describe('<HistoryItemDisplay />', () => {
...baseItem,
type: 'model_stats',
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<SessionStatsProvider>
<HistoryItemDisplay {...baseItem} item={item} />
</SessionStatsProvider>,
@ -180,7 +180,7 @@ describe('<HistoryItemDisplay />', () => {
...baseItem,
type: 'tool_stats',
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<SessionStatsProvider>
<HistoryItemDisplay {...baseItem} item={item} />
</SessionStatsProvider>,
@ -198,7 +198,7 @@ describe('<HistoryItemDisplay />', () => {
type: 'quit',
duration: '1s',
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<SessionStatsProvider>
<HistoryItemDisplay {...baseItem} item={item} />
</SessionStatsProvider>,
@ -215,7 +215,7 @@ describe('<HistoryItemDisplay />', () => {
text: 'Hello, \u001b[31mred\u001b[0m world!',
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HistoryItemDisplay
item={historyItem}
terminalWidth={80}
@ -253,7 +253,7 @@ describe('<HistoryItemDisplay />', () => {
],
};
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<HistoryItemDisplay
item={historyItem}
terminalWidth={80}
@ -279,7 +279,7 @@ describe('<HistoryItemDisplay />', () => {
type: 'thinking',
thought: { subject: 'Thinking', description: 'test' },
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HistoryItemDisplay {...baseItem} item={item} />,
{
settings: createMockSettings({ ui: { inlineThinkingMode: 'full' } }),
@ -297,7 +297,7 @@ describe('<HistoryItemDisplay />', () => {
type: 'thinking',
thought: { subject: 'Thinking', description: 'test' },
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HistoryItemDisplay {...baseItem} item={item} isFirstThinking={true} />,
{
settings: createMockSettings({ ui: { inlineThinkingMode: 'full' } }),
@ -315,7 +315,7 @@ describe('<HistoryItemDisplay />', () => {
type: 'thinking',
thought: { subject: 'Thinking', description: 'test' },
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HistoryItemDisplay {...baseItem} item={item} />,
{
settings: createMockSettings({ ui: { inlineThinkingMode: 'off' } }),
@ -343,18 +343,19 @@ describe('<HistoryItemDisplay />', () => {
type: 'gemini',
text: longCode,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<HistoryItemDisplay
item={item}
isPending={false}
terminalWidth={80}
availableTerminalHeight={10}
/>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(
<HistoryItemDisplay
item={item}
isPending={false}
terminalWidth={80}
availableTerminalHeight={10}
/>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();
@ -367,19 +368,20 @@ describe('<HistoryItemDisplay />', () => {
type: 'gemini',
text: longCode,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<HistoryItemDisplay
item={item}
isPending={false}
terminalWidth={80}
availableTerminalHeight={10}
availableTerminalHeightGemini={Number.MAX_SAFE_INTEGER}
/>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(
<HistoryItemDisplay
item={item}
isPending={false}
terminalWidth={80}
availableTerminalHeight={10}
availableTerminalHeightGemini={Number.MAX_SAFE_INTEGER}
/>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();
@ -392,18 +394,19 @@ describe('<HistoryItemDisplay />', () => {
type: 'gemini_content',
text: longCode,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<HistoryItemDisplay
item={item}
isPending={false}
terminalWidth={80}
availableTerminalHeight={10}
/>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(
<HistoryItemDisplay
item={item}
isPending={false}
terminalWidth={80}
availableTerminalHeight={10}
/>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();
@ -416,19 +419,20 @@ describe('<HistoryItemDisplay />', () => {
type: 'gemini_content',
text: longCode,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<HistoryItemDisplay
item={item}
isPending={false}
terminalWidth={80}
availableTerminalHeight={10}
availableTerminalHeightGemini={Number.MAX_SAFE_INTEGER}
/>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(
<HistoryItemDisplay
item={item}
isPending={false}
terminalWidth={80}
availableTerminalHeight={10}
availableTerminalHeightGemini={Number.MAX_SAFE_INTEGER}
/>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();

View file

@ -35,7 +35,7 @@ describe('HooksDialog', () => {
describe('snapshots', () => {
it('renders empty hooks dialog', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HooksDialog hooks={[]} onClose={vi.fn()} />,
);
await waitUntilReady();
@ -45,7 +45,7 @@ describe('HooksDialog', () => {
it('renders single hook with security warning, source, and tips', async () => {
const hooks = [createMockHook('test-hook', 'before-tool', true)];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} />,
);
await waitUntilReady();
@ -59,7 +59,7 @@ describe('HooksDialog', () => {
createMockHook('hook2', 'before-tool', false),
createMockHook('hook3', 'after-agent', true),
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} />,
);
await waitUntilReady();
@ -80,7 +80,7 @@ describe('HooksDialog', () => {
},
}),
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} />,
);
await waitUntilReady();
@ -100,7 +100,7 @@ describe('HooksDialog', () => {
enabled: true,
},
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} />,
);
await waitUntilReady();
@ -112,7 +112,7 @@ describe('HooksDialog', () => {
describe('keyboard interaction', () => {
it('should call onClose when escape key is pressed', async () => {
const onClose = vi.fn();
const { waitUntilReady, stdin, unmount } = renderWithProviders(
const { waitUntilReady, stdin, unmount } = await renderWithProviders(
<HooksDialog hooks={[]} onClose={onClose} />,
);
await waitUntilReady();
@ -137,7 +137,7 @@ describe('HooksDialog', () => {
createMockHook('hook1', 'before-tool', true),
createMockHook('hook2', 'after-tool', false),
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} maxVisibleHooks={10} />,
);
await waitUntilReady();
@ -149,7 +149,7 @@ describe('HooksDialog', () => {
it('should show scroll down indicator when there are more hooks than maxVisibleHooks', async () => {
const hooks = createManyHooks(15);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} maxVisibleHooks={5} />,
);
await waitUntilReady();
@ -160,9 +160,10 @@ describe('HooksDialog', () => {
it('should scroll down when down arrow is pressed', async () => {
const hooks = createManyHooks(15);
const { lastFrame, waitUntilReady, stdin, unmount } = renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} maxVisibleHooks={5} />,
);
const { lastFrame, waitUntilReady, stdin, unmount } =
await renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} maxVisibleHooks={5} />,
);
await waitUntilReady();
// Initially should not show up indicator
@ -180,9 +181,10 @@ describe('HooksDialog', () => {
it('should scroll up when up arrow is pressed after scrolling down', async () => {
const hooks = createManyHooks(15);
const { lastFrame, waitUntilReady, stdin, unmount } = renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} maxVisibleHooks={5} />,
);
const { lastFrame, waitUntilReady, stdin, unmount } =
await renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} maxVisibleHooks={5} />,
);
await waitUntilReady();
// Scroll down twice
@ -207,9 +209,10 @@ describe('HooksDialog', () => {
it('should not scroll beyond the end', async () => {
const hooks = createManyHooks(10);
const { lastFrame, waitUntilReady, stdin, unmount } = renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} maxVisibleHooks={5} />,
);
const { lastFrame, waitUntilReady, stdin, unmount } =
await renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} maxVisibleHooks={5} />,
);
await waitUntilReady();
// Scroll down many times past the end
@ -229,9 +232,10 @@ describe('HooksDialog', () => {
it('should not scroll above the beginning', async () => {
const hooks = createManyHooks(10);
const { lastFrame, waitUntilReady, stdin, unmount } = renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} maxVisibleHooks={5} />,
);
const { lastFrame, waitUntilReady, stdin, unmount } =
await renderWithProviders(
<HooksDialog hooks={hooks} onClose={vi.fn()} maxVisibleHooks={5} />,
);
await waitUntilReady();
// Try to scroll up when already at top

View file

@ -17,7 +17,7 @@ describe('IdeTrustChangeDialog', () => {
});
it('renders the correct message for CONNECTION_CHANGE', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<IdeTrustChangeDialog reason="CONNECTION_CHANGE" />,
);
await waitUntilReady();
@ -31,7 +31,7 @@ describe('IdeTrustChangeDialog', () => {
});
it('renders the correct message for TRUST_CHANGE', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<IdeTrustChangeDialog reason="TRUST_CHANGE" />,
);
await waitUntilReady();
@ -48,7 +48,7 @@ describe('IdeTrustChangeDialog', () => {
const debugLoggerWarnSpy = vi
.spyOn(debugLogger, 'warn')
.mockImplementation(() => {});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<IdeTrustChangeDialog reason="NONE" />,
);
await waitUntilReady();
@ -65,7 +65,7 @@ describe('IdeTrustChangeDialog', () => {
const relaunchAppSpy = vi
.spyOn(processUtils, 'relaunchApp')
.mockResolvedValue(undefined);
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<IdeTrustChangeDialog reason="NONE" />,
);
await waitUntilReady();
@ -83,7 +83,7 @@ describe('IdeTrustChangeDialog', () => {
const relaunchAppSpy = vi
.spyOn(processUtils, 'relaunchApp')
.mockResolvedValue(undefined);
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<IdeTrustChangeDialog reason="CONNECTION_CHANGE" />,
);
await waitUntilReady();
@ -101,7 +101,7 @@ describe('IdeTrustChangeDialog', () => {
const relaunchAppSpy = vi
.spyOn(processUtils, 'relaunchApp')
.mockResolvedValue(undefined);
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<IdeTrustChangeDialog reason="CONNECTION_CHANGE" />,
);
await waitUntilReady();

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,7 @@ vi.mock('../hooks/useTerminalSize.js', () => ({
const useTerminalSizeMock = vi.mocked(useTerminalSize.useTerminalSize);
const renderWithContext = (
const renderWithContext = async (
ui: React.ReactElement,
streamingStateValue: StreamingState,
width = 120,
@ -55,7 +55,7 @@ describe('<LoadingIndicator />', () => {
};
it('should render blank when streamingState is Idle and no loading phrase or thought', async () => {
const { lastFrame, waitUntilReady } = renderWithContext(
const { lastFrame, waitUntilReady } = await renderWithContext(
<LoadingIndicator elapsedTime={5} />,
StreamingState.Idle,
);
@ -64,7 +64,7 @@ describe('<LoadingIndicator />', () => {
});
it('should render spinner, phrase, and time when streamingState is Responding', async () => {
const { lastFrame, waitUntilReady } = renderWithContext(
const { lastFrame, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...defaultProps} />,
StreamingState.Responding,
);
@ -80,7 +80,7 @@ describe('<LoadingIndicator />', () => {
currentLoadingPhrase: 'Confirm action',
elapsedTime: 10,
};
const { lastFrame, waitUntilReady } = renderWithContext(
const { lastFrame, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.WaitingForConfirmation,
);
@ -97,7 +97,7 @@ describe('<LoadingIndicator />', () => {
currentLoadingPhrase: 'Processing data...',
elapsedTime: 3,
};
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
@ -111,7 +111,7 @@ describe('<LoadingIndicator />', () => {
currentLoadingPhrase: 'Working...',
elapsedTime: 60,
};
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
@ -125,7 +125,7 @@ describe('<LoadingIndicator />', () => {
currentLoadingPhrase: 'Working...',
elapsedTime: 125,
};
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
@ -136,7 +136,7 @@ describe('<LoadingIndicator />', () => {
it('should render rightContent when provided', async () => {
const rightContent = <Text>Extra Info</Text>;
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...defaultProps} rightContent={rightContent} />,
StreamingState.Responding,
);
@ -178,7 +178,7 @@ describe('<LoadingIndicator />', () => {
);
};
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<TestWrapper />,
);
await waitUntilReady();
@ -232,7 +232,7 @@ describe('<LoadingIndicator />', () => {
currentLoadingPhrase: 'Loading...',
elapsedTime: 5,
};
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
@ -250,7 +250,7 @@ describe('<LoadingIndicator />', () => {
},
elapsedTime: 5,
};
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
@ -274,7 +274,7 @@ describe('<LoadingIndicator />', () => {
},
elapsedTime: 5,
};
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
@ -293,7 +293,7 @@ describe('<LoadingIndicator />', () => {
currentLoadingPhrase: 'This should not be displayed',
elapsedTime: 5,
};
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
@ -306,7 +306,7 @@ describe('<LoadingIndicator />', () => {
});
it('should not display thought indicator for non-thought loading phrases', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator
currentLoadingPhrase="some random tip..."
elapsedTime={3}
@ -319,7 +319,7 @@ describe('<LoadingIndicator />', () => {
});
it('should truncate long primary text instead of wrapping', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator
{...defaultProps}
currentLoadingPhrase={
@ -337,7 +337,7 @@ describe('<LoadingIndicator />', () => {
describe('responsive layout', () => {
it('should render on a single line on a wide terminal', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator
{...defaultProps}
rightContent={<Text>Right</Text>}
@ -356,7 +356,7 @@ describe('<LoadingIndicator />', () => {
});
it('should render on multiple lines on a narrow terminal', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator
{...defaultProps}
rightContent={<Text>Right</Text>}
@ -382,7 +382,7 @@ describe('<LoadingIndicator />', () => {
});
it('should use wide layout at 80 columns', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...defaultProps} />,
StreamingState.Responding,
80,
@ -393,7 +393,7 @@ describe('<LoadingIndicator />', () => {
});
it('should use narrow layout at 79 columns', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
const { lastFrame, unmount, waitUntilReady } = await renderWithContext(
<LoadingIndicator {...defaultProps} />,
StreamingState.Responding,
79,

View file

@ -23,7 +23,7 @@ describe('LogoutConfirmationDialog', () => {
});
it('should render the dialog with title, description, and hint', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<LogoutConfirmationDialog onSelect={vi.fn()} />,
);
await waitUntilReady();
@ -37,7 +37,7 @@ describe('LogoutConfirmationDialog', () => {
});
it('should render RadioButtonSelect with Login and Exit options', async () => {
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<LogoutConfirmationDialog onSelect={vi.fn()} />,
);
await waitUntilReady();
@ -54,7 +54,7 @@ describe('LogoutConfirmationDialog', () => {
it('should call onSelect with LOGIN when Login is selected', async () => {
const onSelect = vi.fn();
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<LogoutConfirmationDialog onSelect={onSelect} />,
);
await waitUntilReady();
@ -71,7 +71,7 @@ describe('LogoutConfirmationDialog', () => {
it('should call onSelect with EXIT when Exit is selected', async () => {
const onSelect = vi.fn();
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<LogoutConfirmationDialog onSelect={onSelect} />,
);
await waitUntilReady();
@ -88,7 +88,7 @@ describe('LogoutConfirmationDialog', () => {
it('should call onSelect with EXIT when escape key is pressed', async () => {
const onSelect = vi.fn();
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<LogoutConfirmationDialog onSelect={onSelect} />,
);
await waitUntilReady();

View file

@ -12,7 +12,7 @@ describe('LoopDetectionConfirmation', () => {
const onComplete = vi.fn();
it('renders correctly', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<LoopDetectionConfirmation onComplete={onComplete} />,
{ width: 101 },
);
@ -22,7 +22,7 @@ describe('LoopDetectionConfirmation', () => {
});
it('contains the expected options', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<LoopDetectionConfirmation onComplete={onComplete} />,
{ width: 100 },
);

View file

@ -350,7 +350,7 @@ describe('MainContent', () => {
});
it('renders in normal buffer mode', async () => {
const { lastFrame, unmount } = renderWithProviders(<MainContent />, {
const { lastFrame, unmount } = await renderWithProviders(<MainContent />, {
uiState: defaultMockUiState as Partial<UIState>,
});
await waitFor(() => expect(lastFrame()).toContain('AppHeader(full)'));
@ -364,7 +364,7 @@ describe('MainContent', () => {
it('renders in alternate buffer mode', async () => {
vi.mocked(useAlternateBuffer).mockReturnValue(true);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<MainContent />,
{
uiState: defaultMockUiState as Partial<UIState>,
@ -382,7 +382,7 @@ describe('MainContent', () => {
it('renders minimal header in minimal mode (alternate buffer)', async () => {
vi.mocked(useAlternateBuffer).mockReturnValue(true);
const { lastFrame, unmount } = renderWithProviders(<MainContent />, {
const { lastFrame, unmount } = await renderWithProviders(<MainContent />, {
uiState: {
...defaultMockUiState,
cleanUiDetailsVisible: false,
@ -417,7 +417,7 @@ describe('MainContent', () => {
);
};
const { lastFrame } = renderWithProviders(<ToggleHarness />, {
const { lastFrame } = await renderWithProviders(<ToggleHarness />, {
uiState: {
...defaultMockUiState,
cleanUiDetailsVisible: false,
@ -439,7 +439,7 @@ describe('MainContent', () => {
it('always renders full header details in normal buffer mode', async () => {
vi.mocked(useAlternateBuffer).mockReturnValue(false);
const { lastFrame } = renderWithProviders(<MainContent />, {
const { lastFrame } = await renderWithProviders(<MainContent />, {
uiState: {
...defaultMockUiState,
cleanUiDetailsVisible: false,
@ -452,7 +452,7 @@ describe('MainContent', () => {
it('does not constrain height in alternate buffer mode', async () => {
vi.mocked(useAlternateBuffer).mockReturnValue(true);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<MainContent />,
{
uiState: defaultMockUiState as Partial<UIState>,
@ -479,7 +479,7 @@ describe('MainContent', () => {
staticAreaMaxItemHeight: 5,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<MainContent />,
{
uiState: uiState as Partial<UIState>,
@ -507,7 +507,7 @@ describe('MainContent', () => {
staticAreaMaxItemHeight: 5,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<MainContent />,
{
uiState: uiState as unknown as Partial<UIState>,
@ -564,7 +564,7 @@ describe('MainContent', () => {
],
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<MainContent />,
{
uiState: uiState as Partial<UIState>,
@ -626,7 +626,7 @@ describe('MainContent', () => {
],
};
const renderResult = renderWithProviders(<MainContent />, {
const renderResult = await renderWithProviders(<MainContent />, {
uiState: uiState as Partial<UIState>,
});
await renderResult.waitUntilReady();
@ -732,16 +732,14 @@ describe('MainContent', () => {
bannerVisible: false,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<MainContent />,
{
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(<MainContent />, {
uiState: uiState as Partial<UIState>,
config: makeFakeConfig({ useAlternateBuffer: isAlternateBuffer }),
settings: createMockSettings({
ui: { useAlternateBuffer: isAlternateBuffer },
}),
},
);
});
await waitUntilReady();
const output = lastFrame();

View file

@ -108,10 +108,13 @@ describe('<ModelDialog />', () => {
},
});
const result = renderWithProviders(<ModelDialog onClose={mockOnClose} />, {
config: configValue,
settings,
});
const result = await renderWithProviders(
<ModelDialog onClose={mockOnClose} />,
{
config: configValue,
settings,
},
);
await result.waitUntilReady();
return result;
};

View file

@ -49,7 +49,7 @@ describe('NewAgentsNotification', () => {
const onSelect = vi.fn();
it('renders agent list', async () => {
const { lastFrame, waitUntilReady, unmount } = render(
const { lastFrame, waitUntilReady, unmount } = await render(
<NewAgentsNotification agents={mockAgents} onSelect={onSelect} />,
);
await waitUntilReady();
@ -68,7 +68,7 @@ describe('NewAgentsNotification', () => {
inputConfig: { inputSchema: {} },
}));
const { lastFrame, waitUntilReady, unmount } = render(
const { lastFrame, waitUntilReady, unmount } = await render(
<NewAgentsNotification agents={manyAgents} onSelect={onSelect} />,
);
await waitUntilReady();
@ -86,7 +86,7 @@ describe('NewAgentsNotification', () => {
}),
);
const { lastFrame, stdin, unmount } = render(
const { lastFrame, stdin, unmount } = await render(
<NewAgentsNotification agents={mockAgents} onSelect={asyncOnSelect} />,
);

View file

@ -63,6 +63,14 @@ vi.mock('node:path', async () => {
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
const actual =
await importOriginal<typeof import('@google/gemini-cli-core')>();
const MockStorage = vi.fn().mockImplementation(() => ({
getExtensionsDir: () => '/mock/home/.gemini/extensions',
}));
Object.assign(MockStorage, {
getGlobalTempDir: () => '/mock/temp',
getGlobalSettingsPath: () => '/mock/home/.gemini/settings.json',
getGlobalGeminiDir: () => '/mock/home/.gemini',
});
return {
...actual,
GEMINI_DIR: '.gemini',
@ -71,11 +79,7 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
Low: 'low',
High: 'high',
},
Storage: {
...actual.Storage,
getGlobalTempDir: () => '/mock/temp',
getGlobalSettingsPath: () => '/mock/home/.gemini/settings.json',
},
Storage: MockStorage,
};
});
@ -107,7 +111,7 @@ describe('Notifications', () => {
});
it('renders nothing when no notifications', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Notifications />,
{
settings,
@ -133,7 +137,7 @@ describe('Notifications', () => {
version: '1.0.0',
} as AppState;
mockUseAppContext.mockReturnValue(appState);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Notifications />,
{
appState,
@ -159,11 +163,14 @@ describe('Notifications', () => {
} as AppState;
mockUseAppContext.mockReturnValue(appState);
const { waitUntilReady, unmount } = renderWithProviders(<Notifications />, {
appState,
settings,
width: 100,
});
const { waitUntilReady, unmount } = await renderWithProviders(
<Notifications />,
{
appState,
settings,
width: 100,
},
);
await waitUntilReady();
expect(persistentStateMock.set).toHaveBeenCalledWith(
@ -192,7 +199,7 @@ describe('Notifications', () => {
startupWarningCounts: { 'low-1': 3 },
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Notifications />,
{
appState,
@ -221,14 +228,12 @@ describe('Notifications', () => {
} as AppState;
mockUseAppContext.mockReturnValue(appState);
const { lastFrame, stdin, waitUntilReady, unmount } = renderWithProviders(
<Notifications />,
{
const { lastFrame, stdin, waitUntilReady, unmount } =
await renderWithProviders(<Notifications />, {
appState,
settings,
width: 100,
},
);
});
await waitUntilReady();
expect(lastFrame()).toContain('High priority 1');
@ -248,7 +253,7 @@ describe('Notifications', () => {
updateInfo: null,
} as unknown as UIState;
mockUseUIState.mockReturnValue(uiState);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Notifications />,
{
uiState,
@ -268,7 +273,7 @@ describe('Notifications', () => {
updateInfo: null,
} as unknown as UIState;
mockUseUIState.mockReturnValue(uiState);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Notifications />,
{
uiState,
@ -288,7 +293,7 @@ describe('Notifications', () => {
updateInfo: { message: 'Update available' },
} as unknown as UIState;
mockUseUIState.mockReturnValue(uiState);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Notifications />,
{
uiState,
@ -306,7 +311,7 @@ describe('Notifications', () => {
persistentStateMock.setData({ hasSeenScreenReaderNudge: false });
mockFsAccess.mockRejectedValue(new Error('No legacy file'));
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Notifications />,
{
settings,
@ -330,29 +335,24 @@ describe('Notifications', () => {
persistentStateMock.setData({ hasSeenScreenReaderNudge: undefined });
mockFsAccess.mockResolvedValue(undefined);
const { waitUntilReady, unmount } = renderWithProviders(<Notifications />, {
settings,
width: 100,
});
await act(async () => {
await waitUntilReady();
await waitFor(() => {
expect(persistentStateMock.set).toHaveBeenCalledWith(
'hasSeenScreenReaderNudge',
true,
);
expect(mockFsUnlink).toHaveBeenCalled();
await renderWithProviders(<Notifications />, {
settings,
width: 100,
});
});
unmount();
await waitFor(() => {
expect(persistentStateMock.get('hasSeenScreenReaderNudge')).toBe(true);
});
expect(mockFsUnlink).toHaveBeenCalled();
});
it('does not render screen reader nudge when already seen in persistent state', async () => {
mockUseIsScreenReaderEnabled.mockReturnValue(true);
persistentStateMock.setData({ hasSeenScreenReaderNudge: true });
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Notifications />,
{
settings,

View file

@ -29,7 +29,7 @@ describe('OverageMenuDialog', () => {
describe('rendering', () => {
it('should match snapshot with fallback available', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<OverageMenuDialog
failedModel="gemini-2.5-pro"
fallbackModel="gemini-3-flash-preview"
@ -45,7 +45,7 @@ describe('OverageMenuDialog', () => {
});
it('should match snapshot without fallback', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<OverageMenuDialog
failedModel="gemini-2.5-pro"
creditBalance={500}
@ -59,7 +59,7 @@ describe('OverageMenuDialog', () => {
});
it('should display the credit balance', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<OverageMenuDialog
failedModel="gemini-2.5-pro"
creditBalance={200}
@ -75,7 +75,7 @@ describe('OverageMenuDialog', () => {
});
it('should display the model name', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<OverageMenuDialog
failedModel="gemini-2.5-pro"
creditBalance={100}
@ -91,7 +91,7 @@ describe('OverageMenuDialog', () => {
});
it('should display reset time when provided', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<OverageMenuDialog
failedModel="gemini-2.5-pro"
resetTime="3:45 PM"
@ -108,7 +108,7 @@ describe('OverageMenuDialog', () => {
});
it('should not display reset time when not provided', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<OverageMenuDialog
failedModel="gemini-2.5-pro"
creditBalance={100}
@ -123,7 +123,7 @@ describe('OverageMenuDialog', () => {
});
it('should display slash command hints', async () => {
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<OverageMenuDialog
failedModel="gemini-2.5-pro"
creditBalance={100}
@ -143,7 +143,7 @@ describe('OverageMenuDialog', () => {
describe('onChoice handling', () => {
it('should call onChoice with use_credits when selected', async () => {
// use_credits is the first item, so just press Enter
const { unmount, stdin, waitUntilReady } = renderWithProviders(
const { unmount, stdin, waitUntilReady } = await renderWithProviders(
<OverageMenuDialog
failedModel="gemini-2.5-pro"
creditBalance={100}
@ -162,7 +162,7 @@ describe('OverageMenuDialog', () => {
it('should call onChoice with manage when selected', async () => {
// manage is the second item: Down + Enter
const { unmount, stdin, waitUntilReady } = renderWithProviders(
const { unmount, stdin, waitUntilReady } = await renderWithProviders(
<OverageMenuDialog
failedModel="gemini-2.5-pro"
creditBalance={100}
@ -183,7 +183,7 @@ describe('OverageMenuDialog', () => {
it('should call onChoice with use_fallback when selected', async () => {
// With fallback: items are [use_credits, manage, use_fallback, stop]
// use_fallback is the third item: Down x2 + Enter
const { unmount, stdin, waitUntilReady } = renderWithProviders(
const { unmount, stdin, waitUntilReady } = await renderWithProviders(
<OverageMenuDialog
failedModel="gemini-2.5-pro"
fallbackModel="gemini-3-flash-preview"
@ -206,7 +206,7 @@ describe('OverageMenuDialog', () => {
it('should call onChoice with stop when selected', async () => {
// Without fallback: items are [use_credits, manage, stop]
// stop is the third item: Down x2 + Enter
const { unmount, stdin, waitUntilReady } = renderWithProviders(
const { unmount, stdin, waitUntilReady } = await renderWithProviders(
<OverageMenuDialog
failedModel="gemini-2.5-pro"
creditBalance={100}

View file

@ -72,7 +72,7 @@ describe('PermissionsModifyTrustDialog', () => {
});
it('should render the main dialog with current trust level', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<PermissionsModifyTrustDialog onExit={vi.fn()} addItem={vi.fn()} />,
);
await waitUntilReady();
@ -96,7 +96,7 @@ describe('PermissionsModifyTrustDialog', () => {
commitTrustLevelChange: mockCommitTrustLevelChange,
isFolderTrustEnabled: true,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<PermissionsModifyTrustDialog onExit={vi.fn()} addItem={vi.fn()} />,
);
await waitUntilReady();
@ -120,7 +120,7 @@ describe('PermissionsModifyTrustDialog', () => {
commitTrustLevelChange: mockCommitTrustLevelChange,
isFolderTrustEnabled: true,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<PermissionsModifyTrustDialog onExit={vi.fn()} addItem={vi.fn()} />,
);
await waitUntilReady();
@ -134,7 +134,7 @@ describe('PermissionsModifyTrustDialog', () => {
});
it('should render the labels with folder names', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<PermissionsModifyTrustDialog onExit={vi.fn()} addItem={vi.fn()} />,
);
await waitUntilReady();
@ -148,9 +148,10 @@ describe('PermissionsModifyTrustDialog', () => {
it('should call onExit when escape is pressed', async () => {
const onExit = vi.fn();
const { stdin, lastFrame, waitUntilReady, unmount } = renderWithProviders(
<PermissionsModifyTrustDialog onExit={onExit} addItem={vi.fn()} />,
);
const { stdin, lastFrame, waitUntilReady, unmount } =
await renderWithProviders(
<PermissionsModifyTrustDialog onExit={onExit} addItem={vi.fn()} />,
);
await waitUntilReady();
await waitFor(() => expect(lastFrame()).not.toContain('Loading...'));
@ -186,9 +187,10 @@ describe('PermissionsModifyTrustDialog', () => {
});
const onExit = vi.fn();
const { stdin, lastFrame, waitUntilReady, unmount } = renderWithProviders(
<PermissionsModifyTrustDialog onExit={onExit} addItem={vi.fn()} />,
);
const { stdin, lastFrame, waitUntilReady, unmount } =
await renderWithProviders(
<PermissionsModifyTrustDialog onExit={onExit} addItem={vi.fn()} />,
);
await waitUntilReady();
await waitFor(() => expect(lastFrame()).not.toContain('Loading...'));
@ -220,9 +222,10 @@ describe('PermissionsModifyTrustDialog', () => {
});
const onExit = vi.fn();
const { stdin, lastFrame, waitUntilReady, unmount } = renderWithProviders(
<PermissionsModifyTrustDialog onExit={onExit} addItem={vi.fn()} />,
);
const { stdin, lastFrame, waitUntilReady, unmount } =
await renderWithProviders(
<PermissionsModifyTrustDialog onExit={onExit} addItem={vi.fn()} />,
);
await waitUntilReady();
await waitFor(() => expect(lastFrame()).not.toContain('Loading...'));

View file

@ -57,7 +57,7 @@ describe('PolicyUpdateDialog', () => {
});
it('renders correctly and matches snapshot', async () => {
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<PolicyUpdateDialog
config={mockConfig}
request={mockRequest}
@ -75,7 +75,7 @@ describe('PolicyUpdateDialog', () => {
});
it('handles ACCEPT correctly', async () => {
const { stdin } = renderWithProviders(
const { stdin } = await renderWithProviders(
<PolicyUpdateDialog
config={mockConfig}
request={mockRequest}
@ -98,7 +98,7 @@ describe('PolicyUpdateDialog', () => {
});
it('handles IGNORE correctly', async () => {
const { stdin } = renderWithProviders(
const { stdin } = await renderWithProviders(
<PolicyUpdateDialog
config={mockConfig}
request={mockRequest}
@ -122,7 +122,7 @@ describe('PolicyUpdateDialog', () => {
});
it('calls onClose when Escape key is pressed', async () => {
const { stdin } = renderWithProviders(
const { stdin } = await renderWithProviders(
<PolicyUpdateDialog
config={mockConfig}
request={mockRequest}

View file

@ -23,7 +23,7 @@ describe('RewindConfirmation', () => {
details: [{ fileName: 'test.ts', diff: '' }],
};
const onConfirm = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<RewindConfirmation
stats={stats}
onConfirm={onConfirm}
@ -40,7 +40,7 @@ describe('RewindConfirmation', () => {
it('renders correctly without stats', async () => {
const onConfirm = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<RewindConfirmation
stats={null}
onConfirm={onConfirm}
@ -58,7 +58,7 @@ describe('RewindConfirmation', () => {
it('calls onConfirm with Cancel on Escape', async () => {
const onConfirm = vi.fn();
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<RewindConfirmation
stats={null}
onConfirm={onConfirm}
@ -81,7 +81,7 @@ describe('RewindConfirmation', () => {
it('renders timestamp when provided', async () => {
const onConfirm = vi.fn();
const timestamp = new Date().toISOString();
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<RewindConfirmation
stats={null}
onConfirm={onConfirm}

View file

@ -91,7 +91,7 @@ describe('RewindViewer', () => {
const conversation = createConversation([
{ type: 'user', content: 'Hello', id: '1', timestamp: '1' },
]);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={vi.fn()}
@ -130,7 +130,7 @@ describe('RewindViewer', () => {
const conversation = createConversation(messages as MessageRecord[]);
const onExit = vi.fn();
const onRewind = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={onExit}
@ -154,13 +154,14 @@ describe('RewindViewer', () => {
]);
const onExit = vi.fn();
const onRewind = vi.fn();
const { lastFrame, stdin, waitUntilReady, unmount } = renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={onExit}
onRewind={onRewind}
/>,
);
const { lastFrame, stdin, waitUntilReady, unmount } =
await renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={onExit}
onRewind={onRewind}
/>,
);
await waitUntilReady();
// Initial state
@ -188,13 +189,14 @@ describe('RewindViewer', () => {
{ type: 'user', content: 'Q2', id: '2', timestamp: '1' },
{ type: 'user', content: 'Q3', id: '3', timestamp: '1' },
]);
const { lastFrame, stdin, waitUntilReady, unmount } = renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={vi.fn()}
onRewind={vi.fn()}
/>,
);
const { lastFrame, stdin, waitUntilReady, unmount } =
await renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={vi.fn()}
onRewind={vi.fn()}
/>,
);
await waitUntilReady();
act(() => {
@ -220,13 +222,14 @@ describe('RewindViewer', () => {
{ type: 'user', content: 'Q2', id: '2', timestamp: '1' },
{ type: 'user', content: 'Q3', id: '3', timestamp: '1' },
]);
const { lastFrame, stdin, waitUntilReady, unmount } = renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={vi.fn()}
onRewind={vi.fn()}
/>,
);
const { lastFrame, stdin, waitUntilReady, unmount } =
await renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={vi.fn()}
onRewind={vi.fn()}
/>,
);
await waitUntilReady();
// Up from first -> Last
@ -297,13 +300,14 @@ describe('RewindViewer', () => {
{ type: 'user', content: 'Original Prompt', id: '1', timestamp: '1' },
]);
const onRewind = vi.fn();
const { lastFrame, stdin, waitUntilReady, unmount } = renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={vi.fn()}
onRewind={onRewind}
/>,
);
const { lastFrame, stdin, waitUntilReady, unmount } =
await renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={vi.fn()}
onRewind={onRewind}
/>,
);
await waitUntilReady();
// Select
@ -354,13 +358,14 @@ describe('RewindViewer', () => {
},
]);
const onRewind = vi.fn();
const { lastFrame, stdin, waitUntilReady, unmount } = renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={vi.fn()}
onRewind={onRewind}
/>,
);
const { lastFrame, stdin, waitUntilReady, unmount } =
await renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={vi.fn()}
onRewind={onRewind}
/>,
);
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();
@ -398,7 +403,7 @@ describe('RewindViewer', () => {
const onExit = vi.fn();
const onRewind = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={onExit}
@ -421,7 +426,7 @@ describe('RewindViewer', () => {
lastFrame: lastFrame2,
waitUntilReady: waitUntilReady2,
unmount: unmount2,
} = renderWithProviders(
} = await renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={onExit}
@ -446,7 +451,7 @@ it('renders accessible screen reader view when screen reader is enabled', async
const onExit = vi.fn();
const onRewind = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<RewindViewer
conversation={conversation}
onExit={onExit}

View file

@ -51,7 +51,7 @@ const renderWithMockedStats = async (
startNewPrompt: vi.fn(),
});
const result = renderWithProviders(
const result = await renderWithProviders(
<SessionSummaryDisplay duration="1h 23m 45s" />,
{
width: 100,

View file

@ -26,6 +26,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { SettingsDialog } from './SettingsDialog.js';
import { SettingScope } from '../../config/settings.js';
import { createMockSettings } from '../../test-utils/settings.js';
import { makeFakeConfig } from '@google/gemini-cli-core';
import { act } from 'react';
import { TEST_ONLY } from '../../utils/settingsUtils.js';
import {
@ -228,7 +229,7 @@ const TOOLS_SHELL_FAKE_SCHEMA: SettingsSchemaType = {
} as unknown as SettingsSchemaType;
// Helper function to render SettingsDialog with standard wrapper
const renderDialog = (
const renderDialog = async (
settings: ReturnType<typeof createMockSettings>,
onSelect: ReturnType<typeof vi.fn>,
options?: {
@ -244,6 +245,7 @@ const renderDialog = (
/>,
{
settings,
config: makeFakeConfig(),
uiState: { terminalBackgroundColor: undefined },
},
);
@ -268,7 +270,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderDialog(
const { lastFrame, waitUntilReady, unmount } = await renderDialog(
settings,
onSelect,
);
@ -286,7 +288,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderDialog(
const { lastFrame, waitUntilReady, unmount } = await renderDialog(
settings,
onSelect,
{
@ -307,7 +309,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const renderResult = renderDialog(settings, onSelect);
const renderResult = await renderDialog(settings, onSelect);
await renderResult.waitUntilReady();
await expect(renderResult).toMatchSvgSnapshot();
@ -319,7 +321,7 @@ describe('SettingsDialog', () => {
const onSelect = vi.fn();
// Render with a fixed height of 25 rows
const { lastFrame, waitUntilReady, unmount } = renderDialog(
const { lastFrame, waitUntilReady, unmount } = await renderDialog(
settings,
onSelect,
{
@ -346,7 +348,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderDialog(
const { lastFrame, waitUntilReady, unmount } = await renderDialog(
settings,
onSelect,
);
@ -379,7 +381,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { stdin, unmount, lastFrame, waitUntilReady } = renderDialog(
const { stdin, unmount, lastFrame, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -414,7 +416,7 @@ describe('SettingsDialog', () => {
it('should allow j and k characters to be typed in search without triggering navigation', async () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, stdin, waitUntilReady, unmount } = renderDialog(
const { lastFrame, stdin, waitUntilReady, unmount } = await renderDialog(
settings,
onSelect,
);
@ -440,7 +442,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { stdin, unmount, lastFrame, waitUntilReady } = renderDialog(
const { stdin, unmount, lastFrame, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -467,7 +469,7 @@ describe('SettingsDialog', () => {
const setValueSpy = vi.spyOn(settings, 'setValue');
const onSelect = vi.fn();
const { stdin, unmount, lastFrame, waitUntilReady } = renderDialog(
const { stdin, unmount, lastFrame, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -520,7 +522,7 @@ describe('SettingsDialog', () => {
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -552,7 +554,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -575,7 +577,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -596,7 +598,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, unmount, waitUntilReady } = renderDialog(
const { lastFrame, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -623,9 +625,13 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onRestartRequest = vi.fn();
const { unmount, waitUntilReady } = renderDialog(settings, vi.fn(), {
onRestartRequest,
});
const { unmount, waitUntilReady } = await renderDialog(
settings,
vi.fn(),
{
onRestartRequest,
},
);
await waitUntilReady();
// This test would need to trigger a restart-required setting change
@ -638,7 +644,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onRestartRequest = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
vi.fn(),
{
@ -663,7 +669,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, unmount, waitUntilReady } = renderDialog(
const { lastFrame, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -690,7 +696,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings({ vimMode: true });
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -727,7 +733,7 @@ describe('SettingsDialog', () => {
});
const onSelect = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderDialog(
const { lastFrame, waitUntilReady, unmount } = await renderDialog(
settings,
onSelect,
);
@ -745,7 +751,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -773,7 +779,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -812,7 +818,7 @@ describe('SettingsDialog', () => {
});
const onSelect = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderDialog(
const { lastFrame, waitUntilReady, unmount } = await renderDialog(
settings,
onSelect,
);
@ -828,7 +834,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -848,7 +854,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, unmount, waitUntilReady } = renderDialog(
const { lastFrame, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -871,7 +877,10 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { unmount, waitUntilReady } = renderDialog(settings, onSelect);
const { unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
await waitUntilReady();
// Restart prompt should be cleared when switching scopes
@ -890,7 +899,7 @@ describe('SettingsDialog', () => {
});
const onSelect = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderDialog(
const { lastFrame, waitUntilReady, unmount } = await renderDialog(
settings,
onSelect,
);
@ -917,7 +926,7 @@ describe('SettingsDialog', () => {
});
const onSelect = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderDialog(
const { lastFrame, waitUntilReady, unmount } = await renderDialog(
settings,
onSelect,
);
@ -968,7 +977,7 @@ describe('SettingsDialog', () => {
const onSelect = vi.fn();
const { stdin, unmount } = renderDialog(settings, onSelect);
const { stdin, unmount } = await renderDialog(settings, onSelect);
for (let i = 0; i < toggleCount; i++) {
act(() => {
@ -998,7 +1007,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1026,7 +1035,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings({ vimMode: true });
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1046,7 +1055,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1069,7 +1078,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, unmount, waitUntilReady } = renderDialog(
const { lastFrame, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1103,7 +1112,7 @@ describe('SettingsDialog', () => {
});
const onSelect = vi.fn();
const { lastFrame, waitUntilReady, unmount } = renderDialog(
const { lastFrame, waitUntilReady, unmount } = await renderDialog(
settings,
onSelect,
);
@ -1119,7 +1128,7 @@ describe('SettingsDialog', () => {
const onSelect = vi.fn();
// Should not crash even if some settings are missing definitions
const { lastFrame, waitUntilReady, unmount } = renderDialog(
const { lastFrame, waitUntilReady, unmount } = await renderDialog(
settings,
onSelect,
);
@ -1135,7 +1144,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, unmount, waitUntilReady } = renderDialog(
const { lastFrame, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1164,7 +1173,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1201,7 +1210,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings({ vimMode: true });
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1237,7 +1246,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onRestartRequest = vi.fn();
const { stdin, unmount, waitUntilReady } = renderDialog(
const { stdin, unmount, waitUntilReady } = await renderDialog(
settings,
vi.fn(),
{
@ -1265,7 +1274,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onRestartRequest = vi.fn();
const { stdin, lastFrame, unmount, waitUntilReady } = renderDialog(
const { stdin, lastFrame, unmount, waitUntilReady } = await renderDialog(
settings,
vi.fn(),
{
@ -1317,7 +1326,7 @@ describe('SettingsDialog', () => {
vi.mocked(getSettingsSchema).mockReturnValue(TOOLS_SHELL_FAKE_SCHEMA);
const settings = createMockSettings();
const { stdin, lastFrame, unmount, waitUntilReady } = renderDialog(
const { stdin, lastFrame, unmount, waitUntilReady } = await renderDialog(
settings,
vi.fn(),
);
@ -1361,9 +1370,9 @@ describe('SettingsDialog', () => {
});
const onSelect = vi.fn();
const { stdin, unmount, waitUntilReady } = renderWithProviders(
const { stdin, unmount, waitUntilReady } = await renderWithProviders(
<SettingsDialog onSelect={onSelect} />,
{ settings },
{ settings, config: makeFakeConfig() },
);
await waitUntilReady();
@ -1434,7 +1443,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const setValueSpy = vi.spyOn(settings, 'setValue');
const { stdin, unmount } = renderDialog(settings, vi.fn());
const { stdin, unmount } = await renderDialog(settings, vi.fn());
await act(async () => {
stdin.write(TerminalKeys.ENTER as string); // Start editing first array setting
@ -1460,7 +1469,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const setValueSpy = vi.spyOn(settings, 'setValue');
const { stdin, unmount } = renderDialog(settings, vi.fn());
const { stdin, unmount } = await renderDialog(settings, vi.fn());
await act(async () => {
stdin.write(TerminalKeys.DOWN_ARROW as string); // Move to second array setting
@ -1490,7 +1499,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, stdin, unmount, waitUntilReady } = renderDialog(
const { lastFrame, stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1520,7 +1529,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, stdin, unmount, waitUntilReady } = renderDialog(
const { lastFrame, stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1543,7 +1552,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, stdin, unmount, waitUntilReady } = renderDialog(
const { lastFrame, stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1576,7 +1585,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, stdin, unmount, waitUntilReady } = renderDialog(
const { lastFrame, stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1609,7 +1618,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
const { lastFrame, stdin, unmount, waitUntilReady } = renderDialog(
const { lastFrame, stdin, unmount, waitUntilReady } = await renderDialog(
settings,
onSelect,
);
@ -1863,7 +1872,7 @@ describe('SettingsDialog', () => {
});
const onSelect = vi.fn();
const renderResult = renderDialog(settings, onSelect);
const renderResult = await renderDialog(settings, onSelect);
await renderResult.waitUntilReady();
if (stdinActions) {

View file

@ -42,7 +42,7 @@ describe('ShortcutsHelp', () => {
value: platform.value,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ShortcutsHelp />,
{
width,
@ -56,7 +56,7 @@ describe('ShortcutsHelp', () => {
);
it('always shows Tab focus UI shortcut', async () => {
const rendered = renderWithProviders(<ShortcutsHelp />);
const rendered = await renderWithProviders(<ShortcutsHelp />);
await rendered.waitUntilReady();
expect(rendered.lastFrame()).toContain('Tab focus UI');
rendered.unmount();

View file

@ -25,7 +25,7 @@ vi.mock('../contexts/SessionContext.js', async (importOriginal) => {
const useSessionStatsMock = vi.mocked(SessionContext.useSessionStats);
const renderWithMockedStats = (metrics: SessionMetrics) => {
const renderWithMockedStats = async (metrics: SessionMetrics) => {
useSessionStatsMock.mockReturnValue({
stats: {
sessionId: 'test-session-id',
@ -39,7 +39,9 @@ const renderWithMockedStats = (metrics: SessionMetrics) => {
startNewPrompt: vi.fn(),
});
return renderWithProviders(<StatsDisplay duration="1s" />, { width: 100 });
return renderWithProviders(<StatsDisplay duration="1s" />, {
width: 100,
});
};
// Helper to create metrics with default zero values
@ -79,7 +81,8 @@ describe('<StatsDisplay />', () => {
it('renders only the Performance section in its zero state', async () => {
const zeroMetrics = createTestMetrics();
const { lastFrame, waitUntilReady } = renderWithMockedStats(zeroMetrics);
const { lastFrame, waitUntilReady } =
await renderWithMockedStats(zeroMetrics);
await waitUntilReady();
const output = lastFrame();
@ -120,7 +123,7 @@ describe('<StatsDisplay />', () => {
},
});
const { lastFrame, waitUntilReady } = renderWithMockedStats(metrics);
const { lastFrame, waitUntilReady } = await renderWithMockedStats(metrics);
await waitUntilReady();
const output = lastFrame();
@ -176,7 +179,7 @@ describe('<StatsDisplay />', () => {
},
});
const { lastFrame, waitUntilReady } = renderWithMockedStats(metrics);
const { lastFrame, waitUntilReady } = await renderWithMockedStats(metrics);
await waitUntilReady();
const output = lastFrame();
@ -218,7 +221,8 @@ describe('<StatsDisplay />', () => {
},
});
const { lastFrame, waitUntilReady } = renderWithMockedStats(metrics);
const { lastFrame, waitUntilReady } =
await renderWithMockedStats(metrics);
await waitUntilReady();
const output = lastFrame();
@ -247,7 +251,8 @@ describe('<StatsDisplay />', () => {
},
});
const { lastFrame, waitUntilReady } = renderWithMockedStats(metrics);
const { lastFrame, waitUntilReady } =
await renderWithMockedStats(metrics);
await waitUntilReady();
const output = lastFrame();
@ -272,7 +277,8 @@ describe('<StatsDisplay />', () => {
byName: {},
},
});
const { lastFrame, waitUntilReady } = renderWithMockedStats(metrics);
const { lastFrame, waitUntilReady } =
await renderWithMockedStats(metrics);
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();
});
@ -293,7 +299,8 @@ describe('<StatsDisplay />', () => {
byName: {},
},
});
const { lastFrame, waitUntilReady } = renderWithMockedStats(metrics);
const { lastFrame, waitUntilReady } =
await renderWithMockedStats(metrics);
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();
});
@ -314,7 +321,8 @@ describe('<StatsDisplay />', () => {
byName: {},
},
});
const { lastFrame, waitUntilReady } = renderWithMockedStats(metrics);
const { lastFrame, waitUntilReady } =
await renderWithMockedStats(metrics);
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();
});
@ -342,7 +350,8 @@ describe('<StatsDisplay />', () => {
},
});
const { lastFrame, waitUntilReady } = renderWithMockedStats(metrics);
const { lastFrame, waitUntilReady } =
await renderWithMockedStats(metrics);
await waitUntilReady();
const output = lastFrame();
@ -369,7 +378,8 @@ describe('<StatsDisplay />', () => {
},
});
const { lastFrame, waitUntilReady } = renderWithMockedStats(metrics);
const { lastFrame, waitUntilReady } =
await renderWithMockedStats(metrics);
await waitUntilReady();
const output = lastFrame();
@ -382,7 +392,8 @@ describe('<StatsDisplay />', () => {
const zeroMetrics = createTestMetrics();
it('renders the default title when no title prop is provided', async () => {
const { lastFrame, waitUntilReady } = renderWithMockedStats(zeroMetrics);
const { lastFrame, waitUntilReady } =
await renderWithMockedStats(zeroMetrics);
await waitUntilReady();
const output = lastFrame();
expect(output).toContain('Session Stats');
@ -404,7 +415,7 @@ describe('<StatsDisplay />', () => {
startNewPrompt: vi.fn(),
});
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<StatsDisplay duration="1s" title="Agent powering down. Goodbye!" />,
{ width: 100 },
);
@ -466,7 +477,7 @@ describe('<StatsDisplay />', () => {
startNewPrompt: vi.fn(),
});
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<StatsDisplay duration="1s" quotas={quotas} />,
{ width: 100 },
);
@ -514,7 +525,7 @@ describe('<StatsDisplay />', () => {
startNewPrompt: vi.fn(),
});
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<StatsDisplay
duration="1s"
quotas={quotas}
@ -570,7 +581,7 @@ describe('<StatsDisplay />', () => {
startNewPrompt: vi.fn(),
});
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<StatsDisplay duration="1s" quotas={quotas} />,
{ width: 100 },
);
@ -603,7 +614,7 @@ describe('<StatsDisplay />', () => {
startNewPrompt: vi.fn(),
});
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<StatsDisplay
duration="1s"
selectedAuthType="oauth"
@ -636,7 +647,7 @@ describe('<StatsDisplay />', () => {
startNewPrompt: vi.fn(),
});
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<StatsDisplay duration="1s" selectedAuthType="Google API Key" />,
{ width: 100 },
);

View file

@ -13,7 +13,7 @@ describe('StickyHeader', () => {
it.each([true, false])(
'renders children with isFirst=%s',
async (isFirst) => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<StickyHeader
isFirst={isFirst}
width={80}

View file

@ -51,7 +51,7 @@ describe('ThemeDialog Snapshots', () => {
async (isDev) => {
mockIsDevelopment.value = isDev;
const settings = createMockSettings();
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ThemeDialog {...baseProps} settings={settings} />,
{ settings },
);
@ -64,10 +64,11 @@ describe('ThemeDialog Snapshots', () => {
it('should render correctly in scope selector mode', async () => {
const settings = createMockSettings();
const { lastFrame, stdin, waitUntilReady, unmount } = renderWithProviders(
<ThemeDialog {...baseProps} settings={settings} />,
{ settings },
);
const { lastFrame, stdin, waitUntilReady, unmount } =
await renderWithProviders(
<ThemeDialog {...baseProps} settings={settings} />,
{ settings },
);
await waitUntilReady();
// Press Tab to switch to scope selector mode
@ -85,7 +86,7 @@ describe('ThemeDialog Snapshots', () => {
it('should call onCancel when ESC is pressed', async () => {
const mockOnCancel = vi.fn();
const settings = createMockSettings();
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<ThemeDialog
{...baseProps}
onCancel={mockOnCancel}
@ -112,7 +113,7 @@ describe('ThemeDialog Snapshots', () => {
it('should call onSelect when a theme is selected', async () => {
const settings = createMockSettings();
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<ThemeDialog {...baseProps} settings={settings} />,
{
settings,
@ -148,7 +149,7 @@ describe('Initial Theme Selection', () => {
it('should default to a light theme when terminal background is light and no theme is set', async () => {
const settings = createMockSettings(); // No theme set
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ThemeDialog {...baseProps} settings={settings} />,
{
settings,
@ -165,7 +166,7 @@ describe('Initial Theme Selection', () => {
it('should default to a dark theme when terminal background is dark and no theme is set', async () => {
const settings = createMockSettings(); // No theme set
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ThemeDialog {...baseProps} settings={settings} />,
{
settings,
@ -181,7 +182,7 @@ describe('Initial Theme Selection', () => {
it('should use the theme from settings even if terminal background suggests a different theme type', async () => {
const settings = createMockSettings({ ui: { theme: 'DefaultLight' } }); // Light theme set
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ThemeDialog {...baseProps} settings={settings} />,
{
settings,
@ -207,7 +208,7 @@ describe('Hint Visibility', () => {
it('should show hint when theme background matches terminal background', async () => {
const settings = createMockSettings({ ui: { theme: 'Default' } });
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ThemeDialog {...baseProps} settings={settings} />,
{
settings,
@ -222,7 +223,7 @@ describe('Hint Visibility', () => {
it('should not show hint when theme background does not match terminal background', async () => {
const settings = createMockSettings({ ui: { theme: 'Default' } });
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ThemeDialog {...baseProps} settings={settings} />,
{
settings,

View file

@ -12,7 +12,7 @@ import { type UIState } from '../contexts/UIStateContext.js';
import { type TextBuffer } from './shared/text-buffer.js';
import { type HistoryItem } from '../types.js';
const renderToastDisplay = (uiState: Partial<UIState> = {}) =>
const renderToastDisplay = async (uiState: Partial<UIState> = {}) =>
renderWithProviders(<ToastDisplay />, {
uiState: {
buffer: { text: '' } as TextBuffer,
@ -112,13 +112,13 @@ describe('ToastDisplay', () => {
});
it('renders nothing by default', async () => {
const { lastFrame, waitUntilReady } = renderToastDisplay();
const { lastFrame, waitUntilReady } = await renderToastDisplay();
await waitUntilReady();
expect(lastFrame({ allowEmpty: true })).toBe('');
});
it('renders Ctrl+C prompt', async () => {
const { lastFrame, waitUntilReady } = renderToastDisplay({
const { lastFrame, waitUntilReady } = await renderToastDisplay({
ctrlCPressedOnce: true,
});
await waitUntilReady();
@ -126,7 +126,7 @@ describe('ToastDisplay', () => {
});
it('renders warning message', async () => {
const { lastFrame, waitUntilReady } = renderToastDisplay({
const { lastFrame, waitUntilReady } = await renderToastDisplay({
transientMessage: {
text: 'This is a warning',
type: TransientMessageType.Warning,
@ -137,7 +137,7 @@ describe('ToastDisplay', () => {
});
it('renders hint message', async () => {
const { lastFrame, waitUntilReady } = renderToastDisplay({
const { lastFrame, waitUntilReady } = await renderToastDisplay({
transientMessage: {
text: 'This is a hint',
type: TransientMessageType.Hint,
@ -148,7 +148,7 @@ describe('ToastDisplay', () => {
});
it('renders Ctrl+D prompt', async () => {
const { lastFrame, waitUntilReady } = renderToastDisplay({
const { lastFrame, waitUntilReady } = await renderToastDisplay({
ctrlDPressedOnce: true,
});
await waitUntilReady();
@ -156,7 +156,7 @@ describe('ToastDisplay', () => {
});
it('renders Escape prompt when buffer is empty', async () => {
const { lastFrame, waitUntilReady } = renderToastDisplay({
const { lastFrame, waitUntilReady } = await renderToastDisplay({
showEscapePrompt: true,
history: [{ id: 1, type: 'user', text: 'test' }] as HistoryItem[],
});
@ -165,7 +165,7 @@ describe('ToastDisplay', () => {
});
it('renders Escape prompt when buffer is NOT empty', async () => {
const { lastFrame, waitUntilReady } = renderToastDisplay({
const { lastFrame, waitUntilReady } = await renderToastDisplay({
showEscapePrompt: true,
buffer: { text: 'some text' } as TextBuffer,
});
@ -174,7 +174,7 @@ describe('ToastDisplay', () => {
});
it('renders Queue Error Message', async () => {
const { lastFrame, waitUntilReady } = renderToastDisplay({
const { lastFrame, waitUntilReady } = await renderToastDisplay({
queueErrorMessage: 'Queue Error',
});
await waitUntilReady();
@ -182,7 +182,7 @@ describe('ToastDisplay', () => {
});
it('renders expansion hint when showIsExpandableHint is true', async () => {
const { lastFrame, waitUntilReady } = renderToastDisplay({
const { lastFrame, waitUntilReady } = await renderToastDisplay({
showIsExpandableHint: true,
constrainHeight: true,
});
@ -193,7 +193,7 @@ describe('ToastDisplay', () => {
});
it('renders collapse hint when showIsExpandableHint is true and constrainHeight is false', async () => {
const { lastFrame, waitUntilReady } = renderToastDisplay({
const { lastFrame, waitUntilReady } = await renderToastDisplay({
showIsExpandableHint: true,
constrainHeight: false,
});

View file

@ -79,7 +79,7 @@ describe('ToolConfirmationQueue', () => {
total: 3,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@ -117,7 +117,7 @@ describe('ToolConfirmationQueue', () => {
total: 1,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@ -156,7 +156,7 @@ describe('ToolConfirmationQueue', () => {
total: 1,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Box flexDirection="column" height={30}>
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
@ -210,7 +210,7 @@ describe('ToolConfirmationQueue', () => {
};
// Use a small availableTerminalHeight to force truncation
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@ -265,7 +265,7 @@ describe('ToolConfirmationQueue', () => {
lastFrame,
waitUntilReady,
unmount = vi.fn(),
} = renderWithProviders(
} = await renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@ -321,7 +321,7 @@ describe('ToolConfirmationQueue', () => {
total: 1,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@ -360,7 +360,7 @@ describe('ToolConfirmationQueue', () => {
total: 1,
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@ -398,7 +398,7 @@ describe('ToolConfirmationQueue', () => {
total: 1,
};
const { lastFrame, unmount } = renderWithProviders(
const { lastFrame, unmount } = await renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,

View file

@ -39,7 +39,7 @@ describe('<UserIdentity />', () => {
} as unknown as ContentGeneratorConfig);
vi.spyOn(mockConfig, 'getUserTierName').mockReturnValue(undefined);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<UserIdentity config={mockConfig} />,
);
await waitUntilReady();
@ -51,7 +51,7 @@ describe('<UserIdentity />', () => {
unmount();
});
it('should render the user email on the very first frame (regression test)', () => {
it('should render the user email on the very first frame (regression test)', async () => {
const mockConfig = makeFakeConfig();
vi.spyOn(mockConfig, 'getContentGeneratorConfig').mockReturnValue({
authType: AuthType.LOGIN_WITH_GOOGLE,
@ -59,7 +59,7 @@ describe('<UserIdentity />', () => {
} as unknown as ContentGeneratorConfig);
vi.spyOn(mockConfig, 'getUserTierName').mockReturnValue(undefined);
const { lastFrameRaw, unmount } = renderWithProviders(
const { lastFrameRaw, unmount } = await renderWithProviders(
<UserIdentity config={mockConfig} />,
);
@ -85,7 +85,7 @@ describe('<UserIdentity />', () => {
} as unknown as ContentGeneratorConfig);
vi.spyOn(mockConfig, 'getUserTierName').mockReturnValue(undefined);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<UserIdentity config={mockConfig} />,
);
await waitUntilReady();
@ -106,7 +106,7 @@ describe('<UserIdentity />', () => {
} as unknown as ContentGeneratorConfig);
vi.spyOn(mockConfig, 'getUserTierName').mockReturnValue('Premium Plan');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<UserIdentity config={mockConfig} />,
);
await waitUntilReady();
@ -135,7 +135,7 @@ describe('<UserIdentity />', () => {
{} as unknown as ContentGeneratorConfig,
);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<UserIdentity config={mockConfig} />,
);
await waitUntilReady();
@ -152,7 +152,7 @@ describe('<UserIdentity />', () => {
} as unknown as ContentGeneratorConfig);
vi.spyOn(mockConfig, 'getUserTierName').mockReturnValue(undefined);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<UserIdentity config={mockConfig} />,
);
await waitUntilReady();
@ -172,7 +172,7 @@ describe('<UserIdentity />', () => {
} as unknown as ContentGeneratorConfig);
vi.spyOn(mockConfig, 'getUserTierName').mockReturnValue('Enterprise Tier');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<UserIdentity config={mockConfig} />,
);
await waitUntilReady();
@ -191,7 +191,7 @@ describe('<UserIdentity />', () => {
} as unknown as ContentGeneratorConfig);
vi.spyOn(mockConfig, 'getUserTierName').mockReturnValue('Advanced Ultra');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<UserIdentity config={mockConfig} />,
);
await waitUntilReady();

View file

@ -18,20 +18,8 @@ Spinner Connecting to MCP servers... (0/5) - Waiting for: s1, s2, s3, +2 more
"
`;
exports[`ConfigInitDisplay > truncates list of waiting servers if too many 2`] = `
"
Spinner Connecting to MCP servers... (0/5) - Waiting for: s1, s2, s3, +2 more
"
`;
exports[`ConfigInitDisplay > updates message on McpClientUpdate event 1`] = `
"
Spinner Connecting to MCP servers... (1/2) - Waiting for: server2
"
`;
exports[`ConfigInitDisplay > updates message on McpClientUpdate event 2`] = `
"
Spinner Connecting to MCP servers... (1/2) - Waiting for: server2
"
`;

View file

@ -29,7 +29,7 @@ describe('<CompressionMessage />', () => {
describe('pending state', () => {
it('renders pending message when compression is in progress', async () => {
const props = createCompressionProps({ isPending: true });
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<CompressionMessage {...props} />,
);
await waitUntilReady();
@ -48,7 +48,7 @@ describe('<CompressionMessage />', () => {
newTokenCount: 50,
compressionStatus: CompressionStatus.COMPRESSED,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<CompressionMessage {...props} />,
);
await waitUntilReady();
@ -73,9 +73,8 @@ describe('<CompressionMessage />', () => {
newTokenCount: newTokens,
compressionStatus: CompressionStatus.COMPRESSED,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<CompressionMessage {...props} />,
);
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(<CompressionMessage {...props} />);
await waitUntilReady();
const output = lastFrame();
@ -99,7 +98,7 @@ describe('<CompressionMessage />', () => {
compressionStatus:
CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<CompressionMessage {...props} />,
);
await waitUntilReady();
@ -120,7 +119,7 @@ describe('<CompressionMessage />', () => {
compressionStatus:
CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<CompressionMessage {...props} />,
);
await waitUntilReady();
@ -159,9 +158,8 @@ describe('<CompressionMessage />', () => {
newTokenCount: newTokens,
compressionStatus: CompressionStatus.COMPRESSED,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<CompressionMessage {...props} />,
);
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(<CompressionMessage {...props} />);
await waitUntilReady();
const output = lastFrame();
@ -184,9 +182,8 @@ describe('<CompressionMessage />', () => {
compressionStatus:
CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<CompressionMessage {...props} />,
);
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(<CompressionMessage {...props} />);
await waitUntilReady();
const output = lastFrame();
@ -212,9 +209,8 @@ describe('<CompressionMessage />', () => {
compressionStatus:
CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<CompressionMessage {...props} />,
);
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(<CompressionMessage {...props} />);
await waitUntilReady();
const output = lastFrame();
@ -232,7 +228,7 @@ describe('<CompressionMessage />', () => {
isPending: false,
compressionStatus: CompressionStatus.COMPRESSION_FAILED_EMPTY_SUMMARY,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<CompressionMessage {...props} />,
);
await waitUntilReady();
@ -251,7 +247,7 @@ describe('<CompressionMessage />', () => {
compressionStatus:
CompressionStatus.COMPRESSION_FAILED_TOKEN_COUNT_ERROR,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<CompressionMessage {...props} />,
);
await waitUntilReady();

View file

@ -7,7 +7,6 @@
import { OverflowProvider } from '../../contexts/OverflowContext.js';
import { renderWithProviders } from '../../../test-utils/render.js';
import { createMockSettings } from '../../../test-utils/settings.js';
import { makeFakeConfig } from '@google/gemini-cli-core';
import { waitFor } from '../../../test-utils/async.js';
import { DiffRenderer } from './DiffRenderer.js';
import * as CodeColorizer from '../../utils/CodeColorizer.js';
@ -36,7 +35,7 @@ index 0000000..e69de29
@@ -0,0 +1 @@
+print("hello world")
`;
renderWithProviders(
await renderWithProviders(
<OverflowProvider>
<DiffRenderer
diffContent={newFileDiffContent}
@ -45,7 +44,6 @@ index 0000000..e69de29
/>
</OverflowProvider>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
@ -71,7 +69,7 @@ index 0000000..e69de29
@@ -0,0 +1 @@
+some content
`;
renderWithProviders(
await renderWithProviders(
<OverflowProvider>
<DiffRenderer
diffContent={newFileDiffContent}
@ -80,7 +78,6 @@ index 0000000..e69de29
/>
</OverflowProvider>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
@ -106,12 +103,11 @@ index 0000000..e69de29
@@ -0,0 +1 @@
+some text content
`;
renderWithProviders(
await renderWithProviders(
<OverflowProvider>
<DiffRenderer diffContent={newFileDiffContent} terminalWidth={80} />
</OverflowProvider>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
@ -138,7 +134,7 @@ index 0000001..0000002 100644
-old line
+new line
`;
const { lastFrame } = renderWithProviders(
const { lastFrame } = await renderWithProviders(
<OverflowProvider>
<DiffRenderer
diffContent={existingFileDiffContent}
@ -147,7 +143,6 @@ index 0000001..0000002 100644
/>
</OverflowProvider>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
@ -172,7 +167,7 @@ index 1234567..1234567 100644
--- a/file.txt
+++ b/file.txt
`;
const { lastFrame } = renderWithProviders(
const { lastFrame } = await renderWithProviders(
<OverflowProvider>
<DiffRenderer
diffContent={noChangeDiff}
@ -181,7 +176,6 @@ index 1234567..1234567 100644
/>
</OverflowProvider>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
@ -191,12 +185,11 @@ index 1234567..1234567 100644
});
it('should handle empty diff content', async () => {
const { lastFrame } = renderWithProviders(
const { lastFrame } = await renderWithProviders(
<OverflowProvider>
<DiffRenderer diffContent="" terminalWidth={80} />
</OverflowProvider>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
@ -220,7 +213,7 @@ index 123..456 100644
context line 10
context line 11
`;
const { lastFrame } = renderWithProviders(
const { lastFrame } = await renderWithProviders(
<OverflowProvider>
<DiffRenderer
diffContent={diffWithGap}
@ -229,7 +222,6 @@ index 123..456 100644
/>
</OverflowProvider>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
@ -257,7 +249,7 @@ index abc..def 100644
context line 14
context line 15
`;
const { lastFrame } = renderWithProviders(
const { lastFrame } = await renderWithProviders(
<OverflowProvider>
<DiffRenderer
diffContent={diffWithSmallGap}
@ -266,7 +258,6 @@ index abc..def 100644
/>
</OverflowProvider>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
@ -309,7 +300,7 @@ index 123..789 100644
])(
'with terminalWidth $terminalWidth and height $height',
async ({ terminalWidth, height }) => {
const { lastFrame } = renderWithProviders(
const { lastFrame } = await renderWithProviders(
<OverflowProvider>
<DiffRenderer
diffContent={diffWithMultipleHunks}
@ -319,7 +310,6 @@ index 123..789 100644
/>
</OverflowProvider>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
@ -347,7 +337,7 @@ fileDiff Index: file.txt
+const anotherNew = 'test';
\\ No newline at end of file
`;
const { lastFrame } = renderWithProviders(
const { lastFrame } = await renderWithProviders(
<OverflowProvider>
<DiffRenderer
diffContent={newFileDiff}
@ -356,7 +346,6 @@ fileDiff Index: file.txt
/>
</OverflowProvider>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);
@ -377,7 +366,7 @@ fileDiff Index: Dockerfile
+RUN npm run build
\\ No newline at end of file
`;
const { lastFrame } = renderWithProviders(
const { lastFrame } = await renderWithProviders(
<OverflowProvider>
<DiffRenderer
diffContent={newFileDiff}
@ -386,7 +375,6 @@ fileDiff Index: Dockerfile
/>
</OverflowProvider>,
{
config: makeFakeConfig({ useAlternateBuffer }),
settings: createMockSettings({ ui: { useAlternateBuffer } }),
},
);

View file

@ -24,7 +24,7 @@ describe('<GeminiMessage /> - Raw Markdown Display Snapshots', () => {
])(
'renders with renderMarkdown=$renderMarkdown $description',
async ({ renderMarkdown }) => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<GeminiMessage {...baseProps} />,
{
uiState: { renderMarkdown, streamingState: StreamingState.Idle },
@ -39,7 +39,7 @@ describe('<GeminiMessage /> - Raw Markdown Display Snapshots', () => {
it.each([{ renderMarkdown: true }, { renderMarkdown: false }])(
'renders pending state with renderMarkdown=$renderMarkdown',
async ({ renderMarkdown }) => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<GeminiMessage {...baseProps} isPending={true} />,
{
uiState: { renderMarkdown, streamingState: StreamingState.Idle },
@ -55,7 +55,7 @@ describe('<GeminiMessage /> - Raw Markdown Display Snapshots', () => {
const terminalWidth = 20;
const text =
'This is a long line that should wrap correctly without truncation';
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<GeminiMessage
text={text}
isPending={false}

View file

@ -33,7 +33,7 @@ describe('ToolConfirmationMessage Redirection', () => {
rootCommands: ['echo'],
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}

View file

@ -59,7 +59,7 @@ describe('<ShellToolMessage />', () => {
['SHELL_COMMAND_NAME', SHELL_COMMAND_NAME],
['SHELL_TOOL_NAME', SHELL_TOOL_NAME],
])('clicks inside the shell area sets focus for %s', async (_, name) => {
const { lastFrame, simulateClick, unmount } = renderWithProviders(
const { lastFrame, simulateClick, unmount } = await renderWithProviders(
<ShellToolMessage {...baseProps} name={name} />,
{ uiActions, mouseEventsEnabled: true },
);
@ -86,7 +86,7 @@ describe('<ShellToolMessage />', () => {
return <ShellToolMessage {...baseProps} status={status} ptyId={1} />;
};
const { lastFrame, unmount } = renderWithProviders(<Wrapper />, {
const { lastFrame, unmount } = await renderWithProviders(<Wrapper />, {
uiActions,
uiState: {
streamingState: StreamingState.Idle,
@ -170,7 +170,7 @@ describe('<ShellToolMessage />', () => {
},
],
])('%s', async (_, props, options) => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ShellToolMessage {...baseProps} {...props} />,
{ uiActions, ...options },
);
@ -219,26 +219,29 @@ describe('<ShellToolMessage />', () => {
focused,
constrainHeight,
) => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ShellToolMessage
{...baseProps}
resultDisplay={LONG_OUTPUT}
renderOutputAsMarkdown={false}
availableTerminalHeight={availableTerminalHeight}
ptyId={1}
status={CoreToolCallStatus.Executing}
/>,
{
uiActions,
config: makeFakeConfig({ useAlternateBuffer: true }),
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
uiState: {
activePtyId: focused ? 1 : 2,
embeddedShellFocused: focused,
constrainHeight,
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(
<ShellToolMessage
{...baseProps}
resultDisplay={LONG_OUTPUT}
renderOutputAsMarkdown={false}
availableTerminalHeight={availableTerminalHeight}
ptyId={1}
status={CoreToolCallStatus.Executing}
/>,
{
uiActions,
config: makeFakeConfig({ useAlternateBuffer: true }),
settings: createMockSettings({
ui: { useAlternateBuffer: true },
}),
uiState: {
activePtyId: focused ? 1 : 2,
embeddedShellFocused: focused,
constrainHeight,
},
},
},
);
);
await waitUntilReady();
const frame = lastFrame();
@ -249,7 +252,7 @@ describe('<ShellToolMessage />', () => {
);
it('fully expands in standard mode when availableTerminalHeight is undefined', async () => {
const { lastFrame, unmount } = renderWithProviders(
const { lastFrame, unmount } = await renderWithProviders(
<ShellToolMessage
{...baseProps}
resultDisplay={LONG_OUTPUT}
@ -273,7 +276,7 @@ describe('<ShellToolMessage />', () => {
});
it('fully expands in alternate buffer mode when constrainHeight is false and isExpandable is true', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ShellToolMessage
{...baseProps}
resultDisplay={LONG_OUTPUT}
@ -303,7 +306,7 @@ describe('<ShellToolMessage />', () => {
});
it('stays constrained in alternate buffer mode when isExpandable is false even if constrainHeight is false', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ShellToolMessage
{...baseProps}
resultDisplay={LONG_OUTPUT}

View file

@ -64,7 +64,7 @@ describe('<SubagentGroupDisplay />', () => {
},
];
const renderSubagentGroup = (
const renderSubagentGroup = async (
toolCallsToRender: IndividualToolCallDisplay[],
height?: number,
) =>
@ -78,12 +78,12 @@ describe('<SubagentGroupDisplay />', () => {
);
it('renders nothing if there are no agent tool calls', async () => {
const { lastFrame } = renderSubagentGroup([], 40);
const { lastFrame } = await renderSubagentGroup([], 40);
expect(lastFrame({ allowEmpty: true })).toBe('');
});
it('renders collapsed view by default with correct agent counts and states', async () => {
const { lastFrame, waitUntilReady } = renderSubagentGroup(
const { lastFrame, waitUntilReady } = await renderSubagentGroup(
mockToolCalls,
40,
);
@ -92,7 +92,10 @@ describe('<SubagentGroupDisplay />', () => {
});
it('expands when availableTerminalHeight is undefined', async () => {
const { lastFrame, rerender } = renderSubagentGroup(mockToolCalls, 40);
const { lastFrame, rerender } = await renderSubagentGroup(
mockToolCalls,
40,
);
// Default collapsed view
await waitFor(() => {

View file

@ -11,7 +11,7 @@ import React from 'react';
describe('ThinkingMessage', () => {
it('renders subject line with vertical rule and "Thinking..." header', async () => {
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<ThinkingMessage
thought={{ subject: 'Planning', description: 'test' }}
terminalWidth={80}
@ -30,7 +30,7 @@ describe('ThinkingMessage', () => {
});
it('uses description when subject is empty', async () => {
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<ThinkingMessage
thought={{ subject: '', description: 'Processing details' }}
terminalWidth={80}
@ -48,7 +48,7 @@ describe('ThinkingMessage', () => {
});
it('renders full mode with left border and full text', async () => {
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<ThinkingMessage
thought={{
subject: 'Planning',
@ -70,7 +70,7 @@ describe('ThinkingMessage', () => {
});
it('renders "Thinking..." header when isFirstThinking is true', async () => {
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<ThinkingMessage
thought={{
subject: 'Summary line',
@ -92,7 +92,7 @@ describe('ThinkingMessage', () => {
});
it('normalizes escaped newline tokens', async () => {
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<ThinkingMessage
thought={{
subject: 'Matching the Blocks',
@ -110,7 +110,7 @@ describe('ThinkingMessage', () => {
});
it('renders empty state gracefully', async () => {
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<ThinkingMessage
thought={{ subject: '', description: '' }}
terminalWidth={80}
@ -124,7 +124,7 @@ describe('ThinkingMessage', () => {
});
it('renders multiple thinking messages sequentially correctly', async () => {
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<React.Fragment>
<ThinkingMessage
thought={{
@ -161,7 +161,7 @@ describe('ThinkingMessage', () => {
});
it('filters out progress dots and empty lines', async () => {
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<ThinkingMessage
thought={{ subject: '...', description: 'Thinking\n.\n..\n...\nDone' }}
terminalWidth={80}

View file

@ -50,7 +50,7 @@ describe('ToolConfirmationMessage', () => {
urls: ['https://example.com'],
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}
@ -77,7 +77,7 @@ describe('ToolConfirmationMessage', () => {
],
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}
@ -101,7 +101,7 @@ describe('ToolConfirmationMessage', () => {
urls: ['https://täst.com'],
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}
@ -132,7 +132,7 @@ describe('ToolConfirmationMessage', () => {
rootCommands: ['curl'],
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}
@ -163,7 +163,7 @@ describe('ToolConfirmationMessage', () => {
rootCommands: ['curl'],
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}
@ -193,7 +193,7 @@ describe('ToolConfirmationMessage', () => {
urls: ['https://еxample.com', 'https://täst.com'],
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}
@ -223,7 +223,7 @@ describe('ToolConfirmationMessage', () => {
commands: ['echo "hello"', 'ls -la', 'whoami'], // Multi-command list
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}
@ -252,7 +252,7 @@ describe('ToolConfirmationMessage', () => {
rootCommands: ['echo'],
};
const result = renderWithProviders(
const result = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}
@ -336,16 +336,17 @@ describe('ToolConfirmationMessage', () => {
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={details}
config={mockConfig}
getPreferredEditor={vi.fn()}
availableTerminalHeight={30}
terminalWidth={80}
/>,
);
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={details}
config={mockConfig}
getPreferredEditor={vi.fn()}
availableTerminalHeight={30}
terminalWidth={80}
/>,
);
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();
@ -359,16 +360,17 @@ describe('ToolConfirmationMessage', () => {
getDisableAlwaysAllow: () => false,
} as unknown as Config;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={details}
config={mockConfig}
getPreferredEditor={vi.fn()}
availableTerminalHeight={30}
terminalWidth={80}
/>,
);
const { lastFrame, waitUntilReady, unmount } =
await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={details}
config={mockConfig}
getPreferredEditor={vi.fn()}
availableTerminalHeight={30}
terminalWidth={80}
/>,
);
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();
@ -394,7 +396,7 @@ describe('ToolConfirmationMessage', () => {
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={editConfirmationDetails}
@ -421,7 +423,7 @@ describe('ToolConfirmationMessage', () => {
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={editConfirmationDetails}
@ -469,7 +471,7 @@ describe('ToolConfirmationMessage', () => {
isDiffingEnabled: false,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={editConfirmationDetails}
@ -497,7 +499,7 @@ describe('ToolConfirmationMessage', () => {
isDiffingEnabled: false,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={editConfirmationDetails}
@ -525,7 +527,7 @@ describe('ToolConfirmationMessage', () => {
isDiffingEnabled: true,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={editConfirmationDetails}
@ -552,7 +554,7 @@ describe('ToolConfirmationMessage', () => {
onConfirm: vi.fn(),
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}
@ -598,7 +600,7 @@ describe('ToolConfirmationMessage', () => {
onConfirm: vi.fn(),
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}
@ -630,7 +632,7 @@ describe('ToolConfirmationMessage', () => {
onConfirm: vi.fn(),
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}
@ -675,7 +677,7 @@ describe('ToolConfirmationMessage', () => {
urls: ['https://example.com'],
};
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
confirmationDetails={confirmationDetails}

View file

@ -75,7 +75,7 @@ describe('<ToolGroupMessage />', () => {
it('renders single successful tool call', async () => {
const toolCalls = [createToolCall()];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{
config: baseMockConfig,
@ -109,7 +109,7 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{ config: baseMockConfig, settings: fullVerbositySettings },
);
@ -130,7 +130,7 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{ config: baseMockConfig, settings: fullVerbositySettings },
);
@ -164,7 +164,7 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{
config: baseMockConfig,
@ -205,7 +205,7 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{
config: baseMockConfig,
@ -238,7 +238,7 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{
config: baseMockConfig,
@ -282,7 +282,7 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{
config: baseMockConfig,
@ -324,7 +324,7 @@ describe('<ToolGroupMessage />', () => {
}),
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={item}
@ -358,7 +358,7 @@ describe('<ToolGroupMessage />', () => {
}),
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={item}
@ -386,7 +386,7 @@ describe('<ToolGroupMessage />', () => {
it('renders empty tool calls array', async () => {
const toolCalls: IndividualToolCallDisplay[] = [];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{
config: baseMockConfig,
@ -423,7 +423,7 @@ describe('<ToolGroupMessage />', () => {
}),
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<Scrollable height={10} hasFocus={true} scrollToBottom={true}>
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />
</Scrollable>,
@ -456,7 +456,7 @@ describe('<ToolGroupMessage />', () => {
}),
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{
config: baseMockConfig,
@ -496,7 +496,7 @@ describe('<ToolGroupMessage />', () => {
];
const item2 = createItem(toolCalls2);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<Scrollable height={6} hasFocus={true} scrollToBottom={true}>
<ToolGroupMessage
{...baseProps}
@ -541,7 +541,7 @@ describe('<ToolGroupMessage />', () => {
}),
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{
config: baseMockConfig,
@ -571,7 +571,7 @@ describe('<ToolGroupMessage />', () => {
}),
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{
config: baseMockConfig,
@ -609,7 +609,7 @@ describe('<ToolGroupMessage />', () => {
}),
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={item}
@ -676,10 +676,15 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{ config: baseMockConfig, settings: fullVerbositySettings },
);
const { lastFrame, unmount, waitUntilReady } =
await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={item}
toolCalls={toolCalls}
/>,
{ config: baseMockConfig, settings: fullVerbositySettings },
);
await waitUntilReady();
if (shouldHide) {
@ -706,7 +711,7 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{ config: baseMockConfig, settings: fullVerbositySettings },
);
@ -729,7 +734,7 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={item}
@ -756,7 +761,7 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={item}
@ -779,7 +784,7 @@ describe('<ToolGroupMessage />', () => {
const toolCalls: IndividualToolCallDisplay[] = [];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={item}
@ -810,7 +815,7 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={item}
@ -843,7 +848,7 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={item}
@ -884,7 +889,7 @@ describe('<ToolGroupMessage />', () => {
const initialItem = createItem(visibleTools);
const hiddenItem = createItem(hiddenTools);
const firstRender = renderWithProviders(
const firstRender = await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={initialItem}
@ -901,7 +906,7 @@ describe('<ToolGroupMessage />', () => {
expect(firstRender.lastFrame()).toContain('visible-tool');
firstRender.unmount();
const secondRender = renderWithProviders(
const secondRender = await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={hiddenItem}
@ -938,7 +943,7 @@ describe('<ToolGroupMessage />', () => {
const toolCalls = [visibleTool, ...hiddenTools];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={item}
@ -964,7 +969,7 @@ describe('<ToolGroupMessage />', () => {
const toolCalls: IndividualToolCallDisplay[] = [];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage
item={item}
toolCalls={toolCalls}
@ -1011,10 +1016,15 @@ describe('<ToolGroupMessage />', () => {
];
const item = createItem(toolCalls);
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
<ToolGroupMessage {...baseProps} item={item} toolCalls={toolCalls} />,
{ config: baseMockConfig, settings: fullVerbositySettings },
);
const { lastFrame, unmount, waitUntilReady } =
await renderWithProviders(
<ToolGroupMessage
{...baseProps}
item={item}
toolCalls={toolCalls}
/>,
{ config: baseMockConfig, settings: fullVerbositySettings },
);
await waitUntilReady();

View file

@ -58,7 +58,7 @@ describe('<ToolMessage />', () => {
};
// Helper to render with context
const renderWithContext = (
const renderWithContext = async (
ui: React.ReactElement,
streamingState: StreamingState,
) =>
@ -78,7 +78,7 @@ describe('<ToolMessage />', () => {
});
it('renders basic tool information', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage {...baseProps} />,
StreamingState.Idle,
);
@ -91,7 +91,7 @@ describe('<ToolMessage />', () => {
describe('JSON rendering', () => {
it('pretty prints valid JSON', async () => {
const testJSONstring = '{"a": 1, "b": [2, 3]}';
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage
{...baseProps}
resultDisplay={testJSONstring}
@ -113,7 +113,7 @@ describe('<ToolMessage />', () => {
});
it('renders pretty JSON in ink frame', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage {...baseProps} resultDisplay='{"a":1,"b":2}' />,
StreamingState.Idle,
);
@ -127,7 +127,7 @@ describe('<ToolMessage />', () => {
it('uses JSON renderer even when renderOutputAsMarkdown=true is true', async () => {
const testJSONstring = '{"a": 1, "b": [2, 3]}';
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage
{...baseProps}
resultDisplay={testJSONstring}
@ -149,7 +149,7 @@ describe('<ToolMessage />', () => {
});
it('falls back to plain text for malformed JSON', async () => {
const testJSONstring = 'a": 1, "b": [2, 3]}';
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage
{...baseProps}
resultDisplay={testJSONstring}
@ -168,7 +168,7 @@ describe('<ToolMessage />', () => {
it('rejects mixed text + JSON renders as plain text', async () => {
const testJSONstring = `{"result": "count": 42,"items": ["apple", "banana"]},"meta": {"timestamp": "2025-09-28T12:34:56Z"}}End.`;
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage
{...baseProps}
resultDisplay={testJSONstring}
@ -188,7 +188,7 @@ describe('<ToolMessage />', () => {
it('rejects ANSI-tained JSON renders as plain text', async () => {
const testJSONstring =
'\u001b[32mOK\u001b[0m {"status": "success", "data": {"id": 123, "values": [10, 20, 30]}}';
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage
{...baseProps}
resultDisplay={testJSONstring}
@ -207,7 +207,7 @@ describe('<ToolMessage />', () => {
it('pretty printing 10kb JSON completes in <50ms', async () => {
const large = '{"key": "' + 'x'.repeat(10000) + '"}';
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage
{...baseProps}
resultDisplay={large}
@ -226,7 +226,7 @@ describe('<ToolMessage />', () => {
describe('ToolStatusIndicator rendering', () => {
it('shows ✓ for Success status', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage {...baseProps} status={CoreToolCallStatus.Success} />,
StreamingState.Idle,
);
@ -236,7 +236,7 @@ describe('<ToolMessage />', () => {
});
it('shows o for Pending status', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage {...baseProps} status={CoreToolCallStatus.Scheduled} />,
StreamingState.Idle,
);
@ -246,7 +246,7 @@ describe('<ToolMessage />', () => {
});
it('shows ? for Confirming status', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage
{...baseProps}
status={CoreToolCallStatus.AwaitingApproval}
@ -259,7 +259,7 @@ describe('<ToolMessage />', () => {
});
it('shows - for Canceled status', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage {...baseProps} status={CoreToolCallStatus.Cancelled} />,
StreamingState.Idle,
);
@ -269,7 +269,7 @@ describe('<ToolMessage />', () => {
});
it('shows x for Error status', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage {...baseProps} status={CoreToolCallStatus.Error} />,
StreamingState.Idle,
);
@ -279,7 +279,7 @@ describe('<ToolMessage />', () => {
});
it('shows paused spinner for Executing status when streamingState is Idle', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage {...baseProps} status={CoreToolCallStatus.Executing} />,
StreamingState.Idle,
);
@ -289,7 +289,7 @@ describe('<ToolMessage />', () => {
});
it('shows paused spinner for Executing status when streamingState is WaitingForConfirmation', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage {...baseProps} status={CoreToolCallStatus.Executing} />,
StreamingState.WaitingForConfirmation,
);
@ -299,7 +299,7 @@ describe('<ToolMessage />', () => {
});
it('shows MockRespondingSpinner for Executing status when streamingState is Responding', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage {...baseProps} status={CoreToolCallStatus.Executing} />,
StreamingState.Responding, // Simulate app still responding
);
@ -317,7 +317,7 @@ describe('<ToolMessage />', () => {
newContent: 'new',
filePath: 'file.txt',
};
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage {...baseProps} resultDisplay={diffResult} />,
StreamingState.Idle,
);
@ -332,7 +332,7 @@ describe('<ToolMessage />', () => {
lastFrame: highEmphasisFrame,
waitUntilReady: waitUntilReadyHigh,
unmount: unmountHigh,
} = renderWithContext(
} = await renderWithContext(
<ToolMessage {...baseProps} emphasis="high" />,
StreamingState.Idle,
);
@ -345,7 +345,7 @@ describe('<ToolMessage />', () => {
lastFrame: lowEmphasisFrame,
waitUntilReady: waitUntilReadyLow,
unmount: unmountLow,
} = renderWithContext(
} = await renderWithContext(
<ToolMessage {...baseProps} emphasis="low" />,
StreamingState.Idle,
);
@ -372,7 +372,7 @@ describe('<ToolMessage />', () => {
},
],
];
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage {...baseProps} resultDisplay={ansiResult} />,
StreamingState.Idle,
);
@ -382,7 +382,7 @@ describe('<ToolMessage />', () => {
});
it('renders McpProgressIndicator with percentage and message for executing tools', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage
{...baseProps}
status={CoreToolCallStatus.Executing}
@ -404,7 +404,7 @@ describe('<ToolMessage />', () => {
});
it('renders only percentage when progressMessage is missing', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage
{...baseProps}
status={CoreToolCallStatus.Executing}
@ -424,7 +424,7 @@ describe('<ToolMessage />', () => {
});
it('renders indeterminate progress when total is missing', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithContext(
const { lastFrame, waitUntilReady, unmount } = await renderWithContext(
<ToolMessage
{...baseProps}
status={CoreToolCallStatus.Executing}
@ -449,7 +449,7 @@ describe('<ToolMessage />', () => {
(_, i) => `Line ${i + 1}`,
).join('\n');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolMessage
{...baseProps}
kind={Kind.Agent}
@ -486,7 +486,7 @@ describe('<ToolMessage />', () => {
(_, i) => `Line ${i + 1}`,
).join('\n');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolMessage
{...baseProps}
kind={Kind.Agent}
@ -516,7 +516,7 @@ describe('<ToolMessage />', () => {
(_, i) => `Line ${i + 1}`,
).join('\n');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolMessage
{...baseProps}
kind={Kind.Read}

View file

@ -66,7 +66,7 @@ describe('Focus Hint', () => {
describe.each(testCases)('$componentName', ({ Component }) => {
it('shows focus hint after delay even with NO output', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Component {...baseProps} resultDisplay={undefined} />,
{ uiState: { streamingState: StreamingState.Idle } },
);
@ -88,7 +88,7 @@ describe('Focus Hint', () => {
});
it('shows focus hint after delay with output', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Component {...baseProps} resultDisplay="Some output" />,
{ uiState: { streamingState: StreamingState.Idle } },
);
@ -111,7 +111,7 @@ describe('Focus Hint', () => {
it('handles long descriptions by shrinking them to show the focus hint', async () => {
const longDescription = 'A'.repeat(100);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolMessage
{...baseProps}
description={longDescription}

View file

@ -64,7 +64,7 @@ describe('<ToolMessage /> - Raw Markdown Display Snapshots', () => {
])(
'renders with renderMarkdown=$renderMarkdown, useAlternateBuffer=$useAlternateBuffer $description',
async ({ renderMarkdown, useAlternateBuffer, availableTerminalHeight }) => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<StreamingContext.Provider value={StreamingState.Idle}>
<ToolMessage
{...baseProps}

View file

@ -41,7 +41,7 @@ describe('ToolOverflowConsistencyChecks: ToolGroupMessage and ToolResultDisplay
return null;
};
const { unmount, waitUntilReady } = renderWithProviders(
const { unmount, waitUntilReady } = await renderWithProviders(
<>
<StateCapture />
<ToolGroupMessage
@ -95,7 +95,7 @@ describe('ToolOverflowConsistencyChecks: ToolGroupMessage and ToolResultDisplay
},
];
const { lastFrame, unmount, waitUntilReady } = renderWithProviders(
const { lastFrame, unmount, waitUntilReady } = await renderWithProviders(
<ToolGroupMessage
item={{ id: 1, type: 'tool_group', tools: toolCalls }}
toolCalls={toolCalls}

View file

@ -31,7 +31,7 @@ describe('ToolResultDisplay', () => {
},
],
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay={ansiResult}
terminalWidth={80}
@ -50,7 +50,7 @@ describe('ToolResultDisplay', () => {
});
it('uses Scrollable for non-ANSI output in alternate buffer mode', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay="**Markdown content**"
terminalWidth={80}
@ -70,7 +70,7 @@ describe('ToolResultDisplay', () => {
});
it('passes hasFocus prop to scrollable components', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay="Some result"
terminalWidth={80}
@ -88,7 +88,7 @@ describe('ToolResultDisplay', () => {
});
it('renders string result as markdown by default', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay resultDisplay="**Some result**" terminalWidth={80} />,
{
config: makeFakeConfig({ useAlternateBuffer: false }),
@ -103,7 +103,7 @@ describe('ToolResultDisplay', () => {
});
it('renders string result as plain text when renderOutputAsMarkdown is false', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay="**Some result**"
terminalWidth={80}
@ -125,7 +125,7 @@ describe('ToolResultDisplay', () => {
it('truncates very long string results', { timeout: 20000 }, async () => {
const longString = 'a'.repeat(1000005);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay={longString}
terminalWidth={80}
@ -149,7 +149,7 @@ describe('ToolResultDisplay', () => {
fileDiff: 'diff content',
fileName: 'test.ts',
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay={diffResult}
terminalWidth={80}
@ -182,7 +182,7 @@ describe('ToolResultDisplay', () => {
},
],
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay={ansiResult as unknown as AnsiOutput}
terminalWidth={80}
@ -204,7 +204,7 @@ describe('ToolResultDisplay', () => {
const todoResult = {
todos: [],
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay={todoResult}
terminalWidth={80}
@ -224,7 +224,7 @@ describe('ToolResultDisplay', () => {
it('does not fall back to plain text if availableHeight is set and not in alternate buffer', async () => {
// availableHeight calculation: 20 - 1 - 5 = 14 > 3
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay="**Some result**"
terminalWidth={80}
@ -244,7 +244,7 @@ describe('ToolResultDisplay', () => {
});
it('keeps markdown if in alternate buffer even with availableHeight', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay="**Some result**"
terminalWidth={80}
@ -326,7 +326,7 @@ describe('ToolResultDisplay', () => {
},
],
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay={ansiResult}
terminalWidth={80}
@ -363,7 +363,7 @@ describe('ToolResultDisplay', () => {
inverse: false,
},
]);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay={ansiResult}
terminalWidth={80}

View file

@ -13,7 +13,7 @@ import { makeFakeConfig, type AnsiOutput } from '@google/gemini-cli-core';
describe('ToolResultDisplay Overflow', () => {
it('shows the head of the content when overflowDirection is bottom (string)', async () => {
const content = 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5';
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay={content}
terminalWidth={80}
@ -40,7 +40,7 @@ describe('ToolResultDisplay Overflow', () => {
it('shows the tail of the content when overflowDirection is top (string default)', async () => {
const content = 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5';
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay={content}
terminalWidth={80}
@ -78,7 +78,7 @@ describe('ToolResultDisplay Overflow', () => {
inverse: false,
},
]);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<ToolResultDisplay
resultDisplay={ansiResult}
terminalWidth={80}

View file

@ -91,7 +91,7 @@ describe('ToolMessage Sticky Header Regression', () => {
);
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Box height={terminalHeight}>
<TestComponent />
</Box>,
@ -181,7 +181,7 @@ describe('ToolMessage Sticky Header Regression', () => {
);
};
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Box height={terminalHeight}>
<TestComponent />
</Box>,

View file

@ -15,7 +15,7 @@ vi.mock('../../utils/commandUtils.js', () => ({
describe('UserMessage', () => {
it('renders normal user message with correct prefix', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<UserMessage text="Hello Gemini" width={80} />,
{ width: 80 },
);
@ -27,7 +27,7 @@ describe('UserMessage', () => {
});
it('renders slash command message', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<UserMessage text="/help" width={80} />,
{ width: 80 },
);
@ -40,7 +40,7 @@ describe('UserMessage', () => {
it('renders multiline user message', async () => {
const message = 'Line 1\nLine 2';
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<UserMessage text={message} width={80} />,
{ width: 80 },
);
@ -53,7 +53,7 @@ describe('UserMessage', () => {
it('transforms image paths in user message', async () => {
const message = 'Check out this image: @/path/to/my-image.png';
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<UserMessage text={message} width={80} />,
{ width: 80 },
);

View file

@ -75,7 +75,9 @@ describe('BaseSelectionList', () => {
...props,
};
const result = renderWithProviders(<BaseSelectionList {...defaultProps} />);
const result = await renderWithProviders(
<BaseSelectionList {...defaultProps} />,
);
await result.waitUntilReady();
return result;
};
@ -310,7 +312,7 @@ describe('BaseSelectionList', () => {
);
const { rerender, lastFrame, waitUntilReady, unmount } =
renderWithProviders(<BaseSelectionList {...componentProps} />);
await renderWithProviders(<BaseSelectionList {...componentProps} />);
await waitUntilReady();
// Function to simulate the activeIndex changing over time

View file

@ -108,7 +108,7 @@ describe('BaseSettingsDialog', () => {
...props,
};
const result = renderWithProviders(
const result = await renderWithProviders(
<BaseSettingsDialog {...defaultProps} />,
);
await result.waitUntilReady();

View file

@ -75,7 +75,7 @@ describe('DescriptiveRadioButtonSelect', () => {
onSelect: mockOnSelect,
...props,
};
const result = renderWithProviders(
const result = await renderWithProviders(
<DescriptiveRadioButtonSelect {...defaultProps} />,
);
await result.waitUntilReady();

View file

@ -25,7 +25,7 @@ const NUMERIC_OPTIONS: readonly SettingEnumOption[] = [
describe('<EnumSelector />', () => {
it('renders with string options and matches snapshot', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={LANGUAGE_OPTIONS}
currentValue="en"
@ -39,7 +39,7 @@ describe('<EnumSelector />', () => {
});
it('renders with numeric options and matches snapshot', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={NUMERIC_OPTIONS}
currentValue={2}
@ -53,7 +53,7 @@ describe('<EnumSelector />', () => {
});
it('renders inactive state and matches snapshot', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={LANGUAGE_OPTIONS}
currentValue="zh"
@ -70,7 +70,7 @@ describe('<EnumSelector />', () => {
const singleOption: readonly SettingEnumOption[] = [
{ label: 'Only Option', value: 'only' },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={singleOption}
currentValue="only"
@ -84,7 +84,7 @@ describe('<EnumSelector />', () => {
});
it('renders nothing when no options are provided', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={[]}
currentValue=""
@ -98,7 +98,7 @@ describe('<EnumSelector />', () => {
});
it('handles currentValue not found in options', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={LANGUAGE_OPTIONS}
currentValue="invalid"
@ -114,7 +114,7 @@ describe('<EnumSelector />', () => {
it('updates when currentValue changes externally', async () => {
const { rerender, lastFrame, waitUntilReady, unmount } =
renderWithProviders(
await renderWithProviders(
<EnumSelector
options={LANGUAGE_OPTIONS}
currentValue="en"
@ -141,7 +141,7 @@ describe('<EnumSelector />', () => {
});
it('shows navigation arrows when multiple options available', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={LANGUAGE_OPTIONS}
currentValue="en"
@ -159,7 +159,7 @@ describe('<EnumSelector />', () => {
const singleOption: readonly SettingEnumOption[] = [
{ label: 'Only Option', value: 'only' },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={singleOption}
currentValue="only"

View file

@ -28,7 +28,7 @@ describe('<HalfLinePaddedBox />', () => {
it('renders standard background and blocks when not iTerm2', async () => {
vi.mocked(isITerm2).mockReturnValue(false);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HalfLinePaddedBox backgroundBaseColor="blue" backgroundOpacity={0.5}>
<Text>Content</Text>
</HalfLinePaddedBox>,
@ -44,7 +44,7 @@ describe('<HalfLinePaddedBox />', () => {
it('renders iTerm2-specific blocks when iTerm2 is detected', async () => {
vi.mocked(isITerm2).mockReturnValue(true);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HalfLinePaddedBox backgroundBaseColor="blue" backgroundOpacity={0.5}>
<Text>Content</Text>
</HalfLinePaddedBox>,
@ -58,7 +58,7 @@ describe('<HalfLinePaddedBox />', () => {
});
it('renders nothing when useBackgroundColor is false', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HalfLinePaddedBox
backgroundBaseColor="blue"
backgroundOpacity={0.5}
@ -78,7 +78,7 @@ describe('<HalfLinePaddedBox />', () => {
it('renders nothing when screen reader is enabled', async () => {
mockUseIsScreenReaderEnabled.mockReturnValue(true);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HalfLinePaddedBox backgroundBaseColor="blue" backgroundOpacity={0.5}>
<Text>Content</Text>
</HalfLinePaddedBox>,

View file

@ -288,7 +288,7 @@ describe('<MaxSizedBox />', () => {
{ length: 20 },
(_, i) => `- Step ${i + 1}: Do something important`,
).join('\n');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<MaxSizedBox maxWidth={80} maxHeight={5} overflowDirection="bottom">
<MarkdownDisplay
text={`## Plan\n\n${markdownContent}`}

View file

@ -70,7 +70,7 @@ describe('RadioButtonSelect', () => {
{ label: 'Option 3', value: 'three', disabled: true, key: 'three' },
];
const renderComponent = (
const renderComponent = async (
props: Partial<RadioButtonSelectProps<string>> = {},
) => {
const defaultProps: RadioButtonSelectProps<string> = {
@ -86,7 +86,7 @@ describe('RadioButtonSelect', () => {
});
describe('Prop forwarding to BaseSelectionList', () => {
it('should forward all props correctly when provided', () => {
it('should forward all props correctly when provided', async () => {
const props = {
items: ITEMS,
initialIndex: 1,
@ -98,7 +98,7 @@ describe('RadioButtonSelect', () => {
showNumbers: false,
};
renderComponent(props);
await renderComponent(props);
expect(BaseSelectionList).toHaveBeenCalledTimes(1);
expect(BaseSelectionList).toHaveBeenCalledWith(
@ -110,8 +110,8 @@ describe('RadioButtonSelect', () => {
);
});
it('should use default props if not provided', () => {
renderComponent({
it('should use default props if not provided', async () => {
await renderComponent({
items: ITEMS,
onSelect: mockOnSelect,
});
@ -137,8 +137,8 @@ describe('RadioButtonSelect', () => {
numberColor: 'MOCK_NUMBER_COLOR',
};
beforeEach(() => {
renderComponent();
beforeEach(async () => {
await renderComponent();
renderItem = extractRenderItem();
});

View file

@ -29,7 +29,7 @@ describe('<Scrollable />', () => {
});
it('renders children', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Scrollable hasFocus={false} height={5}>
<Text>Hello World</Text>
</Scrollable>,
@ -40,7 +40,7 @@ describe('<Scrollable />', () => {
});
it('renders multiple children', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Scrollable hasFocus={false} height={5}>
<Text>Line 1</Text>
<Text>Line 2</Text>
@ -55,7 +55,7 @@ describe('<Scrollable />', () => {
});
it('matches snapshot', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Scrollable hasFocus={false} height={5}>
<Text>Line 1</Text>
<Text>Line 2</Text>
@ -77,7 +77,7 @@ describe('<Scrollable />', () => {
},
);
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<Scrollable hasFocus={true} height={5}>
<Text>Line 1</Text>
<Text>Line 2</Text>
@ -105,7 +105,7 @@ describe('<Scrollable />', () => {
// Initial state with scrollToBottom={true}
unmount();
const { waitUntilReady: waitUntilReady2, unmount: unmount2 } =
renderWithProviders(
await renderWithProviders(
<Scrollable hasFocus={true} height={5} scrollToBottom={true}>
<Text>Line 1</Text>
<Text>Line 2</Text>
@ -197,7 +197,7 @@ describe('<Scrollable />', () => {
},
);
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<Scrollable hasFocus={true} height={5}>
<Box height={scrollHeight}>
<Text>Content</Text>

View file

@ -132,10 +132,10 @@ describe('ScrollableList Demo Behavior', () => {
let lastFrame: (options?: { allowEmpty?: boolean }) => string | undefined;
let waitUntilReady: () => Promise<void>;
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(
result = await renderWithProviders(
<TestComponent
onAddItem={(add) => {
addItem = add;
@ -245,9 +245,9 @@ describe('ScrollableList Demo Behavior', () => {
let lastFrame: () => string | undefined;
let waitUntilReady: () => Promise<void>;
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(<StickyTestComponent />);
result = await renderWithProviders(<StickyTestComponent />);
lastFrame = result.lastFrame;
waitUntilReady = result.waitUntilReady;
});
@ -313,9 +313,9 @@ describe('ScrollableList Demo Behavior', () => {
title: `Item ${i}`,
}));
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(
result = await renderWithProviders(
<Box flexDirection="column" width={80} height={10}>
<ScrollableList
ref={(ref) => {
@ -417,9 +417,9 @@ describe('ScrollableList Demo Behavior', () => {
let lastFrame: (options?: { allowEmpty?: boolean }) => string | undefined;
let waitUntilReady: () => Promise<void>;
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(
result = await renderWithProviders(
<Box width={100} height={20}>
<ScrollableList
data={items}
@ -480,9 +480,9 @@ describe('ScrollableList Demo Behavior', () => {
);
};
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(<TestComp />);
result = await renderWithProviders(<TestComp />);
});
await result!.waitUntilReady();
@ -601,9 +601,9 @@ describe('ScrollableList Demo Behavior', () => {
);
};
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(<TestComp />);
result = await renderWithProviders(<TestComp />);
});
await result!.waitUntilReady();
@ -671,9 +671,9 @@ describe('ScrollableList Demo Behavior', () => {
);
};
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(<TestComp />);
result = await renderWithProviders(<TestComp />);
});
await result!.waitUntilReady();

View file

@ -79,7 +79,7 @@ describe('SearchableList', () => {
mockOnClose = vi.fn();
});
const renderList = (
const renderList = async (
props: Partial<SearchableListProps<GenericListItem>> = {},
) => {
const defaultProps: SearchableListProps<GenericListItem> = {
@ -95,7 +95,7 @@ describe('SearchableList', () => {
};
it('should render all items initially', async () => {
const { lastFrame, waitUntilReady } = renderList();
const { lastFrame, waitUntilReady } = await renderList();
await waitUntilReady();
const frame = lastFrame();
@ -109,7 +109,7 @@ describe('SearchableList', () => {
});
it('should reset selection to top when items change if resetSelectionOnItemsChange is true', async () => {
const { lastFrame, stdin, waitUntilReady } = renderList({
const { lastFrame, stdin, waitUntilReady } = await renderList({
resetSelectionOnItemsChange: true,
});
await waitUntilReady();
@ -150,7 +150,7 @@ describe('SearchableList', () => {
});
it('should filter items based on search query', async () => {
const { lastFrame, stdin } = renderList();
const { lastFrame, stdin } = await renderList();
await React.act(async () => {
stdin.write('Two');
@ -165,7 +165,7 @@ describe('SearchableList', () => {
});
it('should show "No items found." when no items match', async () => {
const { lastFrame, stdin } = renderList();
const { lastFrame, stdin } = await renderList();
await React.act(async () => {
stdin.write('xyz123');
@ -178,7 +178,7 @@ describe('SearchableList', () => {
});
it('should handle selection with Enter', async () => {
const { stdin } = renderList();
const { stdin } = await renderList();
await React.act(async () => {
stdin.write('\r'); // Enter
@ -190,7 +190,7 @@ describe('SearchableList', () => {
});
it('should handle navigation and selection', async () => {
const { stdin } = renderList();
const { stdin } = await renderList();
await React.act(async () => {
stdin.write('\u001B[B'); // Down arrow
@ -206,7 +206,7 @@ describe('SearchableList', () => {
});
it('should handle close with Esc', async () => {
const { stdin } = renderList();
const { stdin } = await renderList();
await React.act(async () => {
stdin.write('\u001B'); // Esc
@ -218,7 +218,7 @@ describe('SearchableList', () => {
});
it('should match snapshot', async () => {
const { lastFrame, waitUntilReady } = renderList();
const { lastFrame, waitUntilReady } = await renderList();
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();
});

View file

@ -37,7 +37,7 @@ describe('<SectionHeader />', () => {
width: 40,
},
])('$description', async ({ title, subtitle, width }) => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<SectionHeader title={title} subtitle={subtitle} />,
{ width },
);

View file

@ -17,7 +17,7 @@ const MOCK_TABS: Tab[] = [
describe('TabHeader', () => {
describe('rendering', () => {
it('renders null for single tab', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader
tabs={[{ key: '0', header: 'Only Tab' }]}
currentIndex={0}
@ -29,7 +29,7 @@ describe('TabHeader', () => {
});
it('renders all tab headers', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
);
await waitUntilReady();
@ -42,7 +42,7 @@ describe('TabHeader', () => {
});
it('renders separators between tabs', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
);
await waitUntilReady();
@ -57,7 +57,7 @@ describe('TabHeader', () => {
describe('arrows', () => {
it('shows arrows by default', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
);
await waitUntilReady();
@ -69,7 +69,7 @@ describe('TabHeader', () => {
});
it('hides arrows when showArrows is false', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} showArrows={false} />,
);
await waitUntilReady();
@ -83,7 +83,7 @@ describe('TabHeader', () => {
describe('status icons', () => {
it('shows status icons by default', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
);
await waitUntilReady();
@ -95,7 +95,7 @@ describe('TabHeader', () => {
});
it('hides status icons when showStatusIcons is false', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} showStatusIcons={false} />,
);
await waitUntilReady();
@ -107,7 +107,7 @@ describe('TabHeader', () => {
});
it('shows checkmark for completed tabs', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader
tabs={MOCK_TABS}
currentIndex={0}
@ -130,7 +130,7 @@ describe('TabHeader', () => {
{ key: '0', header: 'Tab 1' },
{ key: '1', header: 'Review', isSpecial: true },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={tabsWithSpecial} currentIndex={0} />,
);
await waitUntilReady();
@ -146,7 +146,7 @@ describe('TabHeader', () => {
{ key: '0', header: 'Tab 1', statusIcon: '★' },
{ key: '1', header: 'Tab 2' },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={tabsWithCustomIcon} currentIndex={0} />,
);
await waitUntilReady();
@ -158,7 +158,7 @@ describe('TabHeader', () => {
it('uses custom renderStatusIcon when provided', async () => {
const renderStatusIcon = () => '•';
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader
tabs={MOCK_TABS}
currentIndex={0}
@ -178,7 +178,7 @@ describe('TabHeader', () => {
{ key: '0', header: 'ThisIsAVeryLongHeaderThatShouldBeTruncated' },
{ key: '1', header: 'AnotherVeryLongHeader' },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={longTabs} currentIndex={0} />,
);
await waitUntilReady();
@ -197,7 +197,7 @@ describe('TabHeader', () => {
it('falls back to default when renderStatusIcon returns undefined', async () => {
const renderStatusIcon = () => undefined;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader
tabs={MOCK_TABS}
currentIndex={0}

View file

@ -3241,9 +3241,9 @@ describe('Transformation Utilities', () => {
},
])(
'should invalidate cache when line content changes $desc',
({ actFn, expected }) => {
async ({ actFn, expected }) => {
const viewport = { width: 80, height: 24 };
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useTextBuffer({
initialText: 'original line',
viewport,
@ -3262,9 +3262,9 @@ describe('Transformation Utilities', () => {
},
);
it('should invalidate cache when viewport width changes', () => {
it('should invalidate cache when viewport width changes', async () => {
const viewport = { width: 80, height: 24 };
const { result, rerender } = renderHookWithProviders(
const { result, rerender } = await renderHookWithProviders(
({ vp }) =>
useTextBuffer({
initialText:
@ -3284,10 +3284,10 @@ describe('Transformation Utilities', () => {
expect(result.current.allVisualLines.length).toBeGreaterThan(1);
});
it('should correctly handle cursor expansion/collapse in cached layout', () => {
it('should correctly handle cursor expansion/collapse in cached layout', async () => {
const viewport = { width: 80, height: 24 };
const text = 'Check @image.png here';
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useTextBuffer({
initialText: text,
viewport,
@ -3317,10 +3317,10 @@ describe('Transformation Utilities', () => {
expect(result.current.allVisualLines[0]).toContain('[Image image.png]');
});
it('should reuse cache for unchanged lines during editing', () => {
it('should reuse cache for unchanged lines during editing', async () => {
const viewport = { width: 80, height: 24 };
const initialText = 'line 1\nline 2\nline 3';
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useTextBuffer({
initialText,
viewport,

View file

@ -41,7 +41,7 @@ describe('ExtensionDetails', () => {
mockOnInstall = vi.fn();
});
const renderDetails = (isInstalled = false) =>
const renderDetails = async (isInstalled = false) =>
renderWithProviders(
<ExtensionDetails
extension={mockExtension}
@ -52,7 +52,7 @@ describe('ExtensionDetails', () => {
);
it('should render extension details correctly', async () => {
const { lastFrame } = renderDetails();
const { lastFrame } = await renderDetails();
await waitFor(() => {
expect(lastFrame()).toContain('Test Extension');
expect(lastFrame()).toContain('v1.2.3');
@ -69,7 +69,7 @@ describe('ExtensionDetails', () => {
});
it('should show install prompt when not installed', async () => {
const { lastFrame } = renderDetails(false);
const { lastFrame } = await renderDetails(false);
await waitFor(() => {
expect(lastFrame()).toContain('[Enter] Install');
expect(lastFrame()).not.toContain('Already Installed');
@ -77,7 +77,7 @@ describe('ExtensionDetails', () => {
});
it('should show already installed message when installed', async () => {
const { lastFrame } = renderDetails(true);
const { lastFrame } = await renderDetails(true);
await waitFor(() => {
expect(lastFrame()).toContain('Already Installed');
expect(lastFrame()).not.toContain('[Enter] Install');
@ -85,7 +85,7 @@ describe('ExtensionDetails', () => {
});
it('should call onBack when Escape is pressed', async () => {
const { stdin } = renderDetails();
const { stdin } = await renderDetails();
await React.act(async () => {
stdin.write('\x1b'); // Escape
});
@ -95,7 +95,7 @@ describe('ExtensionDetails', () => {
});
it('should call onInstall when Enter is pressed and not installed', async () => {
const { stdin } = renderDetails(false);
const { stdin } = await renderDetails(false);
await React.act(async () => {
stdin.write('\r'); // Enter
});
@ -106,7 +106,7 @@ describe('ExtensionDetails', () => {
it('should NOT call onInstall when Enter is pressed and already installed', async () => {
vi.useFakeTimers();
const { stdin } = renderDetails(true);
const { stdin } = await renderDetails(true);
await React.act(async () => {
stdin.write('\r'); // Enter
});

View file

@ -7,6 +7,7 @@
import React from 'react';
import { renderWithProviders } from '../../../test-utils/render.js';
import { waitFor } from '../../../test-utils/async.js';
import { makeFakeConfig } from '@google/gemini-cli-core';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { ExtensionRegistryView } from './ExtensionRegistryView.js';
import { type ExtensionManager } from '../../../config/extension-manager.js';
@ -121,7 +122,7 @@ describe('ExtensionRegistryView', () => {
);
});
const renderView = () =>
const renderView = async () =>
renderWithProviders(
<ExtensionRegistryView
extensionManager={mockExtensionManager}
@ -129,6 +130,7 @@ describe('ExtensionRegistryView', () => {
onClose={mockOnClose}
/>,
{
config: makeFakeConfig(),
uiState: {
staticExtraHeight: 5,
terminalHeight: 40,
@ -137,7 +139,7 @@ describe('ExtensionRegistryView', () => {
);
it('should render extensions', async () => {
const { lastFrame, waitUntilReady } = renderView();
const { lastFrame, waitUntilReady } = await renderView();
await waitUntilReady();
await waitFor(() => {
@ -146,8 +148,8 @@ describe('ExtensionRegistryView', () => {
});
});
it('should use useRegistrySearch hook', () => {
renderView();
it('should use useRegistrySearch hook', async () => {
await renderView();
expect(useRegistrySearch).toHaveBeenCalled();
});
@ -185,7 +187,7 @@ describe('ExtensionRegistryView', () => {
},
);
renderView();
await renderView();
await waitFor(() => {
expect(useRegistrySearch).toHaveBeenCalledWith(
@ -197,7 +199,7 @@ describe('ExtensionRegistryView', () => {
});
it('should call onSelect when extension is selected and Enter is pressed in details', async () => {
const { stdin, lastFrame } = renderView();
const { stdin, lastFrame } = await renderView();
// Select the first extension in the list (Enter opens details)
await React.act(async () => {

View file

@ -32,7 +32,7 @@ const mockTools: ToolDefinition[] = [
describe('<ToolsList />', () => {
it('renders correctly with descriptions', async () => {
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<ToolsList
tools={mockTools}
showDescriptions={true}
@ -44,7 +44,7 @@ describe('<ToolsList />', () => {
});
it('renders correctly without descriptions', async () => {
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<ToolsList
tools={mockTools}
showDescriptions={false}
@ -56,7 +56,7 @@ describe('<ToolsList />', () => {
});
it('renders correctly with no tools', async () => {
const { lastFrame, waitUntilReady } = renderWithProviders(
const { lastFrame, waitUntilReady } = await renderWithProviders(
<ToolsList tools={[]} showDescriptions={true} terminalWidth={40} />,
);
await waitUntilReady();

View file

@ -49,10 +49,10 @@ class MockStdin extends EventEmitter {
}
// Helper function to setup keypress test with standard configuration
const setupKeypressTest = () => {
const setupKeypressTest = async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() => useKeypressContext());
act(() => result.current.subscribe(keyHandler));
return { result, keyHandler };
@ -85,7 +85,7 @@ describe('KeypressContext', () => {
sequence: '\x1b[57414u',
},
])('should recognize $name in kitty protocol', async ({ sequence }) => {
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write(sequence));
@ -100,7 +100,7 @@ describe('KeypressContext', () => {
});
it('should handle backslash return', async () => {
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write('\\\r'));
@ -133,7 +133,7 @@ describe('KeypressContext', () => {
])(
'should handle numpad enter with $modifier modifier',
async ({ sequence, expected }) => {
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write(sequence));
@ -147,7 +147,7 @@ describe('KeypressContext', () => {
);
it('should recognize \n (LF) as ctrl+j', async () => {
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write('\n'));
@ -162,7 +162,7 @@ describe('KeypressContext', () => {
});
it('should recognize \\x1b\\n as Alt+Enter (return with meta)', async () => {
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write('\x1b\n'));
@ -190,7 +190,7 @@ describe('KeypressContext', () => {
afterEach(() => kittySpy.mockRestore());
it('should buffer return key pressed quickly after another key', async () => {
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write('a'));
expect(keyHandler).toHaveBeenLastCalledWith(
@ -219,7 +219,7 @@ describe('KeypressContext', () => {
});
it('should NOT buffer return key if delay is long enough', async () => {
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write('a'));
@ -241,7 +241,7 @@ describe('KeypressContext', () => {
describe('Escape key handling', () => {
it('should recognize escape key (keycode 27) in kitty protocol', async () => {
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
// Send kitty protocol sequence for escape: ESC[27u
act(() => {
@ -261,7 +261,9 @@ describe('KeypressContext', () => {
it('should handle double Escape', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
act(() => {
@ -295,7 +297,9 @@ describe('KeypressContext', () => {
it('should handle lone Escape key (keycode 27) with timeout when kitty protocol is enabled', async () => {
// Use real timers for this test to avoid issues with stream/buffer timing
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
// Send just ESC
@ -369,7 +373,7 @@ describe('KeypressContext', () => {
])(
'should recognize $name in kitty protocol',
async ({ inputSequence, expected }) => {
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
act(() => {
stdin.write(inputSequence);
@ -418,7 +422,9 @@ describe('KeypressContext', () => {
])('should $name', async ({ pastedText, writeSequence }) => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -438,7 +444,9 @@ describe('KeypressContext', () => {
it('should parse valid OSC 52 response', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -459,7 +467,9 @@ describe('KeypressContext', () => {
it('should handle split OSC 52 response', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -485,7 +495,9 @@ describe('KeypressContext', () => {
it('should handle OSC 52 response terminated by ESC \\', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -506,7 +518,9 @@ describe('KeypressContext', () => {
it('should ignore unknown OSC sequences', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -523,7 +537,9 @@ describe('KeypressContext', () => {
it('should ignore invalid OSC 52 format', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -555,11 +571,14 @@ describe('KeypressContext', () => {
it('should not log keystrokes when debugKeystrokeLogging is false', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext(), {
settings: createMockSettings({
general: { debugKeystrokeLogging: false },
}),
});
const { result } = await renderHookWithProviders(
() => useKeypressContext(),
{
settings: createMockSettings({
general: { debugKeystrokeLogging: false },
}),
},
);
act(() => result.current.subscribe(keyHandler));
@ -577,11 +596,14 @@ describe('KeypressContext', () => {
it('should log kitty buffer accumulation when debugKeystrokeLogging is true', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext(), {
settings: createMockSettings({
general: { debugKeystrokeLogging: true },
}),
});
const { result } = await renderHookWithProviders(
() => useKeypressContext(),
{
settings: createMockSettings({
general: { debugKeystrokeLogging: true },
}),
},
);
act(() => result.current.subscribe(keyHandler));
@ -596,11 +618,14 @@ describe('KeypressContext', () => {
it('should show char codes when debugKeystrokeLogging is true even without debug mode', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext(), {
settings: createMockSettings({
general: { debugKeystrokeLogging: true },
}),
});
const { result } = await renderHookWithProviders(
() => useKeypressContext(),
{
settings: createMockSettings({
general: { debugKeystrokeLogging: true },
}),
},
);
act(() => result.current.subscribe(keyHandler));
@ -743,9 +768,11 @@ describe('KeypressContext', () => {
},
])(
'should recognize sequence "$sequence" as $expected.name',
({ sequence, expected }) => {
async ({ sequence, expected }) => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
act(() => stdin.write(sequence));
@ -835,8 +862,8 @@ describe('KeypressContext', () => {
},
])(
'should recognize numpad sequence "$sequence" as $expected.name',
({ sequence, expected }) => {
const { keyHandler } = setupKeypressTest();
async ({ sequence, expected }) => {
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write(sequence));
expect(keyHandler).toHaveBeenCalledWith(
expect.objectContaining(expected),
@ -847,7 +874,7 @@ describe('KeypressContext', () => {
describe('Double-tap and batching', () => {
it('should emit two delete events for double-tap CSI[3~', async () => {
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write(`\x1b[3~`));
act(() => stdin.write(`\x1b[3~`));
@ -875,7 +902,7 @@ describe('KeypressContext', () => {
});
it('should parse two concatenated tilde-coded sequences in one chunk', async () => {
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write(`\x1b[3~\x1b[5~`));
@ -978,9 +1005,17 @@ describe('KeypressContext', () => {
),
)(
'should handle Alt+$key in $terminal',
({ chunk, expected }: { chunk: string; expected: Partial<Key> }) => {
async ({
chunk,
expected,
}: {
chunk: string;
expected: Partial<Key>;
}) => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
act(() => stdin.write(chunk));
@ -993,8 +1028,8 @@ describe('KeypressContext', () => {
});
describe('Backslash key handling', () => {
it('should treat backslash as a regular keystroke', () => {
const { keyHandler } = setupKeypressTest();
it('should treat backslash as a regular keystroke', async () => {
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write('\\'));
@ -1017,7 +1052,9 @@ describe('KeypressContext', () => {
it('should timeout and flush incomplete kitty sequences after 50ms', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1052,7 +1089,9 @@ describe('KeypressContext', () => {
it('should immediately flush non-kitty CSI sequences', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1074,7 +1113,9 @@ describe('KeypressContext', () => {
it('should parse valid kitty sequences immediately when complete', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1092,7 +1133,9 @@ describe('KeypressContext', () => {
it('should handle batched kitty sequences correctly', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1119,7 +1162,9 @@ describe('KeypressContext', () => {
it('should handle mixed valid and invalid sequences', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1147,7 +1192,9 @@ describe('KeypressContext', () => {
'should handle sequences arriving character by character with %s ms delay',
async (delay) => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1171,7 +1218,9 @@ describe('KeypressContext', () => {
it('should reset timeout when new input arrives', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1206,7 +1255,9 @@ describe('KeypressContext', () => {
describe('SGR Mouse Handling', () => {
it('should ignore SGR mouse sequences', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1224,7 +1275,9 @@ describe('KeypressContext', () => {
it('should handle mixed SGR mouse and key sequences', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1250,7 +1303,9 @@ describe('KeypressContext', () => {
it('should ignore X11 mouse sequences', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1266,7 +1321,9 @@ describe('KeypressContext', () => {
it('should not flush slow SGR mouse sequences as garbage', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1286,7 +1343,9 @@ describe('KeypressContext', () => {
it('should ignore specific SGR mouse sequence sandwiched between keystrokes', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
@ -1317,7 +1376,9 @@ describe('KeypressContext', () => {
{ name: 'another mouse', sequence: '\u001b[<0;29;19m' },
])('should ignore $name sequence', async ({ sequence }) => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
for (const char of sequence) {
@ -1342,7 +1403,9 @@ describe('KeypressContext', () => {
it('should handle F12', async () => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
act(() => {
@ -1371,7 +1434,9 @@ describe('KeypressContext', () => {
'A你B好C', // Mixed characters
])('should correctly handle string "%s"', async (inputString) => {
const keyHandler = vi.fn();
const { result } = renderHookWithProviders(() => useKeypressContext());
const { result } = await renderHookWithProviders(() =>
useKeypressContext(),
);
act(() => result.current.subscribe(keyHandler));
act(() => stdin.write(inputString));
@ -1424,7 +1489,7 @@ describe('KeypressContext', () => {
if (lang) vi.stubEnv('LANG', lang);
if (lcAll) vi.stubEnv('LC_ALL', lcAll);
const { keyHandler } = setupKeypressTest();
const { keyHandler } = await setupKeypressTest();
act(() => stdin.write(char));

View file

@ -62,9 +62,9 @@ describe('MouseContext', () => {
vi.restoreAllMocks();
});
it('should subscribe and unsubscribe a handler', () => {
it('should subscribe and unsubscribe a handler', async () => {
const handler = vi.fn();
const { result } = renderHookWithProviders(() => useMouseContext(), {
const { result } = await renderHookWithProviders(() => useMouseContext(), {
mouseEventsEnabled: true,
});
@ -89,11 +89,14 @@ describe('MouseContext', () => {
expect(handler).toHaveBeenCalledTimes(1);
});
it('should not call handler if not active', () => {
it('should not call handler if not active', async () => {
const handler = vi.fn();
renderHookWithProviders(() => useMouse(handler, { isActive: false }), {
mouseEventsEnabled: true,
});
await renderHookWithProviders(
() => useMouse(handler, { isActive: false }),
{
mouseEventsEnabled: true,
},
);
act(() => {
stdin.write('\x1b[<0;10;20M');
@ -102,8 +105,8 @@ describe('MouseContext', () => {
expect(handler).not.toHaveBeenCalled();
});
it('should emit SelectionWarning when move event is unhandled and has coordinates', () => {
renderHookWithProviders(() => useMouseContext(), {
it('should emit SelectionWarning when move event is unhandled and has coordinates', async () => {
await renderHookWithProviders(() => useMouseContext(), {
mouseEventsEnabled: true,
});
@ -115,9 +118,9 @@ describe('MouseContext', () => {
expect(appEvents.emit).toHaveBeenCalledWith(AppEvent.SelectionWarning);
});
it('should not emit SelectionWarning when move event is handled', () => {
it('should not emit SelectionWarning when move event is handled', async () => {
const handler = vi.fn().mockReturnValue(true);
const { result } = renderHookWithProviders(() => useMouseContext(), {
const { result } = await renderHookWithProviders(() => useMouseContext(), {
mouseEventsEnabled: true,
});
@ -217,11 +220,14 @@ describe('MouseContext', () => {
}, // Shift + scroll up
])(
'should recognize sequence "$sequence" as $expected.name',
({ sequence, expected }) => {
async ({ sequence, expected }) => {
const mouseHandler = vi.fn();
const { result } = renderHookWithProviders(() => useMouseContext(), {
mouseEventsEnabled: true,
});
const { result } = await renderHookWithProviders(
() => useMouseContext(),
{
mouseEventsEnabled: true,
},
);
act(() => result.current.subscribe(mouseHandler));
act(() => stdin.write(sequence));
@ -233,9 +239,9 @@ describe('MouseContext', () => {
);
});
it('should emit a double-click event when two left-presses occur quickly at the same position', () => {
it('should emit a double-click event when two left-presses occur quickly at the same position', async () => {
const handler = vi.fn();
const { result } = renderHookWithProviders(() => useMouseContext(), {
const { result } = await renderHookWithProviders(() => useMouseContext(), {
mouseEventsEnabled: true,
});
@ -265,9 +271,9 @@ describe('MouseContext', () => {
);
});
it('should NOT emit a double-click event if clicks are too far apart', () => {
it('should NOT emit a double-click event if clicks are too far apart', async () => {
const handler = vi.fn();
const { result } = renderHookWithProviders(() => useMouseContext(), {
const { result } = await renderHookWithProviders(() => useMouseContext(), {
mouseEventsEnabled: true,
});
@ -294,7 +300,7 @@ describe('MouseContext', () => {
it('should NOT emit a double-click event if too much time passes', async () => {
vi.useFakeTimers();
const handler = vi.fn();
const { result } = renderHookWithProviders(() => useMouseContext(), {
const { result } = await renderHookWithProviders(() => useMouseContext(), {
mouseEventsEnabled: true,
});

View file

@ -505,9 +505,7 @@ export const useSlashCommandProcessor = (
const props = result.props as Record<string, unknown>;
if (
!props ||
// eslint-disable-next-line no-restricted-syntax
typeof props['name'] !== 'string' ||
// eslint-disable-next-line no-restricted-syntax
typeof props['displayName'] !== 'string' ||
!props['definition']
) {

View file

@ -38,6 +38,17 @@ vi.mock('./useAtCompletion', () => ({
useAtCompletion: vi.fn(),
}));
vi.mock('./usePromptCompletion', () => ({
usePromptCompletion: vi.fn(() => ({
text: '',
isLoading: false,
isActive: false,
accept: vi.fn(),
clear: vi.fn(),
markSelected: vi.fn(),
})),
}));
vi.mock('./useSlashCompletion', () => ({
useSlashCompletion: vi.fn(() => ({
completionStart: 0,
@ -183,13 +194,13 @@ describe('useCommandCompletion', () => {
return null;
}
const renderCommandCompletionHook = (
const renderCommandCompletionHook = async (
initialText: string,
cursorOffset?: number,
shellModeActive = false,
active = true,
) => {
const renderResult = renderWithProviders(
const renderResult = await renderWithProviders(
<TestComponent
initialText={initialText}
cursorOffset={cursorOffset}
@ -219,8 +230,8 @@ describe('useCommandCompletion', () => {
describe('Core Hook Behavior', () => {
describe('State Management', () => {
it('should initialize with default state', () => {
const { result } = renderCommandCompletionHook('');
it('should initialize with default state', async () => {
const { result } = await renderCommandCompletionHook('');
expect(result.current.suggestions).toEqual([]);
expect(result.current.activeSuggestionIndex).toBe(-1);
@ -235,7 +246,7 @@ describe('useCommandCompletion', () => {
atSuggestions: [{ label: 'src/file.txt', value: 'src/file.txt' }],
});
const { result } = renderCommandCompletionHook('@file');
const { result } = await renderCommandCompletionHook('@file');
await waitFor(() => {
expect(result.current.suggestions).toHaveLength(1);
@ -256,8 +267,8 @@ describe('useCommandCompletion', () => {
});
});
it('should reset all state to default values', () => {
const { result } = renderCommandCompletionHook('@files');
it('should reset all state to default values', async () => {
const { result } = await renderCommandCompletionHook('@files');
act(() => {
result.current.setActiveSuggestionIndex(5);
@ -274,7 +285,7 @@ describe('useCommandCompletion', () => {
it('should call useAtCompletion with the correct query for an escaped space', async () => {
const text = '@src/a\\ file.txt';
const { result } = renderCommandCompletionHook(text);
const { result } = await renderCommandCompletionHook(text);
await waitFor(() => {
expect(useAtCompletion).toHaveBeenLastCalledWith(
@ -291,7 +302,7 @@ describe('useCommandCompletion', () => {
const text = '@file1 @file2';
const cursorOffset = 3; // @fi|le1 @file2
renderCommandCompletionHook(text, cursorOffset);
await renderCommandCompletionHook(text, cursorOffset);
await waitFor(() => {
expect(useAtCompletion).toHaveBeenLastCalledWith(
@ -329,7 +340,7 @@ describe('useCommandCompletion', () => {
slashSuggestions: [{ label: 'clear', value: 'clear' }],
});
const { result } = renderCommandCompletionHook(
const { result } = await renderCommandCompletionHook(
'/',
undefined,
shellModeActive,
@ -361,10 +372,10 @@ describe('useCommandCompletion', () => {
setupMocks({ slashSuggestions: mockSuggestions });
});
it('should handle navigateUp with no suggestions', () => {
it('should handle navigateUp with no suggestions', async () => {
setupMocks({ slashSuggestions: [] });
const { result } = renderCommandCompletionHook('/');
const { result } = await renderCommandCompletionHook('/');
act(() => {
result.current.navigateUp();
@ -373,9 +384,9 @@ describe('useCommandCompletion', () => {
expect(result.current.activeSuggestionIndex).toBe(-1);
});
it('should handle navigateDown with no suggestions', () => {
it('should handle navigateDown with no suggestions', async () => {
setupMocks({ slashSuggestions: [] });
const { result } = renderCommandCompletionHook('/');
const { result } = await renderCommandCompletionHook('/');
act(() => {
result.current.navigateDown();
@ -385,7 +396,7 @@ describe('useCommandCompletion', () => {
});
it('should navigate up through suggestions with wrap-around', async () => {
const { result } = renderCommandCompletionHook('/');
const { result } = await renderCommandCompletionHook('/');
await waitFor(() => {
expect(result.current.suggestions.length).toBe(5);
@ -401,7 +412,7 @@ describe('useCommandCompletion', () => {
});
it('should navigate down through suggestions with wrap-around', async () => {
const { result } = renderCommandCompletionHook('/');
const { result } = await renderCommandCompletionHook('/');
await waitFor(() => {
expect(result.current.suggestions.length).toBe(5);
@ -420,7 +431,7 @@ describe('useCommandCompletion', () => {
});
it('should handle navigation with multiple suggestions', async () => {
const { result } = renderCommandCompletionHook('/');
const { result } = await renderCommandCompletionHook('/');
await waitFor(() => {
expect(result.current.suggestions.length).toBe(5);
@ -447,7 +458,7 @@ describe('useCommandCompletion', () => {
it('should automatically select the first item when suggestions are available', async () => {
setupMocks({ slashSuggestions: mockSuggestions });
const { result } = renderCommandCompletionHook('/');
const { result } = await renderCommandCompletionHook('/');
await waitFor(() => {
expect(result.current.suggestions.length).toBe(
@ -466,7 +477,7 @@ describe('useCommandCompletion', () => {
slashCompletionRange: { completionStart: 1, completionEnd: 4 },
});
const { result } = renderCommandCompletionHook('/mem');
const { result } = await renderCommandCompletionHook('/mem');
await waitFor(() => {
expect(result.current.suggestions.length).toBe(1);
@ -484,7 +495,7 @@ describe('useCommandCompletion', () => {
atSuggestions: [{ label: 'src/file1.txt', value: 'src/file1.txt' }],
});
const { result } = renderCommandCompletionHook('@src/fi');
const { result } = await renderCommandCompletionHook('@src/fi');
await waitFor(() => {
expect(result.current.suggestions.length).toBe(1);
@ -509,7 +520,7 @@ describe('useCommandCompletion', () => {
slashCompletionRange: { completionStart: 1, completionEnd: 5 },
});
const { result } = renderCommandCompletionHook('/resu');
const { result } = await renderCommandCompletionHook('/resu');
await waitFor(() => {
expect(result.current.suggestions.length).toBe(1);
@ -530,7 +541,7 @@ describe('useCommandCompletion', () => {
atSuggestions: [{ label: 'src/file1.txt', value: 'src/file1.txt' }],
});
const { result } = renderCommandCompletionHook(text, cursorOffset);
const { result } = await renderCommandCompletionHook(text, cursorOffset);
await waitFor(() => {
expect(result.current.suggestions.length).toBe(1);
@ -550,7 +561,7 @@ describe('useCommandCompletion', () => {
atSuggestions: [{ label: 'src/components/', value: 'src/components/' }],
});
const { result } = renderCommandCompletionHook('@src/comp');
const { result } = await renderCommandCompletionHook('@src/comp');
await waitFor(() => {
expect(result.current.suggestions.length).toBe(1);
@ -570,7 +581,7 @@ describe('useCommandCompletion', () => {
],
});
const { result } = renderCommandCompletionHook('@src\\comp');
const { result } = await renderCommandCompletionHook('@src\\comp');
await waitFor(() => {
expect(result.current.suggestions.length).toBe(1);
@ -595,7 +606,7 @@ describe('useCommandCompletion', () => {
},
});
const { result } = renderCommandCompletionHook(
const { result } = await renderCommandCompletionHook(
text,
text.length,
true, // shellModeActive
@ -624,7 +635,7 @@ describe('useCommandCompletion', () => {
},
});
const { result } = renderCommandCompletionHook(
const { result } = await renderCommandCompletionHook(
text,
text.length,
true, // shellModeActive
@ -642,7 +653,7 @@ describe('useCommandCompletion', () => {
const text = 'ls ';
const cursorOffset = text.length;
const { result } = renderCommandCompletionHook(
const { result } = await renderCommandCompletionHook(
text,
cursorOffset,
true, // shellModeActive
@ -668,7 +679,7 @@ describe('useCommandCompletion', () => {
},
});
const { result } = renderCommandCompletionHook(
const { result } = await renderCommandCompletionHook(
textWithoutSpace,
textWithoutSpace.length,
true, // shellModeActive
@ -733,7 +744,7 @@ describe('useCommandCompletion', () => {
hookResult = { ...completion, textBuffer };
return null;
}
renderWithProviders(<TestComponent />);
await renderWithProviders(<TestComponent />);
// Should not trigger prompt completion for comments
await waitFor(() => {
@ -768,7 +779,7 @@ describe('useCommandCompletion', () => {
hookResult = { ...completion, textBuffer };
return null;
}
renderWithProviders(<TestComponent />);
await renderWithProviders(<TestComponent />);
// Should not trigger prompt completion for comments
await waitFor(() => {
@ -803,7 +814,7 @@ describe('useCommandCompletion', () => {
hookResult = { ...completion, textBuffer };
return null;
}
renderWithProviders(<TestComponent />);
await renderWithProviders(<TestComponent />);
// This test verifies that comments are filtered out while regular text is not
await waitFor(() => {
@ -823,7 +834,7 @@ describe('useCommandCompletion', () => {
const text = '/mycommand @src/fi';
const cursorOffset = text.length;
renderCommandCompletionHook(text, cursorOffset);
await renderCommandCompletionHook(text, cursorOffset);
await waitFor(() => {
expect(useAtCompletion).toHaveBeenLastCalledWith(
@ -843,7 +854,7 @@ describe('useCommandCompletion', () => {
const text = '/mycom';
const cursorOffset = text.length;
const { result } = renderCommandCompletionHook(text, cursorOffset);
const { result } = await renderCommandCompletionHook(text, cursorOffset);
await waitFor(() => {
expect(result.current.suggestions).toHaveLength(1);
@ -859,7 +870,7 @@ describe('useCommandCompletion', () => {
const text = '/command @';
const cursorOffset = text.length;
renderCommandCompletionHook(text, cursorOffset);
await renderCommandCompletionHook(text, cursorOffset);
await waitFor(() => {
expect(useAtCompletion).toHaveBeenLastCalledWith(
@ -879,7 +890,7 @@ describe('useCommandCompletion', () => {
const text = '/diff @src/foo.ts @src/ba';
const cursorOffset = text.length;
renderCommandCompletionHook(text, cursorOffset);
await renderCommandCompletionHook(text, cursorOffset);
await waitFor(() => {
expect(useAtCompletion).toHaveBeenLastCalledWith(
@ -896,7 +907,7 @@ describe('useCommandCompletion', () => {
atSuggestions: [{ label: 'src/file.txt', value: 'src/file.txt' }],
});
const { result } = renderCommandCompletionHook('/cmd @src/fi');
const { result } = await renderCommandCompletionHook('/cmd @src/fi');
await waitFor(() => {
expect(result.current.suggestions.length).toBe(1);
@ -915,7 +926,7 @@ describe('useCommandCompletion', () => {
});
const text = '/help ';
renderCommandCompletionHook(text);
await renderCommandCompletionHook(text);
await waitFor(() => {
expect(useSlashCompletion).toHaveBeenLastCalledWith(

View file

@ -47,13 +47,13 @@ describe('useFocus', () => {
stdin.removeAllListeners();
});
const renderFocusHook = () => {
const renderFocusHook = async () => {
let hookResult: ReturnType<typeof useFocus>;
function TestComponent() {
hookResult = useFocus();
return null;
}
const { unmount } = renderWithProviders(<TestComponent />);
const { unmount } = await renderWithProviders(<TestComponent />);
return {
result: {
get current() {
@ -64,15 +64,15 @@ describe('useFocus', () => {
};
};
it('should initialize with focus and enable focus reporting', () => {
const { result } = renderFocusHook();
it('should initialize with focus and enable focus reporting', async () => {
const { result } = await renderFocusHook();
expect(result.current.isFocused).toBe(true);
expect(stdout.write).toHaveBeenCalledWith('\x1b[?1004h');
});
it('should set isFocused to false when a focus-out event is received', () => {
const { result } = renderFocusHook();
it('should set isFocused to false when a focus-out event is received', async () => {
const { result } = await renderFocusHook();
// Initial state is focused
expect(result.current.isFocused).toBe(true);
@ -86,8 +86,8 @@ describe('useFocus', () => {
expect(result.current.isFocused).toBe(false);
});
it('should set isFocused to true when a focus-in event is received', () => {
const { result } = renderFocusHook();
it('should set isFocused to true when a focus-in event is received', async () => {
const { result } = await renderFocusHook();
// Simulate focus-out to set initial state to false
act(() => {
@ -104,8 +104,8 @@ describe('useFocus', () => {
expect(result.current.isFocused).toBe(true);
});
it('should clean up and disable focus reporting on unmount', () => {
const { unmount } = renderFocusHook();
it('should clean up and disable focus reporting on unmount', async () => {
const { unmount } = await renderFocusHook();
// At this point we should have listeners from both KeypressProvider and useFocus
const listenerCountAfterMount = stdin.listenerCount('data');
@ -119,8 +119,8 @@ describe('useFocus', () => {
expect(stdin.listenerCount('data')).toBeLessThan(listenerCountAfterMount);
});
it('should handle multiple focus events correctly', () => {
const { result } = renderFocusHook();
it('should handle multiple focus events correctly', async () => {
const { result } = await renderFocusHook();
act(() => {
stdin.emit('data', '\x1b[O');
@ -143,8 +143,8 @@ describe('useFocus', () => {
expect(result.current.isFocused).toBe(true);
});
it('restores focus on keypress after focus is lost', () => {
const { result } = renderFocusHook();
it('restores focus on keypress after focus is lost', async () => {
const { result } = await renderFocusHook();
// Simulate focus-out event
act(() => {
@ -159,8 +159,8 @@ describe('useFocus', () => {
expect(result.current.isFocused).toBe(true);
});
it('tracks whether any focus event has been received', () => {
const { result } = renderFocusHook();
it('tracks whether any focus event has been received', async () => {
const { result } = await renderFocusHook();
expect(result.current.hasReceivedFocusEvent).toBe(false);

View file

@ -375,7 +375,7 @@ describe('useGeminiStream', () => {
setValue: vi.fn(),
} as unknown as LoadedSettings;
const renderTestHook = (
const renderTestHook = async (
initialToolCalls: TrackedToolCall[] = [],
geminiClient?: any,
loadedSettings: LoadedSettings = mockLoadedSettings,
@ -436,7 +436,7 @@ describe('useGeminiStream', () => {
];
});
const { result, rerender } = renderHookWithProviders(
const { result, rerender } = await renderHookWithProviders(
(props: typeof initialProps) =>
useGeminiStream(
props.client,
@ -518,7 +518,7 @@ describe('useGeminiStream', () => {
});
// Helper to render hook with default parameters - reduces boilerplate
const renderHookWithDefaults = (
const renderHookWithDefaults = async (
options: {
shellModeActive?: boolean;
onCancelSubmit?: () => void;
@ -562,7 +562,7 @@ describe('useGeminiStream', () => {
);
};
it('should not submit tool responses if not all tool calls are completed', () => {
it('should not submit tool responses if not all tool calls are completed', async () => {
const toolCalls: TrackedToolCall[] = [
{
request: {
@ -617,7 +617,7 @@ describe('useGeminiStream', () => {
];
const { mockMarkToolsAsSubmitted, mockSendMessageStream } =
renderTestHook(toolCalls);
await renderTestHook(toolCalls);
// Effect for submitting tool responses depends on toolCalls and isResponding
// isResponding is initially false, so the effect should run.
@ -626,7 +626,7 @@ describe('useGeminiStream', () => {
expect(mockSendMessageStream).not.toHaveBeenCalled(); // submitQuery uses this
});
it('should expose activePtyId for non-shell executing tools that report an execution ID', () => {
it('should expose activePtyId for non-shell executing tools that report an execution ID', async () => {
const remoteExecutingTool: TrackedExecutingToolCall = {
request: {
callId: 'remote-call-1',
@ -651,7 +651,7 @@ describe('useGeminiStream', () => {
pid: 4242,
};
const { result } = renderTestHook([remoteExecutingTool]);
const { result } = await renderTestHook([remoteExecutingTool]);
expect(result.current.activePtyId).toBe(4242);
});
@ -716,7 +716,7 @@ describe('useGeminiStream', () => {
];
});
renderHookWithProviders(() =>
await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -817,7 +817,7 @@ describe('useGeminiStream', () => {
];
});
renderHookWithProviders(() =>
await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -927,7 +927,7 @@ describe('useGeminiStream', () => {
];
});
renderHookWithProviders(() =>
await renderHookWithProviders(() =>
useGeminiStream(
client,
[],
@ -998,7 +998,7 @@ describe('useGeminiStream', () => {
];
const client = new MockedGeminiClientClass(mockConfig);
const { result } = renderTestHook([], client);
const { result } = await renderTestHook([], client);
// Trigger the onComplete callback with STOP_EXECUTION tool
await act(async () => {
@ -1077,7 +1077,7 @@ describe('useGeminiStream', () => {
} as LoadedSettings;
const client = new MockedGeminiClientClass(mockConfig);
const { result } = renderTestHook([], client, lowVerbositySettings);
const { result } = await renderTestHook([], client, lowVerbositySettings);
await act(async () => {
if (capturedOnComplete) {
@ -1190,7 +1190,7 @@ describe('useGeminiStream', () => {
];
});
renderHookWithProviders(() =>
await renderHookWithProviders(() =>
useGeminiStream(
client,
[],
@ -1307,7 +1307,7 @@ describe('useGeminiStream', () => {
];
});
const { result, rerender } = renderHookWithProviders(() =>
const { result, rerender } = await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -1408,7 +1408,7 @@ describe('useGeminiStream', () => {
})();
mockSendMessageStream.mockReturnValue(mockStream);
const { result } = renderTestHook();
const { result } = await renderTestHook();
// Start a query
await act(async () => {
@ -1445,7 +1445,7 @@ describe('useGeminiStream', () => {
})();
mockSendMessageStream.mockReturnValue(mockStream);
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
mockConfig.getGeminiClient(),
[],
@ -1486,7 +1486,7 @@ describe('useGeminiStream', () => {
})();
mockSendMessageStream.mockReturnValue(mockStream);
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
mockConfig.getGeminiClient(),
[],
@ -1519,8 +1519,8 @@ describe('useGeminiStream', () => {
expect(setShellInputFocusedSpy).toHaveBeenCalledWith(false);
});
it('should not do anything if escape is pressed when not responding', () => {
const { result } = renderTestHook();
it('should not do anything if escape is pressed when not responding', async () => {
const { result } = await renderTestHook();
expect(result.current.streamingState).toBe(StreamingState.Idle);
@ -1548,7 +1548,7 @@ describe('useGeminiStream', () => {
})();
mockSendMessageStream.mockReturnValue(mockStream);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
@ -1600,7 +1600,7 @@ describe('useGeminiStream', () => {
} as TrackedExecutingToolCall,
];
const { result } = renderTestHook(toolCalls);
const { result } = await renderTestHook(toolCalls);
// State is `Responding` because a tool is running
expect(result.current.streamingState).toBe(StreamingState.Responding);
@ -1648,7 +1648,7 @@ describe('useGeminiStream', () => {
} as TrackedWaitingToolCall,
];
const { result } = renderTestHook(toolCalls);
const { result } = await renderTestHook(toolCalls);
// State is `WaitingForConfirmation` because a tool is awaiting approval
expect(result.current.streamingState).toBe(
@ -1677,7 +1677,7 @@ describe('useGeminiStream', () => {
describe('Retry Handling', () => {
it('should update retryStatus when CoreEvent.RetryAttempt is emitted', async () => {
const { result } = renderHookWithDefaults();
const { result } = await renderHookWithDefaults();
const retryPayload = {
model: 'gemini-2.5-pro',
@ -1694,7 +1694,7 @@ describe('useGeminiStream', () => {
});
it('should reset retryStatus when isResponding becomes false', async () => {
const { result } = renderTestHook();
const { result } = await renderTestHook();
const retryPayload = {
model: 'gemini-2.5-pro',
@ -1744,7 +1744,7 @@ describe('useGeminiStream', () => {
};
mockHandleSlashCommand.mockResolvedValue(clientToolRequest);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('/memory add "test fact"');
@ -1771,7 +1771,7 @@ describe('useGeminiStream', () => {
};
mockHandleSlashCommand.mockResolvedValue(uiOnlyCommandResult);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('/help');
@ -1792,7 +1792,7 @@ describe('useGeminiStream', () => {
mockHandleSlashCommand.mockResolvedValue(customCommandResult);
const { result, mockSendMessageStream: localMockSendMessageStream } =
renderTestHook();
await renderTestHook();
await act(async () => {
await result.current.submitQuery('/my-custom-command');
@ -1830,7 +1830,7 @@ describe('useGeminiStream', () => {
mockHandleSlashCommand.mockResolvedValue(emptyPromptResult);
const { result, mockSendMessageStream: localMockSendMessageStream } =
renderTestHook();
await renderTestHook();
await act(async () => {
await result.current.submitQuery('/emptycmd');
@ -1851,7 +1851,7 @@ describe('useGeminiStream', () => {
it('should not call handleSlashCommand for line comments', async () => {
const { result, mockSendMessageStream: localMockSendMessageStream } =
renderTestHook();
await renderTestHook();
await act(async () => {
await result.current.submitQuery('// This is a line comment');
@ -1872,7 +1872,7 @@ describe('useGeminiStream', () => {
it('should not call handleSlashCommand for block comments', async () => {
const { result, mockSendMessageStream: localMockSendMessageStream } =
renderTestHook();
await renderTestHook();
await act(async () => {
await result.current.submitQuery('/* This is a block comment */');
@ -1892,7 +1892,7 @@ describe('useGeminiStream', () => {
});
it('should not call handleSlashCommand is shell mode is active', async () => {
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -1972,7 +1972,7 @@ describe('useGeminiStream', () => {
];
});
renderHookWithProviders(() =>
await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -2031,7 +2031,7 @@ describe('useGeminiStream', () => {
getModel: vi.fn(() => 'gemini-2.5-pro'),
} as unknown as Config;
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(testConfig),
[],
@ -2078,7 +2078,7 @@ describe('useGeminiStream', () => {
createMockToolCall('read_file', 'call2', 'info'),
];
const { result } = renderTestHook(awaitingApprovalToolCalls);
const { result } = await renderTestHook(awaitingApprovalToolCalls);
await act(async () => {
await result.current.handleApprovalModeChange(ApprovalMode.YOLO);
@ -2108,7 +2108,7 @@ describe('useGeminiStream', () => {
createMockToolCall('read_file', 'call3', 'info'),
];
const { result } = renderTestHook(awaitingApprovalToolCalls);
const { result } = await renderTestHook(awaitingApprovalToolCalls);
await act(async () => {
await result.current.handleApprovalModeChange(ApprovalMode.AUTO_EDIT);
@ -2132,7 +2132,7 @@ describe('useGeminiStream', () => {
createMockToolCall('replace', 'call1', 'edit'),
];
const { result } = renderTestHook(awaitingApprovalToolCalls);
const { result } = await renderTestHook(awaitingApprovalToolCalls);
await act(async () => {
await result.current.handleApprovalModeChange(ApprovalMode.DEFAULT);
@ -2154,7 +2154,7 @@ describe('useGeminiStream', () => {
createMockToolCall('write_file', 'call2', 'edit'),
];
const { result } = renderTestHook(awaitingApprovalToolCalls);
const { result } = await renderTestHook(awaitingApprovalToolCalls);
await act(async () => {
await result.current.handleApprovalModeChange(ApprovalMode.YOLO);
@ -2196,7 +2196,7 @@ describe('useGeminiStream', () => {
} as unknown as TrackedWaitingToolCall,
];
const { result } = renderTestHook(awaitingApprovalToolCalls);
const { result } = await renderTestHook(awaitingApprovalToolCalls);
// Should not throw an error
await act(async () => {
@ -2239,7 +2239,7 @@ describe('useGeminiStream', () => {
} as TrackedExecutingToolCall,
];
const { result } = renderTestHook(mixedStatusToolCalls);
const { result } = await renderTestHook(mixedStatusToolCalls);
await act(async () => {
await result.current.handleApprovalModeChange(ApprovalMode.YOLO);
@ -2260,7 +2260,7 @@ describe('useGeminiStream', () => {
(mockConfig.getApprovalMode as Mock).mockReturnValue(ApprovalMode.PLAN);
// Render the hook, which will initialize the previousApprovalModeRef with PLAN
const { result, client } = renderTestHook([]);
const { result, client } = await renderTestHook([]);
// Update mockConfig to return DEFAULT mode (new mode)
(mockConfig.getApprovalMode as Mock).mockReturnValue(
@ -2300,7 +2300,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -2374,7 +2374,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderHookWithDefaults();
const { result } = await renderHookWithDefaults();
await act(async () => {
await result.current.submitQuery('Test overflow');
@ -2405,7 +2405,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -2454,7 +2454,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderHookWithDefaults();
const { result } = await renderHookWithDefaults();
// Submit a query
await act(async () => {
@ -2541,7 +2541,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderHookWithDefaults();
const { result } = await renderHookWithDefaults();
await act(async () => {
await result.current.submitQuery(`Test ${reason}`);
@ -2613,7 +2613,7 @@ describe('useGeminiStream', () => {
];
});
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -2684,7 +2684,7 @@ describe('useGeminiStream', () => {
shouldProceed: true,
});
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
mockConfig.getGeminiClient(),
[],
@ -2777,7 +2777,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery(userQuery);
@ -2849,7 +2849,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -2904,7 +2904,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('Test query');
@ -2949,7 +2949,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -3021,7 +3021,7 @@ describe('useGeminiStream', () => {
});
});
it('should memoize pendingHistoryItems', () => {
it('should memoize pendingHistoryItems', async () => {
mockUseToolScheduler.mockReturnValue([
[],
mockScheduleToolCalls,
@ -3031,7 +3031,7 @@ describe('useGeminiStream', () => {
0,
]);
const { result, rerender } = renderHookWithProviders(() =>
const { result, rerender } = await renderHookWithProviders(() =>
useGeminiStream(
mockConfig.getGeminiClient(),
[],
@ -3102,7 +3102,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -3159,7 +3159,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -3227,7 +3227,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useGeminiStream(
new MockedGeminiClientClass(mockConfig),
[],
@ -3287,7 +3287,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('test query');
@ -3334,7 +3334,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('test query');
@ -3399,7 +3399,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('test query');
@ -3434,7 +3434,7 @@ describe('useGeminiStream', () => {
});
it('should handle multiple loop detection events properly', async () => {
const { result } = renderTestHook();
const { result } = await renderTestHook();
// First loop detection - set up fresh mock for first call
mockSendMessageStream.mockReturnValueOnce(
@ -3544,7 +3544,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('test query');
@ -3581,7 +3581,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
// Start first query without awaiting (fire-and-forget, like existing tests)
await act(async () => {
@ -3637,7 +3637,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('test query');
@ -3692,7 +3692,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('test stop');
@ -3720,7 +3720,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('test stop');
@ -3751,7 +3751,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('test block');
@ -3778,7 +3778,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('test block');
@ -3807,7 +3807,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('user query');
@ -3855,7 +3855,7 @@ describe('useGeminiStream', () => {
})(),
);
const { result } = renderTestHook();
const { result } = await renderTestHook();
await act(async () => {
await result.current.submitQuery('user query');
@ -3881,7 +3881,7 @@ describe('useGeminiStream', () => {
});
it('should trace UserPrompt telemetry on submitQuery', async () => {
const { result } = renderTestHook();
const { result } = await renderTestHook();
mockSendMessageStream.mockReturnValue(
(async function* () {

View file

@ -43,7 +43,7 @@ describe(`useKeypress`, () => {
const onKeypress = vi.fn();
let originalNodeVersion: string;
const renderKeypressHook = (isActive = true) =>
const renderKeypressHook = async (isActive = true) =>
renderHookWithProviders(() => useKeypress(onKeypress, { isActive }));
beforeEach(() => {
@ -66,8 +66,8 @@ describe(`useKeypress`, () => {
});
});
it('should not listen if isActive is false', () => {
renderKeypressHook(false);
it('should not listen if isActive is false', async () => {
await renderKeypressHook(false);
act(() => stdin.write('a'));
expect(onKeypress).not.toHaveBeenCalled();
});
@ -79,28 +79,31 @@ describe(`useKeypress`, () => {
{ key: { name: 'up', sequence: '\x1b[A' } },
{ key: { name: 'down', sequence: '\x1b[B' } },
{ key: { name: 'tab', sequence: '\x1b[Z', shift: true } },
])('should listen for keypress when active for key $key.name', ({ key }) => {
renderKeypressHook(true);
act(() => stdin.write(key.sequence));
expect(onKeypress).toHaveBeenCalledWith(expect.objectContaining(key));
});
])(
'should listen for keypress when active for key $key.name',
async ({ key }) => {
await renderKeypressHook(true);
act(() => stdin.write(key.sequence));
expect(onKeypress).toHaveBeenCalledWith(expect.objectContaining(key));
},
);
it('should set and release raw mode', () => {
const { unmount } = renderKeypressHook(true);
it('should set and release raw mode', async () => {
const { unmount } = await renderKeypressHook(true);
expect(mockSetRawMode).toHaveBeenCalledWith(true);
unmount();
expect(mockSetRawMode).toHaveBeenCalledWith(false);
});
it('should stop listening after being unmounted', () => {
const { unmount } = renderKeypressHook(true);
it('should stop listening after being unmounted', async () => {
const { unmount } = await renderKeypressHook(true);
unmount();
act(() => stdin.write('a'));
expect(onKeypress).not.toHaveBeenCalled();
});
it('should correctly identify alt+enter (meta key)', () => {
renderKeypressHook(true);
it('should correctly identify alt+enter (meta key)', async () => {
await renderKeypressHook(true);
const key = { name: 'enter', sequence: '\x1B\r' };
act(() => stdin.write(key.sequence));
expect(onKeypress).toHaveBeenCalledWith(
@ -128,8 +131,8 @@ describe(`useKeypress`, () => {
setup();
});
it('should process a paste as a single event', () => {
renderKeypressHook(true);
it('should process a paste as a single event', async () => {
await renderKeypressHook(true);
const pasteText = 'hello world';
act(() => stdin.write(PASTE_START + pasteText + PASTE_END));
@ -145,8 +148,8 @@ describe(`useKeypress`, () => {
});
});
it('should handle keypress interspersed with pastes', () => {
renderKeypressHook(true);
it('should handle keypress interspersed with pastes', async () => {
await renderKeypressHook(true);
const keyA = { name: 'a', sequence: 'a' };
act(() => stdin.write('a'));
@ -169,8 +172,8 @@ describe(`useKeypress`, () => {
expect(onKeypress).toHaveBeenCalledTimes(3);
});
it('should handle lone pastes', () => {
renderKeypressHook(true);
it('should handle lone pastes', async () => {
await renderKeypressHook(true);
const pasteText = 'pasted';
act(() => {
@ -184,7 +187,7 @@ describe(`useKeypress`, () => {
});
it('should handle paste false alarm', async () => {
renderKeypressHook(true);
await renderKeypressHook(true);
act(() => {
stdin.write(PASTE_START.slice(0, 5));
@ -200,8 +203,8 @@ describe(`useKeypress`, () => {
expect(onKeypress).toHaveBeenCalledTimes(2);
});
it('should handle back to back pastes', () => {
renderKeypressHook(true);
it('should handle back to back pastes', async () => {
await renderKeypressHook(true);
const pasteText1 = 'herp';
const pasteText2 = 'derp';
@ -226,7 +229,7 @@ describe(`useKeypress`, () => {
});
it('should handle pastes split across writes', async () => {
renderKeypressHook(true);
await renderKeypressHook(true);
const keyA = { name: 'a', sequence: 'a' };
act(() => stdin.write('a'));

View file

@ -30,10 +30,10 @@ describe('useReverseSearchCompletion', () => {
describe('Core Hook Behavior', () => {
describe('State Management', () => {
it('should initialize with default state', () => {
it('should initialize with default state', async () => {
const mockShellHistory = ['echo hello'];
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useReverseSearchCompletion(
useTextBufferForTest(''),
mockShellHistory,
@ -48,9 +48,9 @@ describe('useReverseSearchCompletion', () => {
expect(result.current.isLoadingSuggestions).toBe(false);
});
it('should reset state when reverseSearchActive becomes false', () => {
it('should reset state when reverseSearchActive becomes false', async () => {
const mockShellHistory = ['echo hello'];
const { result, rerender } = renderHookWithProviders(
const { result, rerender } = await renderHookWithProviders(
({ text, active }) => {
const textBuffer = useTextBufferForTest(text);
return useReverseSearchCompletion(
@ -72,10 +72,10 @@ describe('useReverseSearchCompletion', () => {
});
describe('Navigation', () => {
it('should handle navigateUp with no suggestions', () => {
it('should handle navigateUp with no suggestions', async () => {
const mockShellHistory = ['echo hello'];
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useReverseSearchCompletion(
useTextBufferForTest('grep'),
mockShellHistory,
@ -90,9 +90,9 @@ describe('useReverseSearchCompletion', () => {
expect(result.current.activeSuggestionIndex).toBe(-1);
});
it('should handle navigateDown with no suggestions', () => {
it('should handle navigateDown with no suggestions', async () => {
const mockShellHistory = ['echo hello'];
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useReverseSearchCompletion(
useTextBufferForTest('grep'),
mockShellHistory,
@ -107,7 +107,7 @@ describe('useReverseSearchCompletion', () => {
expect(result.current.activeSuggestionIndex).toBe(-1);
});
it('should navigate up through suggestions with wrap-around', () => {
it('should navigate up through suggestions with wrap-around', async () => {
const mockShellHistory = [
'ls -l',
'ls -la',
@ -117,7 +117,7 @@ describe('useReverseSearchCompletion', () => {
'echo Hi',
];
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useReverseSearchCompletion(
useTextBufferForTest('echo'),
mockShellHistory,
@ -135,7 +135,7 @@ describe('useReverseSearchCompletion', () => {
expect(result.current.activeSuggestionIndex).toBe(1);
});
it('should navigate down through suggestions with wrap-around', () => {
it('should navigate down through suggestions with wrap-around', async () => {
const mockShellHistory = [
'ls -l',
'ls -la',
@ -144,7 +144,7 @@ describe('useReverseSearchCompletion', () => {
'echo "Hello, World!"',
'echo Hi',
];
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useReverseSearchCompletion(
useTextBufferForTest('ls'),
mockShellHistory,
@ -162,7 +162,7 @@ describe('useReverseSearchCompletion', () => {
expect(result.current.activeSuggestionIndex).toBe(1);
});
it('should handle navigation with multiple suggestions', () => {
it('should handle navigation with multiple suggestions', async () => {
const mockShellHistory = [
'ls -l',
'ls -la',
@ -172,7 +172,7 @@ describe('useReverseSearchCompletion', () => {
'echo "Hi all"',
];
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useReverseSearchCompletion(
useTextBufferForTest('l'),
mockShellHistory,
@ -209,13 +209,13 @@ describe('useReverseSearchCompletion', () => {
expect(result.current.activeSuggestionIndex).toBe(4);
});
it('should handle navigation with large suggestion lists and scrolling', () => {
it('should handle navigation with large suggestion lists and scrolling', async () => {
const largeMockCommands = Array.from(
{ length: 15 },
(_, i) => `echo ${i}`,
);
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useReverseSearchCompletion(
useTextBufferForTest('echo'),
largeMockCommands,
@ -239,9 +239,9 @@ describe('useReverseSearchCompletion', () => {
});
describe('Filtering', () => {
it('filters history by buffer.text and sets showSuggestions', () => {
it('filters history by buffer.text and sets showSuggestions', async () => {
const history = ['foo', 'barfoo', 'baz'];
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useReverseSearchCompletion(useTextBufferForTest('foo'), history, true),
);
@ -253,9 +253,9 @@ describe('useReverseSearchCompletion', () => {
expect(result.current.showSuggestions).toBe(true);
});
it('hides suggestions when there are no matches', () => {
it('hides suggestions when there are no matches', async () => {
const history = ['alpha', 'beta'];
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useReverseSearchCompletion(useTextBufferForTest('γ'), history, true),
);

View file

@ -48,10 +48,13 @@ describe('useSnowfall', () => {
vi.useRealTimers();
});
it('initially enables animation during holiday season with Holiday theme', () => {
const { result } = renderHookWithProviders(() => useSnowfall(mockArt), {
uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
});
it('initially enables animation during holiday season with Holiday theme', async () => {
const { result } = await renderHookWithProviders(
() => useSnowfall(mockArt),
{
uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
},
);
// Should contain holiday trees
expect(result.current).toContain('|_|');
@ -59,10 +62,13 @@ describe('useSnowfall', () => {
expect(debugState.debugNumAnimatedComponents).toBeGreaterThan(0);
});
it('stops animation after 15 seconds', () => {
const { result } = renderHookWithProviders(() => useSnowfall(mockArt), {
uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
});
it('stops animation after 15 seconds', async () => {
const { result } = await renderHookWithProviders(
() => useSnowfall(mockArt),
{
uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
},
);
expect(debugState.debugNumAnimatedComponents).toBeGreaterThan(0);
@ -76,35 +82,44 @@ describe('useSnowfall', () => {
expect(result.current).toBe(mockArt);
});
it('does not enable animation if not holiday season', () => {
it('does not enable animation if not holiday season', async () => {
vi.setSystemTime(new Date('2025-06-15'));
const { result } = renderHookWithProviders(() => useSnowfall(mockArt), {
uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
});
const { result } = await renderHookWithProviders(
() => useSnowfall(mockArt),
{
uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
},
);
expect(result.current).toBe(mockArt);
expect(debugState.debugNumAnimatedComponents).toBe(0);
});
it('does not enable animation if theme is not Holiday', () => {
it('does not enable animation if theme is not Holiday', async () => {
vi.mocked(themeManager.getActiveTheme).mockReturnValue({
name: 'Default',
} as Theme);
const { result } = renderHookWithProviders(() => useSnowfall(mockArt), {
uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
});
const { result } = await renderHookWithProviders(
() => useSnowfall(mockArt),
{
uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
},
);
expect(result.current).toBe(mockArt);
expect(debugState.debugNumAnimatedComponents).toBe(0);
});
it('does not enable animation if chat has started', () => {
const { result } = renderHookWithProviders(() => useSnowfall(mockArt), {
uiState: {
history: [{ type: 'user', text: 'hello' }],
historyRemountKey: 0,
} as Partial<UIState>,
});
it('does not enable animation if chat has started', async () => {
const { result } = await renderHookWithProviders(
() => useSnowfall(mockArt),
{
uiState: {
history: [{ type: 'user', text: 'hello' }],
historyRemountKey: 0,
} as Partial<UIState>,
},
);
expect(result.current).toBe(mockArt);
expect(debugState.debugNumAnimatedComponents).toBe(0);

View file

@ -16,8 +16,8 @@ describe('useTips()', () => {
vi.clearAllMocks();
});
it('should return false and call set(1) if state is undefined', () => {
const { result } = renderHookWithProviders(() => useTips());
it('should return false and call set(1) if state is undefined', async () => {
const { result } = await renderHookWithProviders(() => useTips());
expect(result.current.showTips).toBe(true);
@ -25,20 +25,20 @@ describe('useTips()', () => {
expect(persistentStateMock.get('tipsShown')).toBe(1);
});
it('should return false and call set(6) if state is 5', () => {
it('should return false and call set(6) if state is 5', async () => {
persistentStateMock.setData({ tipsShown: 5 });
const { result } = renderHookWithProviders(() => useTips());
const { result } = await renderHookWithProviders(() => useTips());
expect(result.current.showTips).toBe(true);
expect(persistentStateMock.get('tipsShown')).toBe(6);
});
it('should return true if state is 10', () => {
it('should return true if state is 10', async () => {
persistentStateMock.setData({ tipsShown: 10 });
const { result } = renderHookWithProviders(() => useTips());
const { result } = await renderHookWithProviders(() => useTips());
expect(result.current.showTips).toBe(false);
expect(persistentStateMock.set).not.toHaveBeenCalled();

View file

@ -35,7 +35,7 @@ describe('colorizeCode', () => {
hideLineNumbers: true,
});
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<>{result}</>,
);
await waitUntilReady();
@ -76,7 +76,7 @@ describe('colorizeCode', () => {
hideLineNumbers: true,
});
const renderResult = renderWithProviders(<>{result}</>);
const renderResult = await renderWithProviders(<>{result}</>);
await renderResult.waitUntilReady();
await expect(renderResult).toMatchSvgSnapshot();

Some files were not shown because too many files have changed in this diff Show more