Streaming

Respond with a readable stream.

Provide a ReadableStream instance as the mocked response body to initate a stream of data.

Basic example

In this basic example we will stream a string BrandNewWorld to the client in three chunks.

import { http, HttpResponse } from 'msw'
 
const encoder = new TextEncoder()
 
export const handlers = [
  http.get('/video', () => {
    const stream = new ReadableStream({
      start(controller) {
        // Encode the string chunks using "TextEncoder".
        controller.enqueue(encoder.encode('Brand'))
        controller.enqueue(encoder.encode('New'))
        controller.enqueue(encoder.encode('World'))
        controller.close()
      },
    })
 
    // Send the mocked response immediately.
    return new HttpResponse(stream, {
      headers: {
        'Content-Type': 'text/plain',
      },
    })
  }),
]

Note that the client must also read the response as a stream to see the incoming chunks. Reading the response with methods like response.text() or response.json() will await the stream completion before returning the response body.

Transform stream example

Using the TransformStream API, we can describe more complex streaming scenarios.

In the example below, we will describe a video endpoint that establishes a readable stream from the original video resource and pipes it through a custom transform stream that inserts latency between each video stream chunk. This is handy when we wish to test how our UI handles lantecy during streams.

import { http, HttpResponse, delay } from 'msw'
 
export const handlers = [
  http.get('/video', async () => {
    // Request the original video stream.
    const videoResponse = await fetch(
      'https://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4'
    )
    const videoStream = videoResponse.body
 
    // Implement a custom transform stream that
    // takes any stream and inserts a random latency
    // between its chunks.
    const latencyStream = new TransformStream({
      start() {},
      async transform(chunk, controller) {
        await delay()
        controller.enqueue(chunk)
      },
    })
 
    return new HttpResponse(
      // Respond with the original video stream
      // piped through the latency transform stream.
      videoStream.pipeThrough(latencyStream),
      // Inherit the rest of the original video
      // response data, like "headers".
      videoResponse
    )
  }),
]