mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 16:57:46 +00:00
# 🚀 Sync Gemini CLI v0.2.1 - Major Feature Update (#483)
This commit is contained in:
@@ -321,7 +321,7 @@ function visitBoxRow(element: React.ReactNode): Row {
|
||||
const segment: StyledText = { text, props: parentProps ?? {} };
|
||||
|
||||
// Check the 'wrap' property from the merged props to decide the segment type.
|
||||
if (parentProps === undefined || parentProps.wrap === 'wrap') {
|
||||
if (parentProps === undefined || parentProps['wrap'] === 'wrap') {
|
||||
hasSeenWrapped = true;
|
||||
row.segments.push(segment);
|
||||
} else {
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
* 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,
|
||||
type RadioSelectItem,
|
||||
} from './RadioButtonSelect.js';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
|
||||
const ITEMS: Array<RadioSelectItem<string>> = [
|
||||
{ label: 'Option 1', value: 'one' },
|
||||
@@ -19,30 +20,24 @@ 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(
|
||||
<RadioButtonSelect
|
||||
items={ITEMS}
|
||||
initialIndex={1}
|
||||
onSelect={() => {}}
|
||||
isFocused={true}
|
||||
/>,
|
||||
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={() => {}}
|
||||
isFocused={true}
|
||||
showNumbers={false}
|
||||
/>,
|
||||
);
|
||||
@@ -54,11 +49,10 @@ describe('<RadioButtonSelect />', () => {
|
||||
label: `Item ${i + 1}`,
|
||||
value: `item-${i + 1}`,
|
||||
}));
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame } = renderWithProviders(
|
||||
<RadioButtonSelect
|
||||
items={manyItems}
|
||||
onSelect={() => {}}
|
||||
isFocused={true}
|
||||
showScrollArrows={true}
|
||||
maxItemsToShow={5}
|
||||
/>,
|
||||
@@ -81,12 +75,8 @@ describe('<RadioButtonSelect />', () => {
|
||||
themeTypeDisplay: '(Dark)',
|
||||
},
|
||||
];
|
||||
const { lastFrame } = render(
|
||||
<RadioButtonSelect
|
||||
items={themeItems}
|
||||
onSelect={() => {}}
|
||||
isFocused={true}
|
||||
/>,
|
||||
const { lastFrame } = renderWithProviders(
|
||||
<RadioButtonSelect items={themeItems} onSelect={() => {}} />,
|
||||
);
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
});
|
||||
@@ -96,20 +86,96 @@ describe('<RadioButtonSelect />', () => {
|
||||
label: `Item ${i + 1}`,
|
||||
value: `item-${i + 1}`,
|
||||
}));
|
||||
const { lastFrame } = render(
|
||||
<RadioButtonSelect
|
||||
items={manyItems}
|
||||
onSelect={() => {}}
|
||||
isFocused={true}
|
||||
/>,
|
||||
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('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('keyboard navigation', () => {
|
||||
it('should call onSelect when "enter" is pressed', () => {
|
||||
const onSelect = vi.fn();
|
||||
const { stdin } = renderWithProviders(
|
||||
<RadioButtonSelect items={ITEMS} onSelect={onSelect} />,
|
||||
);
|
||||
|
||||
stdin.write('\r');
|
||||
|
||||
expect(onSelect).toHaveBeenCalledWith('one');
|
||||
});
|
||||
|
||||
describe('when isFocused is false', () => {
|
||||
it('should not handle any keyboard input', () => {
|
||||
const onSelect = vi.fn();
|
||||
const { stdin } = renderWithProviders(
|
||||
<RadioButtonSelect
|
||||
items={ITEMS}
|
||||
onSelect={onSelect}
|
||||
isFocused={false}
|
||||
/>,
|
||||
);
|
||||
|
||||
stdin.write('\u001B[B'); // Down arrow
|
||||
stdin.write('\u001B[A'); // Up arrow
|
||||
stdin.write('\r'); // Enter
|
||||
|
||||
expect(onSelect).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe.each([
|
||||
{ description: 'when isFocused is true', isFocused: true },
|
||||
{ description: 'when isFocused is omitted', isFocused: undefined },
|
||||
])('$description', ({ isFocused }) => {
|
||||
it('should navigate down with arrow key and select with enter', async () => {
|
||||
const onSelect = vi.fn();
|
||||
const { stdin, lastFrame } = renderWithProviders(
|
||||
<RadioButtonSelect
|
||||
items={ITEMS}
|
||||
onSelect={onSelect}
|
||||
isFocused={isFocused}
|
||||
/>,
|
||||
);
|
||||
|
||||
stdin.write('\u001B[B'); // Down arrow
|
||||
|
||||
await waitFor(() => {
|
||||
expect(lastFrame()).toContain('● 2. Option 2');
|
||||
});
|
||||
|
||||
stdin.write('\r');
|
||||
|
||||
expect(onSelect).toHaveBeenCalledWith('two');
|
||||
});
|
||||
|
||||
it('should navigate up with arrow key and select with enter', async () => {
|
||||
const onSelect = vi.fn();
|
||||
const { stdin, lastFrame } = renderWithProviders(
|
||||
<RadioButtonSelect
|
||||
items={ITEMS}
|
||||
onSelect={onSelect}
|
||||
initialIndex={1}
|
||||
isFocused={isFocused}
|
||||
/>,
|
||||
);
|
||||
|
||||
stdin.write('\u001B[A'); // Up arrow
|
||||
|
||||
await waitFor(() => {
|
||||
expect(lastFrame()).toContain('● 1. Option 1');
|
||||
});
|
||||
|
||||
stdin.write('\r');
|
||||
|
||||
expect(onSelect).toHaveBeenCalledWith('one');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -55,7 +55,7 @@ export function RadioButtonSelect<T>({
|
||||
initialIndex = 0,
|
||||
onSelect,
|
||||
onHighlight,
|
||||
isFocused,
|
||||
isFocused = true,
|
||||
showScrollArrows = false,
|
||||
maxItemsToShow = 10,
|
||||
showNumbers = true,
|
||||
|
||||
@@ -1833,6 +1833,13 @@ export function useTextBuffer({
|
||||
}): void => {
|
||||
const { sequence: input } = key;
|
||||
|
||||
if (key.paste) {
|
||||
// Do not do any other processing on pastes so ensure we handle them
|
||||
// before all other cases.
|
||||
insert(input, { paste: key.paste });
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
key.name === 'return' ||
|
||||
input === '\r' ||
|
||||
|
||||
Reference in New Issue
Block a user