From d9fbb4eecf68db99ec9d893c71066d64c4ac86a2 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Fri, 2 Oct 2026 02:39:34 -0700 Subject: [PATCH] Keep SSH typing replies inside narrow split terminal panes (#24682) --- .../e2e/helpers/remote-typing-load-script.ts | 2 +- .../remote-typing-load-script.unit.test.ts | 29 ++++++++++++++----- tests/e2e/ssh-docker-relay-perf.spec.ts | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/tests/e2e/helpers/remote-typing-load-script.ts b/tests/e2e/helpers/remote-typing-load-script.ts index f2e2c296c53..8eba98454ab 100644 --- a/tests/e2e/helpers/remote-typing-load-script.ts +++ b/tests/e2e/helpers/remote-typing-load-script.ts @@ -15,7 +15,7 @@ export function remoteTypingLoadScript(runId: string): string { ' for (const char of chunk) {', " if (char === '\\r' || char === '\\n') continue", ' seq += 1', - ` process.stdout.write('\\x1b[' + statusRow + ';2H\\x1b[2KREMOTE_KEY_${runId}_' + seq + '_' + char)`, + ` process.stdout.write('\\x1b[' + statusRow + ';2H\\x1b[2KKEY_${runId}_' + seq + '_' + char)`, ' }', '})' ].join(';') diff --git a/tests/e2e/helpers/remote-typing-load-script.unit.test.ts b/tests/e2e/helpers/remote-typing-load-script.unit.test.ts index 2b06a5897ca..ae9c55cd847 100644 --- a/tests/e2e/helpers/remote-typing-load-script.unit.test.ts +++ b/tests/e2e/helpers/remote-typing-load-script.unit.test.ts @@ -2,20 +2,31 @@ import '../../../src/main/daemon/xterm-env-polyfill' import { EventEmitter } from 'node:events' import { runInNewContext } from 'node:vm' import { Terminal } from '@xterm/headless' +import { SerializeAddon } from '@xterm/addon-serialize' import { expect, it } from 'vitest' import { remoteTypingLoadScript } from './remote-typing-load-script' -it.each([12, 24, 40])( - 'keeps typed output visible through background pressure at %i rows', - async (rows) => { - const terminal = new Terminal({ rows, cols: 80, scrollback: 1000, allowProposedApi: true }) +it.each([ + { rows: 12, cols: 80 }, + { rows: 24, cols: 80 }, + { rows: 40, cols: 80 }, + { rows: 12, cols: 35 }, + { rows: 24, cols: 35 }, + { rows: 40, cols: 35 } +])( + 'keeps typed output visible through background pressure at $rows rows and $cols columns', + async ({ rows, cols }) => { + const terminal = new Terminal({ rows, cols, scrollback: 1000, allowProposedApi: true }) + const serializer = new SerializeAddon() + terminal.loadAddon(serializer) + const runId = cols === 80 ? 'test' : '1790930671681_active' const input = new EventEmitter() const chunks: string[] = [] let background = (): void => { throw new Error('Background pressure did not start') } try { - runInNewContext(remoteTypingLoadScript('test'), { + runInNewContext(remoteTypingLoadScript(runId), { process: { stdin: { isTTY: true, @@ -24,7 +35,7 @@ it.each([12, 24, 40])( resume() {}, on: input.on.bind(input) }, - stdout: { rows, write: (chunk: string) => chunks.push(chunk) }, + stdout: { rows, cols, write: (chunk: string) => chunks.push(chunk) }, exit() {} }, setTimeout: (callback: () => void) => callback(), @@ -34,7 +45,7 @@ it.each([12, 24, 40])( }, clearInterval() {} }) - input.emit('data', 'ab\r\ncd') + input.emit('data', cols === 80 ? 'ab\r\ncd' : 'abcdefghij\r\n') for (let frame = 0; frame < 40; frame += 1) { background() } @@ -48,7 +59,9 @@ it.each([12, 24, 40])( .getLine(terminal.buffer.active.baseY + row) ?.translateToString(true) ?? '' ).join('\n') - expect(screen).toContain('REMOTE_KEY_test_4_d') + const reply = cols === 80 ? 'KEY_test_4_d' : `KEY_${runId}_10_j` + expect(screen).toContain(reply) + expect(serializer.serialize()).toContain(reply) } finally { terminal.dispose() } diff --git a/tests/e2e/ssh-docker-relay-perf.spec.ts b/tests/e2e/ssh-docker-relay-perf.spec.ts index 2a1e00ba265..e29376c1e89 100644 --- a/tests/e2e/ssh-docker-relay-perf.spec.ts +++ b/tests/e2e/ssh-docker-relay-perf.spec.ts @@ -86,7 +86,7 @@ async function measureRemoteTyping( const latencies: number[] = [] for (let index = 0; index < KEY_LATENCY_SAMPLES.length; index += 1) { const char = KEY_LATENCY_SAMPLES[index] - const marker = `REMOTE_KEY_${runId}_${index + 1}_${char}` + const marker = `KEY_${runId}_${index + 1}_${char}` const started = performance.now() await page.evaluate(({ ptyId, char }) => window.api.pty.write(ptyId, char, 'driving'), { ptyId,