Migrate core render util to use xterm.js as part of the rendering loop. (#19044)

This commit is contained in:
Jacob Richman
2026-02-18 16:46:50 -08:00
committed by GitHub
parent 04c52513e7
commit 04f65f3d55
213 changed files with 7065 additions and 3852 deletions

View File

@@ -7,7 +7,7 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { Box } from 'ink';
import { ToolConfirmationQueue } from './ToolConfirmationQueue.js';
import { StreamingState, ToolCallStatus } from '../types.js';
import { StreamingState } from '../types.js';
import { renderWithProviders } from '../../test-utils/render.js';
import { waitFor } from '../../test-utils/async.js';
import { type Config, CoreToolCallStatus } from '@google/gemini-cli-core';
@@ -57,7 +57,7 @@ describe('ToolConfirmationQueue', () => {
vi.clearAllMocks();
});
it('renders the confirming tool with progress indicator', () => {
it('renders the confirming tool with progress indicator', async () => {
const confirmingTool = {
tool: {
callId: 'call-1',
@@ -76,7 +76,7 @@ describe('ToolConfirmationQueue', () => {
total: 3,
};
const { lastFrame } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@@ -87,6 +87,7 @@ describe('ToolConfirmationQueue', () => {
},
},
);
await waitUntilReady();
const output = lastFrame();
expect(output).toContain('Action Required');
@@ -98,9 +99,10 @@ describe('ToolConfirmationQueue', () => {
const stickyHeaderProps = vi.mocked(StickyHeader).mock.calls[0][0];
expect(stickyHeaderProps.borderColor).toBe(theme.status.warning);
unmount();
});
it('returns null if tool has no confirmation details', () => {
it('returns null if tool has no confirmation details', async () => {
const confirmingTool = {
tool: {
callId: 'call-1',
@@ -112,7 +114,7 @@ describe('ToolConfirmationQueue', () => {
total: 1,
};
const { lastFrame } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@@ -123,8 +125,10 @@ describe('ToolConfirmationQueue', () => {
},
},
);
await waitUntilReady();
expect(lastFrame()).toBe('');
expect(lastFrame({ allowEmpty: true })).toBe('');
unmount();
});
it('renders expansion hint when content is long and constrained', async () => {
@@ -149,7 +153,7 @@ describe('ToolConfirmationQueue', () => {
total: 1,
};
const { lastFrame } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<Box flexDirection="column" height={30}>
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
@@ -166,12 +170,14 @@ describe('ToolConfirmationQueue', () => {
},
},
);
await waitUntilReady();
await waitFor(() =>
expect(lastFrame()).toContain('Press ctrl-o to show more lines'),
);
expect(lastFrame()).toMatchSnapshot();
expect(lastFrame()).toContain('Press ctrl-o to show more lines');
unmount();
});
it('calculates availableContentHeight based on availableTerminalHeight from UI state', async () => {
@@ -197,7 +203,7 @@ describe('ToolConfirmationQueue', () => {
};
// Use a small availableTerminalHeight to force truncation
const { lastFrame } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@@ -213,6 +219,7 @@ describe('ToolConfirmationQueue', () => {
},
},
);
await waitUntilReady();
// With availableTerminalHeight = 10:
// maxHeight = Math.max(10 - 1, 4) = 9
@@ -221,6 +228,7 @@ describe('ToolConfirmationQueue', () => {
// It should show truncation message
await waitFor(() => expect(lastFrame()).toContain('first 49 lines hidden'));
expect(lastFrame()).toMatchSnapshot();
unmount();
});
it('provides more height for ask_user by subtracting less overhead', async () => {
@@ -229,7 +237,7 @@ describe('ToolConfirmationQueue', () => {
callId: 'call-1',
name: 'ask_user',
description: 'ask user',
status: ToolCallStatus.Confirming,
status: CoreToolCallStatus.AwaitingApproval,
confirmationDetails: {
type: 'ask_user' as const,
questions: [
@@ -246,7 +254,7 @@ describe('ToolConfirmationQueue', () => {
total: 1,
};
const { lastFrame } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@@ -261,6 +269,7 @@ describe('ToolConfirmationQueue', () => {
},
},
);
await waitUntilReady();
// Calculation:
// availableTerminalHeight: 20 -> maxHeight: 19 (20-1)
@@ -273,9 +282,10 @@ describe('ToolConfirmationQueue', () => {
expect(lastFrame()).not.toContain('lines hidden');
});
expect(lastFrame()).toMatchSnapshot();
unmount();
});
it('does not render expansion hint when constrainHeight is false', () => {
it('does not render expansion hint when constrainHeight is false', async () => {
const longDiff = 'line\n'.repeat(50);
const confirmingTool = {
tool: {
@@ -297,7 +307,7 @@ describe('ToolConfirmationQueue', () => {
total: 1,
};
const { lastFrame } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@@ -311,13 +321,15 @@ describe('ToolConfirmationQueue', () => {
},
},
);
await waitUntilReady();
const output = lastFrame();
expect(output).not.toContain('Press ctrl-o to show more lines');
expect(output).toMatchSnapshot();
unmount();
});
it('renders AskUser tool confirmation with Success color', () => {
it('renders AskUser tool confirmation with Success color', async () => {
const confirmingTool = {
tool: {
callId: 'call-1',
@@ -334,7 +346,7 @@ describe('ToolConfirmationQueue', () => {
total: 1,
};
const { lastFrame } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@@ -345,12 +357,14 @@ describe('ToolConfirmationQueue', () => {
},
},
);
await waitUntilReady();
const output = lastFrame();
expect(output).toMatchSnapshot();
const stickyHeaderProps = vi.mocked(StickyHeader).mock.calls[0][0];
expect(stickyHeaderProps.borderColor).toBe(theme.status.success);
unmount();
});
it('renders ExitPlanMode tool confirmation with Success color', async () => {
@@ -370,7 +384,7 @@ describe('ToolConfirmationQueue', () => {
total: 1,
};
const { lastFrame } = renderWithProviders(
const { lastFrame, unmount } = renderWithProviders(
<ToolConfirmationQueue
confirmingTool={confirmingTool as unknown as ConfirmingToolState}
/>,
@@ -391,5 +405,6 @@ describe('ToolConfirmationQueue', () => {
const stickyHeaderProps = vi.mocked(StickyHeader).mock.calls[0][0];
expect(stickyHeaderProps.borderColor).toBe(theme.status.success);
unmount();
});
});