1- import  {  AbortSignal  }  from  "@smithy/abort-controller" ; 
21import  {  HttpRequest  }  from  "@smithy/protocol-http" ; 
32import  {  afterAll ,  afterEach ,  beforeAll ,  describe ,  expect ,  test  as  it ,  vi  }  from  "vitest" ; 
43
@@ -36,13 +35,19 @@ class XhrMock {
3635    this . captureArgs ( "getAllResponseHeaders" ) ( ) ; 
3736    return  `responseHeaderKey: responseHeaderValue\r\nrk2: rv2` ; 
3837  } 
39-   setRequestHeader  =  this . captureArgs ( "setRequestHeader" ) ; 
40-   open  =  this . captureArgs ( "open" ) ; 
38+   setRequestHeader ( ...args : any [ ] )  { 
39+     return  this . captureArgs ( "setRequestHeader" ) ( ...args ) ; 
40+   } 
41+   open ( ...args : any [ ] )  { 
42+     return  this . captureArgs ( "open" ) ( ...args ) ; 
43+   } 
4144  send ( ...args : any [ ] )  { 
4245    this . captureArgs ( "send" ) ( ...args ) ; 
4346    this . eventListeners [ "readystatechange" ] [ 0 ] ( ) ; 
4447  } 
45-   abort  =  this . captureArgs ( "abort" ) ; 
48+   abort ( ...args : any [ ] )  { 
49+     return  this . captureArgs ( "abort" ) ( ...args ) ; 
50+   } 
4651  addEventListener ( ...args : any [ ] )  { 
4752    this . captureArgs ( "addEventListener" ) ( ...args ) ; 
4853    const  [ event ,  callback ]  =  args ; 
@@ -135,9 +140,9 @@ describe(XhrHttpHandler.name, () => {
135140
136141  it ( "should respond to AbortSignal" ,  async  ( )  =>  { 
137142    const  handler  =  new  XhrHttpHandler ( ) ; 
138-     const  abortSignal  =  new  AbortSignal ( ) ; 
143+     const  abortController  =  new  AbortController ( ) ; 
139144
140-     await  handler . handle ( 
145+     const   p1   =  handler . handle ( 
141146      new  HttpRequest ( { 
142147        method : "PUT" , 
143148        hostname : "localhost" , 
@@ -148,21 +153,22 @@ describe(XhrHttpHandler.name, () => {
148153        protocol : "http:" , 
149154        path : "/api" , 
150155      } ) , 
151-       {  abortSignal } 
156+       {  abortSignal :  abortController . signal  } 
152157    ) ; 
153158
154159    try  { 
155-       abortSignal . abort ( ) ; 
160+       abortController . abort ( ) ; 
161+       await  p1 ; 
156162    }  catch  ( e )  { 
157163      expect ( e . toString ( ) ) . toContain ( "Request aborted" ) ; 
158164    } 
159165
160166    expect ( XhrMock . captures ) . toEqual ( [ 
161-       [ "upload.addEventListener" ,  "progress" ,  expect . any ( Function ) ] , 
162-       [ "addEventListener" ,  "progress" ,  expect . any ( Function ) ] , 
163-       [ "addEventListener" ,  "error" ,  expect . any ( Function ) ] , 
164-       [ "addEventListener" ,  "timeout" ,  expect . any ( Function ) ] , 
165-       [ "addEventListener" ,  "readystatechange" ,  expect . any ( Function ) ] , 
167+       [ "upload.addEventListener" ,  "progress" ,  expect . anything ( ) ] , 
168+       [ "addEventListener" ,  "progress" ,  expect . anything ( ) ] , 
169+       [ "addEventListener" ,  "error" ,  expect . anything ( ) ] , 
170+       [ "addEventListener" ,  "timeout" ,  expect . anything ( ) ] , 
171+       [ "addEventListener" ,  "readystatechange" ,  expect . anything ( ) ] , 
166172      [ "open" ,  "PUT" ,  "http://localhost:3000/api?k=v" ] , 
167173      [ "setRequestHeader" ,  "h" ,  "1" ] , 
168174      [ "send" ,  "hello" ] , 
@@ -171,6 +177,46 @@ describe(XhrHttpHandler.name, () => {
171177    ] ) ; 
172178  } ) ; 
173179
180+   it ( "should allow an AbortSignal to abort multiple requests" ,  async  ( )  =>  { 
181+     const  handler  =  new  XhrHttpHandler ( ) ; 
182+     const  abortController  =  new  AbortController ( ) ; 
183+ 
184+     expect ( abortController . signal . addEventListener ) . toBeInstanceOf ( Function ) ; 
185+ 
186+     const  xhrs  =  [ ]  as  XMLHttpRequest [ ] ; 
187+     handler . on ( XhrHttpHandler . EVENTS . BEFORE_XHR_SEND ,  ( xhr )  =>  { 
188+       xhrs . push ( xhr ) ; 
189+     } ) ; 
190+ 
191+     const  request  =  ( )  => 
192+       handler . handle ( 
193+         new  HttpRequest ( { 
194+           method : "PUT" , 
195+           hostname : "localhost" , 
196+           port : 3000 , 
197+           query : {  k : "v"  } , 
198+           headers : {  h : "1"  } , 
199+           body : "hello" , 
200+           protocol : "http:" , 
201+           path : "/api" , 
202+         } ) , 
203+         {  abortSignal : abortController . signal  } 
204+       ) ; 
205+ 
206+     const  p1  =  request ( ) . catch ( ( _ )  =>  _ ) ; 
207+     const  p2  =  request ( ) . catch ( ( _ )  =>  _ ) ; 
208+     const  p3  =  request ( ) . catch ( ( _ )  =>  _ ) ; 
209+     abortController . abort ( ) ; 
210+     await  p1 ; 
211+     await  p2 ; 
212+     await  p3 ; 
213+     await  request ( ) . catch ( ( _ )  =>  _ ) ; 
214+     await  request ( ) . catch ( ( _ )  =>  _ ) ; 
215+ 
216+     expect ( xhrs . length ) . toEqual ( 3 ) ; 
217+     expect ( XhrMock . captures . filter ( ( [ source ] )  =>  source  ===  "abort" ) ) . toEqual ( [ [ "abort" ] ,  [ "abort" ] ,  [ "abort" ] ] ) ; 
218+   } ) ; 
219+ 
174220  it ( "should ignore forbidden request headers" ,  async  ( )  =>  { 
175221    const  handler  =  new  XhrHttpHandler ( ) ; 
176222
0 commit comments