msw-storybook-addon
Version:
Mock APIs in Storybook using Mock Service Worker.
171 lines (126 loc) • 4.03 kB
Markdown
# MSW Storybook Addon
Mock API requests in Storybook with Mock Service Worker.
## Usage
### Install
```sh
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:
```sh
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](#csf-next) API instead.
```ts
// .storybook/main.ts
export default {
addons: ['msw-storybook-addon'],
}
```
```ts
// .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:
```json
{
"include": [".storybook/preview.ts", "..."],
"compilerOptions": {
"types": ["msw-storybook-addon/csf3"]
}
}
```
#### CSF Next
If you are using the [CSF Next](https://storybook.js.org/docs/api/csf/csf-next) syntax (also known as CSF Factories), it's enough to import and call the addon function in `preview.ts`:
```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:
```json
{
"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`:
```ts
// .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`:
```ts
// .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.
```ts
// .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.
```ts
export const UserProfileNetworkError: Story = {
beforeEach({ msw }) {
msw.use(
http.get('https://api.acme.com/user', () => {
return HttpResponse.error()
}),
)
},
}
```
## Related materials
- [Mock Service Worker](https://mswjs.io/docs)