mirror of
https://github.com/hanzoai/msw.git
synced 2026-09-24 17:00:34 +00:00
93 lines
2.5 KiB
TypeScript
93 lines
2.5 KiB
TypeScript
import { setTimeout } from 'node:timers/promises'
|
|
import { sse } from 'msw'
|
|
import { setupWorker } from 'msw/browser'
|
|
import { createTestHttpServer } from '@epic-web/test-server/http'
|
|
import { DeferredPromise } from '@open-draft/deferred-promise'
|
|
import { test, expect } from '../playwright.extend'
|
|
|
|
declare namespace window {
|
|
export const msw: {
|
|
setupWorker: typeof setupWorker
|
|
sse: typeof sse
|
|
}
|
|
}
|
|
|
|
const EXAMPLE_URL = new URL('./sse.mocks.ts', import.meta.url)
|
|
|
|
const SSE_HEADERS = {
|
|
'access-control-allow-origin': '*',
|
|
'content-type': 'text/event-stream',
|
|
'cache-control': 'no-cache',
|
|
connection: 'keep-alive',
|
|
}
|
|
|
|
test('stops reconnecting to the upstream when the consumer closes mid-backoff', async ({
|
|
loadExample,
|
|
page,
|
|
}) => {
|
|
await loadExample(EXAMPLE_URL, {
|
|
skipActivation: true,
|
|
})
|
|
|
|
let upstreamRequestCount = 0
|
|
const firstRequestReceived = new DeferredPromise<void>()
|
|
|
|
await using server = await createTestHttpServer({
|
|
defineRoutes(router) {
|
|
router.get('/stream', () => {
|
|
upstreamRequestCount += 1
|
|
if (upstreamRequestCount === 1) {
|
|
firstRequestReceived.resolve()
|
|
}
|
|
|
|
const stream = new ReadableStream({
|
|
start(controller) {
|
|
// Set a short reconnection time so the test does not
|
|
// have to wait the default 2s.
|
|
controller.enqueue(new TextEncoder().encode('retry:200\n\n'))
|
|
controller.enqueue(
|
|
new TextEncoder().encode('data: {"message": "hello"}\n\n'),
|
|
)
|
|
// Close the stream to push the upstream EventSource into
|
|
// its reconnect backoff window.
|
|
controller.close()
|
|
},
|
|
})
|
|
|
|
return new Response(stream, { headers: SSE_HEADERS })
|
|
})
|
|
},
|
|
})
|
|
const url = server.http.url('/stream').href
|
|
|
|
await page.evaluate(async (url) => {
|
|
const { setupWorker, sse } = window.msw
|
|
|
|
const worker = setupWorker(
|
|
sse(url, ({ server }) => {
|
|
server.connect()
|
|
}),
|
|
)
|
|
await worker.start()
|
|
}, url)
|
|
|
|
await page.evaluate((url) => {
|
|
return new Promise<void>((resolve) => {
|
|
const source = new EventSource(url)
|
|
source.addEventListener('message', () => {
|
|
// Close while the upstream EventSource is mid-reconnect-backoff (200ms).
|
|
source.close()
|
|
resolve()
|
|
})
|
|
})
|
|
}, url)
|
|
|
|
await firstRequestReceived
|
|
|
|
// Wait long enough for a second reconnect to have fired if the
|
|
// abort wiring did not cancel the backoff.
|
|
await setTimeout(600)
|
|
|
|
expect(upstreamRequestCount).toBe(1)
|
|
})
|