From 4494f9e062020040b88c54c47fe3a788025c3378 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Mon, 9 Feb 2026 20:44:22 -0800 Subject: [PATCH] test(cli): fix AppContainer act() warnings and improve waitFor resilience (#18676) --- packages/cli/src/test-utils/async.ts | 9 +++++-- packages/cli/src/ui/AppContainer.test.tsx | 30 ++++++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/test-utils/async.ts b/packages/cli/src/test-utils/async.ts index ad34cb5814..690f0e0397 100644 --- a/packages/cli/src/test-utils/async.ts +++ b/packages/cli/src/test-utils/async.ts @@ -5,6 +5,7 @@ */ import { act } from 'react'; +import { vi } from 'vitest'; // The waitFor from vitest doesn't properly wrap in act(), so we have to // implement our own like the one in @testing-library/react @@ -13,7 +14,7 @@ import { act } from 'react'; // for React state updates. export async function waitFor( assertion: () => void, - { timeout = 1000, interval = 50 } = {}, + { timeout = 2000, interval = 50 } = {}, ): Promise { const startTime = Date.now(); @@ -27,7 +28,11 @@ export async function waitFor( } await act(async () => { - await new Promise((resolve) => setTimeout(resolve, interval)); + if (vi.isFakeTimers()) { + await vi.advanceTimersByTimeAsync(interval); + } else { + await new Promise((resolve) => setTimeout(resolve, interval)); + } }); } } diff --git a/packages/cli/src/ui/AppContainer.test.tsx b/packages/cli/src/ui/AppContainer.test.tsx index 385185d0d3..b5b512434e 100644 --- a/packages/cli/src/ui/AppContainer.test.tsx +++ b/packages/cli/src/ui/AppContainer.test.tsx @@ -147,12 +147,28 @@ vi.mock('./hooks/useLogger.js'); vi.mock('./hooks/useInputHistoryStore.js'); vi.mock('./hooks/atCommandProcessor.js'); vi.mock('./hooks/useHookDisplayState.js'); +vi.mock('./hooks/useBanner.js', () => ({ + useBanner: vi.fn((bannerData) => ({ + bannerText: ( + bannerData.warningText || + bannerData.defaultText || + '' + ).replace(/\\n/g, '\n'), + })), +})); +vi.mock('./hooks/useShellInactivityStatus.js', () => ({ + useShellInactivityStatus: vi.fn(() => ({ + shouldShowFocusHint: false, + inactivityStatus: 'none', + })), +})); vi.mock('./hooks/useTerminalTheme.js', () => ({ useTerminalTheme: vi.fn(), })); import { useHookDisplayState } from './hooks/useHookDisplayState.js'; import { useTerminalTheme } from './hooks/useTerminalTheme.js'; +import { useShellInactivityStatus } from './hooks/useShellInactivityStatus.js'; // Mock external utilities vi.mock('../utils/events.js'); @@ -256,6 +272,7 @@ describe('AppContainer State Management', () => { const mockedUseInputHistoryStore = useInputHistoryStore as Mock; const mockedUseHookDisplayState = useHookDisplayState as Mock; const mockedUseTerminalTheme = useTerminalTheme as Mock; + const mockedUseShellInactivityStatus = useShellInactivityStatus as Mock; const DEFAULT_GEMINI_STREAM_MOCK = { streamingState: 'idle', @@ -385,6 +402,10 @@ describe('AppContainer State Management', () => { }); mockedUseHookDisplayState.mockReturnValue([]); mockedUseTerminalTheme.mockReturnValue(undefined); + mockedUseShellInactivityStatus.mockReturnValue({ + shouldShowFocusHint: false, + inactivityStatus: 'none', + }); // Mock Config mockConfig = makeFakeConfig(); @@ -1247,8 +1268,15 @@ describe('AppContainer State Management', () => { }); describe('Shell Focus Action Required', () => { - beforeEach(() => { + beforeEach(async () => { vi.useFakeTimers(); + // Use real implementation for these tests to verify title updates + const actual = await vi.importActual< + typeof import('./hooks/useShellInactivityStatus.js') + >('./hooks/useShellInactivityStatus.js'); + mockedUseShellInactivityStatus.mockImplementation( + actual.useShellInactivityStatus, + ); }); afterEach(() => {