Download packages/cli/src/ui/hooks/useFlickerDetector.test.ts from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 4.51 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/ui/hooks/useFlickerDetector.test.ts
- Command line
-
hf download hf://SaylorTwift/gemini-cli/packages/cli/src/ui/hooks/useFlickerDetector.test.ts
-
curl -L -o useFlickerDetector.test.ts https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/ui/hooks/useFlickerDetector.test.ts
4.51 kB
| /** | |
| * @license | |
| * Copyright 2025 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import { renderHook } from '../../test-utils/render.js'; | |
| import { vi, type Mock } from 'vitest'; | |
| import { useFlickerDetector } from './useFlickerDetector.js'; | |
| import { useConfig } from '../contexts/ConfigContext.js'; | |
| import { recordFlickerFrame, type Config } from '@google/gemini-cli-core'; | |
| import { type DOMElement, measureElement } from 'ink'; | |
| import { useUIState } from '../contexts/UIStateContext.js'; | |
| import { appEvents, AppEvent } from '../../utils/events.js'; | |
| // Mock dependencies | |
| vi.mock('../contexts/ConfigContext.js'); | |
| vi.mock('../contexts/UIStateContext.js'); | |
| vi.mock('@google/gemini-cli-core', async (importOriginal) => { | |
| const actual = | |
| await importOriginal<typeof import('@google/gemini-cli-core')>(); | |
| return { | |
| ...actual, | |
| recordFlickerFrame: vi.fn(), | |
| GEMINI_DIR: '.gemini', | |
| }; | |
| }); | |
| vi.mock('ink', async (importOriginal) => { | |
| const original = await importOriginal<typeof import('ink')>(); | |
| return { | |
| ...original, | |
| measureElement: vi.fn(), | |
| }; | |
| }); | |
| vi.mock('../../utils/events.js', () => ({ | |
| appEvents: { | |
| emit: vi.fn(), | |
| }, | |
| AppEvent: { | |
| Flicker: 'flicker', | |
| }, | |
| })); | |
| const mockUseConfig = useConfig as Mock; | |
| const mockUseUIState = useUIState as Mock; | |
| const mockRecordFlickerFrame = recordFlickerFrame as Mock; | |
| const mockMeasureElement = measureElement as Mock; | |
| const mockAppEventsEmit = appEvents.emit as Mock; | |
| describe('useFlickerDetector', () => { | |
| const mockConfig = {} as Config; | |
| let mockRef: React.RefObject<DOMElement | null>; | |
| beforeEach(() => { | |
| mockUseConfig.mockReturnValue(mockConfig); | |
| mockRef = { current: { yogaNode: {} } as DOMElement }; | |
| // Default UI state | |
| mockUseUIState.mockReturnValue({ constrainHeight: true }); | |
| }); | |
| afterEach(() => { | |
| vi.clearAllMocks(); | |
| }); | |
| it('should not record a flicker when height is less than terminal height', async () => { | |
| mockMeasureElement.mockReturnValue({ width: 80, height: 20 }); | |
| await renderHook(() => useFlickerDetector(mockRef, 25)); | |
| expect(mockRecordFlickerFrame).not.toHaveBeenCalled(); | |
| expect(mockAppEventsEmit).not.toHaveBeenCalled(); | |
| }); | |
| it('should not record a flicker when height is equal to terminal height', async () => { | |
| mockMeasureElement.mockReturnValue({ width: 80, height: 25 }); | |
| await renderHook(() => useFlickerDetector(mockRef, 25)); | |
| expect(mockRecordFlickerFrame).not.toHaveBeenCalled(); | |
| expect(mockAppEventsEmit).not.toHaveBeenCalled(); | |
| }); | |
| it('should record a flicker when height is greater than terminal height and height is constrained', async () => { | |
| mockMeasureElement.mockReturnValue({ width: 80, height: 30 }); | |
| await renderHook(() => useFlickerDetector(mockRef, 25)); | |
| expect(mockRecordFlickerFrame).toHaveBeenCalledTimes(1); | |
| expect(mockRecordFlickerFrame).toHaveBeenCalledWith(mockConfig); | |
| expect(mockAppEventsEmit).toHaveBeenCalledTimes(1); | |
| expect(mockAppEventsEmit).toHaveBeenCalledWith(AppEvent.Flicker); | |
| }); | |
| it('should NOT record a flicker when height is greater than terminal height but height is NOT constrained', async () => { | |
| // Override default UI state for this test | |
| mockUseUIState.mockReturnValue({ constrainHeight: false }); | |
| mockMeasureElement.mockReturnValue({ width: 80, height: 30 }); | |
| await renderHook(() => useFlickerDetector(mockRef, 25)); | |
| expect(mockRecordFlickerFrame).not.toHaveBeenCalled(); | |
| expect(mockAppEventsEmit).not.toHaveBeenCalled(); | |
| }); | |
| it('should not check for flicker if the ref is not set', async () => { | |
| mockRef.current = null; | |
| mockMeasureElement.mockReturnValue({ width: 80, height: 30 }); | |
| await renderHook(() => useFlickerDetector(mockRef, 25)); | |
| expect(mockMeasureElement).not.toHaveBeenCalled(); | |
| expect(mockRecordFlickerFrame).not.toHaveBeenCalled(); | |
| expect(mockAppEventsEmit).not.toHaveBeenCalled(); | |
| }); | |
| it('should re-evaluate on re-render', async () => { | |
| // Start with a valid height | |
| mockMeasureElement.mockReturnValue({ width: 80, height: 20 }); | |
| const { rerender } = await renderHook(() => | |
| useFlickerDetector(mockRef, 25), | |
| ); | |
| expect(mockRecordFlickerFrame).not.toHaveBeenCalled(); | |
| // Now, simulate a re-render where the height is too great | |
| mockMeasureElement.mockReturnValue({ width: 80, height: 30 }); | |
| rerender(); | |
| expect(mockRecordFlickerFrame).toHaveBeenCalledTimes(1); | |
| expect(mockAppEventsEmit).toHaveBeenCalledTimes(1); | |
| }); | |
| }); | |