mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-16 23:02:51 -07:00
test(cli): fix App tests and run only App.test.tsx in CI
This commit is contained in:
@@ -27,7 +27,7 @@ jobs:
|
||||
mode: 'source'
|
||||
|
||||
- name: 'Run Suspect Tests'
|
||||
run: 'npx vitest run --pool=forks packages/cli/src/test-utils/render.test.tsx packages/cli/src/ui/App.test.tsx packages/cli/src/test-utils/AppRig.test.tsx packages/cli/src/ui/components/SettingsDialog.test.tsx packages/cli/src/ui/components/messages/DiffRenderer.test.tsx packages/cli/src/ui/components/messages/ThinkingMessage.test.tsx packages/cli/src/ui/components/messages/ToolResultDisplay.test.tsx packages/cli/src/ui/components/messages/ToolResultDisplayOverflow.test.tsx packages/cli/src/ui/components/messages/UserMessage.test.tsx packages/cli/src/ui/components/shared/SearchableList.test.tsx packages/cli/src/ui/components/shared/TextInput.test.tsx packages/cli/src/ui/components/views/ExtensionRegistryView.test.tsx'
|
||||
run: 'npx vitest run --pool=forks packages/cli/src/ui/App.test.tsx'
|
||||
shell: 'bash'
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
type RenderOptions,
|
||||
} from 'ink';
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { Writable } from 'node:stream';
|
||||
import { Box } from 'ink';
|
||||
import { Terminal } from '@xterm/headless';
|
||||
import { vi } from 'vitest';
|
||||
@@ -110,6 +109,7 @@ class XtermStdout extends EventEmitter {
|
||||
renderCount = 0;
|
||||
private queue: { promise: Promise<void> };
|
||||
isTTY = true;
|
||||
public clearScreenOnRender = true;
|
||||
|
||||
getColorDepth(): number {
|
||||
return 24;
|
||||
@@ -118,10 +118,11 @@ class XtermStdout extends EventEmitter {
|
||||
private lastRenderOutput: string | undefined = undefined;
|
||||
private lastRenderStaticContent: string | undefined = undefined;
|
||||
|
||||
constructor(state: TerminalState, queue: { promise: Promise<void> }) {
|
||||
constructor(state: TerminalState, queue: { promise: Promise<void> }, clearScreenOnRender = true) {
|
||||
super();
|
||||
this.state = state;
|
||||
this.queue = queue;
|
||||
this.clearScreenOnRender = clearScreenOnRender;
|
||||
}
|
||||
|
||||
get columns() {
|
||||
@@ -160,8 +161,11 @@ class XtermStdout extends EventEmitter {
|
||||
this.renderCount++;
|
||||
this.lastRenderStaticContent = staticContent;
|
||||
this.lastRenderOutput = output;
|
||||
// Clear screen and move cursor to home before writing the new frame
|
||||
this.write('\x1b[2J\x1b[H' + staticContent + output);
|
||||
if (this.clearScreenOnRender) {
|
||||
this.write('\x1b[2J\x1b[H' + staticContent + output);
|
||||
} else {
|
||||
this.write(staticContent + output);
|
||||
}
|
||||
this.emit('render');
|
||||
};
|
||||
|
||||
@@ -405,6 +409,7 @@ export const render = async (
|
||||
terminalWidth?: number,
|
||||
terminalHeight?: number,
|
||||
allowEmptyFrame = false,
|
||||
clearScreenOnRender = true,
|
||||
): Promise<
|
||||
Omit<RenderInstance, 'capturedOverflowState' | 'capturedOverflowActions'>
|
||||
> => {
|
||||
@@ -426,21 +431,16 @@ export const render = async (
|
||||
cols,
|
||||
rows,
|
||||
};
|
||||
const writeQueue = { promise: Promise.resolve() };
|
||||
const stdout = new XtermStdout(state, writeQueue);
|
||||
const stderr = new XtermStderr(state, writeQueue);
|
||||
const queue = { promise: Promise.resolve() };
|
||||
const stdout = new XtermStdout(state, queue, clearScreenOnRender);
|
||||
const stderr = new XtermStderr(state, queue);
|
||||
const stdin = new XtermStdin();
|
||||
|
||||
let instance!: InkInstance;
|
||||
stdout.clear();
|
||||
const dummyStdout = new Writable({
|
||||
write(_chunk, _encoding, callback) {
|
||||
callback();
|
||||
},
|
||||
});
|
||||
act(() => {
|
||||
instance = inkRenderDirect(tree, {
|
||||
stdout: dummyStdout as unknown as NodeJS.WriteStream,
|
||||
stdout: stdout as unknown as NodeJS.WriteStream,
|
||||
|
||||
stderr: stderr as unknown as NodeJS.WriteStream,
|
||||
|
||||
@@ -654,6 +654,7 @@ export const renderWithProviders = async (
|
||||
toolActions,
|
||||
persistentState,
|
||||
appState = mockAppState,
|
||||
clearScreenOnRender = true,
|
||||
}: {
|
||||
shellFocus?: boolean;
|
||||
settings?: LoadedSettings;
|
||||
@@ -675,6 +676,7 @@ export const renderWithProviders = async (
|
||||
set?: typeof persistentStateMock.set;
|
||||
};
|
||||
appState?: AppState;
|
||||
clearScreenOnRender?: boolean;
|
||||
} = {},
|
||||
): Promise<RenderWithProvidersInstance> => {
|
||||
const baseState: UIState = new Proxy(
|
||||
@@ -837,6 +839,8 @@ export const renderWithProviders = async (
|
||||
wrapWithProviders(component),
|
||||
terminalWidth,
|
||||
terminalHeight,
|
||||
false,
|
||||
clearScreenOnRender,
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -11,6 +11,10 @@ import { createMockSettings } from '../test-utils/settings.js';
|
||||
import { Text, useIsScreenReaderEnabled, type DOMElement } from 'ink';
|
||||
import { App } from './App.js';
|
||||
import { type UIState } from './contexts/UIStateContext.js';
|
||||
|
||||
vi.mock('./hooks/useTips.js', () => ({
|
||||
useTips: () => ({ showTips: true }),
|
||||
}));
|
||||
import { StreamingState } from './types.js';
|
||||
import { makeFakeConfig, CoreToolCallStatus } from '@google/gemini-cli-core';
|
||||
|
||||
@@ -95,11 +99,27 @@ describe.sequential('App', () => {
|
||||
const { lastFrame, unmount } = await renderWithProviders(<App />, {
|
||||
uiState: mockUIState,
|
||||
settings: createMockSettings({ ui: { useAlternateBuffer: false } }),
|
||||
clearScreenOnRender: false,
|
||||
});
|
||||
|
||||
expect(lastFrame()).toContain('Tips for getting started');
|
||||
expect(lastFrame()).toContain('Notifications');
|
||||
expect(lastFrame()).toContain('Composer');
|
||||
let attempts = 0;
|
||||
let frame = '';
|
||||
while (attempts < 100) {
|
||||
frame = lastFrame();
|
||||
if (
|
||||
frame.includes('Tips for getting started') &&
|
||||
frame.includes('Notifications') &&
|
||||
frame.includes('Composer')
|
||||
) {
|
||||
break;
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
attempts++;
|
||||
}
|
||||
|
||||
expect(frame).toContain('Tips for getting started');
|
||||
expect(frame).toContain('Notifications');
|
||||
expect(frame).toContain('Composer');
|
||||
unmount();
|
||||
});
|
||||
|
||||
|
||||
@@ -37,24 +37,45 @@ Tips for getting started:
|
||||
|
||||
|
||||
|
||||
Notifications
|
||||
|
||||
Composer
|
||||
|
||||
▝▜▄ ▗█▀▀▜▙▝█▛▀▀▌▜██▖▟██▘▜█▘▜██▖▝█▛▝█▛
|
||||
▝▜▄ █▌ █▙▟ ▐█▝█▛▐█ ▐█ ▐█▝█▖█▌ █▌
|
||||
▗▟▀ ▜▙ ▝█▛ █▌▝ ▖▐█ ▐█ ▐█ ▐█ ▝██▌ █▌
|
||||
▝▀ ▀▀▀▀▘▝▀▀▀▀▘▀▀▘ ▀▀▘▀▀▘▀▀▘ ▝▀▀▝▀▀
|
||||
|
||||
Gemini CLI v1.2.3
|
||||
|
||||
|
||||
|
||||
Tips for getting started:
|
||||
1. Create GEMINI.md files to customize your interactions
|
||||
2. /help for more information
|
||||
3. Ask coding questions, edit code or run commands
|
||||
4. Be specific for the best results
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -95,23 +116,6 @@ Footer
|
||||
|
||||
|
||||
|
||||
Tips for getting started:
|
||||
1. Create GEMINI.md files to customize your interactions
|
||||
2. /help for more information
|
||||
3. Ask coding questions, edit code or run commands
|
||||
4. Be specific for the best results
|
||||
ComposerNotifications
|
||||
Footer
|
||||
|
||||
▝▜▄ ▗█▀▀▜▙▝█▛▀▀▌▜██▖▟██▘▜█▘▜██▖▝█▛▝█▛
|
||||
▝▜▄ █▌ █▙▟ ▐█▝█▛▐█ ▐█ ▐█▝█▖█▌ █▌
|
||||
▗▟▀ ▜▙ ▝█▛ █▌▝ ▖▐█ ▐█ ▐█ ▐█ ▝██▌ █▌
|
||||
▝▀ ▀▀▀▀▘▝▀▀▀▀▘▀▀▘ ▀▀▘▀▀▘▀▀▘ ▝▀▀▝▀▀
|
||||
|
||||
Gemini CLI v1.2.3
|
||||
|
||||
|
||||
|
||||
Tips for getting started:
|
||||
1. Create GEMINI.md files to customize your interactions
|
||||
2. /help for more information
|
||||
@@ -132,6 +136,34 @@ exports[`App > Snapshots > renders with dialogs visible 1`] = `
|
||||
|
||||
|
||||
|
||||
Tips for getting started:
|
||||
1. Create GEMINI.md files to customize your interactions
|
||||
2. /help for more information
|
||||
3. Ask coding questions, edit code or run commands
|
||||
4. Be specific for the best results
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -158,16 +190,9 @@ exports[`App > Snapshots > renders with dialogs visible 1`] = `
|
||||
|
||||
|
||||
|
||||
Notifications
|
||||
|
||||
DialogManager
|
||||
|
||||
▝▜▄ ▗█▀▀▜▙▝█▛▀▀▌▜██▖▟██▘▜█▘▜██▖▝█▛▝█▛
|
||||
▝▜▄ █▌ █▙▟ ▐█▝█▛▐█ ▐█ ▐█▝█▖█▌ █▌
|
||||
▗▟▀ ▜▙ ▝█▛ █▌▝ ▖▐█ ▐█ ▐█ ▐█ ▝██▌ █▌
|
||||
▝▀ ▀▀▀▀▘▝▀▀▀▀▘▀▀▘ ▀▀▘▀▀▘▀▀▘ ▝▀▀▝▀▀
|
||||
|
||||
Gemini CLI v1.2.3
|
||||
|
||||
|
||||
|
||||
@@ -220,59 +245,80 @@ Tips for getting started:
|
||||
3. Ask coding questions, edit code or run commands
|
||||
4. Be specific for the best results
|
||||
HistoryItemDisplay
|
||||
╭───────────────────────────────────────────────────────────────────────────────
|
||||
│ Action Required
|
||||
│
|
||||
│ ? ls list directory
|
||||
│
|
||||
│ ╭─────────────────────────────────────────────────────────────────────────────
|
||||
│ │ ls
|
||||
│ ╰─────────────────────────────────────────────────────────────────────────────
|
||||
│ Allow execution of [ls]?
|
||||
│
|
||||
│ ● 1. Allow once
|
||||
│ 2. Allow for this session
|
||||
│ 3. No, suggest changes (esc)
|
||||
╰───────────────────────────────────────────────────────────────────────────────
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Action Required │
|
||||
│ │
|
||||
│ ? ls list directory │
|
||||
│ │
|
||||
│ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │
|
||||
│ │ ls │ │
|
||||
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
|
||||
│ Allow execution of [ls]? │
|
||||
│ │
|
||||
│ ● 1. Allow once │
|
||||
│ 2. Allow for this session │
|
||||
│ 3. No, suggest changes (esc) │
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Notifications
|
||||
|
||||
Composer
|
||||
|
||||
▝▜▄ ▗█▀▀▜▙▝█▛▀▀▌▜██▖▟██▘▜█▘▜██▖▝█▛▝█▛
|
||||
▝▜▄ █▌ █▙▟ ▐█▝█▛▐█ ▐█ ▐█▝█▖█▌ █▌
|
||||
▗▟▀ ▜▙ ▝█▛ █▌▝ ▖▐█ ▐█ ▐█ ▐█ ▝██▌ █▌
|
||||
▝▀ ▀▀▀▀▘▝▀▀▀▀▘▀▀▘ ▀▀▘▀▀▘▀▀▘ ▝▀▀▝▀▀
|
||||
|
||||
Gemini CLI v1.2.3
|
||||
|
||||
|
||||
|
||||
Tips for getting started:
|
||||
1. Create GEMINI.md files to customize your interactions
|
||||
2. /help for more information
|
||||
3. Ask coding questions, edit code or run commands
|
||||
4. Be specific for the best results
|
||||
HistoryItemDisplay
|
||||
╭───────────────────────────────────────────────────────────────────────────────
|
||||
│ Action Required
|
||||
│
|
||||
│ ? ls list directory
|
||||
│
|
||||
│ ╭─────────────────────────────────────────────────────────────────────────────
|
||||
│ │ ls
|
||||
│ ╰─────────────────────────────────────────────────────────────────────────────
|
||||
│ Allow execution of [ls]?
|
||||
│
|
||||
│ ● 1. Allow once
|
||||
│ 2. Allow for this session
|
||||
│ 3. No, suggest changes (esc)
|
||||
╰───────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user