mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-04 08:54:28 -07:00
test(cli): refactor tests for async render utilities (#23252)
This commit is contained in:
committed by
GitHub
parent
86a3a913b5
commit
6c78eb7a39
@@ -78,7 +78,6 @@ describe('BaseSelectionList', () => {
|
||||
const result = await renderWithProviders(
|
||||
<BaseSelectionList {...defaultProps} />,
|
||||
);
|
||||
await result.waitUntilReady();
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -313,7 +312,6 @@ describe('BaseSelectionList', () => {
|
||||
|
||||
const { rerender, lastFrame, waitUntilReady, unmount } =
|
||||
await renderWithProviders(<BaseSelectionList {...componentProps} />);
|
||||
await waitUntilReady();
|
||||
|
||||
// Function to simulate the activeIndex changing over time
|
||||
const updateActiveIndex = async (newIndex: number) => {
|
||||
|
||||
@@ -25,7 +25,7 @@ const NUMERIC_OPTIONS: readonly SettingEnumOption[] = [
|
||||
|
||||
describe('<EnumSelector />', () => {
|
||||
it('renders with string options and matches snapshot', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<EnumSelector
|
||||
options={LANGUAGE_OPTIONS}
|
||||
currentValue="en"
|
||||
@@ -33,13 +33,12 @@ describe('<EnumSelector />', () => {
|
||||
onValueChange={async () => {}}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders with numeric options and matches snapshot', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<EnumSelector
|
||||
options={NUMERIC_OPTIONS}
|
||||
currentValue={2}
|
||||
@@ -47,13 +46,12 @@ describe('<EnumSelector />', () => {
|
||||
onValueChange={async () => {}}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders inactive state and matches snapshot', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<EnumSelector
|
||||
options={LANGUAGE_OPTIONS}
|
||||
currentValue="zh"
|
||||
@@ -61,7 +59,6 @@ describe('<EnumSelector />', () => {
|
||||
onValueChange={async () => {}}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
@@ -70,7 +67,7 @@ describe('<EnumSelector />', () => {
|
||||
const singleOption: readonly SettingEnumOption[] = [
|
||||
{ label: 'Only Option', value: 'only' },
|
||||
];
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<EnumSelector
|
||||
options={singleOption}
|
||||
currentValue="only"
|
||||
@@ -78,13 +75,12 @@ describe('<EnumSelector />', () => {
|
||||
onValueChange={async () => {}}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders nothing when no options are provided', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<EnumSelector
|
||||
options={[]}
|
||||
currentValue=""
|
||||
@@ -92,13 +88,12 @@ describe('<EnumSelector />', () => {
|
||||
onValueChange={async () => {}}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame({ allowEmpty: true })).toBe('');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('handles currentValue not found in options', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<EnumSelector
|
||||
options={LANGUAGE_OPTIONS}
|
||||
currentValue="invalid"
|
||||
@@ -106,7 +101,6 @@ describe('<EnumSelector />', () => {
|
||||
onValueChange={async () => {}}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
// Should default to first option
|
||||
expect(lastFrame()).toContain('English');
|
||||
unmount();
|
||||
@@ -122,7 +116,6 @@ describe('<EnumSelector />', () => {
|
||||
onValueChange={async () => {}}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('English');
|
||||
|
||||
await act(async () => {
|
||||
@@ -141,7 +134,7 @@ describe('<EnumSelector />', () => {
|
||||
});
|
||||
|
||||
it('shows navigation arrows when multiple options available', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<EnumSelector
|
||||
options={LANGUAGE_OPTIONS}
|
||||
currentValue="en"
|
||||
@@ -149,7 +142,6 @@ describe('<EnumSelector />', () => {
|
||||
onValueChange={async () => {}}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('←');
|
||||
expect(lastFrame()).toContain('→');
|
||||
unmount();
|
||||
@@ -159,7 +151,7 @@ describe('<EnumSelector />', () => {
|
||||
const singleOption: readonly SettingEnumOption[] = [
|
||||
{ label: 'Only Option', value: 'only' },
|
||||
];
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<EnumSelector
|
||||
options={singleOption}
|
||||
currentValue="only"
|
||||
@@ -167,7 +159,6 @@ describe('<EnumSelector />', () => {
|
||||
onValueChange={async () => {}}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).not.toContain('←');
|
||||
expect(lastFrame()).not.toContain('→');
|
||||
unmount();
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('ExpandableText', () => {
|
||||
const flat = (s: string | undefined) => (s ?? '').replace(/\n/g, '');
|
||||
|
||||
it('renders plain label when no match (short label)', async () => {
|
||||
const renderResult = render(
|
||||
const renderResult = await render(
|
||||
<ExpandableText
|
||||
label="simple command"
|
||||
userInput=""
|
||||
@@ -22,15 +22,14 @@ describe('ExpandableText', () => {
|
||||
isExpanded={false}
|
||||
/>,
|
||||
);
|
||||
const { waitUntilReady, unmount } = renderResult;
|
||||
await waitUntilReady();
|
||||
const { unmount } = renderResult;
|
||||
await expect(renderResult).toMatchSvgSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('truncates long label when collapsed and no match', async () => {
|
||||
const long = 'x'.repeat(MAX_WIDTH + 25);
|
||||
const renderResult = render(
|
||||
const renderResult = await render(
|
||||
<ExpandableText
|
||||
label={long}
|
||||
userInput=""
|
||||
@@ -38,8 +37,7 @@ describe('ExpandableText', () => {
|
||||
isExpanded={false}
|
||||
/>,
|
||||
);
|
||||
const { lastFrame, waitUntilReady, unmount } = renderResult;
|
||||
await waitUntilReady();
|
||||
const { lastFrame, unmount } = renderResult;
|
||||
const out = lastFrame();
|
||||
const f = flat(out);
|
||||
expect(f.endsWith('...')).toBe(true);
|
||||
@@ -50,7 +48,7 @@ describe('ExpandableText', () => {
|
||||
|
||||
it('shows full long label when expanded and no match', async () => {
|
||||
const long = 'y'.repeat(MAX_WIDTH + 25);
|
||||
const renderResult = render(
|
||||
const renderResult = await render(
|
||||
<ExpandableText
|
||||
label={long}
|
||||
userInput=""
|
||||
@@ -58,8 +56,7 @@ describe('ExpandableText', () => {
|
||||
isExpanded={true}
|
||||
/>,
|
||||
);
|
||||
const { lastFrame, waitUntilReady, unmount } = renderResult;
|
||||
await waitUntilReady();
|
||||
const { lastFrame, unmount } = renderResult;
|
||||
const out = lastFrame();
|
||||
const f = flat(out);
|
||||
expect(f.length).toBe(long.length);
|
||||
@@ -71,7 +68,7 @@ describe('ExpandableText', () => {
|
||||
const label = 'run: git commit -m "feat: add search"';
|
||||
const userInput = 'commit';
|
||||
const matchedIndex = label.indexOf(userInput);
|
||||
const renderResult = render(
|
||||
const renderResult = await render(
|
||||
<ExpandableText
|
||||
label={label}
|
||||
userInput={userInput}
|
||||
@@ -81,8 +78,7 @@ describe('ExpandableText', () => {
|
||||
/>,
|
||||
100,
|
||||
);
|
||||
const { waitUntilReady, unmount } = renderResult;
|
||||
await waitUntilReady();
|
||||
const { unmount } = renderResult;
|
||||
await expect(renderResult).toMatchSvgSnapshot();
|
||||
unmount();
|
||||
});
|
||||
@@ -93,7 +89,7 @@ describe('ExpandableText', () => {
|
||||
const suffix = '/and/then/some/more/components/'.repeat(3);
|
||||
const label = prefix + core + suffix;
|
||||
const matchedIndex = prefix.length;
|
||||
const renderResult = render(
|
||||
const renderResult = await render(
|
||||
<ExpandableText
|
||||
label={label}
|
||||
userInput={core}
|
||||
@@ -103,8 +99,7 @@ describe('ExpandableText', () => {
|
||||
/>,
|
||||
100,
|
||||
);
|
||||
const { lastFrame, waitUntilReady, unmount } = renderResult;
|
||||
await waitUntilReady();
|
||||
const { lastFrame, unmount } = renderResult;
|
||||
const out = lastFrame();
|
||||
const f = flat(out);
|
||||
expect(f.includes(core)).toBe(true);
|
||||
@@ -120,7 +115,7 @@ describe('ExpandableText', () => {
|
||||
const suffix = ' in this text';
|
||||
const label = prefix + core + suffix;
|
||||
const matchedIndex = prefix.length;
|
||||
const renderResult = render(
|
||||
const renderResult = await render(
|
||||
<ExpandableText
|
||||
label={label}
|
||||
userInput={core}
|
||||
@@ -129,8 +124,7 @@ describe('ExpandableText', () => {
|
||||
isExpanded={false}
|
||||
/>,
|
||||
);
|
||||
const { lastFrame, waitUntilReady, unmount } = renderResult;
|
||||
await waitUntilReady();
|
||||
const { lastFrame, unmount } = renderResult;
|
||||
const out = lastFrame();
|
||||
const f = flat(out);
|
||||
expect(f.includes('...')).toBe(true);
|
||||
@@ -144,7 +138,7 @@ describe('ExpandableText', () => {
|
||||
it('respects custom maxWidth', async () => {
|
||||
const customWidth = 50;
|
||||
const long = 'z'.repeat(100);
|
||||
const renderResult = render(
|
||||
const renderResult = await render(
|
||||
<ExpandableText
|
||||
label={long}
|
||||
userInput=""
|
||||
@@ -153,8 +147,7 @@ describe('ExpandableText', () => {
|
||||
maxWidth={customWidth}
|
||||
/>,
|
||||
);
|
||||
const { lastFrame, waitUntilReady, unmount } = renderResult;
|
||||
await waitUntilReady();
|
||||
const { lastFrame, unmount } = renderResult;
|
||||
const out = lastFrame();
|
||||
const f = flat(out);
|
||||
expect(f.endsWith('...')).toBe(true);
|
||||
|
||||
@@ -28,13 +28,12 @@ describe('<HalfLinePaddedBox />', () => {
|
||||
it('renders standard background and blocks when not iTerm2', async () => {
|
||||
vi.mocked(isITerm2).mockReturnValue(false);
|
||||
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<HalfLinePaddedBox backgroundBaseColor="blue" backgroundOpacity={0.5}>
|
||||
<Text>Content</Text>
|
||||
</HalfLinePaddedBox>,
|
||||
{ width: 10 },
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
|
||||
@@ -44,13 +43,12 @@ describe('<HalfLinePaddedBox />', () => {
|
||||
it('renders iTerm2-specific blocks when iTerm2 is detected', async () => {
|
||||
vi.mocked(isITerm2).mockReturnValue(true);
|
||||
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<HalfLinePaddedBox backgroundBaseColor="blue" backgroundOpacity={0.5}>
|
||||
<Text>Content</Text>
|
||||
</HalfLinePaddedBox>,
|
||||
{ width: 10 },
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
|
||||
@@ -58,7 +56,7 @@ describe('<HalfLinePaddedBox />', () => {
|
||||
});
|
||||
|
||||
it('renders nothing when useBackgroundColor is false', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<HalfLinePaddedBox
|
||||
backgroundBaseColor="blue"
|
||||
backgroundOpacity={0.5}
|
||||
@@ -68,7 +66,6 @@ describe('<HalfLinePaddedBox />', () => {
|
||||
</HalfLinePaddedBox>,
|
||||
{ width: 10 },
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
|
||||
@@ -78,13 +75,12 @@ describe('<HalfLinePaddedBox />', () => {
|
||||
it('renders nothing when screen reader is enabled', async () => {
|
||||
mockUseIsScreenReaderEnabled.mockReturnValue(true);
|
||||
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<HalfLinePaddedBox backgroundBaseColor="blue" backgroundOpacity={0.5}>
|
||||
<Text>Content</Text>
|
||||
</HalfLinePaddedBox>,
|
||||
{ width: 10 },
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ describe('<MaxSizedBox />', () => {
|
||||
});
|
||||
|
||||
it('renders children without truncation when they fit', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={10}>
|
||||
<Box>
|
||||
@@ -42,7 +42,7 @@ describe('<MaxSizedBox />', () => {
|
||||
});
|
||||
|
||||
it('hides lines when content exceeds maxHeight', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={2}>
|
||||
<Box flexDirection="column">
|
||||
@@ -65,7 +65,7 @@ describe('<MaxSizedBox />', () => {
|
||||
});
|
||||
|
||||
it('hides lines at the end when content exceeds maxHeight and overflowDirection is bottom', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={2} overflowDirection="bottom">
|
||||
<Box flexDirection="column">
|
||||
@@ -88,7 +88,7 @@ describe('<MaxSizedBox />', () => {
|
||||
});
|
||||
|
||||
it('shows plural "lines" when more than one line is hidden', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={2}>
|
||||
<Box flexDirection="column">
|
||||
@@ -111,7 +111,7 @@ describe('<MaxSizedBox />', () => {
|
||||
});
|
||||
|
||||
it('shows singular "line" when exactly one line is hidden', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={2} additionalHiddenLinesCount={1}>
|
||||
<Box flexDirection="column">
|
||||
@@ -132,7 +132,7 @@ describe('<MaxSizedBox />', () => {
|
||||
});
|
||||
|
||||
it('accounts for additionalHiddenLinesCount', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={2} additionalHiddenLinesCount={5}>
|
||||
<Box flexDirection="column">
|
||||
@@ -155,7 +155,7 @@ describe('<MaxSizedBox />', () => {
|
||||
});
|
||||
|
||||
it('wraps text that exceeds maxWidth', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={10} maxHeight={5}>
|
||||
<Box>
|
||||
@@ -175,7 +175,7 @@ describe('<MaxSizedBox />', () => {
|
||||
});
|
||||
|
||||
it('does not truncate when maxHeight is undefined', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={undefined}>
|
||||
<Box flexDirection="column">
|
||||
@@ -195,7 +195,7 @@ describe('<MaxSizedBox />', () => {
|
||||
});
|
||||
|
||||
it('renders an empty box for empty children', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={10}></MaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
@@ -209,7 +209,7 @@ describe('<MaxSizedBox />', () => {
|
||||
});
|
||||
|
||||
it('handles React.Fragment as a child', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={10}>
|
||||
<Box flexDirection="column">
|
||||
@@ -236,7 +236,7 @@ describe('<MaxSizedBox />', () => {
|
||||
{ length: 30 },
|
||||
(_, i) => `Line ${i + 1}`,
|
||||
).join('\n');
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={10} overflowDirection="top">
|
||||
<Box>
|
||||
@@ -262,7 +262,7 @@ describe('<MaxSizedBox />', () => {
|
||||
{ length: 30 },
|
||||
(_, i) => `Line ${i + 1}`,
|
||||
).join('\n');
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={10} overflowDirection="bottom">
|
||||
<Box>
|
||||
|
||||
@@ -29,25 +29,23 @@ describe('<Scrollable />', () => {
|
||||
});
|
||||
|
||||
it('renders children', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<Scrollable hasFocus={false} height={5}>
|
||||
<Text>Hello World</Text>
|
||||
</Scrollable>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('Hello World');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders multiple children', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<Scrollable hasFocus={false} height={5}>
|
||||
<Text>Line 1</Text>
|
||||
<Text>Line 2</Text>
|
||||
<Text>Line 3</Text>
|
||||
</Scrollable>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('Line 1');
|
||||
expect(lastFrame()).toContain('Line 2');
|
||||
expect(lastFrame()).toContain('Line 3');
|
||||
@@ -55,14 +53,13 @@ describe('<Scrollable />', () => {
|
||||
});
|
||||
|
||||
it('matches snapshot', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<Scrollable hasFocus={false} height={5}>
|
||||
<Text>Line 1</Text>
|
||||
<Text>Line 2</Text>
|
||||
<Text>Line 3</Text>
|
||||
</Scrollable>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
@@ -77,7 +74,7 @@ describe('<Scrollable />', () => {
|
||||
},
|
||||
);
|
||||
|
||||
const { waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { unmount } = await renderWithProviders(
|
||||
<Scrollable hasFocus={true} height={5}>
|
||||
<Text>Line 1</Text>
|
||||
<Text>Line 2</Text>
|
||||
@@ -91,7 +88,6 @@ describe('<Scrollable />', () => {
|
||||
<Text>Line 10</Text>
|
||||
</Scrollable>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(capturedEntry).toBeDefined();
|
||||
|
||||
@@ -104,22 +100,20 @@ describe('<Scrollable />', () => {
|
||||
|
||||
// Initial state with scrollToBottom={true}
|
||||
unmount();
|
||||
const { waitUntilReady: waitUntilReady2, unmount: unmount2 } =
|
||||
await renderWithProviders(
|
||||
<Scrollable hasFocus={true} height={5} scrollToBottom={true}>
|
||||
<Text>Line 1</Text>
|
||||
<Text>Line 2</Text>
|
||||
<Text>Line 3</Text>
|
||||
<Text>Line 4</Text>
|
||||
<Text>Line 5</Text>
|
||||
<Text>Line 6</Text>
|
||||
<Text>Line 7</Text>
|
||||
<Text>Line 8</Text>
|
||||
<Text>Line 9</Text>
|
||||
<Text>Line 10</Text>
|
||||
</Scrollable>,
|
||||
);
|
||||
await waitUntilReady2();
|
||||
const { unmount: unmount2 } = await renderWithProviders(
|
||||
<Scrollable hasFocus={true} height={5} scrollToBottom={true}>
|
||||
<Text>Line 1</Text>
|
||||
<Text>Line 2</Text>
|
||||
<Text>Line 3</Text>
|
||||
<Text>Line 4</Text>
|
||||
<Text>Line 5</Text>
|
||||
<Text>Line 6</Text>
|
||||
<Text>Line 7</Text>
|
||||
<Text>Line 8</Text>
|
||||
<Text>Line 9</Text>
|
||||
<Text>Line 10</Text>
|
||||
</Scrollable>,
|
||||
);
|
||||
await waitFor(() => {
|
||||
expect(capturedEntry?.getScrollState().scrollTop).toBe(5);
|
||||
});
|
||||
@@ -197,14 +191,13 @@ describe('<Scrollable />', () => {
|
||||
},
|
||||
);
|
||||
|
||||
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { stdin, unmount, waitUntilReady } = await renderWithProviders(
|
||||
<Scrollable hasFocus={true} height={5}>
|
||||
<Box height={scrollHeight}>
|
||||
<Text>Content</Text>
|
||||
</Box>
|
||||
</Scrollable>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
// Ensure initial state using existing scrollBy method
|
||||
await act(async () => {
|
||||
|
||||
@@ -95,8 +95,7 @@ describe('SearchableList', () => {
|
||||
};
|
||||
|
||||
it('should render all items initially', async () => {
|
||||
const { lastFrame, waitUntilReady } = await renderList();
|
||||
await waitUntilReady();
|
||||
const { lastFrame } = await renderList();
|
||||
const frame = lastFrame();
|
||||
|
||||
expect(frame).toContain('Test List');
|
||||
@@ -109,10 +108,9 @@ describe('SearchableList', () => {
|
||||
});
|
||||
|
||||
it('should reset selection to top when items change if resetSelectionOnItemsChange is true', async () => {
|
||||
const { lastFrame, stdin, waitUntilReady } = await renderList({
|
||||
const { lastFrame, stdin } = await renderList({
|
||||
resetSelectionOnItemsChange: true,
|
||||
});
|
||||
await waitUntilReady();
|
||||
|
||||
await React.act(async () => {
|
||||
stdin.write('\u001B[B'); // Down arrow
|
||||
@@ -218,8 +216,7 @@ describe('SearchableList', () => {
|
||||
});
|
||||
|
||||
it('should match snapshot', async () => {
|
||||
const { lastFrame, waitUntilReady } = await renderList();
|
||||
await waitUntilReady();
|
||||
const { lastFrame } = await renderList();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,11 +37,10 @@ describe('<SectionHeader />', () => {
|
||||
width: 40,
|
||||
},
|
||||
])('$description', async ({ title, subtitle, width }) => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<SectionHeader title={title} subtitle={subtitle} />,
|
||||
{ width },
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
|
||||
@@ -12,21 +12,20 @@ import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('<SlicingMaxSizedBox />', () => {
|
||||
it('renders string data without slicing when it fits', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<SlicingMaxSizedBox data="Hello World" maxWidth={80}>
|
||||
{(truncatedData) => <Text>{truncatedData}</Text>}
|
||||
</SlicingMaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('Hello World');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('slices string data by characters when very long', async () => {
|
||||
const veryLongString = 'A'.repeat(25000);
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<SlicingMaxSizedBox
|
||||
data={veryLongString}
|
||||
@@ -37,7 +36,6 @@ describe('<SlicingMaxSizedBox />', () => {
|
||||
</SlicingMaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
// 20000 characters + 3 for '...'
|
||||
expect(lastFrame()).toContain('20003');
|
||||
unmount();
|
||||
@@ -45,7 +43,7 @@ describe('<SlicingMaxSizedBox />', () => {
|
||||
|
||||
it('slices string data by lines when maxLines is provided', async () => {
|
||||
const multilineString = 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5';
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<SlicingMaxSizedBox
|
||||
data={multilineString}
|
||||
@@ -58,7 +56,6 @@ describe('<SlicingMaxSizedBox />', () => {
|
||||
</SlicingMaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
// maxLines=3, so it should keep 3-1 = 2 lines
|
||||
expect(lastFrame()).toContain('Line 1');
|
||||
expect(lastFrame()).toContain('Line 2');
|
||||
@@ -71,7 +68,7 @@ describe('<SlicingMaxSizedBox />', () => {
|
||||
|
||||
it('slices array data when maxLines is provided', async () => {
|
||||
const dataArray = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'];
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<SlicingMaxSizedBox
|
||||
data={dataArray}
|
||||
@@ -90,7 +87,6 @@ describe('<SlicingMaxSizedBox />', () => {
|
||||
</SlicingMaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
// maxLines=3, so it should keep 3-1 = 2 items
|
||||
expect(lastFrame()).toContain('Item 1');
|
||||
expect(lastFrame()).toContain('Item 2');
|
||||
@@ -103,7 +99,7 @@ describe('<SlicingMaxSizedBox />', () => {
|
||||
|
||||
it('does not slice when isAlternateBuffer is true', async () => {
|
||||
const multilineString = 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5';
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<OverflowProvider>
|
||||
<SlicingMaxSizedBox
|
||||
data={multilineString}
|
||||
@@ -115,7 +111,6 @@ describe('<SlicingMaxSizedBox />', () => {
|
||||
</SlicingMaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('Line 5');
|
||||
expect(lastFrame()).not.toContain('hidden');
|
||||
unmount();
|
||||
|
||||
@@ -17,22 +17,20 @@ const MOCK_TABS: Tab[] = [
|
||||
describe('TabHeader', () => {
|
||||
describe('rendering', () => {
|
||||
it('renders null for single tab', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader
|
||||
tabs={[{ key: '0', header: 'Only Tab' }]}
|
||||
currentIndex={0}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame({ allowEmpty: true })).toBe('');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders all tab headers', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
expect(frame).toContain('Tab 1');
|
||||
expect(frame).toContain('Tab 2');
|
||||
@@ -42,10 +40,9 @@ describe('TabHeader', () => {
|
||||
});
|
||||
|
||||
it('renders separators between tabs', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
// Should have 2 separators for 3 tabs
|
||||
const separatorCount = (frame?.match(/│/g) || []).length;
|
||||
@@ -57,10 +54,9 @@ describe('TabHeader', () => {
|
||||
|
||||
describe('arrows', () => {
|
||||
it('shows arrows by default', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
expect(frame).toContain('←');
|
||||
expect(frame).toContain('→');
|
||||
@@ -69,10 +65,9 @@ describe('TabHeader', () => {
|
||||
});
|
||||
|
||||
it('hides arrows when showArrows is false', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader tabs={MOCK_TABS} currentIndex={0} showArrows={false} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
expect(frame).not.toContain('←');
|
||||
expect(frame).not.toContain('→');
|
||||
@@ -83,10 +78,9 @@ describe('TabHeader', () => {
|
||||
|
||||
describe('status icons', () => {
|
||||
it('shows status icons by default', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
// Default uncompleted icon is □
|
||||
expect(frame).toContain('□');
|
||||
@@ -95,10 +89,9 @@ describe('TabHeader', () => {
|
||||
});
|
||||
|
||||
it('hides status icons when showStatusIcons is false', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader tabs={MOCK_TABS} currentIndex={0} showStatusIcons={false} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
expect(frame).not.toContain('□');
|
||||
expect(frame).not.toContain('✓');
|
||||
@@ -107,14 +100,13 @@ describe('TabHeader', () => {
|
||||
});
|
||||
|
||||
it('shows checkmark for completed tabs', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader
|
||||
tabs={MOCK_TABS}
|
||||
currentIndex={0}
|
||||
completedIndices={new Set([0, 2])}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
// Should have 2 checkmarks and 1 box
|
||||
const checkmarkCount = (frame?.match(/✓/g) || []).length;
|
||||
@@ -130,10 +122,9 @@ describe('TabHeader', () => {
|
||||
{ key: '0', header: 'Tab 1' },
|
||||
{ key: '1', header: 'Review', isSpecial: true },
|
||||
];
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader tabs={tabsWithSpecial} currentIndex={0} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
// Special tab shows ≡ icon
|
||||
expect(frame).toContain('≡');
|
||||
@@ -146,10 +137,9 @@ describe('TabHeader', () => {
|
||||
{ key: '0', header: 'Tab 1', statusIcon: '★' },
|
||||
{ key: '1', header: 'Tab 2' },
|
||||
];
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader tabs={tabsWithCustomIcon} currentIndex={0} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
expect(frame).toContain('★');
|
||||
expect(frame).toMatchSnapshot();
|
||||
@@ -158,14 +148,13 @@ describe('TabHeader', () => {
|
||||
|
||||
it('uses custom renderStatusIcon when provided', async () => {
|
||||
const renderStatusIcon = () => '•';
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader
|
||||
tabs={MOCK_TABS}
|
||||
currentIndex={0}
|
||||
renderStatusIcon={renderStatusIcon}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
const bulletCount = (frame?.match(/•/g) || []).length;
|
||||
expect(bulletCount).toBe(3);
|
||||
@@ -178,10 +167,9 @@ describe('TabHeader', () => {
|
||||
{ key: '0', header: 'ThisIsAVeryLongHeaderThatShouldBeTruncated' },
|
||||
{ key: '1', header: 'AnotherVeryLongHeader' },
|
||||
];
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader tabs={longTabs} currentIndex={0} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
|
||||
// Current tab (index 0) should NOT be truncated
|
||||
@@ -197,14 +185,13 @@ describe('TabHeader', () => {
|
||||
|
||||
it('falls back to default when renderStatusIcon returns undefined', async () => {
|
||||
const renderStatusIcon = () => undefined;
|
||||
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
|
||||
const { lastFrame, unmount } = await renderWithProviders(
|
||||
<TabHeader
|
||||
tabs={MOCK_TABS}
|
||||
currentIndex={0}
|
||||
renderStatusIcon={renderStatusIcon}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
expect(frame).toContain('□');
|
||||
expect(frame).toMatchSnapshot();
|
||||
|
||||
@@ -129,14 +129,13 @@ describe('TextInput', () => {
|
||||
handleInput: vi.fn(),
|
||||
setText: vi.fn(),
|
||||
};
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<TextInput
|
||||
buffer={buffer as unknown as TextBuffer}
|
||||
onSubmit={onSubmit}
|
||||
onCancel={onCancel}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('test');
|
||||
unmount();
|
||||
});
|
||||
@@ -151,7 +150,7 @@ describe('TextInput', () => {
|
||||
handleInput: vi.fn(),
|
||||
setText: vi.fn(),
|
||||
};
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<TextInput
|
||||
buffer={buffer as unknown as TextBuffer}
|
||||
placeholder="testing"
|
||||
@@ -159,16 +158,14 @@ describe('TextInput', () => {
|
||||
onCancel={onCancel}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('testing');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('handles character input', async () => {
|
||||
const { waitUntilReady, unmount } = render(
|
||||
const { waitUntilReady, unmount } = await render(
|
||||
<TextInput buffer={mockBuffer} onSubmit={onSubmit} onCancel={onCancel} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const keypressHandler = mockedUseKeypress.mock.calls[0][0];
|
||||
|
||||
await act(async () => {
|
||||
@@ -197,10 +194,9 @@ describe('TextInput', () => {
|
||||
|
||||
it('handles backspace', async () => {
|
||||
mockBuffer.setText('test');
|
||||
const { waitUntilReady, unmount } = render(
|
||||
const { waitUntilReady, unmount } = await render(
|
||||
<TextInput buffer={mockBuffer} onSubmit={onSubmit} onCancel={onCancel} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const keypressHandler = mockedUseKeypress.mock.calls[0][0];
|
||||
|
||||
await act(async () => {
|
||||
@@ -229,10 +225,9 @@ describe('TextInput', () => {
|
||||
|
||||
it('handles left arrow', async () => {
|
||||
mockBuffer.setText('test');
|
||||
const { waitUntilReady, unmount } = render(
|
||||
const { waitUntilReady, unmount } = await render(
|
||||
<TextInput buffer={mockBuffer} onSubmit={onSubmit} onCancel={onCancel} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const keypressHandler = mockedUseKeypress.mock.calls[0][0];
|
||||
|
||||
await act(async () => {
|
||||
@@ -255,10 +250,9 @@ describe('TextInput', () => {
|
||||
it('handles right arrow', async () => {
|
||||
mockBuffer.setText('test');
|
||||
mockBuffer.visualCursor[1] = 2; // Set initial cursor for right arrow test
|
||||
const { waitUntilReady, unmount } = render(
|
||||
const { waitUntilReady, unmount } = await render(
|
||||
<TextInput buffer={mockBuffer} onSubmit={onSubmit} onCancel={onCancel} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const keypressHandler = mockedUseKeypress.mock.calls[0][0];
|
||||
|
||||
await act(async () => {
|
||||
@@ -279,10 +273,9 @@ describe('TextInput', () => {
|
||||
|
||||
it('calls onSubmit on return', async () => {
|
||||
mockBuffer.setText('test');
|
||||
const { waitUntilReady, unmount } = render(
|
||||
const { waitUntilReady, unmount } = await render(
|
||||
<TextInput buffer={mockBuffer} onSubmit={onSubmit} onCancel={onCancel} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const keypressHandler = mockedUseKeypress.mock.calls[0][0];
|
||||
|
||||
await act(async () => {
|
||||
@@ -306,10 +299,9 @@ describe('TextInput', () => {
|
||||
const realContent = 'line1\nline2\nline3\nline4\nline5\nline6';
|
||||
mockBuffer.setText(placeholder);
|
||||
mockBuffer.pastedContent = { [placeholder]: realContent };
|
||||
const { waitUntilReady, unmount } = render(
|
||||
const { waitUntilReady, unmount } = await render(
|
||||
<TextInput buffer={mockBuffer} onSubmit={onSubmit} onCancel={onCancel} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const keypressHandler = mockedUseKeypress.mock.calls[0][0];
|
||||
|
||||
await act(async () => {
|
||||
@@ -331,10 +323,9 @@ describe('TextInput', () => {
|
||||
it('submits text unchanged when pastedContent is empty', async () => {
|
||||
mockBuffer.setText('normal text');
|
||||
mockBuffer.pastedContent = {};
|
||||
const { waitUntilReady, unmount } = render(
|
||||
const { waitUntilReady, unmount } = await render(
|
||||
<TextInput buffer={mockBuffer} onSubmit={onSubmit} onCancel={onCancel} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const keypressHandler = mockedUseKeypress.mock.calls[0][0];
|
||||
|
||||
await act(async () => {
|
||||
@@ -355,10 +346,9 @@ describe('TextInput', () => {
|
||||
|
||||
it('calls onCancel on escape', async () => {
|
||||
vi.useFakeTimers();
|
||||
const { waitUntilReady, unmount } = render(
|
||||
const { waitUntilReady, unmount } = await render(
|
||||
<TextInput buffer={mockBuffer} onCancel={onCancel} onSubmit={onSubmit} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const keypressHandler = mockedUseKeypress.mock.calls[0][0];
|
||||
|
||||
await act(async () => {
|
||||
@@ -385,17 +375,16 @@ describe('TextInput', () => {
|
||||
|
||||
it('renders the input value', async () => {
|
||||
mockBuffer.setText('secret');
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<TextInput buffer={mockBuffer} onSubmit={onSubmit} onCancel={onCancel} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('secret');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('does not show cursor when not focused', async () => {
|
||||
mockBuffer.setText('test');
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<TextInput
|
||||
buffer={mockBuffer}
|
||||
focus={false}
|
||||
@@ -403,7 +392,6 @@ describe('TextInput', () => {
|
||||
onCancel={onCancel}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).not.toContain('\u001b[7m'); // Inverse video chalk
|
||||
unmount();
|
||||
});
|
||||
@@ -412,10 +400,9 @@ describe('TextInput', () => {
|
||||
mockBuffer.text = 'line1\nline2';
|
||||
mockBuffer.viewportVisualLines = ['line1', 'line2'];
|
||||
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<TextInput buffer={mockBuffer} onSubmit={onSubmit} onCancel={onCancel} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(lastFrame()).toContain('line1');
|
||||
expect(lastFrame()).toContain('line2');
|
||||
|
||||
@@ -59,7 +59,7 @@ describe('<VirtualizedList />', () => {
|
||||
])(
|
||||
'renders only visible items ($name)',
|
||||
async ({ initialScrollIndex, visible, notVisible }) => {
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<Box height={10} width={100} borderStyle="round">
|
||||
<VirtualizedList
|
||||
data={longData}
|
||||
@@ -70,22 +70,21 @@ describe('<VirtualizedList />', () => {
|
||||
/>
|
||||
</Box>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
const frame = lastFrame();
|
||||
const output = lastFrame();
|
||||
visible.forEach((item) => {
|
||||
expect(frame).toContain(item);
|
||||
expect(output).toContain(item);
|
||||
});
|
||||
notVisible.forEach((item) => {
|
||||
expect(frame).not.toContain(item);
|
||||
expect(output).not.toContain(item);
|
||||
});
|
||||
expect(frame).toMatchSnapshot();
|
||||
expect(output).toMatchSnapshot();
|
||||
unmount();
|
||||
},
|
||||
);
|
||||
|
||||
it('sticks to bottom when new items added', async () => {
|
||||
const { lastFrame, rerender, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, rerender, waitUntilReady, unmount } = await render(
|
||||
<Box height={10} width={100} borderStyle="round">
|
||||
<VirtualizedList
|
||||
data={longData}
|
||||
@@ -96,7 +95,6 @@ describe('<VirtualizedList />', () => {
|
||||
/>
|
||||
</Box>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(lastFrame()).toContain('Item 99');
|
||||
|
||||
@@ -126,7 +124,7 @@ describe('<VirtualizedList />', () => {
|
||||
|
||||
it('scrolls down to show new items when requested via ref', async () => {
|
||||
const ref = createRef<VirtualizedListRef<string>>();
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = await render(
|
||||
<Box height={10} width={100} borderStyle="round">
|
||||
<VirtualizedList
|
||||
ref={ref}
|
||||
@@ -137,7 +135,6 @@ describe('<VirtualizedList />', () => {
|
||||
/>
|
||||
</Box>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(lastFrame()).toContain('Item 0');
|
||||
|
||||
@@ -180,7 +177,7 @@ describe('<VirtualizedList />', () => {
|
||||
(_, i) => `Item ${i}`,
|
||||
);
|
||||
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<Box height={20} width={100} borderStyle="round">
|
||||
<VirtualizedList
|
||||
data={veryLongData}
|
||||
@@ -193,7 +190,6 @@ describe('<VirtualizedList />', () => {
|
||||
/>
|
||||
</Box>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
const frame = lastFrame();
|
||||
expect(mountedCount).toBe(expectedMountedCount);
|
||||
@@ -262,8 +258,9 @@ describe('<VirtualizedList />', () => {
|
||||
return null;
|
||||
};
|
||||
|
||||
const { lastFrame, waitUntilReady, unmount } = render(<TestComponent />);
|
||||
await waitUntilReady();
|
||||
const { lastFrame, unmount, waitUntilReady } = await render(
|
||||
<TestComponent />,
|
||||
);
|
||||
|
||||
// Initially, only Item 0 (height 10) fills the 10px viewport
|
||||
expect(lastFrame()).toContain('Item 0');
|
||||
@@ -295,7 +292,7 @@ describe('<VirtualizedList />', () => {
|
||||
);
|
||||
const keyExtractor = (item: string) => item;
|
||||
|
||||
const { waitUntilReady, unmount } = render(
|
||||
const { unmount, waitUntilReady } = await render(
|
||||
<Box height={10} width={100} borderStyle="round">
|
||||
<VirtualizedList
|
||||
ref={ref}
|
||||
@@ -306,7 +303,6 @@ describe('<VirtualizedList />', () => {
|
||||
/>
|
||||
</Box>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(ref.current?.getScrollState().scrollTop).toBe(0);
|
||||
|
||||
@@ -335,7 +331,7 @@ describe('<VirtualizedList />', () => {
|
||||
|
||||
const longData = Array.from({ length: 100 }, (_, i) => `Item ${i}`);
|
||||
// Use copy mode
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<Box height={10} width={100}>
|
||||
<VirtualizedList
|
||||
data={longData}
|
||||
@@ -350,7 +346,6 @@ describe('<VirtualizedList />', () => {
|
||||
/>
|
||||
</Box>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
// Item 50 should be visible
|
||||
expect(lastFrame()).toContain('Item 50');
|
||||
|
||||
@@ -14,9 +14,9 @@ describe('text-buffer performance', () => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should handle pasting large amounts of text efficiently', () => {
|
||||
it('should handle pasting large amounts of text efficiently', async () => {
|
||||
const viewport = { width: 80, height: 24 };
|
||||
const { result } = renderHook(() =>
|
||||
const { result } = await renderHook(() =>
|
||||
useTextBuffer({
|
||||
viewport,
|
||||
}),
|
||||
@@ -39,7 +39,7 @@ describe('text-buffer performance', () => {
|
||||
expect(duration).toBeLessThan(5000);
|
||||
});
|
||||
|
||||
it('should handle character-by-character insertion in a large buffer efficiently', () => {
|
||||
it('should handle character-by-character insertion in a large buffer efficiently', async () => {
|
||||
const lines = 5000;
|
||||
const initialText = Array.from(
|
||||
{ length: lines },
|
||||
@@ -47,7 +47,7 @@ describe('text-buffer performance', () => {
|
||||
).join('\n');
|
||||
const viewport = { width: 80, height: 24 };
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
const { result } = await renderHook(() =>
|
||||
useTextBuffer({
|
||||
initialText,
|
||||
viewport,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user