@@ -4630,3 +4630,78 @@ describe('rerun --wait — dashboardUrl on terminal output', () => {
46304630 ) ;
46314631 } ) ;
46324632} ) ;
4633+
4634+ // ---------------------------------------------------------------------------
4635+ // TimeoutError on single FE rerun --wait: partial stdout + exit 7
4636+ // ---------------------------------------------------------------------------
4637+
4638+ describe ( '[finding-4] single FE rerun --wait: TimeoutError writes partial JSON to stdout' , ( ) => {
4639+ it ( 'exit 7 AND stdout contains {runId, status:"running"} when --timeout polling deadline is exceeded' , async ( ) => {
4640+ const creds = makeCreds ( ) ;
4641+ const rerunResp = makeFeRerunResp ( ) ;
4642+
4643+ let fetchCallCount = 0 ;
4644+ const fetchImpl : typeof globalThis . fetch = async ( input , _init ) => {
4645+ const url =
4646+ typeof input === 'string'
4647+ ? input
4648+ : input instanceof URL
4649+ ? input . toString ( )
4650+ : ( input as { url : string } ) . url ;
4651+ fetchCallCount ++ ;
4652+ if ( url . includes ( '/tests/test_fe_01/runs/rerun' ) ) {
4653+ return new Response ( JSON . stringify ( rerunResp ) , {
4654+ status : 202 ,
4655+ headers : { 'content-type' : 'application/json' } ,
4656+ } ) ;
4657+ }
4658+ if ( url . includes ( '/runs/' ) ) {
4659+ const runningRun : RunResponse = {
4660+ ...makeTerminalRun ( rerunResp . runId , 'passed' ) ,
4661+ status : 'running' ,
4662+ finishedAt : null ,
4663+ } ;
4664+ return new Response ( JSON . stringify ( runningRun ) , {
4665+ status : 200 ,
4666+ headers : { 'content-type' : 'application/json' } ,
4667+ } ) ;
4668+ }
4669+ return new Response ( JSON . stringify ( { error : { code : 'NOT_FOUND' } } ) , { status : 404 } ) ;
4670+ } ;
4671+
4672+ const stdoutLines : string [ ] = [ ] ;
4673+
4674+ const err = await runTestRerun (
4675+ {
4676+ testIds : [ 'test_fe_01' ] ,
4677+ all : false ,
4678+ wait : true ,
4679+ timeoutSeconds : 0 ,
4680+ autoHeal : false ,
4681+ autoHealExplicit : false ,
4682+ skipDependencies : false ,
4683+ maxConcurrency : 10 ,
4684+ output : 'json' ,
4685+ profile : 'default' ,
4686+ dryRun : false ,
4687+ debug : false ,
4688+ verbose : false ,
4689+ } ,
4690+ {
4691+ ...creds ,
4692+ sleep : instantSleep ,
4693+ fetchImpl : fetchImpl as unknown as FetchImpl ,
4694+ stdout : line => stdoutLines . push ( line ) ,
4695+ stderr : ( ) => undefined ,
4696+ } ,
4697+ ) . catch ( e => e ) ;
4698+
4699+ expect ( err ) . toMatchObject ( { exitCode : 7 } ) ;
4700+ expect ( stdoutLines . length ) . toBeGreaterThan ( 0 ) ;
4701+ const parsed = JSON . parse ( stdoutLines . join ( '\n' ) ) as { runId : string ; status : string } ;
4702+ expect ( parsed . runId ) . toBe ( rerunResp . runId ) ;
4703+ expect ( parsed . status ) . toBe ( 'running' ) ;
4704+
4705+ void fetchCallCount ;
4706+ } ) ;
4707+ } ) ;
0 commit comments