Resolve arrow key navigation conflict between history and completion

This commit is contained in:
Alexander Farber 2026-01-16 22:41:01 +01:00
parent 0681c71894
commit 0901b228a7
No known key found for this signature in database
5 changed files with 79 additions and 23 deletions

View file

@ -278,7 +278,7 @@ describe('InputPrompt', () => {
unmount();
});
it('should call completion.navigateUp for both up arrow and Ctrl+P when suggestions are showing', async () => {
it('should call completion.navigateUp for up arrow when suggestions are showing', async () => {
mockedUseCommandCompletion.mockReturnValue({
...mockCommandCompletion,
showSuggestions: true,
@ -293,19 +293,22 @@ describe('InputPrompt', () => {
const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
// Test up arrow
// Test up arrow for completion navigation
stdin.write('\u001B[A'); // Up arrow
await wait();
expect(mockCommandCompletion.navigateUp).toHaveBeenCalledTimes(1);
expect(mockCommandCompletion.navigateDown).not.toHaveBeenCalled();
// Ctrl+P should navigate history, not completion
stdin.write('\u0010'); // Ctrl+P
await wait();
expect(mockCommandCompletion.navigateUp).toHaveBeenCalledTimes(2);
expect(mockCommandCompletion.navigateDown).not.toHaveBeenCalled();
expect(mockCommandCompletion.navigateUp).toHaveBeenCalledTimes(1);
expect(mockInputHistory.navigateUp).toHaveBeenCalled();
unmount();
});
it('should call completion.navigateDown for both down arrow and Ctrl+N when suggestions are showing', async () => {
it('should call completion.navigateDown for down arrow when suggestions are showing', async () => {
mockedUseCommandCompletion.mockReturnValue({
...mockCommandCompletion,
showSuggestions: true,
@ -319,14 +322,17 @@ describe('InputPrompt', () => {
const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
// Test down arrow
// Test down arrow for completion navigation
stdin.write('\u001B[B'); // Down arrow
await wait();
expect(mockCommandCompletion.navigateDown).toHaveBeenCalledTimes(1);
expect(mockCommandCompletion.navigateUp).not.toHaveBeenCalled();
// Ctrl+N should navigate history, not completion
stdin.write('\u000E'); // Ctrl+N
await wait();
expect(mockCommandCompletion.navigateDown).toHaveBeenCalledTimes(2);
expect(mockCommandCompletion.navigateUp).not.toHaveBeenCalled();
expect(mockCommandCompletion.navigateDown).toHaveBeenCalledTimes(1);
expect(mockInputHistory.navigateDown).toHaveBeenCalled();
unmount();
});
@ -764,6 +770,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -791,6 +799,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -818,6 +828,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -845,6 +857,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -872,6 +886,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -900,6 +916,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -927,6 +945,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -955,6 +975,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -983,6 +1005,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -1011,6 +1035,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -1039,6 +1065,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -1069,6 +1097,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -1097,6 +1127,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();
@ -1127,6 +1159,8 @@ describe('InputPrompt', () => {
mockCommandContext,
false,
expect.any(Object),
// active parameter: completion enabled when not just navigated history
true,
);
unmount();