or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdportable-stories.mdpreview-configuration.mdreact-renderer.mdstory-types.mdtesting-integration.md

testing-integration.mddocs/

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.