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
```