Mock API requests in Storybook with Mock Service Worker.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
Modern Storybook loader that applies MSW handlers for each story and waits for MSW readiness.
/**
* Storybook loader that applies MSW handlers and waits for MSW to be ready
* @param context - Storybook context containing story parameters
* @returns Promise that resolves to empty object when ready
*/
function mswLoader(context: Context): Promise<{}>;
interface Context {
parameters: MswParameters;
}Usage Example:
// In .storybook/preview.ts
import { initialize, mswLoader } from "msw-storybook-addon";
// Initialize MSW
initialize();
// Configure the loader globally
export const loaders = [mswLoader];
// In story files
import type { Meta, StoryObj } from "@storybook/react";
import { http, HttpResponse } from "msw";
export const Success: StoryObj = {
parameters: {
msw: {
handlers: [
http.get("/api/user", () => {
return HttpResponse.json({ name: "John Doe" });
}),
],
},
},
};Legacy Storybook decorator for applying MSW handlers. This is deprecated in favor of mswLoader.
/**
* Legacy Storybook decorator for MSW handlers (deprecated)
* @param storyFn - Story function to wrap
* @param context - Storybook context with parameters
* @returns Story function result
* @deprecated Use mswLoader instead
*/
function mswDecorator<Story extends (...args: any[]) => any>(
storyFn: Story,
context: Context
): any;Migration Example:
// OLD (deprecated)
import { mswDecorator } from "msw-storybook-addon";
export const decorators = [mswDecorator];
// NEW (recommended)
import { mswLoader } from "msw-storybook-addon";
export const loaders = [mswLoader];Type definition for MSW parameters in Storybook stories, supporting both array and object formats.
// MSW types imported from 'msw'
import type { RequestHandler } from 'msw';
interface MswParameters {
[key: string]: any;
msw?: RequestHandler[] | {
handlers: RequestHandler[] | Record<string, RequestHandler | RequestHandler[]>;
};
}Usage Examples:
import { http, HttpResponse } from "msw";
// Array format (deprecated but supported)
export const StoryWithArray: StoryObj = {
parameters: {
msw: [
http.get("/api/data", () => HttpResponse.json({ id: 1 })),
],
},
};
// Object format (recommended)
export const StoryWithObject: StoryObj = {
parameters: {
msw: {
handlers: [
http.get("/api/data", () => HttpResponse.json({ id: 1 })),
],
},
},
};
// Named handlers (advanced)
export const StoryWithNamedHandlers: StoryObj = {
parameters: {
msw: {
handlers: {
users: [
http.get("/api/users", () => HttpResponse.json([])),
],
posts: [
http.get("/api/posts", () => HttpResponse.json([])),
],
},
},
},
};Internal function for applying request handlers to the MSW instance. This is exported for backward compatibility but should generally not be used directly.
/**
* Apply MSW request handlers to the current worker/server
* @param handlersListOrObject - Handlers in array or object format
*/
function applyRequestHandlers(
handlersListOrObject: Context['parameters']['msw']
): void;Usage Example (not recommended for direct use):
import { applyRequestHandlers } from "msw-storybook-addon";
import { http, HttpResponse } from "msw";
// Apply handlers manually (use mswLoader instead)
applyRequestHandlers({
handlers: [
http.get("/api/test", () => HttpResponse.json({ test: true })),
],
});The recommended format uses an object with a handlers property:
parameters: {
msw: {
handlers: [
// Array of RequestHandler objects
]
}
}For complex stories, you can organize handlers by name:
parameters: {
msw: {
handlers: {
api: [
http.get("/api/data", () => HttpResponse.json({})),
],
auth: [
http.post("/auth/login", () => HttpResponse.json({ token: "abc" })),
],
}
}
}The array format is deprecated but still supported:
parameters: {
msw: [
// Array of RequestHandler objects (deprecated)
]
}mswLoader is calledwaitForMswReady()api.resetHandlers()api.use(...handlers)The addon includes built-in error handling:
The addon works seamlessly with MSW's request handlers:
import { http, HttpResponse, graphql } from "msw";
// REST API mocking
http.get("/api/users", () => {
return HttpResponse.json([{ id: 1, name: "Alice" }]);
});
// GraphQL mocking
graphql.query("GetUser", () => {
return HttpResponse.json({
data: { user: { id: 1, name: "Alice" } },
});
});
// Error responses
http.get("/api/error", () => {
return new HttpResponse(null, { status: 500 });
});Complete setup example for .storybook/preview.ts:
import { initialize, mswLoader } from "msw-storybook-addon";
// Initialize MSW
initialize();
// Configure preview
const preview = {
parameters: {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
},
loaders: [mswLoader],
};
export default preview;