From b028c663c116304c4b130628c4cf72a1fe00d2c7 Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Sun, 15 Oct 2023 13:31:40 +0200 Subject: [PATCH] test(browser): add ReadableStream response body test (#1770) --- .../response/body/body-stream.mocks.ts | 29 ++++++++++++ .../response/body/body-stream.test.ts | 46 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 test/browser/rest-api/response/body/body-stream.mocks.ts create mode 100644 test/browser/rest-api/response/body/body-stream.test.ts diff --git a/test/browser/rest-api/response/body/body-stream.mocks.ts b/test/browser/rest-api/response/body/body-stream.mocks.ts new file mode 100644 index 000000000..cd88c669f --- /dev/null +++ b/test/browser/rest-api/response/body/body-stream.mocks.ts @@ -0,0 +1,29 @@ +import { http, HttpResponse, delay } from 'msw' +import { setupWorker } from 'msw/browser' + +const encoder = new TextEncoder() +const chunks = ['hello', 'streaming', 'world'] + +const worker = setupWorker( + http.get('/stream', () => { + const stream = new ReadableStream({ + async start(controller) { + for (const chunk of chunks) { + controller.enqueue(encoder.encode(chunk)) + await delay(250) + } + + controller.close() + }, + }) + + return new HttpResponse(stream, { + headers: { + 'Content-Type': 'application/octet-stream', + 'Content-Length': chunks.join('').length.toString(), + }, + }) + }), +) + +worker.start() diff --git a/test/browser/rest-api/response/body/body-stream.test.ts b/test/browser/rest-api/response/body/body-stream.test.ts new file mode 100644 index 000000000..43b76d5a1 --- /dev/null +++ b/test/browser/rest-api/response/body/body-stream.test.ts @@ -0,0 +1,46 @@ +import { test, expect } from '../../../playwright.extend' + +test('responds with a mocked ReadableStream response', async ({ + loadExample, + page, +}) => { + await loadExample(require.resolve('./body-stream.mocks.ts')) + + const chunks = await page.evaluate(() => { + return fetch('/stream').then(async (res) => { + if (res.body === null) { + return [] + } + + const decoder = new TextDecoder() + const chunks: Array<{ text: string; timestamp: number }> = [] + const reader = res.body.getReader() + + while (true) { + const { value, done } = await reader.read() + + if (done) { + return chunks + } + + chunks.push({ + text: decoder.decode(value), + timestamp: Date.now(), + }) + } + }) + }) + + // Must stream the mocked response in three chunks. + const chunksText = chunks.map((chunk) => chunk.text) + expect(chunksText).toEqual(['hello', 'streaming', 'world']) + + const chunkDeltas = chunks.map((chunk, index) => { + const prevChunk = chunks[index - 1] + return prevChunk ? chunk.timestamp - prevChunk.timestamp : 0 + }) + + expect(chunkDeltas[0]).toBe(0) + expect(chunkDeltas[1]).toBeGreaterThanOrEqual(200) + expect(chunkDeltas[2]).toBeGreaterThanOrEqual(200) +})