diff options
| author | Jacob Richman <[email protected]> | 2025-05-23 22:51:47 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-05-23 22:51:47 -0700 |
| commit | 1c3d9d7623ecff0437db0627cace0cbb421b458a (patch) | |
| tree | bc76cbbfd12f2e94c263024d8e021530c9bc8881 /packages/cli/src/ui/hooks/useConsoleMessages.test.ts | |
| parent | 7a3a9066f96440dd1cdbfbc8be576648f7e73fe1 (diff) | |
Make console message support more robust to logging in the middle of rendering. (#521)
Diffstat (limited to 'packages/cli/src/ui/hooks/useConsoleMessages.test.ts')
| -rw-r--r-- | packages/cli/src/ui/hooks/useConsoleMessages.test.ts | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/packages/cli/src/ui/hooks/useConsoleMessages.test.ts b/packages/cli/src/ui/hooks/useConsoleMessages.test.ts new file mode 100644 index 00000000..3b225ecf --- /dev/null +++ b/packages/cli/src/ui/hooks/useConsoleMessages.test.ts @@ -0,0 +1,212 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { act, renderHook } from '@testing-library/react'; +import { useConsoleMessages } from './useConsoleMessages.js'; +import { ConsoleMessageItem } from '../types.js'; + +// Mock setTimeout and clearTimeout +vi.useFakeTimers(); + +describe('useConsoleMessages', () => { + it('should initialize with an empty array of console messages', () => { + const { result } = renderHook(() => useConsoleMessages()); + expect(result.current.consoleMessages).toEqual([]); + }); + + it('should add a new message', () => { + const { result } = renderHook(() => useConsoleMessages()); + const message: ConsoleMessageItem = { + type: 'log', + content: 'Test message', + count: 1, + }; + + act(() => { + result.current.handleNewMessage(message); + }); + + act(() => { + vi.runAllTimers(); // Process the queue + }); + + expect(result.current.consoleMessages).toEqual([{ ...message, count: 1 }]); + }); + + it('should consolidate identical consecutive messages', () => { + const { result } = renderHook(() => useConsoleMessages()); + const message: ConsoleMessageItem = { + type: 'log', + content: 'Test message', + count: 1, + }; + + act(() => { + result.current.handleNewMessage(message); + result.current.handleNewMessage(message); + }); + + act(() => { + vi.runAllTimers(); + }); + + expect(result.current.consoleMessages).toEqual([{ ...message, count: 2 }]); + }); + + it('should not consolidate different messages', () => { + const { result } = renderHook(() => useConsoleMessages()); + const message1: ConsoleMessageItem = { + type: 'log', + content: 'Test message 1', + count: 1, + }; + const message2: ConsoleMessageItem = { + type: 'error', + content: 'Test message 2', + count: 1, + }; + + act(() => { + result.current.handleNewMessage(message1); + result.current.handleNewMessage(message2); + }); + + act(() => { + vi.runAllTimers(); + }); + + expect(result.current.consoleMessages).toEqual([ + { ...message1, count: 1 }, + { ...message2, count: 1 }, + ]); + }); + + it('should not consolidate messages if type is different', () => { + const { result } = renderHook(() => useConsoleMessages()); + const message1: ConsoleMessageItem = { + type: 'log', + content: 'Test message', + count: 1, + }; + const message2: ConsoleMessageItem = { + type: 'error', + content: 'Test message', + count: 1, + }; + + act(() => { + result.current.handleNewMessage(message1); + result.current.handleNewMessage(message2); + }); + + act(() => { + vi.runAllTimers(); + }); + + expect(result.current.consoleMessages).toEqual([ + { ...message1, count: 1 }, + { ...message2, count: 1 }, + ]); + }); + + it('should clear console messages', () => { + const { result } = renderHook(() => useConsoleMessages()); + const message: ConsoleMessageItem = { + type: 'log', + content: 'Test message', + count: 1, + }; + + act(() => { + result.current.handleNewMessage(message); + }); + + act(() => { + vi.runAllTimers(); + }); + + expect(result.current.consoleMessages).toHaveLength(1); + + act(() => { + result.current.clearConsoleMessages(); + }); + + expect(result.current.consoleMessages).toEqual([]); + }); + + it('should clear pending timeout on clearConsoleMessages', () => { + const { result } = renderHook(() => useConsoleMessages()); + const message: ConsoleMessageItem = { + type: 'log', + content: 'Test message', + count: 1, + }; + + act(() => { + result.current.handleNewMessage(message); // This schedules a timeout + }); + + act(() => { + result.current.clearConsoleMessages(); + }); + + // Ensure the queue is empty and no more messages are processed + act(() => { + vi.runAllTimers(); // If timeout wasn't cleared, this would process the queue + }); + + expect(result.current.consoleMessages).toEqual([]); + }); + + it('should clear message queue on clearConsoleMessages', () => { + const { result } = renderHook(() => useConsoleMessages()); + const message: ConsoleMessageItem = { + type: 'log', + content: 'Test message', + count: 1, + }; + + act(() => { + // Add a message but don't process the queue yet + result.current.handleNewMessage(message); + }); + + act(() => { + result.current.clearConsoleMessages(); + }); + + // Process any pending timeouts (should be none related to message queue) + act(() => { + vi.runAllTimers(); + }); + + // The consoleMessages should be empty because the queue was cleared before processing + expect(result.current.consoleMessages).toEqual([]); + }); + + it('should cleanup timeout on unmount', () => { + const { result, unmount } = renderHook(() => useConsoleMessages()); + const message: ConsoleMessageItem = { + type: 'log', + content: 'Test message', + count: 1, + }; + + act(() => { + result.current.handleNewMessage(message); + }); + + unmount(); + + // This is a bit indirect. We check that clearTimeout was called. + // If clearTimeout was not called, and we run timers, an error might occur + // or the state might change, which it shouldn't after unmount. + // Vitest's vi.clearAllTimers() or specific checks for clearTimeout calls + // would be more direct if available and easy to set up here. + // For now, we rely on the useEffect cleanup pattern. + expect(vi.getTimerCount()).toBe(0); // Check if all timers are cleared + }); +}); |
