diff options
| author | Sandy Tao <[email protected]> | 2025-07-24 21:41:35 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-07-25 04:41:35 +0000 |
| commit | 1d7eb0d25078f34b37a0cbd8a6a869d3e61a2602 (patch) | |
| tree | 189320acd768328061c30d6e7abe5458d015e2c8 /packages/cli/src/ui/components/InputPrompt.test.tsx | |
| parent | 273e74c09da89492d16fc076cfbff4d043eafa4c (diff) | |
[Refactor] Centralizes autocompletion logic within useCompletion (#4740)
Diffstat (limited to 'packages/cli/src/ui/components/InputPrompt.test.tsx')
| -rw-r--r-- | packages/cli/src/ui/components/InputPrompt.test.tsx | 91 |
1 files changed, 54 insertions, 37 deletions
diff --git a/packages/cli/src/ui/components/InputPrompt.test.tsx b/packages/cli/src/ui/components/InputPrompt.test.tsx index bad29f10..a1894002 100644 --- a/packages/cli/src/ui/components/InputPrompt.test.tsx +++ b/packages/cli/src/ui/components/InputPrompt.test.tsx @@ -121,6 +121,15 @@ describe('InputPrompt', () => { openInExternalEditor: vi.fn(), newline: vi.fn(), backspace: vi.fn(), + preferredCol: null, + selectionAnchor: null, + insert: vi.fn(), + del: vi.fn(), + undo: vi.fn(), + redo: vi.fn(), + replaceRange: vi.fn(), + deleteWordLeft: vi.fn(), + deleteWordRight: vi.fn(), } as unknown as TextBuffer; mockShellHistory = { @@ -137,12 +146,14 @@ describe('InputPrompt', () => { isLoadingSuggestions: false, showSuggestions: false, visibleStartIndex: 0, + isPerfectMatch: false, navigateUp: vi.fn(), navigateDown: vi.fn(), resetCompletionState: vi.fn(), setActiveSuggestionIndex: vi.fn(), setShowSuggestions: vi.fn(), - } as unknown as UseCompletionReturn; + handleAutocomplete: vi.fn(), + }; mockedUseCompletion.mockReturnValue(mockCompletion); mockInputHistory = { @@ -465,7 +476,7 @@ describe('InputPrompt', () => { stdin.write('\t'); // Press Tab await wait(); - expect(props.buffer.setText).toHaveBeenCalledWith('/memory'); + expect(mockCompletion.handleAutocomplete).toHaveBeenCalledWith(0); unmount(); }); @@ -488,7 +499,7 @@ describe('InputPrompt', () => { stdin.write('\t'); // Press Tab await wait(); - expect(props.buffer.setText).toHaveBeenCalledWith('/memory add'); + expect(mockCompletion.handleAutocomplete).toHaveBeenCalledWith(1); unmount(); }); @@ -513,7 +524,7 @@ describe('InputPrompt', () => { await wait(); // It should NOT become '/show'. It should correctly become '/memory show'. - expect(props.buffer.setText).toHaveBeenCalledWith('/memory show'); + expect(mockCompletion.handleAutocomplete).toHaveBeenCalledWith(0); unmount(); }); @@ -533,7 +544,7 @@ describe('InputPrompt', () => { stdin.write('\t'); // Press Tab await wait(); - expect(props.buffer.setText).toHaveBeenCalledWith('/chat resume fix-foo'); + expect(mockCompletion.handleAutocomplete).toHaveBeenCalledWith(0); unmount(); }); @@ -553,7 +564,7 @@ describe('InputPrompt', () => { await wait(); // The app should autocomplete the text, NOT submit. - expect(props.buffer.setText).toHaveBeenCalledWith('/memory'); + expect(mockCompletion.handleAutocomplete).toHaveBeenCalledWith(0); expect(props.onSubmit).not.toHaveBeenCalled(); unmount(); @@ -583,7 +594,7 @@ describe('InputPrompt', () => { stdin.write('\t'); // Press Tab for autocomplete await wait(); - expect(props.buffer.setText).toHaveBeenCalledWith('/help'); + expect(mockCompletion.handleAutocomplete).toHaveBeenCalledWith(0); unmount(); }); @@ -600,10 +611,29 @@ describe('InputPrompt', () => { unmount(); }); + it('should submit directly on Enter when isPerfectMatch is true', async () => { + mockedUseCompletion.mockReturnValue({ + ...mockCompletion, + showSuggestions: false, + isPerfectMatch: true, + }); + props.buffer.setText('/clear'); + + const { stdin, unmount } = render(<InputPrompt {...props} />); + await wait(); + + stdin.write('\r'); + await wait(); + + expect(props.onSubmit).toHaveBeenCalledWith('/clear'); + unmount(); + }); + it('should submit directly on Enter when a complete leaf command is typed', async () => { mockedUseCompletion.mockReturnValue({ ...mockCompletion, showSuggestions: false, + isPerfectMatch: false, // Added explicit isPerfectMatch false }); props.buffer.setText('/clear'); @@ -632,7 +662,7 @@ describe('InputPrompt', () => { stdin.write('\r'); await wait(); - expect(props.buffer.replaceRangeByOffset).toHaveBeenCalled(); + expect(mockCompletion.handleAutocomplete).toHaveBeenCalledWith(0); expect(props.onSubmit).not.toHaveBeenCalled(); unmount(); }); @@ -697,11 +727,10 @@ describe('InputPrompt', () => { const { unmount } = render(<InputPrompt {...props} />); await wait(); - // Verify useCompletion was called with true (should show completion) + // Verify useCompletion was called with correct signature expect(mockedUseCompletion).toHaveBeenCalledWith( - '@src/components', + mockBuffer, path.join('test', 'project', 'src'), - true, // shouldShowCompletion should be true mockSlashCommands, mockCommandContext, expect.any(Object), @@ -725,9 +754,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - '/memory', + mockBuffer, path.join('test', 'project', 'src'), - true, // shouldShowCompletion should be true mockSlashCommands, mockCommandContext, expect.any(Object), @@ -751,9 +779,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - '@src/file.ts hello', + mockBuffer, path.join('test', 'project', 'src'), - false, // shouldShowCompletion should be false mockSlashCommands, mockCommandContext, expect.any(Object), @@ -777,9 +804,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - '/memory add', + mockBuffer, path.join('test', 'project', 'src'), - false, // shouldShowCompletion should be false mockSlashCommands, mockCommandContext, expect.any(Object), @@ -803,9 +829,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - 'hello world', + mockBuffer, path.join('test', 'project', 'src'), - false, // shouldShowCompletion should be false mockSlashCommands, mockCommandContext, expect.any(Object), @@ -828,10 +853,10 @@ describe('InputPrompt', () => { const { unmount } = render(<InputPrompt {...props} />); await wait(); + // Verify useCompletion was called with the buffer expect(mockedUseCompletion).toHaveBeenCalledWith( - 'first line\n/memory', + mockBuffer, path.join('test', 'project', 'src'), - false, // shouldShowCompletion should be false (isSlashCommand returns false because text doesn't start with /) mockSlashCommands, mockCommandContext, expect.any(Object), @@ -855,9 +880,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - '/memory', + mockBuffer, path.join('test', 'project', 'src'), - true, // shouldShowCompletion should be true (isSlashCommand returns true AND cursor is after / without space) mockSlashCommands, mockCommandContext, expect.any(Object), @@ -882,9 +906,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - '@src/file๐.txt', + mockBuffer, path.join('test', 'project', 'src'), - true, // shouldShowCompletion should be true mockSlashCommands, mockCommandContext, expect.any(Object), @@ -909,9 +932,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - '@src/file๐.txt hello', + mockBuffer, path.join('test', 'project', 'src'), - false, // shouldShowCompletion should be false mockSlashCommands, mockCommandContext, expect.any(Object), @@ -936,9 +958,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - '@src/my\\ file.txt', + mockBuffer, path.join('test', 'project', 'src'), - true, // shouldShowCompletion should be true mockSlashCommands, mockCommandContext, expect.any(Object), @@ -963,9 +984,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - '@path/my\\ file.txt hello', + mockBuffer, path.join('test', 'project', 'src'), - false, // shouldShowCompletion should be false mockSlashCommands, mockCommandContext, expect.any(Object), @@ -992,9 +1012,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - '@docs/my\\ long\\ file\\ name.md', + mockBuffer, path.join('test', 'project', 'src'), - true, // shouldShowCompletion should be true mockSlashCommands, mockCommandContext, expect.any(Object), @@ -1019,9 +1038,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - '/memory\\ test', + mockBuffer, path.join('test', 'project', 'src'), - true, // shouldShowCompletion should be true mockSlashCommands, mockCommandContext, expect.any(Object), @@ -1048,9 +1066,8 @@ describe('InputPrompt', () => { await wait(); expect(mockedUseCompletion).toHaveBeenCalledWith( - '@' + path.join('files', 'emoji\\ ๐\\ test.txt'), + mockBuffer, path.join('test', 'project', 'src'), - true, // shouldShowCompletion should be true mockSlashCommands, mockCommandContext, expect.any(Object), |
