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