@@ -16,6 +16,17 @@ function makeStream(chunks: string[]) {
16
16
} ) ;
17
17
}
18
18
19
+ function toRequest ( input : RequestInfo , init ?: RequestInit ) : Request {
20
+ if ( input instanceof Request ) {
21
+ const url = input . url . startsWith ( 'http' )
22
+ ? input . url
23
+ : `http://localhost${ input . url } ` ;
24
+ return new Request ( url , input ) ;
25
+ }
26
+ const url = input . startsWith ( 'http' ) ? input : `http://localhost${ input } ` ;
27
+ return new Request ( url , init ) ;
28
+ }
29
+
19
30
describe ( 'createSseClient' , ( ) => {
20
31
let fetchMock : any ;
21
32
@@ -35,7 +46,10 @@ describe('createSseClient', () => {
35
46
} ) ;
36
47
37
48
const onEvent = vi . fn ( ) ;
38
- const { stream } = createSseClient ( { onSseEvent : onEvent , url : '/sse' } ) ;
49
+ const { stream } = createSseClient ( {
50
+ onSseEvent : onEvent ,
51
+ url : 'http://localhost/sse' ,
52
+ } ) ;
39
53
40
54
const result : any [ ] = [ ] ;
41
55
for await ( const ev of stream ) result . push ( ev ) ;
@@ -55,7 +69,7 @@ describe('createSseClient', () => {
55
69
ok : true ,
56
70
} ) ;
57
71
58
- const { stream } = createSseClient ( { url : '/sse' } ) ;
72
+ const { stream } = createSseClient ( { url : 'http://localhost /sse' } ) ;
59
73
const result : any [ ] = [ ] ;
60
74
for await ( const ev of stream ) result . push ( ev ) ;
61
75
@@ -76,7 +90,7 @@ describe('createSseClient', () => {
76
90
onSseError : onError ,
77
91
signal : controller . signal ,
78
92
sseDefaultRetryDelay : 0 ,
79
- url : '/sse' ,
93
+ url : 'http://localhost /sse' ,
80
94
} ) ;
81
95
82
96
const iter = stream [ Symbol . asyncIterator ] ( ) ;
@@ -97,7 +111,10 @@ describe('createSseClient', () => {
97
111
} ) ;
98
112
99
113
const onEvent = vi . fn ( ) ;
100
- const { stream } = createSseClient ( { onSseEvent : onEvent , url : '/sse' } ) ;
114
+ const { stream } = createSseClient ( {
115
+ onSseEvent : onEvent ,
116
+ url : 'http://localhost/sse' ,
117
+ } ) ;
101
118
102
119
const iter = stream [ Symbol . asyncIterator ] ( ) ;
103
120
await iter . next ( ) ;
@@ -117,7 +134,7 @@ describe('createSseClient', () => {
117
134
ok : true ,
118
135
} ) ;
119
136
120
- const { stream } = createSseClient ( { url : '/sse' } ) ;
137
+ const { stream } = createSseClient ( { url : 'http://localhost /sse' } ) ;
121
138
const result : any [ ] = [ ] ;
122
139
for await ( const ev of stream ) result . push ( ev ) ;
123
140
expect ( result ) . toEqual ( [ 1 , 2 , 3 ] ) ;
@@ -129,31 +146,39 @@ describe('createSseClient', () => {
129
146
ok : true ,
130
147
} ) ;
131
148
132
- const { stream } = createSseClient ( { url : '/sse' } ) ;
149
+ const { stream } = createSseClient ( { url : 'http://localhost /sse' } ) ;
133
150
const result : any [ ] = [ ] ;
134
151
for await ( const ev of stream ) result . push ( ev ) ;
135
152
expect ( result ) . toEqual ( [ 'partial' ] ) ;
136
153
} ) ;
137
154
138
155
it ( 'sets Last-Event-ID header on reconnect' , async ( ) => {
139
- let headersSeen : Headers | undefined ;
140
- fetchMock . mockImplementation ( async ( _url : any , opts : any ) => {
141
- headersSeen = opts ?. headers . get ( 'Last-Event-ID' ) ;
142
- return {
143
- body : makeStream ( [ 'data: a\n\n' ] ) ,
144
- ok : true ,
145
- } ;
146
- } ) ;
156
+ let headersSeen : string | null | undefined ;
157
+ fetchMock . mockImplementation (
158
+ async ( input : RequestInfo , init ?: RequestInit ) => {
159
+ const req = toRequest ( input , init ) ;
160
+ headersSeen = req . headers . get ( 'Last-Event-ID' ) ;
161
+ return {
162
+ body : makeStream ( [ 'data: a\n\n' ] ) ,
163
+ ok : true ,
164
+ } ;
165
+ } ,
166
+ ) ;
147
167
148
168
const onEvent = vi . fn ( ) ;
149
- const { stream } = createSseClient ( { onSseEvent : onEvent , url : '/sse' } ) ;
169
+ const { stream } = createSseClient ( {
170
+ onSseEvent : onEvent ,
171
+ url : 'http://localhost/sse' ,
172
+ } ) ;
150
173
151
174
const iter = stream [ Symbol . asyncIterator ] ( ) ;
152
175
await iter . next ( ) ;
153
176
await iter . return ?.( ) ;
154
177
155
178
// simulate next fetch after reconnect
156
- await fetchMock ( '/sse' , { headers : new Headers ( { 'Last-Event-ID' : '1' } ) } ) ;
179
+ await fetchMock ( 'http://localhost/sse' , {
180
+ headers : new Headers ( { 'Last-Event-ID' : '1' } ) ,
181
+ } ) ;
157
182
expect ( headersSeen ) . toBe ( '1' ) ;
158
183
} ) ;
159
184
@@ -166,7 +191,7 @@ describe('createSseClient', () => {
166
191
const controller = new AbortController ( ) ;
167
192
const { stream } = createSseClient ( {
168
193
signal : controller . signal ,
169
- url : '/sse' ,
194
+ url : 'http://localhost /sse' ,
170
195
} ) ;
171
196
172
197
const iter = stream [ Symbol . asyncIterator ] ( ) ;
@@ -188,22 +213,28 @@ describe('createSseClient', () => {
188
213
ok : true ,
189
214
} ) ;
190
215
191
- const { stream } = createSseClient ( { url : '/sse' } ) ;
216
+ const { stream } = createSseClient ( { url : 'http://localhost /sse' } ) ;
192
217
const result : any [ ] = [ ] ;
193
218
for await ( const ev of stream ) result . push ( ev ) ;
194
219
expect ( result ) . toEqual ( [ { foo : 1 } , 'bar' , { baz : 2 } ] ) ;
195
220
} ) ;
196
221
197
222
it ( 'passes custom headers' , async ( ) => {
198
- let headersSeen : Headers | undefined ;
199
- fetchMock . mockImplementation ( async ( _url : any , opts : any ) => {
200
- headersSeen = opts . headers . get ( 'X-Custom' ) ;
201
- return { body : makeStream ( [ ] ) , ok : true } ;
202
- } ) ;
223
+ let headersSeen : string | null | undefined ;
224
+ fetchMock . mockImplementation (
225
+ async ( input : RequestInfo , init ?: RequestInit ) => {
226
+ const req = toRequest ( input , init ) ;
227
+ headersSeen = req . headers . get ( 'X-Custom' ) ;
228
+ return {
229
+ body : makeStream ( [ ] ) ,
230
+ ok : true ,
231
+ } ;
232
+ } ,
233
+ ) ;
203
234
204
235
const { stream } = createSseClient ( {
205
236
headers : { 'X-Custom' : 'abc' } ,
206
- url : '/sse' ,
237
+ url : 'http://localhost /sse' ,
207
238
} ) ;
208
239
209
240
const iter = stream [ Symbol . asyncIterator ] ( ) ;
@@ -219,15 +250,15 @@ describe('createSseClient', () => {
219
250
ok : true ,
220
251
} ) ;
221
252
222
- const { stream } = createSseClient ( { url : '/sse' } ) ;
253
+ const { stream } = createSseClient ( { url : 'http://localhost /sse' } ) ;
223
254
const result : any [ ] = [ ] ;
224
255
for await ( const ev of stream ) result . push ( ev ) ;
225
256
expect ( result ) . toEqual ( [ { foo : 'bar' } ] ) ;
226
257
} ) ;
227
258
228
259
it ( 'handles empty stream' , async ( ) => {
229
260
fetchMock . mockResolvedValue ( { body : makeStream ( [ ] ) , ok : true } ) ;
230
- const { stream } = createSseClient ( { url : '/sse' } ) ;
261
+ const { stream } = createSseClient ( { url : 'http://localhost /sse' } ) ;
231
262
const iter = stream [ Symbol . asyncIterator ] ( ) ;
232
263
const first = await iter . next ( ) ;
233
264
expect ( first ) . toEqual ( { done : true , value : undefined } ) ;
@@ -238,14 +269,17 @@ describe('createSseClient', () => {
238
269
fetchMock . mockImplementation ( async ( ) => {
239
270
attempt ++ ;
240
271
if ( attempt < 2 ) throw new Error ( 'fail' ) ;
241
- return { body : makeStream ( [ 'data: ok\n\n' ] ) , ok : true } ;
272
+ return {
273
+ body : makeStream ( [ 'data: ok\n\n' ] ) ,
274
+ ok : true ,
275
+ } ;
242
276
} ) ;
243
277
244
278
const onError = vi . fn ( ) ;
245
279
const { stream } = createSseClient ( {
246
280
onSseError : onError ,
247
281
sseDefaultRetryDelay : 0 ,
248
- url : '/sse' ,
282
+ url : 'http://localhost /sse' ,
249
283
} ) ;
250
284
251
285
const result : any [ ] = [ ] ;
@@ -262,7 +296,10 @@ describe('createSseClient', () => {
262
296
} ) ;
263
297
264
298
const onEvent = vi . fn ( ) ;
265
- const { stream } = createSseClient ( { onSseEvent : onEvent , url : '/sse' } ) ;
299
+ const { stream } = createSseClient ( {
300
+ onSseEvent : onEvent ,
301
+ url : 'http://localhost/sse' ,
302
+ } ) ;
266
303
const iter = stream [ Symbol . asyncIterator ] ( ) ;
267
304
const ev = await iter . next ( ) ;
268
305
expect ( ev . value ) . toBe ( 'x' ) ;
@@ -276,7 +313,10 @@ describe('createSseClient', () => {
276
313
} ) ;
277
314
278
315
const onEvent = vi . fn ( ) ;
279
- const { stream } = createSseClient ( { onSseEvent : onEvent , url : '/sse' } ) ;
316
+ const { stream } = createSseClient ( {
317
+ onSseEvent : onEvent ,
318
+ url : 'http://localhost/sse' ,
319
+ } ) ;
280
320
const iter = stream [ Symbol . asyncIterator ] ( ) ;
281
321
const ev = await iter . next ( ) ;
282
322
expect ( ev . done ) . toBe ( true ) ;
@@ -299,7 +339,7 @@ describe('createSseClient', () => {
299
339
const { stream } = createSseClient ( {
300
340
onSseError : onError ,
301
341
onSseEvent : onEvent ,
302
- url : '/sse' ,
342
+ url : 'http://localhost /sse' ,
303
343
} ) ;
304
344
const iter = stream [ Symbol . asyncIterator ] ( ) ;
305
345
const ev = await iter . next ( ) ;
@@ -316,7 +356,7 @@ describe('createSseClient', () => {
316
356
const controller = new AbortController ( ) ;
317
357
const { stream } = createSseClient ( {
318
358
signal : controller . signal ,
319
- url : '/sse' ,
359
+ url : 'http://localhost /sse' ,
320
360
} ) ;
321
361
const iter = stream [ Symbol . asyncIterator ] ( ) ;
322
362
await iter . next ( ) ;
@@ -343,7 +383,7 @@ describe('createSseClient', () => {
343
383
controller . abort ( ) ;
344
384
const { stream } = createSseClient ( {
345
385
signal : controller . signal ,
346
- url : '/sse' ,
386
+ url : 'http://localhost /sse' ,
347
387
} ) ;
348
388
const iter = stream [ Symbol . asyncIterator ] ( ) ;
349
389
const ev = await iter . next ( ) ;
@@ -352,12 +392,21 @@ describe('createSseClient', () => {
352
392
353
393
it ( 'respects custom HTTP method' , async ( ) => {
354
394
let methodSeen : string | undefined ;
355
- fetchMock . mockImplementation ( async ( _url : any , opts : any ) => {
356
- methodSeen = opts . method ;
357
- return { body : makeStream ( [ 'data: ok\n\n' ] ) , ok : true } ;
358
- } ) ;
395
+ fetchMock . mockImplementation (
396
+ async ( input : RequestInfo , init ?: RequestInit ) => {
397
+ const req = toRequest ( input , init ) ;
398
+ methodSeen = req . method ;
399
+ return {
400
+ body : makeStream ( [ 'data: ok\n\n' ] ) ,
401
+ ok : true ,
402
+ } ;
403
+ } ,
404
+ ) ;
359
405
360
- const { stream } = createSseClient ( { method : 'POST' , url : '/sse' } ) ;
406
+ const { stream } = createSseClient ( {
407
+ method : 'POST' ,
408
+ url : 'http://localhost/sse' ,
409
+ } ) ;
361
410
const iter = stream [ Symbol . asyncIterator ] ( ) ;
362
411
await iter . next ( ) ;
363
412
await iter . return ?.( ) ;
@@ -374,7 +423,7 @@ describe('createSseClient', () => {
374
423
const controller = new AbortController ( ) ;
375
424
const { stream } = createSseClient ( {
376
425
signal : controller . signal ,
377
- url : '/sse' ,
426
+ url : 'http://localhost /sse' ,
378
427
} ) ;
379
428
380
429
const iter = stream [ Symbol . asyncIterator ] ( ) ;
@@ -397,7 +446,7 @@ describe('createSseClient', () => {
397
446
onSseEvent : ( ev ) => {
398
447
lastEventId = ev . id ;
399
448
} ,
400
- url : '/sse' ,
449
+ url : 'http://localhost /sse' ,
401
450
} ) ;
402
451
403
452
stream [ Symbol . asyncIterator ] ( ) ;
@@ -422,7 +471,7 @@ describe('createSseClient', () => {
422
471
onSseError : onError ,
423
472
sseDefaultRetryDelay : 0 ,
424
473
sseMaxRetryAttempts : 2 ,
425
- url : '/sse' ,
474
+ url : 'http://localhost /sse' ,
426
475
} ) ;
427
476
428
477
const iter = stream [ Symbol . asyncIterator ] ( ) ;
@@ -439,7 +488,10 @@ describe('createSseClient', () => {
439
488
fetchMock . mockImplementation ( ( ) => {
440
489
attempt ++ ;
441
490
if ( attempt < 3 ) throw new Error ( 'fail' ) ;
442
- return Promise . resolve ( { body : makeStream ( [ 'data: ok\n\n' ] ) , ok : true } ) ;
491
+ return Promise . resolve ( {
492
+ body : makeStream ( [ 'data: ok\n\n' ] ) ,
493
+ ok : true ,
494
+ } ) ;
443
495
} ) ;
444
496
445
497
const onError = vi . fn ( ) ;
@@ -448,7 +500,7 @@ describe('createSseClient', () => {
448
500
sseDefaultRetryDelay : 10 ,
449
501
// Inject a fake sleep that resolves instantly
450
502
sseSleepFn : async ( ) => { } ,
451
- url : '/sse' ,
503
+ url : 'http://localhost /sse' ,
452
504
} ) ;
453
505
454
506
const iter = stream [ Symbol . asyncIterator ] ( ) ;
@@ -471,7 +523,7 @@ describe('createSseClient', () => {
471
523
const { stream } = createSseClient ( {
472
524
onSseError : onError ,
473
525
sseMaxRetryAttempts : 0 ,
474
- url : '/sse' ,
526
+ url : 'http://localhost /sse' ,
475
527
} ) ;
476
528
477
529
const iter = stream [ Symbol . asyncIterator ] ( ) ;
@@ -494,7 +546,7 @@ describe('createSseClient', () => {
494
546
495
547
const { stream } = createSseClient ( {
496
548
responseValidator : validator ,
497
- url : '/sse' ,
549
+ url : 'http://localhost /sse' ,
498
550
} ) ;
499
551
500
552
const result : any [ ] = [ ] ;
@@ -516,7 +568,7 @@ describe('createSseClient', () => {
516
568
517
569
const { stream } = createSseClient ( {
518
570
responseTransformer : transformer ,
519
- url : '/sse' ,
571
+ url : 'http://localhost /sse' ,
520
572
} ) ;
521
573
522
574
const result : any [ ] = [ ] ;
@@ -546,7 +598,7 @@ describe('createSseClient', () => {
546
598
responseValidator : validator ,
547
599
sseDefaultRetryDelay : 0 ,
548
600
sseMaxRetryAttempts : 1 ,
549
- url : '/sse' ,
601
+ url : 'http://localhost /sse' ,
550
602
} ) ;
551
603
552
604
const iter = stream [ Symbol . asyncIterator ] ( ) ;
@@ -567,7 +619,7 @@ describe('createSseClient', () => {
567
619
const { stream } = createSseClient ( {
568
620
responseTransformer : transformer ,
569
621
responseValidator : validator ,
570
- url : '/sse' ,
622
+ url : 'http://localhost /sse' ,
571
623
} ) ;
572
624
573
625
const result : any [ ] = [ ] ;
0 commit comments