diff options
| author | Jacob Richman <[email protected]> | 2025-05-24 00:44:17 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-05-24 00:44:17 -0700 |
| commit | b4c16d1f56f4e19fffd3d7608b410570f35045f9 (patch) | |
| tree | dfda3634f4d266f5472bd37b78362abebe6a9c9e /packages/cli/src/ui/hooks/useTimer.test.ts | |
| parent | 1c3d9d7623ecff0437db0627cace0cbb421b458a (diff) | |
Code review comment fixes and some refactors. (#525)
No intentional different behavior aside for tweaks suggested from the code review of #506 Refactor: Extract console message logic to custom hook
This commit refactors the console message handling from App.tsx into a new custom hook useConsoleMessages.
This change improves the testability of the console message logic and declutters the main App component.
Created useConsoleMessages.ts to encapsulate console message state and update logic.
Updated App.tsx to utilize the new useConsoleMessages hook.
Added unit tests for useConsoleMessages.ts to ensure its functionality.
I deleted and started over on LoadingIndicator.test.tsx as I spent way too much time trying to fix it before just regenerating the tests as the code was easier to write tests for from scratch and the existing tests were not that good (I added them in the previous pull request).
Diffstat (limited to 'packages/cli/src/ui/hooks/useTimer.test.ts')
| -rw-r--r-- | packages/cli/src/ui/hooks/useTimer.test.ts | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/packages/cli/src/ui/hooks/useTimer.test.ts b/packages/cli/src/ui/hooks/useTimer.test.ts new file mode 100644 index 00000000..20d44d17 --- /dev/null +++ b/packages/cli/src/ui/hooks/useTimer.test.ts @@ -0,0 +1,120 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import { renderHook, act } from '@testing-library/react'; +import { useTimer } from './useTimer.js'; + +describe('useTimer', () => { + beforeEach(() => { + vi.useFakeTimers(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should initialize with 0', () => { + const { result } = renderHook(() => useTimer(false, 0)); + expect(result.current).toBe(0); + }); + + it('should not increment time if isActive is false', () => { + const { result } = renderHook(() => useTimer(false, 0)); + act(() => { + vi.advanceTimersByTime(5000); + }); + expect(result.current).toBe(0); + }); + + it('should increment time every second if isActive is true', () => { + const { result } = renderHook(() => useTimer(true, 0)); + act(() => { + vi.advanceTimersByTime(1000); + }); + expect(result.current).toBe(1); + act(() => { + vi.advanceTimersByTime(2000); + }); + expect(result.current).toBe(3); + }); + + it('should reset to 0 and start incrementing when isActive becomes true from false', () => { + const { result, rerender } = renderHook( + ({ isActive, resetKey }) => useTimer(isActive, resetKey), + { initialProps: { isActive: false, resetKey: 0 } }, + ); + expect(result.current).toBe(0); + + rerender({ isActive: true, resetKey: 0 }); + expect(result.current).toBe(0); // Should reset to 0 upon becoming active + + act(() => { + vi.advanceTimersByTime(1000); + }); + expect(result.current).toBe(1); + }); + + it('should reset to 0 when resetKey changes while active', () => { + const { result, rerender } = renderHook( + ({ isActive, resetKey }) => useTimer(isActive, resetKey), + { initialProps: { isActive: true, resetKey: 0 } }, + ); + act(() => { + vi.advanceTimersByTime(3000); // 3s + }); + expect(result.current).toBe(3); + + rerender({ isActive: true, resetKey: 1 }); // Change resetKey + expect(result.current).toBe(0); // Should reset to 0 + + act(() => { + vi.advanceTimersByTime(1000); + }); + expect(result.current).toBe(1); // Starts incrementing from 0 + }); + + it('should be 0 if isActive is false, regardless of resetKey changes', () => { + const { result, rerender } = renderHook( + ({ isActive, resetKey }) => useTimer(isActive, resetKey), + { initialProps: { isActive: false, resetKey: 0 } }, + ); + expect(result.current).toBe(0); + + rerender({ isActive: false, resetKey: 1 }); + expect(result.current).toBe(0); + }); + + it('should clear timer on unmount', () => { + const { unmount } = renderHook(() => useTimer(true, 0)); + const clearIntervalSpy = vi.spyOn(global, 'clearInterval'); + unmount(); + expect(clearIntervalSpy).toHaveBeenCalledOnce(); + }); + + it('should preserve elapsedTime when isActive becomes false, and reset to 0 when it becomes active again', () => { + const { result, rerender } = renderHook( + ({ isActive, resetKey }) => useTimer(isActive, resetKey), + { initialProps: { isActive: true, resetKey: 0 } }, + ); + + act(() => { + vi.advanceTimersByTime(3000); // Advance to 3 seconds + }); + expect(result.current).toBe(3); + + rerender({ isActive: false, resetKey: 0 }); + expect(result.current).toBe(3); // Time should be preserved when timer becomes inactive + + // Now make it active again, it should reset to 0 + rerender({ isActive: true, resetKey: 0 }); + expect(result.current).toBe(0); + act(() => { + vi.advanceTimersByTime(1000); + }); + expect(result.current).toBe(1); + }); +}); |
