mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-24 12:04:56 -07:00
Migrate core render util to use xterm.js as part of the rendering loop. (#19044)
This commit is contained in:
@@ -33,10 +33,7 @@ describe('ToolResultDisplay', () => {
|
||||
mockUseAlternateBuffer.mockReturnValue(false);
|
||||
});
|
||||
|
||||
// Helper to use renderWithProviders
|
||||
const render = (ui: React.ReactElement) => renderWithProviders(ui);
|
||||
|
||||
it('uses ScrollableList for ANSI output in alternate buffer mode', () => {
|
||||
it('uses ScrollableList for ANSI output in alternate buffer mode', async () => {
|
||||
mockUseAlternateBuffer.mockReturnValue(true);
|
||||
const content = 'ansi content';
|
||||
const ansiResult: AnsiOutput = [
|
||||
@@ -53,57 +50,65 @@ describe('ToolResultDisplay', () => {
|
||||
},
|
||||
],
|
||||
];
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay={ansiResult}
|
||||
terminalWidth={80}
|
||||
maxLines={10}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toContain(content);
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('uses Scrollable for non-ANSI output in alternate buffer mode', () => {
|
||||
it('uses Scrollable for non-ANSI output in alternate buffer mode', async () => {
|
||||
mockUseAlternateBuffer.mockReturnValue(true);
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay="**Markdown content**"
|
||||
terminalWidth={80}
|
||||
maxLines={10}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
// With real components, we check for the content itself
|
||||
expect(output).toContain('Markdown content');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('passes hasFocus prop to scrollable components', () => {
|
||||
it('passes hasFocus prop to scrollable components', async () => {
|
||||
mockUseAlternateBuffer.mockReturnValue(true);
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay="Some result"
|
||||
terminalWidth={80}
|
||||
hasFocus={true}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(lastFrame()).toContain('Some result');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders string result as markdown by default', () => {
|
||||
const { lastFrame } = render(
|
||||
it('renders string result as markdown by default', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay resultDisplay="**Some result**" terminalWidth={80} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders string result as plain text when renderOutputAsMarkdown is false', () => {
|
||||
const { lastFrame } = render(
|
||||
it('renders string result as plain text when renderOutputAsMarkdown is false', async () => {
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay="**Some result**"
|
||||
terminalWidth={80}
|
||||
@@ -111,43 +116,49 @@ describe('ToolResultDisplay', () => {
|
||||
renderOutputAsMarkdown={false}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('truncates very long string results', { timeout: 20000 }, () => {
|
||||
it('truncates very long string results', { timeout: 20000 }, async () => {
|
||||
const longString = 'a'.repeat(1000005);
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay={longString}
|
||||
terminalWidth={80}
|
||||
availableTerminalHeight={20}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders file diff result', () => {
|
||||
it('renders file diff result', async () => {
|
||||
const diffResult = {
|
||||
fileDiff: 'diff content',
|
||||
fileName: 'test.ts',
|
||||
};
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay={diffResult}
|
||||
terminalWidth={80}
|
||||
availableTerminalHeight={20}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders ANSI output result', () => {
|
||||
it('renders ANSI output result', async () => {
|
||||
const ansiResult: AnsiOutput = [
|
||||
[
|
||||
{
|
||||
@@ -162,38 +173,42 @@ describe('ToolResultDisplay', () => {
|
||||
},
|
||||
],
|
||||
];
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay={ansiResult as unknown as AnsiOutput}
|
||||
terminalWidth={80}
|
||||
availableTerminalHeight={20}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders nothing for todos result', () => {
|
||||
it('renders nothing for todos result', async () => {
|
||||
const todoResult = {
|
||||
todos: [],
|
||||
};
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay={todoResult}
|
||||
terminalWidth={80}
|
||||
availableTerminalHeight={20}
|
||||
/>,
|
||||
);
|
||||
const output = lastFrame();
|
||||
await waitUntilReady();
|
||||
const output = lastFrame({ allowEmpty: true });
|
||||
|
||||
expect(output).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('does not fall back to plain text if availableHeight is set and not in alternate buffer', () => {
|
||||
it('does not fall back to plain text if availableHeight is set and not in alternate buffer', async () => {
|
||||
mockUseAlternateBuffer.mockReturnValue(false);
|
||||
// availableHeight calculation: 20 - 1 - 5 = 14 > 3
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay="**Some result**"
|
||||
terminalWidth={80}
|
||||
@@ -201,13 +216,15 @@ describe('ToolResultDisplay', () => {
|
||||
renderOutputAsMarkdown={true}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
expect(output).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('keeps markdown if in alternate buffer even with availableHeight', () => {
|
||||
it('keeps markdown if in alternate buffer even with availableHeight', async () => {
|
||||
mockUseAlternateBuffer.mockReturnValue(true);
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay="**Some result**"
|
||||
terminalWidth={80}
|
||||
@@ -215,12 +232,14 @@ describe('ToolResultDisplay', () => {
|
||||
renderOutputAsMarkdown={true}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('truncates ANSI output when maxLines is provided', () => {
|
||||
it('truncates ANSI output when maxLines is provided', async () => {
|
||||
const ansiResult: AnsiOutput = [
|
||||
[
|
||||
{
|
||||
@@ -259,7 +278,7 @@ describe('ToolResultDisplay', () => {
|
||||
},
|
||||
],
|
||||
];
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay={ansiResult}
|
||||
terminalWidth={80}
|
||||
@@ -267,14 +286,16 @@ describe('ToolResultDisplay', () => {
|
||||
maxLines={2}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).not.toContain('Line 1');
|
||||
expect(output).toContain('Line 2');
|
||||
expect(output).toContain('Line 3');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('truncates ANSI output when maxLines is provided, even if availableTerminalHeight is undefined', () => {
|
||||
it('truncates ANSI output when maxLines is provided, even if availableTerminalHeight is undefined', async () => {
|
||||
const ansiResult: AnsiOutput = Array.from({ length: 50 }, (_, i) => [
|
||||
{
|
||||
text: `Line ${i + 1}`,
|
||||
@@ -287,7 +308,7 @@ describe('ToolResultDisplay', () => {
|
||||
inverse: false,
|
||||
},
|
||||
]);
|
||||
const { lastFrame } = render(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay={ansiResult}
|
||||
terminalWidth={80}
|
||||
@@ -295,10 +316,12 @@ describe('ToolResultDisplay', () => {
|
||||
availableTerminalHeight={undefined}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
// It SHOULD truncate to 25 lines because maxLines is provided
|
||||
expect(output).not.toContain('Line 1');
|
||||
expect(output).toContain('Line 50');
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user