mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-13 05:12:55 -07:00
Fixes for Ink 6.4.0 (#12352)
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import { render as inkRender } from 'ink-testing-library';
|
||||
import { Box } from 'ink';
|
||||
import type React from 'react';
|
||||
import { act } from 'react';
|
||||
import { LoadedSettings, type Settings } from '../config/settings.js';
|
||||
@@ -22,6 +23,7 @@ import { type Config } from '@google/gemini-cli-core';
|
||||
// Wrapper around ink-testing-library's render that ensures act() is called
|
||||
export const render = (
|
||||
tree: React.ReactElement,
|
||||
terminalWidth?: number,
|
||||
): ReturnType<typeof inkRender> => {
|
||||
let renderResult: ReturnType<typeof inkRender> =
|
||||
undefined as unknown as ReturnType<typeof inkRender>;
|
||||
@@ -29,6 +31,19 @@ export const render = (
|
||||
renderResult = inkRender(tree);
|
||||
});
|
||||
|
||||
if (terminalWidth !== undefined && renderResult?.stdout) {
|
||||
// Override the columns getter on the stdout instance provided by ink-testing-library
|
||||
Object.defineProperty(renderResult.stdout, 'columns', {
|
||||
get: () => terminalWidth,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
// Trigger a rerender so Ink can pick up the new terminal width
|
||||
act(() => {
|
||||
renderResult.rerender(tree);
|
||||
});
|
||||
}
|
||||
|
||||
const originalUnmount = renderResult.unmount;
|
||||
const originalRerender = renderResult.rerender;
|
||||
|
||||
@@ -148,13 +163,21 @@ export const renderWithProviders = (
|
||||
<VimModeProvider settings={settings}>
|
||||
<ShellFocusContext.Provider value={shellFocus}>
|
||||
<KeypressProvider kittyProtocolEnabled={kittyProtocolEnabled}>
|
||||
<Box
|
||||
width={terminalWidth}
|
||||
flexShrink={0}
|
||||
flexGrow={0}
|
||||
flexDirection="column"
|
||||
>
|
||||
{component}
|
||||
</Box>
|
||||
</KeypressProvider>
|
||||
</ShellFocusContext.Provider>
|
||||
</VimModeProvider>
|
||||
</UIStateContext.Provider>
|
||||
</SettingsContext.Provider>
|
||||
</ConfigContext.Provider>,
|
||||
terminalWidth,
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ const renderWithContext = (
|
||||
<StreamingContext.Provider value={contextValue}>
|
||||
{ui}
|
||||
</StreamingContext.Provider>,
|
||||
width,
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -67,7 +67,10 @@ export const LoadingIndicator: React.FC<LoadingIndicatorProps> = ({
|
||||
</Text>
|
||||
)}
|
||||
{!isNarrow && cancelAndTimerContent && (
|
||||
<>
|
||||
<Box flexShrink={0} width={1} />
|
||||
<Text color={theme.text.secondary}>{cancelAndTimerContent}</Text>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
{!isNarrow && <Box flexGrow={1}>{/* Spacer */}</Box>}
|
||||
|
||||
@@ -14,6 +14,7 @@ describe('LoopDetectionConfirmation', () => {
|
||||
it('renders correctly', () => {
|
||||
const { lastFrame } = renderWithProviders(
|
||||
<LoopDetectionConfirmation onComplete={onComplete} />,
|
||||
{ width: 101 },
|
||||
);
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
});
|
||||
@@ -21,6 +22,7 @@ describe('LoopDetectionConfirmation', () => {
|
||||
it('contains the expected options', () => {
|
||||
const { lastFrame } = renderWithProviders(
|
||||
<LoopDetectionConfirmation onComplete={onComplete} />,
|
||||
{ width: 100 },
|
||||
);
|
||||
const output = lastFrame()!.toString();
|
||||
|
||||
|
||||
@@ -50,11 +50,12 @@ export function LoopDetectionConfirmation({
|
||||
];
|
||||
|
||||
return (
|
||||
<Box width="100%" flexDirection="row">
|
||||
<Box
|
||||
flexDirection="column"
|
||||
borderStyle="round"
|
||||
borderColor={theme.status.warning}
|
||||
width="100%"
|
||||
flexGrow={1}
|
||||
marginLeft={1}
|
||||
>
|
||||
<Box paddingX={1} paddingY={0} flexDirection="column">
|
||||
@@ -72,12 +73,12 @@ export function LoopDetectionConfirmation({
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box width="100%" marginTop={1}>
|
||||
<Box marginTop={1}>
|
||||
<Box flexDirection="column">
|
||||
<Text color={theme.text.secondary}>
|
||||
This can happen due to repetitive tool calls or other model
|
||||
behavior. Do you want to keep loop detection enabled or disable it
|
||||
for this session?
|
||||
behavior. Do you want to keep loop detection enabled or disable
|
||||
it for this session?
|
||||
</Text>
|
||||
<Box marginTop={1}>
|
||||
<RadioButtonSelect items={OPTIONS} onSelect={onComplete} />
|
||||
@@ -86,5 +87,6 @@ export function LoopDetectionConfirmation({
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -73,13 +73,14 @@ describe('PrepareLabel', () => {
|
||||
textColor={color}
|
||||
isExpanded={true}
|
||||
/>,
|
||||
100,
|
||||
);
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('creates centered window around match when collapsed', () => {
|
||||
const prefix = 'cd /very/long/path/that/keeps/going/'.repeat(3);
|
||||
const prefix = 'cd_/very/long/path/that/keeps/going/'.repeat(3);
|
||||
const core = 'search-here';
|
||||
const suffix = '/and/then/some/more/components/'.repeat(3);
|
||||
const label = prefix + core + suffix;
|
||||
@@ -92,6 +93,7 @@ describe('PrepareLabel', () => {
|
||||
textColor={color}
|
||||
isExpanded={false}
|
||||
/>,
|
||||
100,
|
||||
);
|
||||
const out = lastFrame();
|
||||
const f = flat(out);
|
||||
|
||||
@@ -19,6 +19,7 @@ describe('ShellConfirmationDialog', () => {
|
||||
it('renders correctly', () => {
|
||||
const { lastFrame } = renderWithProviders(
|
||||
<ShellConfirmationDialog request={request} />,
|
||||
{ width: 101 },
|
||||
);
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
});
|
||||
@@ -45,6 +46,7 @@ describe('ShellConfirmationDialog', () => {
|
||||
it('calls onConfirm with Cancel when "No (esc)" is selected', () => {
|
||||
const { lastFrame } = renderWithProviders(
|
||||
<ShellConfirmationDialog request={request} />,
|
||||
{ width: 100 },
|
||||
);
|
||||
const select = lastFrame()!.toString();
|
||||
// Simulate selecting the third option
|
||||
|
||||
@@ -68,12 +68,13 @@ export const ShellConfirmationDialog: React.FC<
|
||||
];
|
||||
|
||||
return (
|
||||
<Box flexDirection="row" width="100%">
|
||||
<Box
|
||||
flexDirection="column"
|
||||
borderStyle="round"
|
||||
borderColor={theme.status.warning}
|
||||
padding={1}
|
||||
width="100%"
|
||||
flexGrow={1}
|
||||
marginLeft={1}
|
||||
>
|
||||
<Box flexDirection="column" marginBottom={1}>
|
||||
@@ -104,5 +105,6 @@ export const ShellConfirmationDialog: React.FC<
|
||||
|
||||
<RadioButtonSelect items={options} onSelect={handleSelect} isFocused />
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -112,7 +112,7 @@ export function SuggestionsDisplay({
|
||||
</Box>
|
||||
)}
|
||||
{isActive && isLong && (
|
||||
<Box>
|
||||
<Box width={3} flexShrink={0}>
|
||||
<Text color={Colors.Gray}>{isExpanded ? ' ← ' : ' → '}</Text>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`<LoadingIndicator /> > should truncate long primary text instead of wrapping 1`] = `
|
||||
"MockResponding This is an extremely long loading phrase that should be truncated in t (esc to
|
||||
Spinner cancel, 5s)"
|
||||
"MockRespondin This is an extremely long loading phrase that shoul… (esc to
|
||||
gSpinner cancel, 5s)"
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`PrepareLabel > creates centered window around match when collapsed 1`] = `
|
||||
"...ry/long/path/that/keeps/going/cd /very/long/path/that/keeps/going/search-here/and/then/some/more/
|
||||
"...ry/long/path/that/keeps/going/cd_/very/long/path/that/keeps/going/search-here/and/then/some/more/
|
||||
components//and/then/some/more/components//and/..."
|
||||
`;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user