Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 15 additions & 25 deletions packages/cli/src/test-utils/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ class XtermStdout extends EventEmitter {
isTTY = true;

private lastRenderOutput: string | undefined = undefined;
private lastRenderStaticContent: string | undefined = undefined;

constructor(state: TerminalState, queue: { promise: Promise<void> }) {
super();
Expand Down Expand Up @@ -109,7 +108,6 @@ class XtermStdout extends EventEmitter {
clear = () => {
this.state.terminal.reset();
this.lastRenderOutput = undefined;
this.lastRenderStaticContent = undefined;
};

dispose = () => {
Expand All @@ -118,32 +116,22 @@ class XtermStdout extends EventEmitter {

onRender = (staticContent: string, output: string) => {
this.renderCount++;
this.lastRenderStaticContent = staticContent;
this.lastRenderOutput = output;
this.emit('render');
};

lastFrame = (options: { allowEmpty?: boolean } = {}) => {
let result: string;
// On Windows, xterm.js headless can sometimes have timing or rendering issues
// that lead to duplicated content or incorrect buffer state in tests.
// As a fallback, we can trust the raw output Ink provided during onRender.
if (os.platform() === 'win32') {
result =
(this.lastRenderStaticContent ?? '') + (this.lastRenderOutput ?? '');
} else {
const buffer = this.state.terminal.buffer.active;
const allLines: string[] = [];
for (let i = 0; i < buffer.length; i++) {
allLines.push(buffer.getLine(i)?.translateToString(true) ?? '');
}
const buffer = this.state.terminal.buffer.active;
const allLines: string[] = [];
for (let i = 0; i < buffer.length; i++) {
allLines.push(buffer.getLine(i)?.translateToString(true) ?? '');
}

const trimmed = [...allLines];
while (trimmed.length > 0 && trimmed[trimmed.length - 1] === '') {
trimmed.pop();
}
result = trimmed.join('\n');
const trimmed = [...allLines];
while (trimmed.length > 0 && trimmed[trimmed.length - 1] === '') {
trimmed.pop();
}
const result = trimmed.join('\n');

// Normalize for cross-platform snapshot stability:
// Normalize any \r\n to \n
Expand Down Expand Up @@ -195,9 +183,7 @@ class XtermStdout extends EventEmitter {
const currentFrame = stripAnsi(
this.lastFrame({ allowEmpty: true }),
).trim();
const expectedFrame = stripAnsi(
(this.lastRenderStaticContent ?? '') + (this.lastRenderOutput ?? ''),
)
const expectedFrame = stripAnsi(this.lastRenderOutput ?? '')
.trim()
.replace(/\r\n/g, '\n');

Expand Down Expand Up @@ -336,7 +322,11 @@ export const render = (
terminalWidth?: number,
): RenderInstance => {
const cols = terminalWidth ?? 100;
const rows = 40;
// We use 1000 rows to avoid windows with incorrect snapshots if a correct
// value was used (e.g. 40 rows). The alternatives to make things worse are
// windows unfortunately with odd duplicate content in the backbuffer
// which does not match actual behavior in xterm.js on windows.
const rows = 1000;
const terminal = new Terminal({
cols,
rows,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,20 @@ Spinner Connecting to MCP servers... (0/5) - Waiting for: s1, s2, s3, +2 more
"
`;

exports[`ConfigInitDisplay > truncates list of waiting servers if too many 2`] = `
"
Spinner Connecting to MCP servers... (0/5) - Waiting for: s1, s2, s3, +2 more
"
`;

exports[`ConfigInitDisplay > updates message on McpClientUpdate event 1`] = `
"
Spinner Connecting to MCP servers... (1/2) - Waiting for: server2
"
`;

exports[`ConfigInitDisplay > updates message on McpClientUpdate event 2`] = `
"
Spinner Connecting to MCP servers... (1/2) - Waiting for: server2
"
`;
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,33 @@ Enter to select · ↑/↓ to navigate · Esc to cancel
"
`;

exports[`ExitPlanModeDialog > useAlternateBuffer: false > bubbles up Ctrl+C when feedback is empty while editing 2`] = `
"Overview

Add user authentication to the CLI application.

Implementation Steps

1. Create src/auth/AuthService.ts with login/logout methods
2. Add session storage in src/storage/SessionStore.ts
3. Update src/commands/index.ts to check auth status
4. Add tests in src/auth/__tests__/

Files to Modify

- src/index.ts - Add auth middleware
- src/config.ts - Add auth configuration options

1. Yes, automatically accept edits
Approves plan and allows tools to run automatically
2. Yes, manually accept edits
Approves plan but requires confirmation for each tool
● 3. Type your feedback...

Enter to submit · Esc to cancel
"
`;

exports[`ExitPlanModeDialog > useAlternateBuffer: false > calls onFeedback when feedback is typed and submitted 1`] = `
"Overview

Expand Down Expand Up @@ -54,6 +81,33 @@ Enter to select · ↑/↓ to navigate · Esc to cancel
"
`;

exports[`ExitPlanModeDialog > useAlternateBuffer: false > calls onFeedback when feedback is typed and submitted 2`] = `
"Overview

Add user authentication to the CLI application.

Implementation Steps

1. Create src/auth/AuthService.ts with login/logout methods
2. Add session storage in src/storage/SessionStore.ts
3. Update src/commands/index.ts to check auth status
4. Add tests in src/auth/__tests__/

Files to Modify

- src/index.ts - Add auth middleware
- src/config.ts - Add auth configuration options

1. Yes, automatically accept edits
Approves plan and allows tools to run automatically
2. Yes, manually accept edits
Approves plan but requires confirmation for each tool
● 3. Add tests

Enter to submit · Esc to cancel
"
`;

exports[`ExitPlanModeDialog > useAlternateBuffer: false > displays error state when file read fails 1`] = `
" Error reading plan: File not found
"
Expand Down Expand Up @@ -140,6 +194,33 @@ Enter to select · ↑/↓ to navigate · Esc to cancel
"
`;

exports[`ExitPlanModeDialog > useAlternateBuffer: true > bubbles up Ctrl+C when feedback is empty while editing 2`] = `
"Overview

Add user authentication to the CLI application.

Implementation Steps

1. Create src/auth/AuthService.ts with login/logout methods
2. Add session storage in src/storage/SessionStore.ts
3. Update src/commands/index.ts to check auth status
4. Add tests in src/auth/__tests__/

Files to Modify

- src/index.ts - Add auth middleware
- src/config.ts - Add auth configuration options

1. Yes, automatically accept edits
Approves plan and allows tools to run automatically
2. Yes, manually accept edits
Approves plan but requires confirmation for each tool
● 3. Type your feedback...

Enter to submit · Esc to cancel
"
`;

exports[`ExitPlanModeDialog > useAlternateBuffer: true > calls onFeedback when feedback is typed and submitted 1`] = `
"Overview

Expand Down Expand Up @@ -167,6 +248,33 @@ Enter to select · ↑/↓ to navigate · Esc to cancel
"
`;

exports[`ExitPlanModeDialog > useAlternateBuffer: true > calls onFeedback when feedback is typed and submitted 2`] = `
"Overview

Add user authentication to the CLI application.

Implementation Steps

1. Create src/auth/AuthService.ts with login/logout methods
2. Add session storage in src/storage/SessionStore.ts
3. Update src/commands/index.ts to check auth status
4. Add tests in src/auth/__tests__/

Files to Modify

- src/index.ts - Add auth middleware
- src/config.ts - Add auth configuration options

1. Yes, automatically accept edits
Approves plan and allows tools to run automatically
2. Yes, manually accept edits
Approves plan but requires confirmation for each tool
● 3. Add tests

Enter to submit · Esc to cancel
"
`;

exports[`ExitPlanModeDialog > useAlternateBuffer: true > displays error state when file read fails 1`] = `
" Error reading plan: File not found
"
Expand Down
Loading