diff options
Diffstat (limited to 'packages/cli/src/ui/hooks/useGeminiStream.test.tsx')
| -rw-r--r-- | packages/cli/src/ui/hooks/useGeminiStream.test.tsx | 110 |
1 files changed, 39 insertions, 71 deletions
diff --git a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx index 6a41234b..3a002919 100644 --- a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx +++ b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx @@ -19,7 +19,12 @@ import { import { Config, EditorType, AuthType } from '@google/gemini-cli-core'; import { Part, PartListUnion } from '@google/genai'; import { UseHistoryManagerReturn } from './useHistoryManager.js'; -import { HistoryItem, MessageType, StreamingState } from '../types.js'; +import { + HistoryItem, + MessageType, + SlashCommandProcessorResult, + StreamingState, +} from '../types.js'; import { Dispatch, SetStateAction } from 'react'; import { LoadedSettings } from '../../config/settings.js'; @@ -360,10 +365,7 @@ describe('useGeminiStream', () => { onDebugMessage: (message: string) => void; handleSlashCommand: ( cmd: PartListUnion, - ) => Promise< - | import('./slashCommandProcessor.js').SlashCommandActionReturn - | boolean - >; + ) => Promise<SlashCommandProcessorResult | false>; shellModeActive: boolean; loadedSettings: LoadedSettings; toolCalls?: TrackedToolCall[]; // Allow passing updated toolCalls @@ -396,10 +398,7 @@ describe('useGeminiStream', () => { onDebugMessage: mockOnDebugMessage, handleSlashCommand: mockHandleSlashCommand as unknown as ( cmd: PartListUnion, - ) => Promise< - | import('./slashCommandProcessor.js').SlashCommandActionReturn - | boolean - >, + ) => Promise<SlashCommandProcessorResult | false>, shellModeActive: false, loadedSettings: mockLoadedSettings, toolCalls: initialToolCalls, @@ -966,83 +965,52 @@ describe('useGeminiStream', () => { }); }); - describe('Client-Initiated Tool Calls', () => { - it('should execute a client-initiated tool without sending a response to Gemini', async () => { - const clientToolRequest = { - shouldScheduleTool: true, + describe('Slash Command Handling', () => { + it('should schedule a tool call when the command processor returns a schedule_tool action', async () => { + const clientToolRequest: SlashCommandProcessorResult = { + type: 'schedule_tool', toolName: 'save_memory', toolArgs: { fact: 'test fact' }, }; mockHandleSlashCommand.mockResolvedValue(clientToolRequest); - const completedToolCall: TrackedCompletedToolCall = { - request: { - callId: 'client-call-1', - name: clientToolRequest.toolName, - args: clientToolRequest.toolArgs, - isClientInitiated: true, - }, - status: 'success', - responseSubmittedToGemini: false, - response: { - callId: 'client-call-1', - responseParts: [{ text: 'Memory saved' }], - resultDisplay: 'Success: Memory saved', - error: undefined, - }, - tool: { - name: clientToolRequest.toolName, - description: 'Saves memory', - getDescription: vi.fn(), - } as any, - }; + const { result } = renderTestHook(); - // Capture the onComplete callback - let capturedOnComplete: - | ((completedTools: TrackedToolCall[]) => Promise<void>) - | null = null; + await act(async () => { + await result.current.submitQuery('/memory add "test fact"'); + }); - mockUseReactToolScheduler.mockImplementation((onComplete) => { - capturedOnComplete = onComplete; - return [[], mockScheduleToolCalls, mockMarkToolsAsSubmitted]; + await waitFor(() => { + expect(mockScheduleToolCalls).toHaveBeenCalledWith( + [ + expect.objectContaining({ + name: 'save_memory', + args: { fact: 'test fact' }, + isClientInitiated: true, + }), + ], + expect.any(AbortSignal), + ); + expect(mockSendMessageStream).not.toHaveBeenCalled(); }); + }); - const { result } = renderHook(() => - useGeminiStream( - new MockedGeminiClientClass(mockConfig), - [], - mockAddItem, - mockSetShowHelp, - mockConfig, - mockOnDebugMessage, - mockHandleSlashCommand, - false, - () => 'vscode' as EditorType, - () => {}, - () => Promise.resolve(), - ), - ); + it('should stop processing and not call Gemini when a command is handled without a tool call', async () => { + const uiOnlyCommandResult: SlashCommandProcessorResult = { + type: 'handled', + }; + mockHandleSlashCommand.mockResolvedValue(uiOnlyCommandResult); - // --- User runs the slash command --- - await act(async () => { - await result.current.submitQuery('/memory add "test fact"'); - }); + const { result } = renderTestHook(); - // Trigger the onComplete callback with the completed client-initiated tool await act(async () => { - if (capturedOnComplete) { - await capturedOnComplete([completedToolCall]); - } + await result.current.submitQuery('/help'); }); - // --- Assert the outcome --- await waitFor(() => { - // The tool should be marked as submitted locally - expect(mockMarkToolsAsSubmitted).toHaveBeenCalledWith([ - 'client-call-1', - ]); - // Crucially, no message should be sent to the Gemini API - expect(mockSendMessageStream).not.toHaveBeenCalled(); + expect(mockHandleSlashCommand).toHaveBeenCalledWith('/help'); + expect(mockScheduleToolCalls).not.toHaveBeenCalled(); + expect(mockSendMessageStream).not.toHaveBeenCalled(); // No LLM call made }); }); }); |
