diff options
| author | Bryan Morgan <[email protected]> | 2025-06-07 15:06:18 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-06-07 15:06:18 -0400 |
| commit | 28ff62e7b1b2191c5f5193314523f848a0f3dea5 (patch) | |
| tree | 6285889f556c2840031fde0180c4cd5a2817d135 /packages/cli/src/ui/hooks/slashCommandProcessor.test.ts | |
| parent | 6ea4479064a4275390ef96216f5d68bd27f65ae7 (diff) | |
Added /mcp command support and cleaned up broken tests (#817)
Diffstat (limited to 'packages/cli/src/ui/hooks/slashCommandProcessor.test.ts')
| -rw-r--r-- | packages/cli/src/ui/hooks/slashCommandProcessor.test.ts | 230 |
1 files changed, 223 insertions, 7 deletions
diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts index 1d33d218..5466e887 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts @@ -56,7 +56,11 @@ import { type SlashCommandActionReturn, } from './slashCommandProcessor.js'; import { MessageType } from '../types.js'; -import { type Config } from '@gemini-code/core'; +import { + type Config, + MCPServerStatus, + getMCPServerStatus, +} from '@gemini-code/core'; import * as ShowMemoryCommandModule from './useShowMemoryCommand.js'; import { GIT_COMMIT_INFO } from '../../generated/git-commit.js'; @@ -378,39 +382,54 @@ Add any other context about the problem here. expect(commandResult).toBe(true); }); - it('should display available tools when tools are found', async () => { - const mockTools = [{ name: 'tool1' }, { name: 'tool2' }]; + it('should display only Gemini CLI tools (filtering out MCP tools)', async () => { + // Create mock tools - some with serverName property (MCP tools) and some without (Gemini CLI tools) + const mockTools = [ + { name: 'tool1' }, + { name: 'tool2' }, + { name: 'mcp_tool1', serverName: 'mcp-server1' }, + { name: 'mcp_tool2', serverName: 'mcp-server1' }, + ]; + mockConfig = { ...mockConfig, getToolRegistry: vi.fn().mockResolvedValue({ getAllTools: vi.fn().mockReturnValue(mockTools), }), } as unknown as Config; + const { handleSlashCommand } = getProcessor(); let commandResult: SlashCommandActionReturn | boolean = false; await act(async () => { commandResult = handleSlashCommand('/tools'); }); + // Should only show tool1 and tool2, not the MCP tools expect(mockAddItem).toHaveBeenNthCalledWith( 2, expect.objectContaining({ type: MessageType.INFO, - text: 'Available tools:\n\ntool1\ntool2', + text: 'Available Gemini CLI tools:\n\ntool1\ntool2', }), expect.any(Number), ); expect(commandResult).toBe(true); }); - it('should display a message when no tools are available', async () => { - const mockTools: unknown[] = []; + it('should display a message when no Gemini CLI tools are available', async () => { + // Only MCP tools available + const mockTools = [ + { name: 'mcp_tool1', serverName: 'mcp-server1' }, + { name: 'mcp_tool2', serverName: 'mcp-server1' }, + ]; + mockConfig = { ...mockConfig, getToolRegistry: vi.fn().mockResolvedValue({ getAllTools: vi.fn().mockReturnValue(mockTools), }), } as unknown as Config; + const { handleSlashCommand } = getProcessor(); let commandResult: SlashCommandActionReturn | boolean = false; await act(async () => { @@ -421,10 +440,207 @@ Add any other context about the problem here. 2, expect.objectContaining({ type: MessageType.INFO, - text: 'Available tools:\n\n', + text: 'Available Gemini CLI tools:\n\n', + }), + expect.any(Number), + ); + expect(commandResult).toBe(true); + }); + }); + + describe('/mcp command', () => { + beforeEach(() => { + // Mock the core module with getMCPServerStatus + vi.mock('@gemini-code/core', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + MCPServerStatus: { + CONNECTED: 'connected', + CONNECTING: 'connecting', + DISCONNECTED: 'disconnected', + }, + getMCPServerStatus: vi.fn(), + }; + }); + }); + + it('should show an error if tool registry is not available', async () => { + mockConfig = { + ...mockConfig, + getToolRegistry: vi.fn().mockResolvedValue(undefined), + } as unknown as Config; + const { handleSlashCommand } = getProcessor(); + let commandResult: SlashCommandActionReturn | boolean = false; + await act(async () => { + commandResult = handleSlashCommand('/mcp'); + }); + + expect(mockAddItem).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + type: MessageType.ERROR, + text: 'Could not retrieve tool registry.', + }), + expect.any(Number), + ); + expect(commandResult).toBe(true); + }); + + it('should display a message when no MCP servers are configured', async () => { + mockConfig = { + ...mockConfig, + getToolRegistry: vi.fn().mockResolvedValue({ + getToolsByServer: vi.fn().mockReturnValue([]), + }), + getMcpServers: vi.fn().mockReturnValue({}), + } as unknown as Config; + + const { handleSlashCommand } = getProcessor(); + let commandResult: SlashCommandActionReturn | boolean = false; + await act(async () => { + commandResult = handleSlashCommand('/mcp'); + }); + + expect(mockAddItem).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + type: MessageType.INFO, + text: 'No MCP servers configured.', + }), + expect.any(Number), + ); + expect(commandResult).toBe(true); + }); + + it('should display configured MCP servers with status indicators and their tools', async () => { + // Mock MCP servers configuration + const mockMcpServers = { + server1: { command: 'cmd1' }, + server2: { command: 'cmd2' }, + server3: { command: 'cmd3' }, + }; + + // Setup getMCPServerStatus mock implementation + vi.mocked(getMCPServerStatus).mockImplementation((serverName) => { + if (serverName === 'server1') return MCPServerStatus.CONNECTED; + if (serverName === 'server2') return MCPServerStatus.CONNECTING; + return MCPServerStatus.DISCONNECTED; // Default for server3 and others + }); + + // Mock tools from each server + const mockServer1Tools = [ + { name: 'server1_tool1' }, + { name: 'server1_tool2' }, + ]; + + const mockServer2Tools = [{ name: 'server2_tool1' }]; + + const mockServer3Tools = [{ name: 'server3_tool1' }]; + + const mockGetToolsByServer = vi.fn().mockImplementation((serverName) => { + if (serverName === 'server1') return mockServer1Tools; + if (serverName === 'server2') return mockServer2Tools; + if (serverName === 'server3') return mockServer3Tools; + return []; + }); + + mockConfig = { + ...mockConfig, + getToolRegistry: vi.fn().mockResolvedValue({ + getToolsByServer: mockGetToolsByServer, + }), + getMcpServers: vi.fn().mockReturnValue(mockMcpServers), + } as unknown as Config; + + const { handleSlashCommand } = getProcessor(); + let commandResult: SlashCommandActionReturn | boolean = false; + await act(async () => { + commandResult = handleSlashCommand('/mcp'); + }); + + expect(mockAddItem).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + type: MessageType.INFO, + text: expect.stringContaining('Configured MCP servers and tools:'), }), expect.any(Number), ); + + // Check that the message contains details about both servers and their tools + const message = mockAddItem.mock.calls[1][0].text; + // Server 1 - Connected (green dot) + expect(message).toContain('🟢 server1 (2 tools):'); + expect(message).toContain('server1_tool1'); + expect(message).toContain('server1_tool2'); + + // Server 2 - Connecting (yellow dot) + expect(message).toContain('🟡 server2 (1 tools):'); + expect(message).toContain('server2_tool1'); + + // Server 3 - No status, should default to Disconnected (red dot) + expect(message).toContain('🔴 server3 (1 tools):'); + expect(message).toContain('server3_tool1'); + + expect(commandResult).toBe(true); + }); + + it('should indicate when a server has no tools', async () => { + // Mock MCP servers configuration + const mockMcpServers = { + server1: { command: 'cmd1' }, + server2: { command: 'cmd2' }, + }; + + // Setup getMCPServerStatus mock implementation + vi.mocked(getMCPServerStatus).mockImplementation((serverName) => { + if (serverName === 'server1') return MCPServerStatus.CONNECTED; + if (serverName === 'server2') return MCPServerStatus.DISCONNECTED; + return MCPServerStatus.DISCONNECTED; + }); + + // Mock tools from each server - server2 has no tools + const mockServer1Tools = [{ name: 'server1_tool1' }]; + + const mockServer2Tools = []; + + const mockGetToolsByServer = vi.fn().mockImplementation((serverName) => { + if (serverName === 'server1') return mockServer1Tools; + if (serverName === 'server2') return mockServer2Tools; + return []; + }); + + mockConfig = { + ...mockConfig, + getToolRegistry: vi.fn().mockResolvedValue({ + getToolsByServer: mockGetToolsByServer, + }), + getMcpServers: vi.fn().mockReturnValue(mockMcpServers), + } as unknown as Config; + + const { handleSlashCommand } = getProcessor(); + let commandResult: SlashCommandActionReturn | boolean = false; + await act(async () => { + commandResult = handleSlashCommand('/mcp'); + }); + + expect(mockAddItem).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + type: MessageType.INFO, + text: expect.stringContaining('Configured MCP servers and tools:'), + }), + expect.any(Number), + ); + + // Check that the message contains details about both servers and their tools + const message = mockAddItem.mock.calls[1][0].text; + expect(message).toContain('🟢 server1 (1 tools):'); + expect(message).toContain('server1_tool1'); + expect(message).toContain('🔴 server2 (0 tools):'); + expect(message).toContain('No tools available'); + expect(commandResult).toBe(true); }); }); |
