@neyugn/agent-kits 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +514 -0
- package/README.vi.md +410 -0
- package/README.zh.md +410 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +422 -0
- package/kits/coder/ARCHITECTURE.md +289 -0
- package/kits/coder/agents/ai-engineer.md +344 -0
- package/kits/coder/agents/backend-specialist.md +270 -0
- package/kits/coder/agents/cloud-architect.md +363 -0
- package/kits/coder/agents/code-reviewer.md +284 -0
- package/kits/coder/agents/data-engineer.md +401 -0
- package/kits/coder/agents/database-specialist.md +251 -0
- package/kits/coder/agents/debugger.md +209 -0
- package/kits/coder/agents/devops-engineer.md +281 -0
- package/kits/coder/agents/documentation-writer.md +296 -0
- package/kits/coder/agents/frontend-specialist.md +298 -0
- package/kits/coder/agents/i18n-specialist.md +348 -0
- package/kits/coder/agents/integration-specialist.md +314 -0
- package/kits/coder/agents/mobile-developer.md +271 -0
- package/kits/coder/agents/multi-tenant-architect.md +281 -0
- package/kits/coder/agents/orchestrator.md +263 -0
- package/kits/coder/agents/performance-analyst.md +327 -0
- package/kits/coder/agents/project-planner.md +277 -0
- package/kits/coder/agents/queue-specialist.md +282 -0
- package/kits/coder/agents/realtime-specialist.md +267 -0
- package/kits/coder/agents/security-auditor.md +253 -0
- package/kits/coder/agents/test-engineer.md +315 -0
- package/kits/coder/agents/ux-researcher.md +388 -0
- package/kits/coder/rules/.cursorrules +287 -0
- package/kits/coder/rules/CLAUDE.md +287 -0
- package/kits/coder/rules/CODEX.md +287 -0
- package/kits/coder/rules/GEMINI.md +287 -0
- package/kits/coder/scripts/checklist.py +318 -0
- package/kits/coder/scripts/kit_status.py +292 -0
- package/kits/coder/scripts/skills_manager.py +243 -0
- package/kits/coder/scripts/verify_all.py +391 -0
- package/kits/coder/skills/accessibility-patterns/SKILL.md +372 -0
- package/kits/coder/skills/accessibility-patterns/scripts/a11y_checker.py +211 -0
- package/kits/coder/skills/ai-rag-patterns/SKILL.md +444 -0
- package/kits/coder/skills/api-patterns/SKILL.md +316 -0
- package/kits/coder/skills/api-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/api-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/api-patterns/scripts/api_validator.py +253 -0
- package/kits/coder/skills/api-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/auth-patterns/SKILL.md +267 -0
- package/kits/coder/skills/aws-patterns/SKILL.md +576 -0
- package/kits/coder/skills/brainstorming/SKILL.md +370 -0
- package/kits/coder/skills/brainstorming/assets/.gitkeep +1 -0
- package/kits/coder/skills/brainstorming/references/deep-dive.md +21 -0
- package/kits/coder/skills/brainstorming/scripts/validate.py +56 -0
- package/kits/coder/skills/clean-code/SKILL.md +240 -0
- package/kits/coder/skills/clean-code/assets/.gitkeep +1 -0
- package/kits/coder/skills/clean-code/references/deep-dive.md +21 -0
- package/kits/coder/skills/clean-code/scripts/lint_runner.py +186 -0
- package/kits/coder/skills/clean-code/scripts/validate.py +56 -0
- package/kits/coder/skills/database-design/SKILL.md +255 -0
- package/kits/coder/skills/database-design/assets/.gitkeep +1 -0
- package/kits/coder/skills/database-design/references/deep-dive.md +21 -0
- package/kits/coder/skills/database-design/scripts/schema_validator.py +272 -0
- package/kits/coder/skills/database-design/scripts/validate.py +56 -0
- package/kits/coder/skills/docker-patterns/SKILL.md +240 -0
- package/kits/coder/skills/documentation-templates/SKILL.md +441 -0
- package/kits/coder/skills/e2e-testing/SKILL.md +457 -0
- package/kits/coder/skills/flutter-patterns/SKILL.md +330 -0
- package/kits/coder/skills/frontend-design/SKILL.md +127 -0
- package/kits/coder/skills/github-actions/SKILL.md +349 -0
- package/kits/coder/skills/gitlab-ci-patterns/SKILL.md +466 -0
- package/kits/coder/skills/graphql-patterns/SKILL.md +558 -0
- package/kits/coder/skills/i18n-localization/SKILL.md +345 -0
- package/kits/coder/skills/i18n-localization/scripts/i18n_checker.py +267 -0
- package/kits/coder/skills/kubernetes-patterns/SKILL.md +357 -0
- package/kits/coder/skills/mermaid-diagrams/SKILL.md +351 -0
- package/kits/coder/skills/mobile-design/SKILL.md +305 -0
- package/kits/coder/skills/monitoring-observability/SKILL.md +458 -0
- package/kits/coder/skills/multi-tenancy/SKILL.md +317 -0
- package/kits/coder/skills/multi-tenancy/assets/.gitkeep +1 -0
- package/kits/coder/skills/multi-tenancy/references/deep-dive.md +21 -0
- package/kits/coder/skills/multi-tenancy/scripts/validate.py +56 -0
- package/kits/coder/skills/nodejs-best-practices/SKILL.md +220 -0
- package/kits/coder/skills/performance-profiling/SKILL.md +333 -0
- package/kits/coder/skills/performance-profiling/assets/.gitkeep +1 -0
- package/kits/coder/skills/performance-profiling/references/deep-dive.md +21 -0
- package/kits/coder/skills/performance-profiling/scripts/validate.py +56 -0
- package/kits/coder/skills/plan-writing/SKILL.md +360 -0
- package/kits/coder/skills/plan-writing/assets/.gitkeep +1 -0
- package/kits/coder/skills/plan-writing/references/deep-dive.md +21 -0
- package/kits/coder/skills/plan-writing/scripts/validate.py +56 -0
- package/kits/coder/skills/postgres-patterns/SKILL.md +361 -0
- package/kits/coder/skills/prompt-engineering/SKILL.md +277 -0
- package/kits/coder/skills/queue-patterns/SKILL.md +359 -0
- package/kits/coder/skills/queue-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/queue-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/queue-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/react-native-patterns/SKILL.md +393 -0
- package/kits/coder/skills/react-patterns/SKILL.md +319 -0
- package/kits/coder/skills/realtime-patterns/SKILL.md +506 -0
- package/kits/coder/skills/realtime-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/realtime-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/realtime-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/redis-patterns/SKILL.md +484 -0
- package/kits/coder/skills/security-fundamentals/SKILL.md +363 -0
- package/kits/coder/skills/security-fundamentals/assets/.gitkeep +1 -0
- package/kits/coder/skills/security-fundamentals/references/deep-dive.md +21 -0
- package/kits/coder/skills/security-fundamentals/scripts/security_scan.py +326 -0
- package/kits/coder/skills/security-fundamentals/scripts/validate.py +56 -0
- package/kits/coder/skills/seo-patterns/SKILL.md +262 -0
- package/kits/coder/skills/seo-patterns/scripts/seo_checker.py +211 -0
- package/kits/coder/skills/systematic-debugging/SKILL.md +478 -0
- package/kits/coder/skills/systematic-debugging/assets/.gitkeep +1 -0
- package/kits/coder/skills/systematic-debugging/references/deep-dive.md +21 -0
- package/kits/coder/skills/systematic-debugging/scripts/validate.py +56 -0
- package/kits/coder/skills/tailwind-patterns/SKILL.md +395 -0
- package/kits/coder/skills/terraform-patterns/SKILL.md +470 -0
- package/kits/coder/skills/testing-patterns/SKILL.md +285 -0
- package/kits/coder/skills/testing-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/testing-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/testing-patterns/scripts/test_runner.py +219 -0
- package/kits/coder/skills/testing-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/typescript-patterns/SKILL.md +417 -0
- package/kits/coder/skills/ui-ux-pro-max/SKILL.md +364 -0
- package/kits/coder/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/kits/coder/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/kits/coder/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/kits/coder/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/kits/coder/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/kits/coder/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/kits/coder/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/kits/coder/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/kits/coder/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/kits/coder/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/kits/coder/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/kits/coder/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/core.py +257 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/design_system.py +488 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/search.py +76 -0
- package/kits/coder/workflows/.gitkeep +20 -0
- package/kits/coder/workflows/create.md +152 -0
- package/kits/coder/workflows/debug.md +223 -0
- package/kits/coder/workflows/deploy.md +283 -0
- package/kits/coder/workflows/orchestrate.md +243 -0
- package/kits/coder/workflows/plan.md +134 -0
- package/kits/coder/workflows/test.md +237 -0
- package/kits/coder/workflows/ui-ux-pro-max.md +109 -0
- package/package.json +49 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: e2e-testing
|
|
3
|
+
description: End-to-end testing patterns with Playwright and Cypress. Use when implementing E2E tests, debugging flaky tests, testing critical user flows, setting up CI/CD test pipelines, or establishing E2E testing standards. Covers test design, reliability patterns, CI integration, and visual regression.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# E2E Testing Patterns
|
|
8
|
+
|
|
9
|
+
> **Philosophy:** E2E tests should give confidence to ship, not slow you down. Test critical paths, make them reliable, run them fast.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 📑 Content Map
|
|
14
|
+
|
|
15
|
+
| File | When to Read |
|
|
16
|
+
| -------------------------------- | ---------------------------- |
|
|
17
|
+
| `references/playwright-api.md` | Playwright-specific patterns |
|
|
18
|
+
| `references/cypress-patterns.md` | Cypress-specific patterns |
|
|
19
|
+
| `references/ci-integration.md` | CI/CD setup and optimization |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 1. When to Use E2E Testing
|
|
24
|
+
|
|
25
|
+
### ✅ Use E2E When
|
|
26
|
+
|
|
27
|
+
| Scenario | Why E2E |
|
|
28
|
+
| --------------------------- | --------------------------- |
|
|
29
|
+
| Critical user journeys | Full flow validation |
|
|
30
|
+
| Authentication flows | Security-critical paths |
|
|
31
|
+
| Payment/checkout | Money-critical paths |
|
|
32
|
+
| Cross-browser compatibility | Real browser behavior |
|
|
33
|
+
| Accessibility validation | Full page context needed |
|
|
34
|
+
| Visual regression | Layout/styling verification |
|
|
35
|
+
|
|
36
|
+
### ❌ Don't Use E2E When
|
|
37
|
+
|
|
38
|
+
| Scenario | Better Alternative |
|
|
39
|
+
| ------------------------------- | ----------------------------------- |
|
|
40
|
+
| Unit logic testing | Unit tests (Vitest, Jest) |
|
|
41
|
+
| Component behavior | Integration tests (Testing Library) |
|
|
42
|
+
| API contract validation | API tests (Supertest, Hurl) |
|
|
43
|
+
| Unstable/frequently changing UI | Lower-level tests first |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 2. Playwright vs Cypress Decision
|
|
48
|
+
|
|
49
|
+
| Factor | Playwright | Cypress |
|
|
50
|
+
| --------------------- | --------------------------- | --------------------- |
|
|
51
|
+
| **Multi-browser** | ✅ Chrome, FF, Safari, Edge | ⚠️ Limited Safari |
|
|
52
|
+
| **Speed** | ✅ Faster parallel | ⚠️ Slower |
|
|
53
|
+
| **Cross-origin** | ✅ Full support | ⚠️ Limited |
|
|
54
|
+
| **API testing** | ✅ Built-in | ⚠️ Needs plugins |
|
|
55
|
+
| **Learning curve** | Medium | Easy |
|
|
56
|
+
| **Debugging** | Trace viewer | Time-travel debugging |
|
|
57
|
+
| **Component testing** | ✅ Supported | ✅ Supported |
|
|
58
|
+
|
|
59
|
+
**Recommendation:** Use **Playwright** for new projects (2025+).
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 3. Test Design Principles
|
|
64
|
+
|
|
65
|
+
### Page Object Model (POM)
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// pages/login.page.ts
|
|
69
|
+
export class LoginPage {
|
|
70
|
+
constructor(private page: Page) {}
|
|
71
|
+
|
|
72
|
+
readonly email = this.page.getByLabel("Email");
|
|
73
|
+
readonly password = this.page.getByLabel("Password");
|
|
74
|
+
readonly submitBtn = this.page.getByRole("button", { name: "Sign in" });
|
|
75
|
+
readonly errorMessage = this.page.getByRole("alert");
|
|
76
|
+
|
|
77
|
+
async login(email: string, password: string) {
|
|
78
|
+
await this.email.fill(email);
|
|
79
|
+
await this.password.fill(password);
|
|
80
|
+
await this.submitBtn.click();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async expectError(message: string) {
|
|
84
|
+
await expect(this.errorMessage).toContainText(message);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// tests/login.spec.ts
|
|
89
|
+
test("successful login redirects to dashboard", async ({ page }) => {
|
|
90
|
+
const loginPage = new LoginPage(page);
|
|
91
|
+
await page.goto("/login");
|
|
92
|
+
|
|
93
|
+
await loginPage.login("user@example.com", "password123");
|
|
94
|
+
|
|
95
|
+
await expect(page).toHaveURL("/dashboard");
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Test Structure (AAA Pattern)
|
|
100
|
+
|
|
101
|
+
| Phase | Action |
|
|
102
|
+
| ----------- | -------------------------- |
|
|
103
|
+
| **Arrange** | Navigate, set up test data |
|
|
104
|
+
| **Act** | Perform user actions |
|
|
105
|
+
| **Assert** | Verify expected outcomes |
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 4. Selector Strategies (Priority Order)
|
|
110
|
+
|
|
111
|
+
### ✅ Recommended Selectors
|
|
112
|
+
|
|
113
|
+
| Priority | Selector Type | Example |
|
|
114
|
+
| -------- | -------------------- | --------------------------------------- |
|
|
115
|
+
| 1 | Role (accessibility) | `getByRole('button', {name: 'Submit'})` |
|
|
116
|
+
| 2 | Label | `getByLabel('Email')` |
|
|
117
|
+
| 3 | Placeholder | `getByPlaceholder('Search...')` |
|
|
118
|
+
| 4 | Text | `getByText('Welcome')` |
|
|
119
|
+
| 5 | Test ID | `getByTestId('submit-btn')` |
|
|
120
|
+
|
|
121
|
+
### ❌ Avoid
|
|
122
|
+
|
|
123
|
+
| Selector | Why |
|
|
124
|
+
| ------------- | --------------------------- |
|
|
125
|
+
| CSS class | Styling changes break tests |
|
|
126
|
+
| Tag name only | Too generic, fragile |
|
|
127
|
+
| XPath | Hard to read, fragile |
|
|
128
|
+
| nth-child | Order-dependent, fragile |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 5. Reliability Patterns
|
|
133
|
+
|
|
134
|
+
### Auto-Waiting (Playwright)
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
// ✅ Playwright auto-waits for elements
|
|
138
|
+
await page.click("button"); // Waits until clickable
|
|
139
|
+
|
|
140
|
+
// ✅ Explicit assertions wait
|
|
141
|
+
await expect(page.getByRole("heading")).toBeVisible();
|
|
142
|
+
await expect(page.getByTestId("data")).toContainText("Loaded");
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Handling Flaky Tests
|
|
146
|
+
|
|
147
|
+
| Symptom | Solution |
|
|
148
|
+
| ---------------------- | --------------------------------------- |
|
|
149
|
+
| Element not found | Use auto-wait, increase timeout |
|
|
150
|
+
| Race conditions | Wait for network idle, specific element |
|
|
151
|
+
| Animation interference | Disable animations in CI |
|
|
152
|
+
| Timing issues | Use explicit waits, not setTimeout |
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// ✅ Wait for network idle
|
|
156
|
+
await page.goto("/dashboard", { waitUntil: "networkidle" });
|
|
157
|
+
|
|
158
|
+
// ✅ Wait for specific element
|
|
159
|
+
await page.waitForSelector('[data-testid="data-loaded"]');
|
|
160
|
+
|
|
161
|
+
// ✅ Wait for navigation
|
|
162
|
+
await Promise.all([
|
|
163
|
+
page.waitForNavigation(),
|
|
164
|
+
page.click('a[href="/next-page"]'),
|
|
165
|
+
]);
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Test Isolation
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
// ✅ Each test gets fresh context
|
|
172
|
+
test.beforeEach(async ({ page }) => {
|
|
173
|
+
await page.goto("/");
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// ✅ Clean up after destructive tests
|
|
177
|
+
test.afterEach(async ({ request }) => {
|
|
178
|
+
await request.delete("/api/test-data");
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## 6. Authentication Patterns
|
|
185
|
+
|
|
186
|
+
### Reusable Auth State
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// playwright.config.ts
|
|
190
|
+
export default defineConfig({
|
|
191
|
+
projects: [
|
|
192
|
+
{ name: "setup", testMatch: /.*\.setup\.ts/ },
|
|
193
|
+
{
|
|
194
|
+
name: "chromium",
|
|
195
|
+
dependencies: ["setup"],
|
|
196
|
+
use: {
|
|
197
|
+
storageState: "playwright/.auth/user.json",
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// tests/auth.setup.ts
|
|
204
|
+
import { test as setup, expect } from "@playwright/test";
|
|
205
|
+
|
|
206
|
+
setup("authenticate", async ({ page }) => {
|
|
207
|
+
await page.goto("/login");
|
|
208
|
+
await page.getByLabel("Email").fill("user@example.com");
|
|
209
|
+
await page.getByLabel("Password").fill("password123");
|
|
210
|
+
await page.getByRole("button", { name: "Sign in" }).click();
|
|
211
|
+
|
|
212
|
+
await expect(page).toHaveURL("/dashboard");
|
|
213
|
+
await page.context().storageState({ path: "playwright/.auth/user.json" });
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 7. Visual Regression Testing
|
|
220
|
+
|
|
221
|
+
### Playwright Screenshots
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
test("homepage visual regression", async ({ page }) => {
|
|
225
|
+
await page.goto("/");
|
|
226
|
+
await expect(page).toHaveScreenshot("homepage.png", {
|
|
227
|
+
maxDiffPixels: 100,
|
|
228
|
+
animations: "disabled",
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Component screenshot
|
|
233
|
+
test("button states", async ({ page }) => {
|
|
234
|
+
const button = page.getByRole("button", { name: "Submit" });
|
|
235
|
+
await expect(button).toHaveScreenshot("button-default.png");
|
|
236
|
+
|
|
237
|
+
await button.hover();
|
|
238
|
+
await expect(button).toHaveScreenshot("button-hover.png");
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Viewport Testing
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const viewports = [
|
|
246
|
+
{ name: "mobile", width: 375, height: 667 },
|
|
247
|
+
{ name: "tablet", width: 768, height: 1024 },
|
|
248
|
+
{ name: "desktop", width: 1920, height: 1080 },
|
|
249
|
+
];
|
|
250
|
+
|
|
251
|
+
for (const viewport of viewports) {
|
|
252
|
+
test(`responsive - ${viewport.name}`, async ({ page }) => {
|
|
253
|
+
await page.setViewportSize(viewport);
|
|
254
|
+
await page.goto("/");
|
|
255
|
+
await expect(page).toHaveScreenshot(`${viewport.name}.png`);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## 8. API Testing with Playwright
|
|
263
|
+
|
|
264
|
+
### Mock API Responses
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
test("handles API error gracefully", async ({ page }) => {
|
|
268
|
+
await page.route("**/api/users", (route) => {
|
|
269
|
+
route.fulfill({
|
|
270
|
+
status: 500,
|
|
271
|
+
body: JSON.stringify({ error: "Server error" }),
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
await page.goto("/users");
|
|
276
|
+
await expect(page.getByRole("alert")).toContainText("Something went wrong");
|
|
277
|
+
});
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### API Request Testing
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
test("API returns correct data", async ({ request }) => {
|
|
284
|
+
const response = await request.get("/api/users");
|
|
285
|
+
|
|
286
|
+
expect(response.ok()).toBeTruthy();
|
|
287
|
+
const data = await response.json();
|
|
288
|
+
expect(data.users).toHaveLength(10);
|
|
289
|
+
});
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## 9. CI/CD Integration
|
|
295
|
+
|
|
296
|
+
### GitHub Actions Example
|
|
297
|
+
|
|
298
|
+
```yaml
|
|
299
|
+
# .github/workflows/e2e.yml
|
|
300
|
+
name: E2E Tests
|
|
301
|
+
|
|
302
|
+
on: [push, pull_request]
|
|
303
|
+
|
|
304
|
+
jobs:
|
|
305
|
+
test:
|
|
306
|
+
runs-on: ubuntu-latest
|
|
307
|
+
steps:
|
|
308
|
+
- uses: actions/checkout@v4
|
|
309
|
+
|
|
310
|
+
- uses: actions/setup-node@v4
|
|
311
|
+
with:
|
|
312
|
+
node-version: "20"
|
|
313
|
+
cache: "pnpm"
|
|
314
|
+
|
|
315
|
+
- name: Install dependencies
|
|
316
|
+
run: pnpm install
|
|
317
|
+
|
|
318
|
+
- name: Install Playwright
|
|
319
|
+
run: pnpm exec playwright install --with-deps chromium
|
|
320
|
+
|
|
321
|
+
- name: Start app
|
|
322
|
+
run: pnpm dev &
|
|
323
|
+
|
|
324
|
+
- name: Wait for app
|
|
325
|
+
run: pnpm wait-on http://localhost:3000
|
|
326
|
+
|
|
327
|
+
- name: Run E2E tests
|
|
328
|
+
run: pnpm test:e2e
|
|
329
|
+
|
|
330
|
+
- name: Upload artifacts
|
|
331
|
+
if: always()
|
|
332
|
+
uses: actions/upload-artifact@v4
|
|
333
|
+
with:
|
|
334
|
+
name: playwright-report
|
|
335
|
+
path: playwright-report/
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### CI Optimization
|
|
339
|
+
|
|
340
|
+
| Technique | Impact |
|
|
341
|
+
| ---------------- | -------------------------------- |
|
|
342
|
+
| Parallel workers | 2-4x faster |
|
|
343
|
+
| Sharding | Distribute across machines |
|
|
344
|
+
| Caching browsers | Faster setup |
|
|
345
|
+
| Headless mode | Required in CI |
|
|
346
|
+
| Fail fast | Stop on first failure (optional) |
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
// playwright.config.ts
|
|
350
|
+
export default defineConfig({
|
|
351
|
+
fullyParallel: true,
|
|
352
|
+
workers: process.env.CI ? 4 : undefined,
|
|
353
|
+
retries: process.env.CI ? 2 : 0,
|
|
354
|
+
reporter: process.env.CI ? "github" : "html",
|
|
355
|
+
use: {
|
|
356
|
+
trace: "on-first-retry",
|
|
357
|
+
screenshot: "only-on-failure",
|
|
358
|
+
},
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## 10. Debugging Techniques
|
|
365
|
+
|
|
366
|
+
### Playwright Trace Viewer
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
# Generate trace
|
|
370
|
+
pnpm playwright test --trace on
|
|
371
|
+
|
|
372
|
+
# View trace
|
|
373
|
+
pnpm playwright show-trace trace.zip
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Debug Mode
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
# Run with browser visible + pause
|
|
380
|
+
PWDEBUG=1 pnpm playwright test
|
|
381
|
+
|
|
382
|
+
# Run specific test with UI
|
|
383
|
+
pnpm playwright test --ui
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Console Logging
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
test("debug example", async ({ page }) => {
|
|
390
|
+
// Log network requests
|
|
391
|
+
page.on("request", (req) => console.log("→", req.url()));
|
|
392
|
+
page.on("response", (res) => console.log("←", res.status(), res.url()));
|
|
393
|
+
|
|
394
|
+
// Log console messages
|
|
395
|
+
page.on("console", (msg) => console.log("Console:", msg.text()));
|
|
396
|
+
|
|
397
|
+
await page.goto("/");
|
|
398
|
+
});
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## 11. Anti-Patterns
|
|
404
|
+
|
|
405
|
+
| ❌ Don't | ✅ Do |
|
|
406
|
+
| --------------------------- | --------------------------------- |
|
|
407
|
+
| Test implementation details | Test user-visible behavior |
|
|
408
|
+
| Use fixed `setTimeout` | Use explicit waits |
|
|
409
|
+
| Share state between tests | Isolate each test |
|
|
410
|
+
| Test everything in E2E | Use testing pyramid |
|
|
411
|
+
| Skip flaky tests | Fix root cause |
|
|
412
|
+
| Hard-coded credentials | Environment variables, test users |
|
|
413
|
+
| Run against production | Use staging/preview environments |
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## 12. Test Data Management
|
|
418
|
+
|
|
419
|
+
### Strategies
|
|
420
|
+
|
|
421
|
+
| Strategy | Use Case | Pros/Cons |
|
|
422
|
+
| ---------------- | ------------------------------- | ------------------------- |
|
|
423
|
+
| API seeding | Create data via API before test | Fast, reliable |
|
|
424
|
+
| Database seeding | Direct DB manipulation | Complete control, coupled |
|
|
425
|
+
| Factory patterns | Generate random valid data | Flexible, realistic |
|
|
426
|
+
| Fixtures | Static test data files | Simple, explicit |
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
// Factory pattern example
|
|
430
|
+
import { faker } from "@faker-js/faker";
|
|
431
|
+
|
|
432
|
+
const createUser = () => ({
|
|
433
|
+
email: faker.internet.email(),
|
|
434
|
+
name: faker.person.fullName(),
|
|
435
|
+
password: faker.internet.password({ length: 12 }),
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
test("user registration", async ({ page }) => {
|
|
439
|
+
const user = createUser();
|
|
440
|
+
// Use user data in test...
|
|
441
|
+
});
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Related Skills
|
|
447
|
+
|
|
448
|
+
| Need | Skill |
|
|
449
|
+
| ------------------------ | ----------------------- |
|
|
450
|
+
| Unit/integration testing | `testing-patterns` |
|
|
451
|
+
| CI/CD pipelines | `github-actions` |
|
|
452
|
+
| Performance testing | `performance-profiling` |
|
|
453
|
+
| Accessibility | `web-design-guidelines` |
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
> **Remember:** A flaky test is worse than no test. Fix it or delete it. Never skip it forever.
|