Revamp KeypressContext (#12746)

This commit is contained in:
Tommaso Sciortino
2025-11-09 08:45:04 -08:00
committed by GitHub
parent f649948713
commit 9e4ae214a8
16 changed files with 891 additions and 1660 deletions
@@ -1297,7 +1297,6 @@ describe('InputPrompt', () => {
const { stdin, unmount } = renderWithProviders(
<InputPrompt {...props} />,
{ kittyProtocolEnabled: true },
);
await act(async () => {
await vi.runAllTimersAsync();
@@ -1352,6 +1351,9 @@ describe('InputPrompt', () => {
});
describe('enhanced input UX - double ESC clear functionality', () => {
beforeEach(() => vi.useFakeTimers());
afterEach(() => vi.useRealTimers());
it('should clear buffer on second ESC press', async () => {
const onEscapePromptChange = vi.fn();
props.onEscapePromptChange = onEscapePromptChange;
@@ -1359,22 +1361,40 @@ describe('InputPrompt', () => {
const { stdin, unmount } = renderWithProviders(
<InputPrompt {...props} />,
{ kittyProtocolEnabled: false },
);
await act(async () => {
stdin.write('\x1B');
await waitFor(() => {
expect(onEscapePromptChange).toHaveBeenCalledWith(false);
});
vi.advanceTimersByTime(100);
expect(onEscapePromptChange).toHaveBeenCalledWith(false);
});
await act(async () => {
stdin.write('\x1B');
await waitFor(() => {
expect(props.buffer.setText).toHaveBeenCalledWith('');
expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
});
vi.advanceTimersByTime(100);
expect(props.buffer.setText).toHaveBeenCalledWith('');
expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
});
unmount();
});
it('should clear buffer on double ESC', async () => {
const onEscapePromptChange = vi.fn();
props.onEscapePromptChange = onEscapePromptChange;
props.buffer.setText('text to clear');
const { stdin, unmount } = renderWithProviders(
<InputPrompt {...props} />,
);
await act(async () => {
stdin.write('\x1B\x1B');
vi.advanceTimersByTime(100);
expect(props.buffer.setText).toHaveBeenCalledWith('');
expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
});
unmount();
});
@@ -1386,7 +1406,6 @@ describe('InputPrompt', () => {
const { stdin, unmount } = renderWithProviders(
<InputPrompt {...props} />,
{ kittyProtocolEnabled: false },
);
await act(async () => {
@@ -1410,14 +1429,13 @@ describe('InputPrompt', () => {
const { stdin, unmount } = renderWithProviders(
<InputPrompt {...props} />,
{ kittyProtocolEnabled: false },
);
await act(async () => {
stdin.write('\x1B');
await waitFor(() =>
expect(props.setShellModeActive).toHaveBeenCalledWith(false),
);
vi.advanceTimersByTime(100);
expect(props.setShellModeActive).toHaveBeenCalledWith(false);
});
unmount();
});
@@ -1431,26 +1449,23 @@ describe('InputPrompt', () => {
const { stdin, unmount } = renderWithProviders(
<InputPrompt {...props} />,
{ kittyProtocolEnabled: false },
);
await act(async () => {
stdin.write('\x1B');
vi.advanceTimersByTime(100);
expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
});
await waitFor(() =>
expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled(),
);
unmount();
});
it('should not call onEscapePromptChange when not provided', async () => {
vi.useFakeTimers();
props.onEscapePromptChange = undefined;
props.buffer.setText('some text');
const { stdin, unmount } = renderWithProviders(
<InputPrompt {...props} />,
{ kittyProtocolEnabled: false },
);
await act(async () => {
await vi.runAllTimersAsync();
@@ -1463,14 +1478,12 @@ describe('InputPrompt', () => {
await vi.runAllTimersAsync();
});
vi.useRealTimers();
unmount();
});
it('should not interfere with existing keyboard shortcuts', async () => {
const { stdin, unmount } = renderWithProviders(
<InputPrompt {...props} />,
{ kittyProtocolEnabled: false },
);
await act(async () => {
@@ -1535,18 +1548,13 @@ describe('InputPrompt', () => {
});
it.each([
{ name: 'standard', kittyProtocolEnabled: false, escapeSequence: '\x1B' },
{
name: 'kitty',
kittyProtocolEnabled: true,
escapeSequence: '\u001b[27u',
},
{ name: 'standard', escapeSequence: '\x1B' },
{ name: 'kitty', escapeSequence: '\u001b[27u' },
])(
'resets reverse search state on Escape ($name)',
async ({ kittyProtocolEnabled, escapeSequence }) => {
async ({ escapeSequence }) => {
const { stdin, stdout, unmount } = renderWithProviders(
<InputPrompt {...props} />,
{ kittyProtocolEnabled },
);
await act(async () => {
@@ -234,7 +234,7 @@ const renderDialog = (
},
) =>
render(
<KeypressProvider kittyProtocolEnabled={false}>
<KeypressProvider>
<SettingsDialog
settings={settings}
onSelect={onSelect}
@@ -679,7 +679,7 @@ describe('SettingsDialog', () => {
const { stdin, unmount } = render(
<VimModeProvider settings={settings}>
<KeypressProvider kittyProtocolEnabled={false}>
<KeypressProvider>
<SettingsDialog settings={settings} onSelect={onSelect} />
</KeypressProvider>
</VimModeProvider>,
@@ -1062,7 +1062,7 @@ describe('SettingsDialog', () => {
const onSelect = vi.fn();
const { stdin, unmount, rerender } = render(
<KeypressProvider kittyProtocolEnabled={false}>
<KeypressProvider>
<SettingsDialog settings={settings} onSelect={onSelect} />
</KeypressProvider>,
);
@@ -1087,7 +1087,7 @@ describe('SettingsDialog', () => {
{},
);
rerender(
<KeypressProvider kittyProtocolEnabled={false}>
<KeypressProvider>
<SettingsDialog settings={settings} onSelect={onSelect} />
</KeypressProvider>,
);
@@ -78,7 +78,7 @@ describe('ThemeDialog Snapshots', () => {
const settings = createMockSettings();
const { lastFrame } = render(
<SettingsContext.Provider value={settings}>
<KeypressProvider kittyProtocolEnabled={false}>
<KeypressProvider>
<ThemeDialog {...baseProps} settings={settings} />
</KeypressProvider>
</SettingsContext.Provider>,
@@ -91,7 +91,7 @@ describe('ThemeDialog Snapshots', () => {
const settings = createMockSettings();
const { lastFrame, stdin } = render(
<SettingsContext.Provider value={settings}>
<KeypressProvider kittyProtocolEnabled={false}>
<KeypressProvider>
<ThemeDialog {...baseProps} settings={settings} />
</KeypressProvider>
</SettingsContext.Provider>,
@@ -113,7 +113,7 @@ describe('ThemeDialog Snapshots', () => {
const settings = createMockSettings();
const { stdin } = render(
<SettingsContext.Provider value={settings}>
<KeypressProvider kittyProtocolEnabled={false}>
<KeypressProvider>
<ThemeDialog
{...baseProps}
onCancel={mockOnCancel}
@@ -78,7 +78,7 @@ const TestComponent = ({
return (
<MouseProvider mouseEventsEnabled={false}>
<KeypressProvider kittyProtocolEnabled={false}>
<KeypressProvider>
<ScrollProvider>
<Box flexDirection="column" width={80} height={24} padding={1}>
<Box flexGrow={1} borderStyle="round" borderColor="cyan">