0
# Testing Integration
1
2
Testing utilities and experimental Playwright integration for enhanced testing workflows. Provides tools for integrating Storybook stories with various testing frameworks and environments.
3
4
## Type Dependencies
5
6
The testing integration features depend on Storybook preview API:
7
8
```typescript
9
// Experimental Playwright integration
10
import { createTest } from "@storybook/react/experimental-playwright";
11
12
// Portable stories for testing (see Portable Stories documentation)
13
import { composeStory, composeStories, setProjectAnnotations } from "@storybook/react";
14
15
// Re-exported from storybook/preview-api
16
import { createPlaywrightTest } from "storybook/preview-api";
17
```
18
19
## Capabilities
20
21
### Create Test (Playwright Integration)
22
23
Experimental Playwright testing utility for creating test functions that work with Storybook stories.
24
25
```typescript { .api }
26
/**
27
* Creates Playwright test function for Storybook integration.
28
* Re-exported from storybook/preview-api for convenience.
29
*
30
* @returns Playwright test creation function
31
*/
32
function createTest(): any;
33
```
34
35
This function is part of the experimental Playwright integration and provides utilities for running Storybook stories in Playwright test environments.
36
37
**Usage Example:**
38
39
```typescript
40
import { createTest } from "@storybook/react/experimental-playwright";
41
42
const test = createTest();
43
44
test("Button stories", async ({ page }) => {
45
// Use with Playwright for visual testing
46
await page.goto("/storybook-iframe.html?id=example-button--primary");
47
await expect(page).toHaveScreenshot("primary-button.png");
48
});
49
```
50
51
## Testing Patterns with React Testing Library
52
53
While not directly exported from @storybook/react, the package is designed to work seamlessly with React Testing Library through portable stories:
54
55
```typescript
56
import { render, screen, fireEvent } from "@testing-library/react";
57
import { composeStory, composeStories } from "@storybook/react";
58
import Meta, { Primary, Secondary } from "./Button.stories";
59
60
// Single story testing
61
const PrimaryButton = composeStory(Primary, Meta);
62
63
test("renders primary button", () => {
64
render(<PrimaryButton />);
65
expect(screen.getByRole("button")).toHaveClass("primary");
66
});
67
68
// Testing with custom props
69
test("button accepts custom props", () => {
70
render(<PrimaryButton size="large" onClick={vi.fn()} />);
71
expect(screen.getByRole("button")).toHaveClass("large");
72
});
73
74
// Multiple story testing
75
const { Primary: PrimaryStory, Secondary: SecondaryStory } = composeStories(Meta);
76
77
describe("Button component", () => {
78
test("all stories render correctly", () => {
79
Object.entries(composeStories(Meta)).forEach(([name, Story]) => {
80
render(<Story />);
81
expect(screen.getByRole("button")).toBeInTheDocument();
82
});
83
});
84
});
85
```
86
87
## Jest/Vitest Integration
88
89
```typescript
90
import { beforeAll } from "vitest";
91
import { setProjectAnnotations } from "@storybook/react";
92
import * as projectAnnotations from "../.storybook/preview";
93
94
// Setup global configuration
95
beforeAll(() => {
96
setProjectAnnotations(projectAnnotations);
97
});
98
99
// Test individual stories
100
import { composeStory } from "@storybook/react";
101
import Meta, { Default } from "./Component.stories";
102
103
const DefaultStory = composeStory(Default, Meta);
104
105
test("story renders with default args", () => {
106
render(<DefaultStory />);
107
// Test the rendered component
108
});
109
```
110
111
## Testing with Context Providers
112
113
```typescript
114
import { render } from "@testing-library/react";
115
import { composeStory } from "@storybook/react";
116
import { ThemeProvider } from "./theme";
117
import Meta, { Themed } from "./Button.stories";
118
119
const ThemedButton = composeStory(Themed, Meta);
120
121
test("button works with theme context", () => {
122
render(
123
<ThemeProvider theme="dark">
124
<ThemedButton />
125
</ThemeProvider>
126
);
127
128
// Test themed behavior
129
});
130
```
131
132
## Visual Regression Testing
133
134
```typescript
135
// Using @storybook/test-runner or Playwright
136
import type { TestRunnerConfig } from "@storybook/test-runner";
137
138
const config: TestRunnerConfig = {
139
async postRender(page, context) {
140
// Take screenshot of each story
141
const elementHandler = await page.$("#storybook-root");
142
const innerHTML = await elementHandler.innerHTML();
143
expect(innerHTML).toMatchSnapshot(`${context.id}.html`);
144
},
145
};
146
147
export default config;
148
```
149
150
## Accessibility Testing
151
152
```typescript
153
import { render } from "@testing-library/react";
154
import { axe, toHaveNoViolations } from "jest-axe";
155
import { composeStories } from "@storybook/react";
156
import * as stories from "./Button.stories";
157
158
expect.extend(toHaveNoViolations);
159
160
const { Primary, Secondary } = composeStories(stories);
161
162
test("Primary button should be accessible", async () => {
163
const { container } = render(<Primary />);
164
const results = await axe(container);
165
expect(results).toHaveNoViolations();
166
});
167
```
168
169
## Mock Function Testing
170
171
```typescript
172
import { render, fireEvent } from "@testing-library/react";
173
import { composeStory } from "@storybook/react";
174
import { fn } from "@storybook/test";
175
import Meta, { Interactive } from "./Button.stories";
176
177
const InteractiveButton = composeStory(Interactive, Meta);
178
179
test("button calls onClick handler", () => {
180
const mockFn = fn();
181
render(<InteractiveButton onClick={mockFn} />);
182
183
fireEvent.click(screen.getByRole("button"));
184
expect(mockFn).toHaveBeenCalledTimes(1);
185
});
186
```
187
188
## Integration with Testing Libraries
189
190
### Setup for React Testing Library
191
192
```typescript
193
// test-setup.ts
194
import "@testing-library/jest-dom";
195
import { setProjectAnnotations } from "@storybook/react";
196
import * as projectAnnotations from "../.storybook/preview";
197
198
setProjectAnnotations(projectAnnotations);
199
```
200
201
### Setup for Vitest
202
203
```typescript
204
// vitest.config.ts
205
import { defineConfig } from "vitest/config";
206
207
export default defineConfig({
208
test: {
209
environment: "jsdom",
210
setupFiles: ["./test-setup.ts"],
211
},
212
});
213
```
214
215
### Setup for Jest
216
217
```javascript
218
// jest.config.js
219
module.exports = {
220
testEnvironment: "jsdom",
221
setupFilesAfterEnv: ["<rootDir>/test-setup.ts"],
222
transform: {
223
"^.+\\.(ts|tsx)$": "ts-jest",
224
},
225
};
226
```
227
228
## Advanced Testing Patterns
229
230
### Testing Story Parameters
231
232
```typescript
233
import { composeStory } from "@storybook/react";
234
import Meta, { WithBackground } from "./Button.stories";
235
236
const ButtonWithBackground = composeStory(WithBackground, Meta);
237
238
test("story uses correct background parameter", () => {
239
expect(ButtonWithBackground.parameters.backgrounds.default).toBe("dark");
240
});
241
```
242
243
### Testing Story Args
244
245
```typescript
246
const PrimaryButton = composeStory(Primary, Meta);
247
248
test("story has correct default args", () => {
249
expect(PrimaryButton.args).toEqual({
250
primary: true,
251
label: "Button",
252
size: "medium",
253
});
254
});
255
```
256
257
### Testing with Loaders
258
259
```typescript
260
import { composeStory } from "@storybook/react";
261
import Meta, { WithData } from "./DataComponent.stories";
262
263
const DataComponent = composeStory(WithData, Meta);
264
265
test("story with loader works correctly", async () => {
266
// The story's loader will run automatically when composed
267
render(<DataComponent />);
268
269
// Test the component with loaded data
270
await waitFor(() => {
271
expect(screen.getByText("Loaded Data")).toBeInTheDocument();
272
});
273
});
274
```
275
276
## Experimental Features
277
278
The testing integration includes experimental features that may change in future versions:
279
280
- **Playwright Integration**: Enhanced Playwright support for visual testing
281
- **Component Testing**: Direct component testing within Storybook environment
282
- **Test Runner Integration**: Built-in test runner for Storybook stories
283
284
These features are available through the `experimental-playwright` export and should be used with caution in production environments.