1
- import { AbortSignal } from "@smithy/abort-controller" ;
2
1
import { HttpRequest } from "@smithy/protocol-http" ;
3
2
import { afterAll , afterEach , beforeAll , describe , expect , test as it , vi } from "vitest" ;
4
3
@@ -36,13 +35,19 @@ class XhrMock {
36
35
this . captureArgs ( "getAllResponseHeaders" ) ( ) ;
37
36
return `responseHeaderKey: responseHeaderValue\r\nrk2: rv2` ;
38
37
}
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
+ }
41
44
send ( ...args : any [ ] ) {
42
45
this . captureArgs ( "send" ) ( ...args ) ;
43
46
this . eventListeners [ "readystatechange" ] [ 0 ] ( ) ;
44
47
}
45
- abort = this . captureArgs ( "abort" ) ;
48
+ abort ( ...args : any [ ] ) {
49
+ return this . captureArgs ( "abort" ) ( ...args ) ;
50
+ }
46
51
addEventListener ( ...args : any [ ] ) {
47
52
this . captureArgs ( "addEventListener" ) ( ...args ) ;
48
53
const [ event , callback ] = args ;
@@ -135,9 +140,9 @@ describe(XhrHttpHandler.name, () => {
135
140
136
141
it ( "should respond to AbortSignal" , async ( ) => {
137
142
const handler = new XhrHttpHandler ( ) ;
138
- const abortSignal = new AbortSignal ( ) ;
143
+ const abortController = new AbortController ( ) ;
139
144
140
- await handler . handle (
145
+ const p1 = handler . handle (
141
146
new HttpRequest ( {
142
147
method : "PUT" ,
143
148
hostname : "localhost" ,
@@ -148,21 +153,22 @@ describe(XhrHttpHandler.name, () => {
148
153
protocol : "http:" ,
149
154
path : "/api" ,
150
155
} ) ,
151
- { abortSignal }
156
+ { abortSignal : abortController . signal }
152
157
) ;
153
158
154
159
try {
155
- abortSignal . abort ( ) ;
160
+ abortController . abort ( ) ;
161
+ await p1 ;
156
162
} catch ( e ) {
157
163
expect ( e . toString ( ) ) . toContain ( "Request aborted" ) ;
158
164
}
159
165
160
166
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 ( ) ] ,
166
172
[ "open" , "PUT" , "http://localhost:3000/api?k=v" ] ,
167
173
[ "setRequestHeader" , "h" , "1" ] ,
168
174
[ "send" , "hello" ] ,
@@ -171,6 +177,46 @@ describe(XhrHttpHandler.name, () => {
171
177
] ) ;
172
178
} ) ;
173
179
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
+
174
220
it ( "should ignore forbidden request headers" , async ( ) => {
175
221
const handler = new XhrHttpHandler ( ) ;
176
222
0 commit comments