summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/hooks/useConsoleMessages.test.ts
diff options
context:
space:
mode:
authorJacob Richman <[email protected]>2025-05-23 22:51:47 -0700
committerGitHub <[email protected]>2025-05-23 22:51:47 -0700
commit1c3d9d7623ecff0437db0627cace0cbb421b458a (patch)
treebc76cbbfd12f2e94c263024d8e021530c9bc8881 /packages/cli/src/ui/hooks/useConsoleMessages.test.ts
parent7a3a9066f96440dd1cdbfbc8be576648f7e73fe1 (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.ts212
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
+ });
+});