| |
| |
| |
| |
| |
|
|
| import { act } from 'react'; |
| import type { EventEmitter } from 'node:events'; |
| import { renderWithProviders } from '../../test-utils/render.js'; |
| import { waitFor } from '../../test-utils/async.js'; |
| import { ConfigInitDisplay } from './ConfigInitDisplay.js'; |
| import { |
| describe, |
| it, |
| expect, |
| vi, |
| beforeEach, |
| afterEach, |
| type MockInstance, |
| } from 'vitest'; |
| import { |
| CoreEvent, |
| MCPServerStatus, |
| type McpClient, |
| coreEvents, |
| } from '@google/gemini-cli-core'; |
| import { Text } from 'ink'; |
|
|
| |
| vi.mock('./GeminiSpinner.js', () => ({ |
| GeminiSpinner: () => <Text>Spinner</Text>, |
| })); |
|
|
| describe('ConfigInitDisplay', () => { |
| let onSpy: MockInstance<EventEmitter['on']>; |
|
|
| beforeEach(() => { |
| onSpy = vi.spyOn(coreEvents as EventEmitter, 'on'); |
| }); |
|
|
| afterEach(() => { |
| vi.restoreAllMocks(); |
| }); |
|
|
| it('renders initial state', async () => { |
| const { lastFrame } = await renderWithProviders(<ConfigInitDisplay />); |
| expect(lastFrame()).toMatchSnapshot(); |
| }); |
|
|
| it('updates message on McpClientUpdate event', async () => { |
| let listener: ((clients?: Map<string, McpClient>) => void) | undefined; |
| onSpy.mockImplementation((event: unknown, fn: unknown) => { |
| if (event === CoreEvent.McpClientUpdate) { |
| listener = fn as (clients?: Map<string, McpClient>) => void; |
| } |
| return coreEvents; |
| }); |
|
|
| const { lastFrame } = await renderWithProviders(<ConfigInitDisplay />); |
|
|
| |
| await waitFor(() => { |
| if (!listener) throw new Error('Listener not registered yet'); |
| }); |
|
|
| const mockClient1 = { |
| getStatus: () => MCPServerStatus.CONNECTED, |
| } as McpClient; |
| const mockClient2 = { |
| getStatus: () => MCPServerStatus.CONNECTING, |
| } as McpClient; |
| const clients = new Map<string, McpClient>([ |
| ['server1', mockClient1], |
| ['server2', mockClient2], |
| ]); |
|
|
| |
| act(() => { |
| listener!(clients); |
| }); |
|
|
| |
| await waitFor(() => { |
| expect(lastFrame()).toMatchSnapshot(); |
| }); |
| }); |
|
|
| it('truncates list of waiting servers if too many', async () => { |
| let listener: ((clients?: Map<string, McpClient>) => void) | undefined; |
| onSpy.mockImplementation((event: unknown, fn: unknown) => { |
| if (event === CoreEvent.McpClientUpdate) { |
| listener = fn as (clients?: Map<string, McpClient>) => void; |
| } |
| return coreEvents; |
| }); |
|
|
| const { lastFrame } = await renderWithProviders(<ConfigInitDisplay />); |
|
|
| await waitFor(() => { |
| if (!listener) throw new Error('Listener not registered yet'); |
| }); |
|
|
| const mockClientConnecting = { |
| getStatus: () => MCPServerStatus.CONNECTING, |
| } as McpClient; |
|
|
| const clients = new Map<string, McpClient>([ |
| ['s1', mockClientConnecting], |
| ['s2', mockClientConnecting], |
| ['s3', mockClientConnecting], |
| ['s4', mockClientConnecting], |
| ['s5', mockClientConnecting], |
| ]); |
|
|
| act(() => { |
| listener!(clients); |
| }); |
|
|
| await waitFor(() => { |
| expect(lastFrame()).toMatchSnapshot(); |
| }); |
| }); |
|
|
| it('handles empty clients map', async () => { |
| let listener: ((clients?: Map<string, McpClient>) => void) | undefined; |
| onSpy.mockImplementation((event: unknown, fn: unknown) => { |
| if (event === CoreEvent.McpClientUpdate) { |
| listener = fn as (clients?: Map<string, McpClient>) => void; |
| } |
| return coreEvents; |
| }); |
|
|
| const { lastFrame } = await renderWithProviders(<ConfigInitDisplay />); |
|
|
| await waitFor(() => { |
| if (!listener) throw new Error('Listener not registered yet'); |
| }); |
|
|
| if (listener) { |
| const safeListener = listener; |
| act(() => { |
| safeListener(new Map()); |
| }); |
| } |
|
|
| await waitFor(() => { |
| expect(lastFrame()).toMatchSnapshot(); |
| }); |
| }); |
| }); |
|
|