mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-01 00:40:42 -07:00
Migrate core render util to use xterm.js as part of the rendering loop. (#19044)
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import { render, renderWithProviders } from '../../../test-utils/render.js';
|
||||
import { waitFor } from '../../../test-utils/async.js';
|
||||
import { OverflowProvider } from '../../contexts/OverflowContext.js';
|
||||
import { MaxSizedBox } from './MaxSizedBox.js';
|
||||
import { MarkdownDisplay } from '../../utils/MarkdownDisplay.js';
|
||||
@@ -14,7 +13,7 @@ import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('<MaxSizedBox />', () => {
|
||||
it('renders children without truncation when they fit', async () => {
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={10}>
|
||||
<Box>
|
||||
@@ -23,13 +22,14 @@ describe('<MaxSizedBox />', () => {
|
||||
</MaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitFor(() => expect(lastFrame()).toContain('Hello, World!'));
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('Hello, World!');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('hides lines when content exceeds maxHeight', async () => {
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={2}>
|
||||
<Box flexDirection="column">
|
||||
@@ -40,15 +40,14 @@ describe('<MaxSizedBox />', () => {
|
||||
</MaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(lastFrame()).toContain('... first 2 lines hidden ...'),
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('... first 2 lines hidden ...');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('hides lines at the end when content exceeds maxHeight and overflowDirection is bottom', async () => {
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={2} overflowDirection="bottom">
|
||||
<Box flexDirection="column">
|
||||
@@ -59,15 +58,14 @@ describe('<MaxSizedBox />', () => {
|
||||
</MaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(lastFrame()).toContain('... last 2 lines hidden ...'),
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('... last 2 lines hidden ...');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('shows plural "lines" when more than one line is hidden', async () => {
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={2}>
|
||||
<Box flexDirection="column">
|
||||
@@ -78,15 +76,14 @@ describe('<MaxSizedBox />', () => {
|
||||
</MaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(lastFrame()).toContain('... first 2 lines hidden ...'),
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('... first 2 lines hidden ...');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('shows singular "line" when exactly one line is hidden', async () => {
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={2} additionalHiddenLinesCount={1}>
|
||||
<Box flexDirection="column">
|
||||
@@ -95,15 +92,14 @@ describe('<MaxSizedBox />', () => {
|
||||
</MaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(lastFrame()).toContain('... first 1 line hidden ...'),
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('... first 1 line hidden ...');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('accounts for additionalHiddenLinesCount', async () => {
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={2} additionalHiddenLinesCount={5}>
|
||||
<Box flexDirection="column">
|
||||
@@ -114,15 +110,14 @@ describe('<MaxSizedBox />', () => {
|
||||
</MaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(lastFrame()).toContain('... first 7 lines hidden ...'),
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('... first 7 lines hidden ...');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('wraps text that exceeds maxWidth', async () => {
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={10} maxHeight={5}>
|
||||
<Box>
|
||||
@@ -132,13 +127,14 @@ describe('<MaxSizedBox />', () => {
|
||||
</OverflowProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() => expect(lastFrame()).toContain('This is a'));
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('This is a');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('does not truncate when maxHeight is undefined', async () => {
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={undefined}>
|
||||
<Box flexDirection="column">
|
||||
@@ -148,25 +144,25 @@ describe('<MaxSizedBox />', () => {
|
||||
</MaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitFor(() => expect(lastFrame()).toContain('Line 1'));
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('Line 1');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders an empty box for empty children', async () => {
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={10}></MaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
// Use waitFor to ensure ResizeObserver has a chance to run
|
||||
await waitFor(() => expect(lastFrame()).toBeDefined());
|
||||
expect(lastFrame()?.trim()).equals('');
|
||||
await waitUntilReady();
|
||||
expect(lastFrame({ allowEmpty: true })?.trim()).equals('');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('handles React.Fragment as a child', async () => {
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={10}>
|
||||
<Box flexDirection="column">
|
||||
@@ -179,7 +175,8 @@ describe('<MaxSizedBox />', () => {
|
||||
</MaxSizedBox>
|
||||
</OverflowProvider>,
|
||||
);
|
||||
await waitFor(() => expect(lastFrame()).toContain('Line 1 from Fragment'));
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('Line 1 from Fragment');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
@@ -189,7 +186,7 @@ describe('<MaxSizedBox />', () => {
|
||||
{ length: 30 },
|
||||
(_, i) => `Line ${i + 1}`,
|
||||
).join('\n');
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={10} overflowDirection="top">
|
||||
<Box>
|
||||
@@ -199,9 +196,8 @@ describe('<MaxSizedBox />', () => {
|
||||
</OverflowProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(lastFrame()).toContain('... first 21 lines hidden ...'),
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('... first 21 lines hidden ...');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
@@ -211,7 +207,7 @@ describe('<MaxSizedBox />', () => {
|
||||
{ length: 30 },
|
||||
(_, i) => `Line ${i + 1}`,
|
||||
).join('\n');
|
||||
const { lastFrame, unmount } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
<OverflowProvider>
|
||||
<MaxSizedBox maxWidth={80} maxHeight={10} overflowDirection="bottom">
|
||||
<Box>
|
||||
@@ -221,9 +217,8 @@ describe('<MaxSizedBox />', () => {
|
||||
</OverflowProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(lastFrame()).toContain('... last 21 lines hidden ...'),
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('... last 21 lines hidden ...');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
@@ -233,7 +228,7 @@ describe('<MaxSizedBox />', () => {
|
||||
{ length: 20 },
|
||||
(_, i) => `- Step ${i + 1}: Do something important`,
|
||||
).join('\n');
|
||||
const { lastFrame } = renderWithProviders(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<MaxSizedBox maxWidth={80} maxHeight={5} overflowDirection="bottom">
|
||||
<MarkdownDisplay
|
||||
text={`## Plan\n\n${markdownContent}`}
|
||||
@@ -244,14 +239,16 @@ describe('<MaxSizedBox />', () => {
|
||||
{ width: 80 },
|
||||
);
|
||||
|
||||
await waitFor(() => expect(lastFrame()).toContain('... last'));
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('... last');
|
||||
|
||||
const frame = lastFrame()!;
|
||||
const lines = frame.split('\n');
|
||||
const frame = lastFrame();
|
||||
const lines = frame.trim().split('\n');
|
||||
const lastLine = lines[lines.length - 1];
|
||||
|
||||
// The last line should only contain the hidden indicator, no leaked content
|
||||
expect(lastLine).toMatch(/^\.\.\. last \d+ lines? hidden \.\.\.$/);
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user