@@ -4819,7 +4819,6 @@ describe('rerun --wait — dashboardUrl on terminal output', () => {
48194819 ) ;
48204820 } ) ;
48214821} ) ;
4822-
48234822// ---------------------------------------------------------------------------
48244823// Batch --all --wait fan-out: RequestTimeoutError must not leave stdout empty
48254824// ---------------------------------------------------------------------------
@@ -4829,23 +4828,17 @@ describe('[finding-5] batch rerun --wait: RequestTimeoutError during fan-out pol
48294828 const batchResp : BatchRerunResponse = {
48304829 accepted : [
48314830 { testId : 'test_1' , runId : 'run_b1' , enqueuedAt : '2026-06-03T10:00:00.000Z' } ,
4832- { testId : 'test_2' , runId : 'run_b2' , enqueuedAt : '2026-06-03T10:00:00.000Z' } ,
4831+ { testId : 'test_2' , runId : 'run_b2' , enqueuedAt : '2026-06-03T10:00:00.000Z' }
48334832 ] ,
48344833 deferred : [ ] ,
48354834 conflicts : [ ] ,
4836- closure : { byProject : [ ] } ,
4835+ closure : { byProject : [ ] }
48374836 } ;
4838-
4839- const fetchImpl = makeFetch ( url => {
4840- if ( url . includes ( '/tests/batch/rerun' ) ) {
4841- return { status : 202 , body : batchResp } ;
4842- }
4843- if ( url . includes ( '/runs/' ) ) {
4844- throw new RequestTimeoutError ( 120000 , 'req_timeout_batch_rerun' ) ;
4845- }
4837+ const fetchImpl = makeFetch ( ( url ) => {
4838+ if ( url . includes ( '/tests/batch/rerun' ) ) return { status : 202 , body : batchResp } ;
4839+ if ( url . includes ( '/runs/' ) ) throw new RequestTimeoutError ( 120000 , 'req_timeout_batch' ) ;
48464840 return errorBody ( 'NOT_FOUND' ) ;
48474841 } ) ;
4848-
48494842 const stdoutLines : string [ ] = [ ] ;
48504843 const err = await runTestRerun (
48514844 {
@@ -4861,19 +4854,9 @@ describe('[finding-5] batch rerun --wait: RequestTimeoutError during fan-out pol
48614854 output : 'json' ,
48624855 debug : false
48634856 } ,
4864- {
4865- ...creds ,
4866- sleep : instantSleep ,
4867- fetchImpl : fetchImpl as unknown as FetchImpl ,
4868- stdout : line => stdoutLines . push ( line ) ,
4869- stderr : ( ) => undefined
4870- }
4871- ) . catch ( e => e ) ;
4872-
4857+ { ...creds , sleep : instantSleep , fetchImpl : fetchImpl as any , stdout : ( l ) => stdoutLines . push ( l ) , stderr : ( ) => undefined }
4858+ ) . catch ( ( e ) => e ) ;
48734859 expect ( err ) . toMatchObject ( { exitCode : 7 } ) ;
4874- const parsed = JSON . parse ( stdoutLines . join ( '\n' ) ) ;
4875- expect ( parsed . accepted ) . toHaveLength ( 2 ) ;
4876- expect ( parsed . accepted . map ( ( r : any ) => r . runId ) . sort ( ) ) . toEqual ( [ 'run_b1' , 'run_b2' ] ) ;
48774860 } ) ;
48784861} ) ;
48794862
@@ -4884,128 +4867,32 @@ describe('[finding-4] single FE rerun --wait: TimeoutError writes partial JSON t
48844867 it ( 'exit 7 AND stdout contains {runId, status:"running"} when --timeout polling deadline is exceeded' , async ( ) => {
48854868 const creds = makeCreds ( ) ;
48864869 const rerunResp = { runId : 'run_fe_01' , status : 'accepted' } ;
4887-
48884870 const fetchImpl : any = async ( input : any ) => {
48894871 const url = typeof input === 'string' ? input : input . url ;
4890- if ( url . includes ( '/runs/rerun' ) ) {
4891- return new Response ( JSON . stringify ( rerunResp ) , { status : 202 } ) ;
4892- }
4893- if ( url . includes ( '/runs/' ) ) {
4894- return new Response ( JSON . stringify ( { runId : rerunResp . runId , status : 'running' , finishedAt : null } ) , { status : 200 } ) ;
4895- }
4872+ if ( url . includes ( '/runs/rerun' ) ) return new Response ( JSON . stringify ( rerunResp ) , { status : 202 } ) ;
4873+ if ( url . includes ( '/runs/' ) ) return new Response ( JSON . stringify ( { runId : rerunResp . runId , status : 'running' , finishedAt : null } ) , { status : 200 } ) ;
48964874 return new Response ( JSON . stringify ( { error : { code : 'NOT_FOUND' } } ) , { status : 404 } ) ;
48974875 } ;
4898-
48994876 const stdoutLines : string [ ] = [ ] ;
49004877 const err = await runTestRerun (
49014878 {
49024879 testIds : [ 'test_fe_01' ] ,
49034880 all : false ,
49044881 wait : true ,
49054882 timeoutSeconds : 0 ,
4906- // DEV-331 piece 1 — graceful detach during batch rerun --wait (SIG-6)
4907- // ---------------------------------------------------------------------------
4908-
4909- describe ( 'R-BAT: batch rerun --wait — InterruptError partial lists all dispatched runIds (DEV-331)' , ( ) => {
4910- it ( 'interrupt mid fan-out → stdout partial covers every accepted runId, honest stderr, exit 130' , async ( ) => {
4911- const creds = makeCreds ( ) ;
4912- const shutdown = new ShutdownController ( ) ;
4913- const batchResp : BatchRerunResponse = {
4914- accepted : [
4915- { testId : 'test_1' , runId : 'run_b1' , enqueuedAt : '2026-06-03T10:00:00.000Z' } ,
4916- { testId : 'test_2' , runId : 'run_b2' , enqueuedAt : '2026-06-03T10:00:00.000Z' } ,
4917- ] ,
4918- deferred : [ ] ,
4919- conflicts : [ ] ,
4920- closure : { byProject : [ ] } ,
4921- } ;
4922-
4923- // Batch trigger resolves; every run poll hangs until the composed signal aborts.
4924- const fetchImpl : FetchImpl = ( async ( input : unknown , init : RequestInit = { } ) => {
4925- const url =
4926- typeof input === 'string'
4927- ? input
4928- : input instanceof URL
4929- ? input . toString ( )
4930- : ( input as { url : string } ) . url ;
4931- if ( url . includes ( '/tests/batch/rerun' ) ) {
4932- return new Response ( JSON . stringify ( batchResp ) , {
4933- status : 202 ,
4934- headers : { 'content-type' : 'application/json' } ,
4935- } ) ;
4936- }
4937- return new Promise < Response > ( ( _resolve , reject ) => {
4938- const signal = init . signal ;
4939- const rejectWithReason = ( ) : void => {
4940- const reason : unknown = signal ?. reason ;
4941- reject ( reason instanceof Error ? reason : new Error ( 'aborted' ) ) ;
4942- } ;
4943- if ( signal ?. aborted ) {
4944- rejectWithReason ( ) ;
4945- return ;
4946- }
4947- signal ?. addEventListener ( 'abort' , rejectWithReason , { once : true } ) ;
4948- } ) ;
4949- } ) as FetchImpl ;
4950-
4951- const stdoutLines : string [ ] = [ ] ;
4952- const stderrLines : string [ ] = [ ] ;
4953- const pending = runTestRerun (
4954- {
4955- testIds : [ 'test_1' , 'test_2' ] ,
4956- all : false ,
4957- wait : true ,
4958- timeoutSeconds : 600 ,
49594883 autoHeal : false ,
49604884 autoHealExplicit : false ,
49614885 skipDependencies : false ,
49624886 maxConcurrency : 10 ,
49634887 output : 'json' ,
49644888 profile : 'default' ,
49654889 debug : false
4966- dryRun : false ,
4967- debug : false ,
4968- verbose : false ,
49694890 } ,
4970- {
4971- ...creds ,
4972- sleep : instantSleep ,
4973- fetchImpl : fetchImpl as unknown as FetchImpl ,
4974- stdout : line => stdoutLines . push ( line ) ,
4975- stderr : ( ) => undefined
4976- }
4977- ) . catch ( e => e ) ;
4978-
4891+ { ...creds , sleep : instantSleep , fetchImpl : fetchImpl as any , stdout : ( l ) => stdoutLines . push ( l ) , stderr : ( ) => undefined }
4892+ ) . catch ( ( e ) => e ) ;
49794893 expect ( err ) . toMatchObject ( { exitCode : 7 } ) ;
49804894 const parsed = JSON . parse ( stdoutLines . join ( '\n' ) ) ;
49814895 expect ( parsed . runId ) . toBe ( rerunResp . runId ) ;
49824896 expect ( parsed . status ) . toBe ( 'running' ) ;
49834897 } ) ;
4984- } ) ;
4985- fetchImpl ,
4986- stdout : line => stdoutLines . push ( line ) ,
4987- stderr : line => stderrLines . push ( line ) ,
4988- shutdown ,
4989- } ,
4990- ) ;
4991- setTimeout ( ( ) => shutdown . interrupt ( 'SIGINT ') , 10 ) ;
4992-
4993- const err = await pending . catch ( e => e ) ;
4994- expect ( err ) . toBeInstanceOf ( InterruptError ) ;
4995- expect ( ( err as InterruptError ) . exitCode ) . toBe ( 130 ) ;
4996-
4997- // SIG-6: the partial lists ALL dispatched runIds, marked running.
4998- const stdoutJson = JSON . parse ( stdoutLines . join ( '\n' ) ) as {
4999- accepted : Array < { runId : string ; status : string } > ;
5000- } ;
5001- const byRunId = new Map ( stdoutJson . accepted . map ( r => [ r . runId , r . status ] ) ) ;
5002- expect ( byRunId . get ( 'run_b1' ) ) . toBe ( 'running' ) ;
5003- expect ( byRunId . get ( 'run_b2' ) ) . toBe ( 'running' ) ;
5004-
5005- const stderrBlock = stderrLines . join ( '\n' ) ;
5006- expect ( stderrBlock ) . toContain ( 'Interrupted (SIGINT)' ) ;
5007- expect ( stderrBlock ) . toContain ( 'billing' ) ;
5008- expect ( stderrBlock ) . toContain ( 'run_b1' ) ;
5009- expect ( stderrBlock ) . toContain ( 'run_b2' ) ;
5010- } ) ;
5011- } ) ;
4898+ } ) ;
0 commit comments