Skip to content

Repository files navigation

MSW Storybook Addon

Mock API requests in Storybook with Mock Service Worker.

Usage

Install

npm i msw-storybook-addon -D

Make sure you have msw@2.x installed as a peer dependency.

Generate the worker script

Next, use the MSW CLI to generate a worker script at the given path:

npx msw init ./public --save

Replace ./public with the path to your static directory of Storybook.

Configure Storybook

CSF 3.0

The loader API for CSF 3.0 is deprecated. Please consider using the CSF Next API instead.

// .storybook/main.ts
export default {
  addons: ['msw-storybook-addon'],
}
// .storybook/preview.ts
import { mswLoader } from 'msw-storybook-addon/csf3'

export default {
  loaders: [mswLoader()],
  parameters: {
    msw: [...initialHandlers]
  }
}

Include the addon's types in your tsconfig.json for a type safe parameters.msw experience in your setup and stories:

{
  "include": [".storybook/preview.ts", "..."],
  "compilerOptions": {
    "types": ["msw-storybook-addon/csf3"]
  }
}

CSF Next

If you are using the CSF Next syntax (also known as CSF Factories), it's enough to import and call the addon function in preview.ts:

// .storybook/preview.ts
import addonMsw from 'msw-storybook-addon'

export default definePreview({
  addons: [addonMsw()],
})

parameters.msw is not supported in CSF Next. It is preserved only for CSF 3.0 to make migration easier — use the beforeEach hook instead.

Include the addon's types in your tsconfig.json for a type-safe experience in your setup and stories:

{
  "include": [".storybook/preview.ts", "..."],
  "compilerOptions": {
    "types": ["msw-storybook-addon/types"]
  }
}

Custom worker setup

By default, the addon creates and starts the worker for you: it starts quietly and ignores common asset and Storybook-internal requests. To customize that behavior (e.g. worker.start() options or initial handlers), provide a setup function that creates the worker, starts it, and returns it.

In CSF 3.0, pass it to mswLoader:

// .storybook/preview.ts
import { setupWorker } from 'msw/browser'
import { mswLoader } from 'msw-storybook-addon/csf3'

export default {
  loaders: [
    mswLoader(async () => {
      const worker = setupWorker()
      await worker.start({ onUnhandledRequest: 'bypass' })
      return worker
    })
  ]
}

In CSF Next, pass it to addonMsw:

// .storybook/preview.ts
import { setupWorker } from 'msw/browser'
import addonMsw from 'msw-storybook-addon'

export default definePreview({
  addons: [
    addonMsw(async () => {
      const worker = setupWorker()
      await worker.start({ onUnhandledRequest: 'bypass' })
      return worker
    })
  ],
})

Handlers passed to setupWorker() act as initial handlers and survive the automatic handler reset between stories.

Provide handlers

If you have correctly installed and configured this addon, it will extend your story context with the msw property. Use that reference to control API mocking in your stories, e.g. by adding request handler overrides via msw.use().

Global handlers

Provide request handlers in preview.ts to define the network behaviors that affect all your stories.

// .storybook/preview.ts
import { http, HttpResponse } from 'msw'

export default {
  beforeEach({ msw }) {
    msw.use(
      http.get('https://api.acme.com/user', () => {
        return HttpResponse.json({ name: 'John Maverick' })
      }),
    )
  },
}

Story handlers

To describe network behaviors on a story basis, add them in the beforeEach hook of the respective story.

export const UserProfileNetworkError: Story = {
  beforeEach({ msw }) {
    msw.use(
      http.get('https://api.acme.com/user', () => {
        return HttpResponse.error()
      }),
    )
  },
}

Related materials

Releases

Used by

Contributors

Languages