diff options
Diffstat (limited to 'packages/cli/src/ui/components')
| -rw-r--r-- | packages/cli/src/ui/components/InputPrompt.test.tsx | 33 | ||||
| -rw-r--r-- | packages/cli/src/ui/components/InputPrompt.tsx | 8 |
2 files changed, 24 insertions, 17 deletions
diff --git a/packages/cli/src/ui/components/InputPrompt.test.tsx b/packages/cli/src/ui/components/InputPrompt.test.tsx index e1d68125..1a100c36 100644 --- a/packages/cli/src/ui/components/InputPrompt.test.tsx +++ b/packages/cli/src/ui/components/InputPrompt.test.tsx @@ -9,7 +9,7 @@ import { InputPrompt, InputPromptProps } from './InputPrompt.js'; import type { TextBuffer } from './shared/text-buffer.js'; import { Config } from '@google/gemini-cli-core'; import { CommandContext, SlashCommand } from '../commands/types.js'; -import { vi } from 'vitest'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; import { useShellHistory } from '../hooks/useShellHistory.js'; import { useCompletion } from '../hooks/useCompletion.js'; import { useInputHistory } from '../hooks/useInputHistory.js'; @@ -341,7 +341,7 @@ describe('InputPrompt', () => { }); }); - it('should complete a partial parent command and add a space', async () => { + it('should complete a partial parent command', async () => { // SCENARIO: /mem -> Tab mockedUseCompletion.mockReturnValue({ ...mockCompletion, @@ -357,12 +357,12 @@ describe('InputPrompt', () => { stdin.write('\t'); // Press Tab await wait(); - expect(props.buffer.setText).toHaveBeenCalledWith('/memory '); + expect(props.buffer.setText).toHaveBeenCalledWith('/memory'); unmount(); }); - it('should append a sub-command when the parent command is already complete with a space', async () => { - // SCENARIO: /memory -> Tab (to accept 'add') + it('should append a sub-command when the parent command is already complete', async () => { + // SCENARIO: /memory -> Tab (to accept 'add') mockedUseCompletion.mockReturnValue({ ...mockCompletion, showSuggestions: true, @@ -380,13 +380,12 @@ describe('InputPrompt', () => { stdin.write('\t'); // Press Tab await wait(); - expect(props.buffer.setText).toHaveBeenCalledWith('/memory add '); + expect(props.buffer.setText).toHaveBeenCalledWith('/memory add'); unmount(); }); it('should handle the "backspace" edge case correctly', async () => { - // SCENARIO: /memory -> Backspace -> /memory -> Tab (to accept 'show') - // This is the critical bug we fixed. + // SCENARIO: /memory -> Backspace -> /memory -> Tab (to accept 'show') mockedUseCompletion.mockReturnValue({ ...mockCompletion, showSuggestions: true, @@ -405,8 +404,8 @@ describe('InputPrompt', () => { stdin.write('\t'); // Press Tab await wait(); - // It should NOT become '/show '. It should correctly become '/memory show '. - expect(props.buffer.setText).toHaveBeenCalledWith('/memory show '); + // It should NOT become '/show'. It should correctly become '/memory show'. + expect(props.buffer.setText).toHaveBeenCalledWith('/memory show'); unmount(); }); @@ -426,7 +425,7 @@ describe('InputPrompt', () => { stdin.write('\t'); // Press Tab await wait(); - expect(props.buffer.setText).toHaveBeenCalledWith('/chat resume fix-foo '); + expect(props.buffer.setText).toHaveBeenCalledWith('/chat resume fix-foo'); unmount(); }); @@ -446,7 +445,7 @@ describe('InputPrompt', () => { await wait(); // The app should autocomplete the text, NOT submit. - expect(props.buffer.setText).toHaveBeenCalledWith('/memory '); + expect(props.buffer.setText).toHaveBeenCalledWith('/memory'); expect(props.onSubmit).not.toHaveBeenCalled(); unmount(); @@ -471,10 +470,10 @@ describe('InputPrompt', () => { const { stdin, unmount } = render(<InputPrompt {...props} />); await wait(); - stdin.write('\t'); // Press Tab + stdin.write('\t'); // Press Tab for autocomplete await wait(); - expect(props.buffer.setText).toHaveBeenCalledWith('/help '); + expect(props.buffer.setText).toHaveBeenCalledWith('/help'); unmount(); }); @@ -505,7 +504,6 @@ describe('InputPrompt', () => { await wait(); expect(props.onSubmit).toHaveBeenCalledWith('/clear'); - expect(props.buffer.setText).not.toHaveBeenCalledWith('/clear '); unmount(); }); @@ -530,7 +528,10 @@ describe('InputPrompt', () => { }); it('should add a newline on enter when the line ends with a backslash', async () => { - props.buffer.setText('first line\\'); + // This test simulates multi-line input, not submission + mockBuffer.text = 'first line\\'; + mockBuffer.cursor = [0, 11]; + mockBuffer.lines = ['first line\\']; const { stdin, unmount } = render(<InputPrompt {...props} />); await wait(); diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx index 01ed8db1..4d66b10c 100644 --- a/packages/cli/src/ui/components/InputPrompt.tsx +++ b/packages/cli/src/ui/components/InputPrompt.tsx @@ -162,7 +162,7 @@ export const InputPrompt: React.FC<InputPromptProps> = ({ // - Otherwise, the base is everything EXCEPT the last partial part. const basePath = hasTrailingSpace || isParentPath ? parts : parts.slice(0, -1); - const newValue = `/${[...basePath, suggestion].join(' ')} `; + const newValue = `/${[...basePath, suggestion].join(' ')}`; buffer.setText(newValue); } else { @@ -266,6 +266,12 @@ export const InputPrompt: React.FC<InputPromptProps> = ({ return; } + // If the command is a perfect match, pressing enter should execute it. + if (completion.isPerfectMatch && key.name === 'return') { + handleSubmitAndClear(buffer.text); + return; + } + if (completion.showSuggestions) { if (completion.suggestions.length > 1) { if (key.name === 'up') { |
