0
# Storybook Integration
1
2
Storybook loaders and decorators for applying MSW handlers on a per-story basis, with automatic cleanup and error handling. This enables mocking different API responses for different story variants.
3
4
## Capabilities
5
6
### MSW Loader
7
8
Modern Storybook loader that applies MSW handlers for each story and waits for MSW readiness.
9
10
```typescript { .api }
11
/**
12
* Storybook loader that applies MSW handlers and waits for MSW to be ready
13
* @param context - Storybook context containing story parameters
14
* @returns Promise that resolves to empty object when ready
15
*/
16
function mswLoader(context: Context): Promise<{}>;
17
18
interface Context {
19
parameters: MswParameters;
20
}
21
```
22
23
**Usage Example:**
24
25
```typescript
26
// In .storybook/preview.ts
27
import { initialize, mswLoader } from "msw-storybook-addon";
28
29
// Initialize MSW
30
initialize();
31
32
// Configure the loader globally
33
export const loaders = [mswLoader];
34
35
// In story files
36
import type { Meta, StoryObj } from "@storybook/react";
37
import { http, HttpResponse } from "msw";
38
39
export const Success: StoryObj = {
40
parameters: {
41
msw: {
42
handlers: [
43
http.get("/api/user", () => {
44
return HttpResponse.json({ name: "John Doe" });
45
}),
46
],
47
},
48
},
49
};
50
```
51
52
### MSW Decorator (Deprecated)
53
54
Legacy Storybook decorator for applying MSW handlers. **This is deprecated in favor of `mswLoader`.**
55
56
```typescript { .api }
57
/**
58
* Legacy Storybook decorator for MSW handlers (deprecated)
59
* @param storyFn - Story function to wrap
60
* @param context - Storybook context with parameters
61
* @returns Story function result
62
* @deprecated Use mswLoader instead
63
*/
64
function mswDecorator<Story extends (...args: any[]) => any>(
65
storyFn: Story,
66
context: Context
67
): any;
68
```
69
70
**Migration Example:**
71
72
```typescript
73
// OLD (deprecated)
74
import { mswDecorator } from "msw-storybook-addon";
75
76
export const decorators = [mswDecorator];
77
78
// NEW (recommended)
79
import { mswLoader } from "msw-storybook-addon";
80
81
export const loaders = [mswLoader];
82
```
83
84
### MSW Parameters Interface
85
86
Type definition for MSW parameters in Storybook stories, supporting both array and object formats.
87
88
```typescript { .api }
89
// MSW types imported from 'msw'
90
import type { RequestHandler } from 'msw';
91
92
interface MswParameters {
93
[key: string]: any;
94
msw?: RequestHandler[] | {
95
handlers: RequestHandler[] | Record<string, RequestHandler | RequestHandler[]>;
96
};
97
}
98
```
99
100
**Usage Examples:**
101
102
```typescript
103
import { http, HttpResponse } from "msw";
104
105
// Array format (deprecated but supported)
106
export const StoryWithArray: StoryObj = {
107
parameters: {
108
msw: [
109
http.get("/api/data", () => HttpResponse.json({ id: 1 })),
110
],
111
},
112
};
113
114
// Object format (recommended)
115
export const StoryWithObject: StoryObj = {
116
parameters: {
117
msw: {
118
handlers: [
119
http.get("/api/data", () => HttpResponse.json({ id: 1 })),
120
],
121
},
122
},
123
};
124
125
// Named handlers (advanced)
126
export const StoryWithNamedHandlers: StoryObj = {
127
parameters: {
128
msw: {
129
handlers: {
130
users: [
131
http.get("/api/users", () => HttpResponse.json([])),
132
],
133
posts: [
134
http.get("/api/posts", () => HttpResponse.json([])),
135
],
136
},
137
},
138
},
139
};
140
```
141
142
### Apply Request Handlers Function
143
144
Internal function for applying request handlers to the MSW instance. **This is exported for backward compatibility but should generally not be used directly.**
145
146
```typescript { .api }
147
/**
148
* Apply MSW request handlers to the current worker/server
149
* @param handlersListOrObject - Handlers in array or object format
150
*/
151
function applyRequestHandlers(
152
handlersListOrObject: Context['parameters']['msw']
153
): void;
154
```
155
156
**Usage Example (not recommended for direct use):**
157
158
```typescript
159
import { applyRequestHandlers } from "msw-storybook-addon";
160
import { http, HttpResponse } from "msw";
161
162
// Apply handlers manually (use mswLoader instead)
163
applyRequestHandlers({
164
handlers: [
165
http.get("/api/test", () => HttpResponse.json({ test: true })),
166
],
167
});
168
```
169
170
## Parameter Formats
171
172
### Recommended Object Format
173
174
The recommended format uses an object with a `handlers` property:
175
176
```typescript
177
parameters: {
178
msw: {
179
handlers: [
180
// Array of RequestHandler objects
181
]
182
}
183
}
184
```
185
186
### Named Handlers Format
187
188
For complex stories, you can organize handlers by name:
189
190
```typescript
191
parameters: {
192
msw: {
193
handlers: {
194
api: [
195
http.get("/api/data", () => HttpResponse.json({})),
196
],
197
auth: [
198
http.post("/auth/login", () => HttpResponse.json({ token: "abc" })),
199
],
200
}
201
}
202
}
203
```
204
205
### Legacy Array Format (Deprecated)
206
207
The array format is deprecated but still supported:
208
209
```typescript
210
parameters: {
211
msw: [
212
// Array of RequestHandler objects (deprecated)
213
]
214
}
215
```
216
217
## Handler Lifecycle
218
219
1. **Story Load**: When a story loads, `mswLoader` is called
220
2. **Wait for MSW**: Loader waits for MSW to be ready via `waitForMswReady()`
221
3. **Reset Handlers**: Any existing handlers are cleared with `api.resetHandlers()`
222
4. **Apply New Handlers**: Story-specific handlers are applied with `api.use(...handlers)`
223
5. **Story Render**: Story renders with new handlers active
224
225
## Error Handling
226
227
The addon includes built-in error handling:
228
229
- **Missing MSW**: If MSW is not initialized, handlers will not be applied
230
- **Invalid Handlers**: Malformed handler configurations are filtered out
231
- **Deprecation Warnings**: Using deprecated formats shows console warnings
232
233
## Integration with MSW
234
235
The addon works seamlessly with MSW's request handlers:
236
237
```typescript
238
import { http, HttpResponse, graphql } from "msw";
239
240
// REST API mocking
241
http.get("/api/users", () => {
242
return HttpResponse.json([{ id: 1, name: "Alice" }]);
243
});
244
245
// GraphQL mocking
246
graphql.query("GetUser", () => {
247
return HttpResponse.json({
248
data: { user: { id: 1, name: "Alice" } },
249
});
250
});
251
252
// Error responses
253
http.get("/api/error", () => {
254
return new HttpResponse(null, { status: 500 });
255
});
256
```
257
258
## Storybook Configuration
259
260
Complete setup example for `.storybook/preview.ts`:
261
262
```typescript
263
import { initialize, mswLoader } from "msw-storybook-addon";
264
265
// Initialize MSW
266
initialize();
267
268
// Configure preview
269
const preview = {
270
parameters: {
271
actions: { argTypesRegex: "^on[A-Z].*" },
272
controls: {
273
matchers: {
274
color: /(background|color)$/i,
275
date: /Date$/,
276
},
277
},
278
},
279
loaders: [mswLoader],
280
};
281
282
export default preview;
283
```