Skip to content

Commit ab2f831

Browse files
committed
refactor(standard-server): prefer time mocking
1 parent 91ac36a commit ab2f831

File tree

1 file changed

+116
-72
lines changed

1 file changed

+116
-72
lines changed

packages/standard-server-fetch/src/event-iterator.test.ts

Lines changed: 116 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ const runInSpanContextSpy = vi.spyOn(shared, 'runInSpanContext')
88

99
beforeEach(() => {
1010
vi.clearAllMocks()
11+
vi.useFakeTimers()
12+
})
13+
14+
afterEach(() => {
15+
expect(vi.getTimerCount()).toBe(0) // ensure no timers are left hanging
16+
vi.useRealTimers()
1117
})
1218

1319
describe('toEventIterator', () => {
@@ -99,8 +105,8 @@ describe('toEventIterator', () => {
99105
it('with empty stream', async () => {
100106
const generator = toEventIterator(null)
101107
expect(generator).toSatisfy(isAsyncIteratorObject)
102-
expect(await generator.next()).toEqual({ done: true, value: undefined })
103-
expect(await generator.next()).toEqual({ done: true, value: undefined })
108+
expect(await generator.next()).toEqual({ done: true })
109+
expect(await generator.next()).toEqual({ done: true })
104110

105111
expect(startSpanSpy).toHaveBeenCalledTimes(1)
106112
expect(runInSpanContextSpy).toHaveBeenCalledTimes(1)
@@ -172,12 +178,13 @@ describe('toEventIterator', () => {
172178

173179
// should throw if .return is called while waiting for .next()
174180
const nextPromise = expect(generator.next()).rejects.toBeInstanceOf(shared.AbortError)
175-
await new Promise(resolve => setTimeout(resolve, 0))
181+
await vi.advanceTimersByTimeAsync(0)
176182

177183
await generator.return(undefined)
178184
await nextPromise
179185

180-
await vi.waitFor(() => expect(stream.getReader().closed).resolves.toBe(undefined))
186+
await vi.advanceTimersByTimeAsync(25)
187+
await expect(stream.getReader().closed).resolves.toBe(undefined)
181188

182189
expect(startSpanSpy).toHaveBeenCalledTimes(1)
183190
expect(runInSpanContextSpy).toHaveBeenCalledTimes(3)
@@ -202,7 +209,9 @@ describe('toEventIterator', () => {
202209
return true
203210
})
204211

205-
await expect(generator.next()).rejects.toThrow('Test error')
212+
const errorPromise = expect(generator.next()).rejects.toThrow('Test error')
213+
await vi.advanceTimersByTimeAsync(10)
214+
await errorPromise
206215

207216
expect(startSpanSpy).toHaveBeenCalledTimes(1)
208217
expect(runInSpanContextSpy).toHaveBeenCalledTimes(3)
@@ -227,7 +236,7 @@ describe('toEventStream', () => {
227236
expect((await reader.read())).toEqual({ done: false, value: 'event: message\nretry: 20000\ndata: {"order":2}\n\n' })
228237
expect((await reader.read())).toEqual({ done: false, value: 'event: message\n\n' })
229238
expect((await reader.read())).toEqual({ done: false, value: 'event: done\nretry: 40000\nid: id-4\ndata: {"order":4}\n\n' })
230-
expect((await reader.read())).toEqual({ done: true, value: undefined })
239+
expect((await reader.read())).toEqual({ done: true })
231240

232241
expect(startSpanSpy).toHaveBeenCalledTimes(1)
233242
expect(runInSpanContextSpy).toHaveBeenCalledTimes(4)
@@ -248,7 +257,7 @@ describe('toEventStream', () => {
248257
expect((await reader.read())).toEqual({ done: false, value: 'event: message\nid: id-1\ndata: {"order":1}\n\n' })
249258
expect((await reader.read())).toEqual({ done: false, value: 'event: message\nretry: 20000\ndata: {"order":2}\n\n' })
250259
expect((await reader.read())).toEqual({ done: false, value: 'event: message\n\n' })
251-
expect((await reader.read())).toEqual({ done: true, value: undefined })
260+
expect((await reader.read())).toEqual({ done: true })
252261

253262
expect(startSpanSpy).toHaveBeenCalledTimes(1)
254263
expect(runInSpanContextSpy).toHaveBeenCalledTimes(4)
@@ -315,15 +324,20 @@ describe('toEventStream', () => {
315324
}
316325

317326
const stream = toEventStream(gen())
318-
319327
const reader = stream.getReader()
320-
await reader.read()
321-
await reader.read()
322-
await reader.cancel()
323328

324-
await vi.waitFor(() => {
325-
expect(hasFinally).toBe(true)
326-
})
329+
await Promise.all([
330+
reader.read(),
331+
vi.advanceTimersByTimeAsync(10),
332+
])
333+
334+
await Promise.all([
335+
reader.read(),
336+
vi.advanceTimersByTimeAsync(10),
337+
])
338+
339+
await reader.cancel()
340+
expect(hasFinally).toBe(true)
327341

328342
expect(startSpanSpy).toHaveBeenCalledTimes(1)
329343
expect(runInSpanContextSpy).toHaveBeenCalledTimes(3)
@@ -347,13 +361,22 @@ describe('toEventStream', () => {
347361
const stream = toEventStream(gen())
348362

349363
const reader = stream.getReader()
350-
await reader.read()
351-
await reader.read()
364+
365+
await Promise.all([
366+
reader.read(),
367+
vi.advanceTimersByTimeAsync(10),
368+
])
369+
370+
reader.read()
371+
// start waiting for the error
372+
await vi.advanceTimersByTimeAsync(5)
373+
374+
// Cancel before the error is thrown
352375
await reader.cancel()
353376

354-
await vi.waitFor(() => {
355-
expect(hasFinally).toBe(true)
356-
})
377+
// finish the error throwing
378+
await vi.advanceTimersByTimeAsync(5)
379+
expect(hasFinally).toBe(true)
357380

358381
expect(startSpanSpy).toHaveBeenCalledTimes(1)
359382
expect(runInSpanContextSpy).toHaveBeenCalledTimes(3)
@@ -379,15 +402,18 @@ describe('toEventStream', () => {
379402

380403
const reader = stream.getReader()
381404
await reader.read()
382-
await reader.read()
405+
406+
// start iterator
407+
await Promise.all([
408+
reader.read(),
409+
vi.advanceTimersByTimeAsync(10),
410+
])
411+
383412
/**
384413
* This should throw, but because TextEncoderStream not rethrows cancel errors from the source stream,
385414
*/
386415
await reader.cancel()
387-
388-
await vi.waitFor(() => {
389-
expect(hasFinally).toBe(true)
390-
})
416+
expect(hasFinally).toBe(true)
391417

392418
expect(startSpanSpy).toHaveBeenCalledTimes(1)
393419
expect(runInSpanContextSpy).toHaveBeenCalledTimes(3)
@@ -396,7 +422,7 @@ describe('toEventStream', () => {
396422
describe('keep alive', () => {
397423
it('enabled', async () => {
398424
async function* gen() {
399-
while (true) {
425+
for (let i = 0; i < 2; i++) {
400426
await new Promise(resolve => setTimeout(resolve, 100))
401427
yield 'hello'
402428
}
@@ -413,41 +439,47 @@ describe('toEventStream', () => {
413439
.pipeThrough(new TextDecoderStream())
414440
.getReader()
415441

416-
const now = Date.now()
417-
await expect(reader.read()).resolves.toEqual({ done: false, value: ': ping\n\n' })
418-
expect(Date.now() - now).toBeGreaterThanOrEqual(40)
419-
expect(Date.now() - now).toBeLessThan(50)
420-
421-
await expect(reader.read()).resolves.toEqual({ done: false, value: ': ping\n\n' })
422-
expect(Date.now() - now).toBeGreaterThanOrEqual(80)
423-
expect(Date.now() - now).toBeLessThan(100)
424-
425-
await expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello"\n\n' })
426-
expect(Date.now() - now).toBeGreaterThanOrEqual(100)
427-
expect(Date.now() - now).toBeLessThan(130)
428-
429-
await expect(reader.read()).resolves.toEqual({ done: false, value: ': ping\n\n' })
430-
expect(Date.now() - now).toBeGreaterThanOrEqual(140)
431-
expect(Date.now() - now).toBeLessThan(180)
432-
433-
await expect(reader.read()).resolves.toEqual({ done: false, value: ': ping\n\n' })
434-
expect(Date.now() - now).toBeGreaterThanOrEqual(180)
435-
expect(Date.now() - now).toBeLessThan(230)
436-
437-
await expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello"\n\n' })
438-
expect(Date.now() - now).toBeGreaterThanOrEqual(200)
439-
expect(Date.now() - now).toBeLessThan(260)
440-
442+
await Promise.all([
443+
expect(reader.read()).resolves.toEqual({ done: false, value: ': ping\n\n' }),
444+
vi.advanceTimersByTimeAsync(40),
445+
])
446+
447+
await Promise.all([
448+
expect(reader.read()).resolves.toEqual({ done: false, value: ': ping\n\n' }),
449+
vi.advanceTimersByTimeAsync(40),
450+
])
451+
452+
await Promise.all([
453+
expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello"\n\n' }),
454+
vi.advanceTimersByTimeAsync(20),
455+
])
456+
457+
await Promise.all([
458+
expect(reader.read()).resolves.toEqual({ done: false, value: ': ping\n\n' }),
459+
vi.advanceTimersByTimeAsync(40),
460+
])
461+
462+
await Promise.all([
463+
expect(reader.read()).resolves.toEqual({ done: false, value: ': ping\n\n' }),
464+
vi.advanceTimersByTimeAsync(40),
465+
])
466+
467+
await Promise.all([
468+
expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello"\n\n' }),
469+
vi.advanceTimersByTimeAsync(20),
470+
])
471+
472+
await expect(reader.read()).resolves.toEqual({ done: true })
441473
expect(startSpanSpy).toHaveBeenCalledTimes(1)
442474
expect(runInSpanContextSpy).toHaveBeenCalledTimes(3)
443475
})
444476

445477
it('disabled', async () => {
446478
async function* gen() {
447-
while (true) {
448-
await new Promise(resolve => setTimeout(resolve, 100))
449-
yield 'hello'
450-
}
479+
await new Promise(resolve => setTimeout(resolve, 100))
480+
yield 'hello1'
481+
await new Promise(resolve => setTimeout(resolve, 100))
482+
yield 'hello2'
451483
}
452484

453485
const stream = toEventStream(gen(), {
@@ -461,15 +493,17 @@ describe('toEventStream', () => {
461493
.pipeThrough(new TextDecoderStream())
462494
.getReader()
463495

464-
const now = Date.now()
465-
await expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello"\n\n' })
466-
expect(Date.now() - now).toBeGreaterThanOrEqual(100)
467-
expect(Date.now() - now).toBeLessThan(110)
496+
await Promise.all([
497+
expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello1"\n\n' }),
498+
vi.advanceTimersByTimeAsync(100),
499+
])
468500

469-
await expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello"\n\n' })
470-
expect(Date.now() - now).toBeGreaterThanOrEqual(200)
471-
expect(Date.now() - now).toBeLessThan(220)
501+
await Promise.all([
502+
expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello2"\n\n' }),
503+
vi.advanceTimersByTimeAsync(100),
504+
])
472505

506+
await expect(reader.read()).resolves.toEqual({ done: true })
473507
expect(startSpanSpy).toHaveBeenCalledTimes(1)
474508
expect(runInSpanContextSpy).toHaveBeenCalledTimes(3)
475509
})
@@ -492,12 +526,15 @@ describe('toEventStream', () => {
492526
.pipeThrough(new TextDecoderStream())
493527
.getReader()
494528

495-
const start = Date.now()
529+
// Initial comment is sent immediately
496530
await expect(reader.read()).resolves.toEqual({ done: false, value: ': stream-started\n\n' })
497-
expect(Date.now() - start).toBeLessThan(10)
498-
await expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello"\n\n' })
499-
expect(Date.now() - start).toBeGreaterThanOrEqual(50)
500-
expect(Date.now() - start).toBeLessThan(60)
531+
532+
await Promise.all([
533+
expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello"\n\n' }),
534+
vi.advanceTimersByTimeAsync(50),
535+
])
536+
537+
await expect(reader.read()).resolves.toEqual({ done: true })
501538
})
502539

503540
it('disabled', async () => {
@@ -515,10 +552,12 @@ describe('toEventStream', () => {
515552
.pipeThrough(new TextDecoderStream())
516553
.getReader()
517554

518-
const start = Date.now()
519-
await expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello"\n\n' })
520-
expect(Date.now() - start).toBeGreaterThanOrEqual(50)
521-
expect(Date.now() - start).toBeLessThan(60)
555+
await Promise.all([
556+
expect(reader.read()).resolves.toEqual({ done: false, value: 'event: message\ndata: "hello"\n\n' }),
557+
vi.advanceTimersByTimeAsync(50),
558+
])
559+
560+
await expect(reader.read()).resolves.toEqual({ done: true })
522561
})
523562
})
524563
})
@@ -534,7 +573,12 @@ it.each([
534573
}
535574
})(), { eventIteratorKeepAliveInterval: 10 }))
536575

537-
for await (const value of iterator) {
538-
expect(value).toEqual(values.shift())
576+
for (const expectedValue of values) {
577+
await Promise.all([
578+
expect(iterator.next()).resolves.toEqual({ done: false, value: expectedValue }),
579+
vi.advanceTimersByTimeAsync(50),
580+
])
539581
}
582+
583+
await iterator.next()
540584
})

0 commit comments

Comments
 (0)