or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdinitialization.mdstorybook-integration.mdworker-management.md

storybook-integration.mddocs/

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

```