or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

app-setup.mdcomponent-testing.mdindex.mdportable-stories.mdstory-types.md

component-testing.mddocs/

0

# Component Testing with Playwright

1

2

Integration with Playwright for component testing, providing utilities to create test functions for Vue components within the Storybook environment. This enables automated browser-based testing of individual components and stories.

3

4

## Capabilities

5

6

### Create Test Function

7

8

Creates a Playwright test function specifically designed for component testing with Storybook Vue 3 components.

9

10

```typescript { .api }

11

/**

12

* Creates Playwright test function for component testing.

13

* Provides a test runner that can render and interact with Vue components

14

* in a browser environment using Playwright.

15

*

16

* @param options - Configuration options for the test runner

17

*/

18

function createTest(options?: any): any;

19

```

20

21

**Usage Example:**

22

23

```typescript

24

import { createTest } from "@storybook/vue3/experimental-playwright";

25

import { test, expect } from "@playwright/experimental-ct-vue";

26

27

const storybookTest = createTest();

28

29

storybookTest("Button renders correctly", async ({ mount }) => {

30

const component = await mount(MyButton, {

31

props: {

32

label: "Click me",

33

primary: true,

34

},

35

});

36

37

await expect(component).toContainText("Click me");

38

await expect(component).toHaveClass(/btn-primary/);

39

});

40

```

41

42

## Advanced Testing Patterns

43

44

### Testing with Stories

45

46

```typescript

47

import { createTest } from "@storybook/vue3/experimental-playwright";

48

import { composeStory } from "@storybook/vue3";

49

import Meta, { Primary } from "./Button.stories";

50

51

const test = createTest();

52

const PrimaryStory = composeStory(Primary, Meta);

53

54

test("Primary story renders correctly", async ({ mount }) => {

55

const component = await mount(PrimaryStory);

56

57

await expect(component).toBeVisible();

58

await expect(component.getByRole("button")).toHaveText("Button");

59

});

60

```

61

62

### Interactive Testing

63

64

```typescript

65

import { createTest } from "@storybook/vue3/experimental-playwright";

66

67

const test = createTest();

68

69

test("Button interaction", async ({ mount }) => {

70

let clicked = false;

71

72

const component = await mount(MyButton, {

73

props: {

74

label: "Click me",

75

onClick: () => { clicked = true; },

76

},

77

});

78

79

await component.getByRole("button").click();

80

expect(clicked).toBe(true);

81

});

82

```

83

84

### Form Testing

85

86

```typescript

87

import { createTest } from "@storybook/vue3/experimental-playwright";

88

89

const test = createTest();

90

91

test("Form submission", async ({ mount }) => {

92

const component = await mount(ContactForm, {

93

props: {

94

onSubmit: (data) => console.log("Form submitted:", data),

95

},

96

});

97

98

await component.getByLabel("Name").fill("John Doe");

99

await component.getByLabel("Email").fill("john@example.com");

100

await component.getByRole("button", { name: "Submit" }).click();

101

102

await expect(component.getByText("Form submitted successfully")).toBeVisible();

103

});

104

```

105

106

## Component Testing Configuration

107

108

### Playwright Config Setup

109

110

```typescript

111

// playwright-ct.config.ts

112

import { defineConfig, devices } from "@playwright/experimental-ct-vue";

113

import { resolve } from "path";

114

115

export default defineConfig({

116

testDir: "./src/components",

117

fullyParallel: true,

118

forbidOnly: !!process.env.CI,

119

retries: process.env.CI ? 2 : 0,

120

workers: process.env.CI ? 1 : undefined,

121

reporter: "html",

122

use: {

123

trace: "on-first-retry",

124

ctViteConfig: {

125

resolve: {

126

alias: {

127

"@": resolve(__dirname, "./src"),

128

},

129

},

130

},

131

},

132

projects: [

133

{

134

name: "chromium",

135

use: { ...devices["Desktop Chrome"] },

136

},

137

{

138

name: "firefox",

139

use: { ...devices["Desktop Firefox"] },

140

},

141

{

142

name: "webkit",

143

use: { ...devices["Desktop Safari"] },

144

},

145

],

146

});

147

```

148

149

### Test Setup File

150

151

```typescript

152

// test-setup.ts

153

import { beforeMount } from "@playwright/experimental-ct-vue";

154

import { setup } from "@storybook/vue3";

155

import { createPinia } from "pinia";

156

157

// Setup global plugins for component tests

158

setup(() => createPinia());

159

160

beforeMount(async ({ app }) => {

161

// Additional test-specific setup

162

app.config.globalProperties.$testMode = true;

163

});

164

```

165

166

## Testing Best Practices

167

168

### Component Isolation

169

170

```typescript

171

import { createTest } from "@storybook/vue3/experimental-playwright";

172

173

const test = createTest();

174

175

test.describe("Button Component", () => {

176

test("renders with default props", async ({ mount }) => {

177

const component = await mount(MyButton);

178

await expect(component).toBeVisible();

179

});

180

181

test("applies custom styling", async ({ mount }) => {

182

const component = await mount(MyButton, {

183

props: { variant: "danger", size: "large" },

184

});

185

186

await expect(component).toHaveClass(/btn-danger/);

187

await expect(component).toHaveClass(/btn-lg/);

188

});

189

});

190

```

191

192

### Accessibility Testing

193

194

```typescript

195

import { createTest } from "@storybook/vue3/experimental-playwright";

196

import AxeBuilder from "@axe-core/playwright";

197

198

const test = createTest();

199

200

test("Button is accessible", async ({ mount, page }) => {

201

await mount(MyButton, {

202

props: { label: "Accessible Button" },

203

});

204

205

const accessibilityScanResults = await new AxeBuilder({ page }).analyze();

206

expect(accessibilityScanResults.violations).toEqual([]);

207

});

208

```

209

210

### Visual Regression Testing

211

212

```typescript

213

import { createTest } from "@storybook/vue3/experimental-playwright";

214

215

const test = createTest();

216

217

test("Button visual regression", async ({ mount }) => {

218

const component = await mount(MyButton, {

219

props: {

220

label: "Visual Test Button",

221

primary: true,

222

},

223

});

224

225

await expect(component).toHaveScreenshot("primary-button.png");

226

});

227

```

228

229

## Integration with CI/CD

230

231

```yaml

232

# .github/workflows/component-tests.yml

233

name: Component Tests

234

on: [push, pull_request]

235

236

jobs:

237

test:

238

runs-on: ubuntu-latest

239

steps:

240

- uses: actions/checkout@v3

241

- uses: actions/setup-node@v3

242

with:

243

node-version: 18

244

245

- name: Install dependencies

246

run: npm install

247

248

- name: Install Playwright

249

run: npx playwright install --with-deps

250

251

- name: Run component tests

252

run: npx playwright test -c playwright-ct.config.ts

253

254

- name: Upload test results

255

uses: actions/upload-artifact@v3

256

if: always()

257

with:

258

name: playwright-report

259

path: playwright-report/

260

```