@@ -29,24 +29,22 @@ const TMUX_SESSION = 'agent-e2e'
2929const STUBBORN = "trap '' HUP INT TERM"
3030
3131const 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. */
3333const 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 ) => / t m u x | s l e e p | b a s h | z s h / . test ( line ) )
48- . join ( '\n' ) ,
49- ] . join ( '\n' )
44+ . join ( '\n' )
45+ } catch ( error ) {
46+ return String ( error )
47+ }
5048}
5149const 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