feat(ui): Show waiting MCP servers in ConfigInitDisplay (#13721)

This commit is contained in:
Andrew Garrett
2025-11-27 11:26:44 +11:00
committed by GitHub
parent 5bed97064a
commit 5949d56370
3 changed files with 64 additions and 7 deletions

View File

@@ -6,6 +6,7 @@
import { act } from 'react';
import { render } from '../../test-utils/render.js';
import { waitFor } from '../../test-utils/async.js';
import { ConfigInitDisplay } from './ConfigInitDisplay.js';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { AppEvent } from '../../utils/events.js';
@@ -63,7 +64,7 @@ describe('ConfigInitDisplay', () => {
const { lastFrame } = render(<ConfigInitDisplay />);
// Wait for listener to be registered
await vi.waitFor(() => {
await waitFor(() => {
if (!listener) throw new Error('Listener not registered yet');
});
@@ -84,7 +85,42 @@ describe('ConfigInitDisplay', () => {
});
// Wait for the UI to update
await vi.waitFor(() => {
await waitFor(() => {
expect(lastFrame()).toMatchSnapshot();
});
});
it('truncates list of waiting servers if too many', async () => {
let listener: ((clients?: Map<string, McpClient>) => void) | undefined;
mockOn.mockImplementation((event, fn) => {
if (event === AppEvent.McpClientUpdate) {
listener = fn;
}
});
const { lastFrame } = render(<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();
});
});
@@ -99,7 +135,7 @@ describe('ConfigInitDisplay', () => {
const { lastFrame } = render(<ConfigInitDisplay />);
await vi.waitFor(() => {
await waitFor(() => {
if (!listener) throw new Error('Listener not registered yet');
});
@@ -110,7 +146,7 @@ describe('ConfigInitDisplay', () => {
});
}
await vi.waitFor(() => {
await waitFor(() => {
expect(lastFrame()).toMatchSnapshot();
});
});

View File

@@ -21,12 +21,28 @@ export const ConfigInitDisplay = () => {
return;
}
let connected = 0;
for (const client of clients.values()) {
const connecting: string[] = [];
for (const [name, client] of clients.entries()) {
if (client.getStatus() === MCPServerStatus.CONNECTED) {
connected++;
} else {
connecting.push(name);
}
}
setMessage(`Connecting to MCP servers... (${connected}/${clients.size})`);
if (connecting.length > 0) {
const maxDisplay = 3;
const displayedServers = connecting.slice(0, maxDisplay).join(', ');
const remaining = connecting.length - maxDisplay;
const suffix = remaining > 0 ? `, +${remaining} more` : '';
setMessage(
`Connecting to MCP servers... (${connected}/${clients.size}) - Waiting for: ${displayedServers}${suffix}`,
);
} else {
setMessage(
`Connecting to MCP servers... (${connected}/${clients.size})`,
);
}
};
appEvents.on(AppEvent.McpClientUpdate, onChange);

View File

@@ -10,7 +10,12 @@ exports[`ConfigInitDisplay > renders initial state 1`] = `
Spinner Initializing..."
`;
exports[`ConfigInitDisplay > truncates list of waiting servers if too many 1`] = `
"
Spinner Connecting to MCP servers... (0/5) - Waiting for: s1, s2, s3, +2 more"
`;
exports[`ConfigInitDisplay > updates message on McpClientUpdate event 1`] = `
"
Spinner Connecting to MCP servers... (1/2)"
Spinner Connecting to MCP servers... (1/2) - Waiting for: server2"
`;