mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-21 10:34:35 -07:00
test: support tests that include color information (#20220)
This commit is contained in:
@@ -51,6 +51,7 @@ import { SessionStatsProvider } from '../ui/contexts/SessionContext.js';
|
||||
import { themeManager, DEFAULT_THEME } from '../ui/themes/theme-manager.js';
|
||||
import { DefaultLight } from '../ui/themes/default-light.js';
|
||||
import { pickDefaultThemeName } from '../ui/themes/theme.js';
|
||||
import { generateSvgForTerminal } from './svg.js';
|
||||
|
||||
export const persistentStateMock = new FakePersistentState();
|
||||
|
||||
@@ -105,7 +106,12 @@ class XtermStdout extends EventEmitter {
|
||||
private queue: { promise: Promise<void> };
|
||||
isTTY = true;
|
||||
|
||||
getColorDepth(): number {
|
||||
return 24;
|
||||
}
|
||||
|
||||
private lastRenderOutput: string | undefined = undefined;
|
||||
private lastRenderStaticContent: string | undefined = undefined;
|
||||
|
||||
constructor(state: TerminalState, queue: { promise: Promise<void> }) {
|
||||
super();
|
||||
@@ -138,6 +144,7 @@ class XtermStdout extends EventEmitter {
|
||||
clear = () => {
|
||||
this.state.terminal.reset();
|
||||
this.lastRenderOutput = undefined;
|
||||
this.lastRenderStaticContent = undefined;
|
||||
};
|
||||
|
||||
dispose = () => {
|
||||
@@ -146,10 +153,32 @@ class XtermStdout extends EventEmitter {
|
||||
|
||||
onRender = (staticContent: string, output: string) => {
|
||||
this.renderCount++;
|
||||
this.lastRenderStaticContent = staticContent;
|
||||
this.lastRenderOutput = output;
|
||||
this.emit('render');
|
||||
};
|
||||
|
||||
private normalizeFrame = (text: string): string =>
|
||||
text.replace(/\r\n/g, '\n');
|
||||
|
||||
generateSvg = (): string => generateSvgForTerminal(this.state.terminal);
|
||||
|
||||
lastFrameRaw = (options: { allowEmpty?: boolean } = {}) => {
|
||||
const result =
|
||||
(this.lastRenderStaticContent ?? '') + (this.lastRenderOutput ?? '');
|
||||
|
||||
const normalized = this.normalizeFrame(result);
|
||||
|
||||
if (normalized === '' && !options.allowEmpty) {
|
||||
throw new Error(
|
||||
'lastFrameRaw() returned an empty string. If this is intentional, use lastFrameRaw({ allowEmpty: true }). ' +
|
||||
'Otherwise, ensure you are calling await waitUntilReady() and that the component is rendering correctly.',
|
||||
);
|
||||
}
|
||||
|
||||
return normalized;
|
||||
};
|
||||
|
||||
lastFrame = (options: { allowEmpty?: boolean } = {}) => {
|
||||
const buffer = this.state.terminal.buffer.active;
|
||||
const allLines: string[] = [];
|
||||
@@ -163,9 +192,7 @@ class XtermStdout extends EventEmitter {
|
||||
}
|
||||
const result = trimmed.join('\n');
|
||||
|
||||
// Normalize for cross-platform snapshot stability:
|
||||
// Normalize any \r\n to \n
|
||||
const normalized = result.replace(/\r\n/g, '\n');
|
||||
const normalized = this.normalizeFrame(result);
|
||||
|
||||
if (normalized === '' && !options.allowEmpty) {
|
||||
throw new Error(
|
||||
@@ -213,9 +240,11 @@ class XtermStdout extends EventEmitter {
|
||||
const currentFrame = stripAnsi(
|
||||
this.lastFrame({ allowEmpty: true }),
|
||||
).trim();
|
||||
const expectedFrame = stripAnsi(this.lastRenderOutput ?? '')
|
||||
.trim()
|
||||
.replace(/\r\n/g, '\n');
|
||||
const expectedFrame = this.normalizeFrame(
|
||||
stripAnsi(
|
||||
(this.lastRenderStaticContent ?? '') + (this.lastRenderOutput ?? ''),
|
||||
),
|
||||
).trim();
|
||||
|
||||
lastCurrent = currentFrame;
|
||||
lastExpected = expectedFrame;
|
||||
@@ -340,6 +369,8 @@ export type RenderInstance = {
|
||||
stdin: XtermStdin;
|
||||
frames: string[];
|
||||
lastFrame: (options?: { allowEmpty?: boolean }) => string;
|
||||
lastFrameRaw: (options?: { allowEmpty?: boolean }) => string;
|
||||
generateSvg: () => string;
|
||||
terminal: Terminal;
|
||||
waitUntilReady: () => Promise<void>;
|
||||
capturedOverflowState: OverflowState | undefined;
|
||||
@@ -424,6 +455,8 @@ export const render = (
|
||||
stdin,
|
||||
frames: stdout.frames,
|
||||
lastFrame: stdout.lastFrame,
|
||||
lastFrameRaw: stdout.lastFrameRaw,
|
||||
generateSvg: stdout.generateSvg,
|
||||
terminal: state.terminal,
|
||||
waitUntilReady: () => stdout.waitUntilReady(),
|
||||
};
|
||||
@@ -767,6 +800,7 @@ export function renderHook<Result, Props>(
|
||||
rerender: (props?: Props) => void;
|
||||
unmount: () => void;
|
||||
waitUntilReady: () => Promise<void>;
|
||||
generateSvg: () => string;
|
||||
} {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const result = { current: undefined as unknown as Result };
|
||||
@@ -789,6 +823,7 @@ export function renderHook<Result, Props>(
|
||||
let inkRerender: (tree: React.ReactElement) => void = () => {};
|
||||
let unmount: () => void = () => {};
|
||||
let waitUntilReady: () => Promise<void> = async () => {};
|
||||
let generateSvg: () => string = () => '';
|
||||
|
||||
act(() => {
|
||||
const renderResult = render(
|
||||
@@ -799,6 +834,7 @@ export function renderHook<Result, Props>(
|
||||
inkRerender = renderResult.rerender;
|
||||
unmount = renderResult.unmount;
|
||||
waitUntilReady = renderResult.waitUntilReady;
|
||||
generateSvg = renderResult.generateSvg;
|
||||
});
|
||||
|
||||
function rerender(props?: Props) {
|
||||
@@ -815,7 +851,7 @@ export function renderHook<Result, Props>(
|
||||
});
|
||||
}
|
||||
|
||||
return { result, rerender, unmount, waitUntilReady };
|
||||
return { result, rerender, unmount, waitUntilReady, generateSvg };
|
||||
}
|
||||
|
||||
export function renderHookWithProviders<Result, Props>(
|
||||
@@ -837,6 +873,7 @@ export function renderHookWithProviders<Result, Props>(
|
||||
rerender: (props?: Props) => void;
|
||||
unmount: () => void;
|
||||
waitUntilReady: () => Promise<void>;
|
||||
generateSvg: () => string;
|
||||
} {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const result = { current: undefined as unknown as Result };
|
||||
@@ -887,5 +924,6 @@ export function renderHookWithProviders<Result, Props>(
|
||||
});
|
||||
},
|
||||
waitUntilReady: () => renderResult.waitUntilReady(),
|
||||
generateSvg: () => renderResult.generateSvg(),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user