Skip to content

Commit aa1ee57

Browse files
committed
test(desktop): attach terminal-cancel diagnostics instead of printing them, write a suite report, and keep the user pane through a session ended elsewhere
1 parent f8ce008 commit aa1ee57

2 files changed

Lines changed: 34 additions & 29 deletions

File tree

‎.github/workflows/desktop-e2e.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ jobs:
9090
run: bunx playwright test
9191
env:
9292
BACKGROUND_EXECUTOR_REPORT_PATH: test-results/background-executor-report.json
93+
TERMINAL_CANCEL_REPORT_PATH: test-results/terminal-cancel-report.json
9394

9495
- name: Upload test results
9596
if: failure()

‎apps/desktop/e2e/terminal-cancel.spec.ts‎

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,22 @@ const TMUX_SESSION = 'agent-e2e'
2929
const STUBBORN = "trap '' HUP INT TERM"
3030

3131
const sim = new FixtureSim()
32-
/** The app's own log output for the current test, printed when it fails. */
32+
/** The app's own log output for the current test, attached when it fails. */
3333
const appOutput: string[] = []
34+
/** Each scenario's outcome, written to `TERMINAL_CANCEL_REPORT_PATH` when the suite ends. */
35+
const report: Array<{ name: string; status: string; durationMs: number }> = []
3436

35-
/** The process tree and tmux's clients, for a failure that is about who started what. */
36-
function diagnose(): string {
37-
const run = (command: string, args: string[]) => {
38-
try {
39-
return execFileSync(command, args).toString()
40-
} catch (error) {
41-
return String(error)
42-
}
43-
}
44-
return [
45-
run('ps', ['-eo', 'pid,ppid,pgid,args'])
37+
/** The shells, sleeps and tmux processes running, for a failure about who started what. */
38+
function processes(): string {
39+
try {
40+
return execFileSync('ps', ['-eo', 'pid,ppid,pgid,args'])
41+
.toString()
4642
.split('\n')
4743
.filter((line) => /tmux|sleep|bash|zsh/.test(line))
48-
.join('\n'),
49-
].join('\n')
44+
.join('\n')
45+
} catch (error) {
46+
return String(error)
47+
}
5048
}
5149
const REAL_TMUX = findTmux()
5250

@@ -268,6 +266,11 @@ test.describe('terminal cancel', () => {
268266

269267
test.afterEach(async () => {
270268
const testInfo = test.info()
269+
report.push({
270+
name: testInfo.title,
271+
status: testInfo.status ?? 'unknown',
272+
durationMs: testInfo.duration,
273+
})
271274
if (testInfo.status !== testInfo.expectedStatus) {
272275
// What each call came back with, and the panes tmux held, explain most failures.
273276
const calls = [...sim.calls.values()].map((call) => ({
@@ -283,18 +286,8 @@ test.describe('terminal cancel', () => {
283286
await testInfo.attach('calls', {
284287
body: JSON.stringify({ calls, panes: tmux.panes() }, null, 2),
285288
})
286-
console.log(JSON.stringify({ calls, panes: tmux.panes() }, null, 2))
287-
console.log(appOutput.join('').slice(-6_000))
288-
console.log(diagnose())
289-
console.log(
290-
(() => {
291-
try {
292-
return tmux.run(['list-clients', '-F', '#{client_pid} #{client_tty} #{client_session}'])
293-
} catch (error) {
294-
return String(error)
295-
}
296-
})()
297-
)
289+
await testInfo.attach('app-output', { body: appOutput.join('').slice(-6_000) })
290+
await testInfo.attach('processes', { body: processes() })
298291
}
299292
appOutput.length = 0
300293
// Quitting with a command still running in a tab asks first (natively, on macOS), and nobody
@@ -322,6 +315,13 @@ test.describe('terminal cancel', () => {
322315

323316
test.afterAll(async () => {
324317
await sim.stop()
318+
const reportPath = process.env.TERMINAL_CANCEL_REPORT_PATH
319+
if (reportPath) {
320+
writeFileSync(
321+
reportPath,
322+
JSON.stringify({ suite: 'terminal-cancel', checks: report }, null, 2)
323+
)
324+
}
325325
})
326326

327327
async function start(
@@ -393,19 +393,23 @@ test.describe('terminal cancel', () => {
393393
}
394394
})
395395

396-
test('a session ended by another account signing in stops every agent command', async () => {
396+
test('a session ended by another account signing in stops every agent command and leaves the user pane running', async () => {
397397
const { window, deviceId } = await start('account')
398-
leftovers.push(slept(731), slept(733))
398+
leftovers.push(slept(731), slept(733), slept(734))
399399
await agentRunsPlain(deviceId, 731)
400400
const run = REAL_TMUX ? await agentRunsInTmux(deviceId, tmux, 733) : null
401+
const users = run ? tmux.split(run.pane.id, stubborn(734)) : null
402+
if (users) await expect.poll(() => processRunning(slept(734)), { timeout: 15_000 }).toBe(true)
401403

402404
// Another account signing in replaces the session: the old session cookie goes away.
403405
await window.goto(`${sim.origin}/session-ended`)
404406

405407
await expect.poll(() => processRunning(slept(731)), { timeout: 30_000 }).toBe(false)
406-
if (run) {
408+
if (run && users) {
407409
await expect.poll(() => processRunning(slept(733)), { timeout: 15_000 }).toBe(false)
408410
await expect.poll(() => tmux.hasPane(run.pane.id), { timeout: 10_000 }).toBe(false)
411+
expect(tmux.hasPane(users)).toBe(true)
412+
expect(processRunning(slept(734))).toBe(true)
409413
}
410414
})
411415

0 commit comments

Comments
 (0)