summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/components
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/ui/components')
-rw-r--r--packages/cli/src/ui/components/AuthDialog.test.tsx22
-rw-r--r--packages/cli/src/ui/components/FolderTrustDialog.test.tsx10
-rw-r--r--packages/cli/src/ui/components/InputPrompt.test.tsx156
-rw-r--r--packages/cli/src/ui/components/InputPrompt.tsx4
-rw-r--r--packages/cli/src/ui/components/SettingsDialog.test.tsx78
-rw-r--r--packages/cli/src/ui/components/ShellConfirmationDialog.test.tsx18
-rw-r--r--packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx6
-rw-r--r--packages/cli/src/ui/components/shared/RadioButtonSelect.test.tsx24
8 files changed, 184 insertions, 134 deletions
diff --git a/packages/cli/src/ui/components/AuthDialog.test.tsx b/packages/cli/src/ui/components/AuthDialog.test.tsx
index a8893215..3efc3c01 100644
--- a/packages/cli/src/ui/components/AuthDialog.test.tsx
+++ b/packages/cli/src/ui/components/AuthDialog.test.tsx
@@ -4,11 +4,11 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { render } from 'ink-testing-library';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { AuthDialog } from './AuthDialog.js';
import { LoadedSettings, SettingScope } from '../../config/settings.js';
import { AuthType } from '@google/gemini-cli-core';
+import { renderWithProviders } from '../../test-utils/render.js';
describe('AuthDialog', () => {
const wait = (ms = 50) => new Promise((resolve) => setTimeout(resolve, ms));
@@ -47,7 +47,7 @@ describe('AuthDialog', () => {
[],
);
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<AuthDialog
onSelect={() => {}}
settings={settings}
@@ -84,7 +84,7 @@ describe('AuthDialog', () => {
[],
);
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
@@ -117,7 +117,7 @@ describe('AuthDialog', () => {
[],
);
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
@@ -150,7 +150,7 @@ describe('AuthDialog', () => {
[],
);
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
@@ -184,7 +184,7 @@ describe('AuthDialog', () => {
[],
);
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
@@ -213,7 +213,7 @@ describe('AuthDialog', () => {
[],
);
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
@@ -244,7 +244,7 @@ describe('AuthDialog', () => {
[],
);
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<AuthDialog onSelect={() => {}} settings={settings} />,
);
@@ -279,7 +279,7 @@ describe('AuthDialog', () => {
[],
);
- const { lastFrame, stdin, unmount } = render(
+ const { lastFrame, stdin, unmount } = renderWithProviders(
<AuthDialog onSelect={onSelect} settings={settings} />,
);
await wait();
@@ -318,7 +318,7 @@ describe('AuthDialog', () => {
[],
);
- const { lastFrame, stdin, unmount } = render(
+ const { lastFrame, stdin, unmount } = renderWithProviders(
<AuthDialog
onSelect={onSelect}
settings={settings}
@@ -360,7 +360,7 @@ describe('AuthDialog', () => {
[],
);
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<AuthDialog onSelect={onSelect} settings={settings} />,
);
await wait();
diff --git a/packages/cli/src/ui/components/FolderTrustDialog.test.tsx b/packages/cli/src/ui/components/FolderTrustDialog.test.tsx
index d1be0b61..e2b695e2 100644
--- a/packages/cli/src/ui/components/FolderTrustDialog.test.tsx
+++ b/packages/cli/src/ui/components/FolderTrustDialog.test.tsx
@@ -4,14 +4,16 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { render } from 'ink-testing-library';
+import { renderWithProviders } from '../../test-utils/render.js';
import { waitFor } from '@testing-library/react';
import { vi } from 'vitest';
import { FolderTrustDialog, FolderTrustChoice } from './FolderTrustDialog.js';
describe('FolderTrustDialog', () => {
it('should render the dialog with title and description', () => {
- const { lastFrame } = render(<FolderTrustDialog onSelect={vi.fn()} />);
+ const { lastFrame } = renderWithProviders(
+ <FolderTrustDialog onSelect={vi.fn()} />,
+ );
expect(lastFrame()).toContain('Do you trust this folder?');
expect(lastFrame()).toContain(
@@ -21,7 +23,9 @@ describe('FolderTrustDialog', () => {
it('should call onSelect with DO_NOT_TRUST when escape is pressed', async () => {
const onSelect = vi.fn();
- const { stdin } = render(<FolderTrustDialog onSelect={onSelect} />);
+ const { stdin } = renderWithProviders(
+ <FolderTrustDialog onSelect={onSelect} />,
+ );
stdin.write('\x1b');
diff --git a/packages/cli/src/ui/components/InputPrompt.test.tsx b/packages/cli/src/ui/components/InputPrompt.test.tsx
index ec2d7441..a4aaf6e9 100644
--- a/packages/cli/src/ui/components/InputPrompt.test.tsx
+++ b/packages/cli/src/ui/components/InputPrompt.test.tsx
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { render } from 'ink-testing-library';
+import { renderWithProviders } from '../../test-utils/render.js';
import { waitFor } from '@testing-library/react';
import { InputPrompt, InputPromptProps } from './InputPrompt.js';
import type { TextBuffer } from './shared/text-buffer.js';
@@ -197,7 +197,7 @@ describe('InputPrompt', () => {
it('should call shellHistory.getPreviousCommand on up arrow in shell mode', async () => {
props.shellModeActive = true;
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\u001B[A');
@@ -209,7 +209,7 @@ describe('InputPrompt', () => {
it('should call shellHistory.getNextCommand on down arrow in shell mode', async () => {
props.shellModeActive = true;
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\u001B[B');
@@ -224,7 +224,7 @@ describe('InputPrompt', () => {
vi.mocked(mockShellHistory.getPreviousCommand).mockReturnValue(
'previous command',
);
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\u001B[A');
@@ -238,7 +238,7 @@ describe('InputPrompt', () => {
it('should call shellHistory.addCommandToHistory on submit in shell mode', async () => {
props.shellModeActive = true;
props.buffer.setText('ls -l');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\r');
@@ -251,7 +251,7 @@ describe('InputPrompt', () => {
it('should NOT call shell history methods when not in shell mode', async () => {
props.buffer.setText('some text');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\u001B[A'); // Up arrow
@@ -283,7 +283,7 @@ describe('InputPrompt', () => {
props.buffer.setText('/mem');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
// Test up arrow
@@ -309,7 +309,7 @@ describe('InputPrompt', () => {
});
props.buffer.setText('/mem');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
// Test down arrow
@@ -331,7 +331,7 @@ describe('InputPrompt', () => {
});
props.buffer.setText('some text');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\u001B[A'); // Up arrow
@@ -363,7 +363,9 @@ describe('InputPrompt', () => {
'/test/.gemini-clipboard/clipboard-123.png',
);
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
// Send Ctrl+V
@@ -384,7 +386,9 @@ describe('InputPrompt', () => {
it('should not insert anything when clipboard has no image', async () => {
vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x16'); // Ctrl+V
@@ -400,7 +404,9 @@ describe('InputPrompt', () => {
vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(true);
vi.mocked(clipboardUtils.saveClipboardImage).mockResolvedValue(null);
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x16'); // Ctrl+V
@@ -426,7 +432,9 @@ describe('InputPrompt', () => {
mockBuffer.lines = ['Hello world'];
mockBuffer.replaceRangeByOffset = vi.fn();
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x16'); // Ctrl+V
@@ -454,7 +462,9 @@ describe('InputPrompt', () => {
new Error('Clipboard error'),
);
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x16'); // Ctrl+V
@@ -481,7 +491,7 @@ describe('InputPrompt', () => {
});
props.buffer.setText('/mem');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\t'); // Press Tab
@@ -504,7 +514,7 @@ describe('InputPrompt', () => {
});
props.buffer.setText('/memory ');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\t'); // Press Tab
@@ -528,7 +538,7 @@ describe('InputPrompt', () => {
// The user has backspaced, so the query is now just '/memory'
props.buffer.setText('/memory');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\t'); // Press Tab
@@ -549,7 +559,7 @@ describe('InputPrompt', () => {
});
props.buffer.setText('/chat resume fi-');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\t'); // Press Tab
@@ -568,7 +578,7 @@ describe('InputPrompt', () => {
});
props.buffer.setText('/mem');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\r');
@@ -599,7 +609,7 @@ describe('InputPrompt', () => {
});
props.buffer.setText('/?');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\t'); // Press Tab for autocomplete
@@ -612,7 +622,7 @@ describe('InputPrompt', () => {
it('should not submit on Enter when the buffer is empty or only contains whitespace', async () => {
props.buffer.setText(' '); // Set buffer to whitespace
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\r'); // Press Enter
@@ -630,7 +640,7 @@ describe('InputPrompt', () => {
});
props.buffer.setText('/clear');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\r');
@@ -648,7 +658,7 @@ describe('InputPrompt', () => {
});
props.buffer.setText('/clear');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\r');
@@ -667,7 +677,7 @@ describe('InputPrompt', () => {
});
props.buffer.setText('@src/components/');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\r');
@@ -684,7 +694,7 @@ describe('InputPrompt', () => {
mockBuffer.cursor = [0, 11];
mockBuffer.lines = ['first line\\'];
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\r');
@@ -698,7 +708,7 @@ describe('InputPrompt', () => {
it('should clear the buffer on Ctrl+C if it has text', async () => {
props.buffer.setText('some text to clear');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\x03'); // Ctrl+C character
@@ -712,7 +722,7 @@ describe('InputPrompt', () => {
it('should NOT clear the buffer on Ctrl+C if it is empty', async () => {
props.buffer.text = '';
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
stdin.write('\x03'); // Ctrl+C character
@@ -735,7 +745,7 @@ describe('InputPrompt', () => {
suggestions: [{ label: 'Button.tsx', value: 'Button.tsx' }],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
// Verify useCompletion was called with correct signature
@@ -763,7 +773,7 @@ describe('InputPrompt', () => {
suggestions: [{ label: 'show', value: 'show' }],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -790,7 +800,7 @@ describe('InputPrompt', () => {
suggestions: [],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -817,7 +827,7 @@ describe('InputPrompt', () => {
suggestions: [],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -844,7 +854,7 @@ describe('InputPrompt', () => {
suggestions: [],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -871,7 +881,7 @@ describe('InputPrompt', () => {
suggestions: [],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
// Verify useCompletion was called with the buffer
@@ -899,7 +909,7 @@ describe('InputPrompt', () => {
suggestions: [{ label: 'show', value: 'show' }],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -927,7 +937,7 @@ describe('InputPrompt', () => {
suggestions: [{ label: 'file👍.txt', value: 'file👍.txt' }],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -955,7 +965,7 @@ describe('InputPrompt', () => {
suggestions: [],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -983,7 +993,7 @@ describe('InputPrompt', () => {
suggestions: [{ label: 'my file.txt', value: 'my file.txt' }],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -1011,7 +1021,7 @@ describe('InputPrompt', () => {
suggestions: [],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -1041,7 +1051,7 @@ describe('InputPrompt', () => {
],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -1069,7 +1079,7 @@ describe('InputPrompt', () => {
suggestions: [{ label: 'test-command', value: 'test-command' }],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -1099,7 +1109,7 @@ describe('InputPrompt', () => {
],
});
- const { unmount } = render(<InputPrompt {...props} />);
+ const { unmount } = renderWithProviders(<InputPrompt {...props} />);
await wait();
expect(mockedUseCommandCompletion).toHaveBeenCalledWith(
@@ -1120,7 +1130,9 @@ describe('InputPrompt', () => {
it('should not call buffer.handleInput when vim mode is enabled and vim handles the input', async () => {
props.vimModeEnabled = true;
props.vimHandleInput = vi.fn().mockReturnValue(true); // Mock that vim handled it.
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('i');
@@ -1134,7 +1146,9 @@ describe('InputPrompt', () => {
it('should call buffer.handleInput when vim mode is enabled but vim does not handle the input', async () => {
props.vimModeEnabled = true;
props.vimHandleInput = vi.fn().mockReturnValue(false); // Mock that vim did NOT handle it.
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('i');
@@ -1148,7 +1162,9 @@ describe('InputPrompt', () => {
it('should call handleInput when vim mode is disabled', async () => {
// Mock vimHandleInput to return false (vim didn't handle the input)
props.vimHandleInput = vi.fn().mockReturnValue(false);
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('i');
@@ -1163,7 +1179,9 @@ describe('InputPrompt', () => {
describe('unfocused paste', () => {
it('should handle bracketed paste when not focused', async () => {
props.focus = false;
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x1B[200~pasted text\x1B[201~');
@@ -1180,7 +1198,9 @@ describe('InputPrompt', () => {
it('should ignore regular keypresses when not focused', async () => {
props.focus = false;
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('a');
@@ -1197,7 +1217,9 @@ describe('InputPrompt', () => {
props.onEscapePromptChange = onEscapePromptChange;
props.buffer.setText('text to clear');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x1B');
@@ -1216,7 +1238,9 @@ describe('InputPrompt', () => {
props.onEscapePromptChange = onEscapePromptChange;
props.buffer.setText('some text');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
stdin.write('\x1B');
@@ -1235,7 +1259,9 @@ describe('InputPrompt', () => {
it('should handle ESC in shell mode by disabling shell mode', async () => {
props.shellModeActive = true;
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x1B');
@@ -1252,7 +1278,9 @@ describe('InputPrompt', () => {
suggestions: [{ label: 'suggestion', value: 'suggestion' }],
});
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x1B');
@@ -1266,7 +1294,9 @@ describe('InputPrompt', () => {
props.onEscapePromptChange = undefined;
props.buffer.setText('some text');
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x1B');
@@ -1276,7 +1306,9 @@ describe('InputPrompt', () => {
});
it('should not interfere with existing keyboard shortcuts', async () => {
- const { stdin, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x0C');
@@ -1306,7 +1338,9 @@ describe('InputPrompt', () => {
});
it('invokes reverse search on Ctrl+R', async () => {
- const { stdin, stdout, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, stdout, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x12');
@@ -1322,7 +1356,9 @@ describe('InputPrompt', () => {
});
it('resets reverse search state on Escape', async () => {
- const { stdin, stdout, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, stdout, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
await wait();
stdin.write('\x12');
@@ -1339,7 +1375,9 @@ describe('InputPrompt', () => {
});
it('completes the highlighted entry on Tab and exits reverse-search', async () => {
- const { stdin, stdout, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, stdout, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
stdin.write('\x12');
await wait();
stdin.write('\t');
@@ -1353,7 +1391,9 @@ describe('InputPrompt', () => {
});
it('submits the highlighted entry on Enter and exits reverse-search', async () => {
- const { stdin, stdout, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, stdout, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
stdin.write('\x12');
await wait();
expect(stdout.lastFrame()).toContain('(r:)');
@@ -1370,7 +1410,9 @@ describe('InputPrompt', () => {
it('text and cursor position should be restored after reverse search', async () => {
props.buffer.setText('initial text');
props.buffer.cursor = [0, 3];
- const { stdin, stdout, unmount } = render(<InputPrompt {...props} />);
+ const { stdin, stdout, unmount } = renderWithProviders(
+ <InputPrompt {...props} />,
+ );
stdin.write('\x12');
await wait();
expect(stdout.lastFrame()).toContain('(r:)');
diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx
index 94cbcf1b..dcfdace3 100644
--- a/packages/cli/src/ui/components/InputPrompt.tsx
+++ b/packages/cli/src/ui/components/InputPrompt.tsx
@@ -17,7 +17,6 @@ import { useShellHistory } from '../hooks/useShellHistory.js';
import { useReverseSearchCompletion } from '../hooks/useReverseSearchCompletion.js';
import { useCommandCompletion } from '../hooks/useCommandCompletion.js';
import { useKeypress, Key } from '../hooks/useKeypress.js';
-import { useKittyKeyboardProtocol } from '../hooks/useKittyKeyboardProtocol.js';
import { keyMatchers, Command } from '../keyMatchers.js';
import { CommandContext, SlashCommand } from '../commands/types.js';
import { Config } from '@google/gemini-cli-core';
@@ -67,7 +66,6 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
const [escPressCount, setEscPressCount] = useState(0);
const [showEscapePrompt, setShowEscapePrompt] = useState(false);
const escapeTimerRef = useRef<NodeJS.Timeout | null>(null);
- const kittyProtocolStatus = useKittyKeyboardProtocol();
const [dirs, setDirs] = useState<readonly string[]>(
config.getWorkspaceContext().getDirectories(),
@@ -529,8 +527,6 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
useKeypress(handleInput, {
isActive: true,
- kittyProtocolEnabled: kittyProtocolStatus.enabled,
- config,
});
const linesToRender = buffer.viewportVisualLines;
diff --git a/packages/cli/src/ui/components/SettingsDialog.test.tsx b/packages/cli/src/ui/components/SettingsDialog.test.tsx
index 94f33561..e636bad5 100644
--- a/packages/cli/src/ui/components/SettingsDialog.test.tsx
+++ b/packages/cli/src/ui/components/SettingsDialog.test.tsx
@@ -21,8 +21,8 @@
*
*/
-import { render } from 'ink-testing-library';
import { waitFor } from '@testing-library/react';
+import { renderWithProviders } from '../../test-utils/render.js';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { SettingsDialog } from './SettingsDialog.js';
import { LoadedSettings, SettingScope } from '../../config/settings.js';
@@ -102,7 +102,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -116,7 +116,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -129,7 +129,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -144,7 +144,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -160,7 +160,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -177,7 +177,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -194,7 +194,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -212,7 +212,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -227,7 +227,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -242,7 +242,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -261,7 +261,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -280,7 +280,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { lastFrame, stdin, unmount } = render(
+ const { lastFrame, stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -308,7 +308,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onRestartRequest = vi.fn();
- const { unmount } = render(
+ const { unmount } = renderWithProviders(
<SettingsDialog
settings={settings}
onSelect={() => {}}
@@ -327,7 +327,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onRestartRequest = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog
settings={settings}
onSelect={() => {}}
@@ -349,7 +349,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -368,7 +368,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings({ vimMode: true });
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -392,7 +392,7 @@ describe('SettingsDialog', () => {
);
const onSelect = vi.fn();
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -409,7 +409,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -427,7 +427,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -449,7 +449,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -468,7 +468,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<VimModeProvider settings={settings}>
<SettingsDialog settings={settings} onSelect={onSelect} />
</VimModeProvider>,
@@ -492,7 +492,7 @@ describe('SettingsDialog', () => {
);
const onSelect = vi.fn();
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -505,7 +505,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -521,7 +521,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { lastFrame, unmount } = render(
+ const { lastFrame, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -541,7 +541,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { unmount } = render(
+ const { unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -559,7 +559,7 @@ describe('SettingsDialog', () => {
);
const onSelect = vi.fn();
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -576,7 +576,7 @@ describe('SettingsDialog', () => {
);
const onSelect = vi.fn();
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -591,7 +591,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -610,7 +610,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings({ vimMode: true }); // Start with vimMode enabled
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -626,7 +626,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings({ vimMode: true }); // Start with vimMode enabled
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -642,7 +642,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -659,7 +659,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { lastFrame, stdin, unmount } = render(
+ const { lastFrame, stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -692,7 +692,7 @@ describe('SettingsDialog', () => {
);
const onSelect = vi.fn();
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -705,7 +705,7 @@ describe('SettingsDialog', () => {
const onSelect = vi.fn();
// Should not crash even if some settings are missing definitions
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -718,7 +718,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -763,7 +763,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -792,7 +792,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings({ vimMode: true });
const onSelect = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog settings={settings} onSelect={onSelect} />,
);
@@ -816,7 +816,7 @@ describe('SettingsDialog', () => {
const settings = createMockSettings();
const onRestartRequest = vi.fn();
- const { stdin, unmount } = render(
+ const { stdin, unmount } = renderWithProviders(
<SettingsDialog
settings={settings}
onSelect={() => {}}
diff --git a/packages/cli/src/ui/components/ShellConfirmationDialog.test.tsx b/packages/cli/src/ui/components/ShellConfirmationDialog.test.tsx
index 35783d44..bacf055f 100644
--- a/packages/cli/src/ui/components/ShellConfirmationDialog.test.tsx
+++ b/packages/cli/src/ui/components/ShellConfirmationDialog.test.tsx
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { render } from 'ink-testing-library';
+import { renderWithProviders } from '../../test-utils/render.js';
import { describe, it, expect, vi } from 'vitest';
import { ShellConfirmationDialog } from './ShellConfirmationDialog.js';
@@ -17,12 +17,16 @@ describe('ShellConfirmationDialog', () => {
};
it('renders correctly', () => {
- const { lastFrame } = render(<ShellConfirmationDialog request={request} />);
+ const { lastFrame } = renderWithProviders(
+ <ShellConfirmationDialog request={request} />,
+ );
expect(lastFrame()).toMatchSnapshot();
});
it('calls onConfirm with ProceedOnce when "Yes, allow once" is selected', () => {
- const { lastFrame } = render(<ShellConfirmationDialog request={request} />);
+ const { lastFrame } = renderWithProviders(
+ <ShellConfirmationDialog request={request} />,
+ );
const select = lastFrame()!.toString();
// Simulate selecting the first option
// This is a simplified way to test the selection
@@ -30,14 +34,18 @@ describe('ShellConfirmationDialog', () => {
});
it('calls onConfirm with ProceedAlways when "Yes, allow always for this session" is selected', () => {
- const { lastFrame } = render(<ShellConfirmationDialog request={request} />);
+ const { lastFrame } = renderWithProviders(
+ <ShellConfirmationDialog request={request} />,
+ );
const select = lastFrame()!.toString();
// Simulate selecting the second option
expect(select).toContain('Yes, allow always for this session');
});
it('calls onConfirm with Cancel when "No (esc)" is selected', () => {
- const { lastFrame } = render(<ShellConfirmationDialog request={request} />);
+ const { lastFrame } = renderWithProviders(
+ <ShellConfirmationDialog request={request} />,
+ );
const select = lastFrame()!.toString();
// Simulate selecting the third option
expect(select).toContain('No (esc)');
diff --git a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx
index 968c1d6f..6950b02e 100644
--- a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx
+++ b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx
@@ -4,10 +4,10 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { render } from 'ink-testing-library';
import { describe, it, expect, vi } from 'vitest';
import { ToolConfirmationMessage } from './ToolConfirmationMessage.js';
import { ToolCallConfirmationDetails } from '@google/gemini-cli-core';
+import { renderWithProviders } from '../../../test-utils/render.js';
describe('ToolConfirmationMessage', () => {
it('should not display urls if prompt and url are the same', () => {
@@ -19,7 +19,7 @@ describe('ToolConfirmationMessage', () => {
onConfirm: vi.fn(),
};
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<ToolConfirmationMessage
confirmationDetails={confirmationDetails}
availableTerminalHeight={30}
@@ -42,7 +42,7 @@ describe('ToolConfirmationMessage', () => {
onConfirm: vi.fn(),
};
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<ToolConfirmationMessage
confirmationDetails={confirmationDetails}
availableTerminalHeight={30}
diff --git a/packages/cli/src/ui/components/shared/RadioButtonSelect.test.tsx b/packages/cli/src/ui/components/shared/RadioButtonSelect.test.tsx
index d4c13ba5..cb6db77f 100644
--- a/packages/cli/src/ui/components/shared/RadioButtonSelect.test.tsx
+++ b/packages/cli/src/ui/components/shared/RadioButtonSelect.test.tsx
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { render } from 'ink-testing-library';
+import { renderWithProviders } from '../../../test-utils/render.js';
import { waitFor } from '@testing-library/react';
import {
RadioButtonSelect,
@@ -20,21 +20,21 @@ const ITEMS: Array<RadioSelectItem<string>> = [
describe('<RadioButtonSelect />', () => {
it('renders a list of items and matches snapshot', () => {
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<RadioButtonSelect items={ITEMS} onSelect={() => {}} isFocused={true} />,
);
expect(lastFrame()).toMatchSnapshot();
});
it('renders with the second item selected and matches snapshot', () => {
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<RadioButtonSelect items={ITEMS} initialIndex={1} onSelect={() => {}} />,
);
expect(lastFrame()).toMatchSnapshot();
});
it('renders with numbers hidden and matches snapshot', () => {
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<RadioButtonSelect
items={ITEMS}
onSelect={() => {}}
@@ -49,7 +49,7 @@ describe('<RadioButtonSelect />', () => {
label: `Item ${i + 1}`,
value: `item-${i + 1}`,
}));
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<RadioButtonSelect
items={manyItems}
onSelect={() => {}}
@@ -75,7 +75,7 @@ describe('<RadioButtonSelect />', () => {
themeTypeDisplay: '(Dark)',
},
];
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<RadioButtonSelect items={themeItems} onSelect={() => {}} />,
);
expect(lastFrame()).toMatchSnapshot();
@@ -86,14 +86,14 @@ describe('<RadioButtonSelect />', () => {
label: `Item ${i + 1}`,
value: `item-${i + 1}`,
}));
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<RadioButtonSelect items={manyItems} onSelect={() => {}} />,
);
expect(lastFrame()).toMatchSnapshot();
});
it('renders nothing when no items are provided', () => {
- const { lastFrame } = render(
+ const { lastFrame } = renderWithProviders(
<RadioButtonSelect items={[]} onSelect={() => {}} isFocused={true} />,
);
expect(lastFrame()).toBe('');
@@ -103,7 +103,7 @@ describe('<RadioButtonSelect />', () => {
describe('keyboard navigation', () => {
it('should call onSelect when "enter" is pressed', () => {
const onSelect = vi.fn();
- const { stdin } = render(
+ const { stdin } = renderWithProviders(
<RadioButtonSelect items={ITEMS} onSelect={onSelect} />,
);
@@ -115,7 +115,7 @@ describe('keyboard navigation', () => {
describe('when isFocused is false', () => {
it('should not handle any keyboard input', () => {
const onSelect = vi.fn();
- const { stdin } = render(
+ const { stdin } = renderWithProviders(
<RadioButtonSelect
items={ITEMS}
onSelect={onSelect}
@@ -137,7 +137,7 @@ describe('keyboard navigation', () => {
])('$description', ({ isFocused }) => {
it('should navigate down with arrow key and select with enter', async () => {
const onSelect = vi.fn();
- const { stdin, lastFrame } = render(
+ const { stdin, lastFrame } = renderWithProviders(
<RadioButtonSelect
items={ITEMS}
onSelect={onSelect}
@@ -158,7 +158,7 @@ describe('keyboard navigation', () => {
it('should navigate up with arrow key and select with enter', async () => {
const onSelect = vi.fn();
- const { stdin, lastFrame } = render(
+ const { stdin, lastFrame } = renderWithProviders(
<RadioButtonSelect
items={ITEMS}
onSelect={onSelect}