maestro-bundle 1.3.1 → 1.4.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/package.json +1 -1
- package/templates/bundle-ai-agents/skills/agent-orchestration/SKILL.md +107 -41
- package/templates/bundle-ai-agents/skills/agent-orchestration/references/graph-patterns.md +50 -0
- package/templates/bundle-ai-agents/skills/agent-orchestration/references/routing-strategies.md +47 -0
- package/templates/bundle-ai-agents/skills/api-design/SKILL.md +125 -16
- package/templates/bundle-ai-agents/skills/api-design/references/pydantic-patterns.md +72 -0
- package/templates/bundle-ai-agents/skills/api-design/references/rest-conventions.md +51 -0
- package/templates/bundle-ai-agents/skills/clean-architecture/SKILL.md +113 -21
- package/templates/bundle-ai-agents/skills/clean-architecture/references/dependency-injection.md +60 -0
- package/templates/bundle-ai-agents/skills/clean-architecture/references/layer-rules.md +56 -0
- package/templates/bundle-ai-agents/skills/context-engineering/SKILL.md +104 -36
- package/templates/bundle-ai-agents/skills/context-engineering/references/compression-techniques.md +76 -0
- package/templates/bundle-ai-agents/skills/context-engineering/references/context-budget-calculator.md +45 -0
- package/templates/bundle-ai-agents/skills/database-modeling/SKILL.md +146 -19
- package/templates/bundle-ai-agents/skills/database-modeling/references/index-strategies.md +48 -0
- package/templates/bundle-ai-agents/skills/database-modeling/references/naming-conventions.md +27 -0
- package/templates/bundle-ai-agents/skills/docker-containerization/SKILL.md +124 -15
- package/templates/bundle-ai-agents/skills/docker-containerization/references/compose-patterns.md +97 -0
- package/templates/bundle-ai-agents/skills/docker-containerization/references/dockerfile-checklist.md +37 -0
- package/templates/bundle-ai-agents/skills/eval-testing/SKILL.md +113 -25
- package/templates/bundle-ai-agents/skills/eval-testing/references/eval-types.md +52 -0
- package/templates/bundle-ai-agents/skills/eval-testing/references/golden-dataset-template.md +59 -0
- package/templates/bundle-ai-agents/skills/memory-management/SKILL.md +112 -28
- package/templates/bundle-ai-agents/skills/memory-management/references/memory-tiers.md +41 -0
- package/templates/bundle-ai-agents/skills/memory-management/references/namespace-conventions.md +41 -0
- package/templates/bundle-ai-agents/skills/prompt-engineering/SKILL.md +139 -47
- package/templates/bundle-ai-agents/skills/prompt-engineering/references/anti-patterns.md +59 -0
- package/templates/bundle-ai-agents/skills/prompt-engineering/references/prompt-templates.md +75 -0
- package/templates/bundle-ai-agents/skills/rag-pipeline/SKILL.md +104 -27
- package/templates/bundle-ai-agents/skills/rag-pipeline/references/chunking-strategies.md +27 -0
- package/templates/bundle-ai-agents/skills/rag-pipeline/references/embedding-models.md +31 -0
- package/templates/bundle-ai-agents/skills/rag-pipeline/references/rag-evaluation.md +39 -0
- package/templates/bundle-ai-agents/skills/testing-strategy/SKILL.md +127 -18
- package/templates/bundle-ai-agents/skills/testing-strategy/references/fixture-patterns.md +81 -0
- package/templates/bundle-ai-agents/skills/testing-strategy/references/naming-conventions.md +69 -0
- package/templates/bundle-base/skills/branch-strategy/SKILL.md +134 -21
- package/templates/bundle-base/skills/branch-strategy/references/branch-rules.md +40 -0
- package/templates/bundle-base/skills/code-review/SKILL.md +123 -38
- package/templates/bundle-base/skills/code-review/references/review-checklist.md +45 -0
- package/templates/bundle-base/skills/commit-pattern/SKILL.md +98 -39
- package/templates/bundle-base/skills/commit-pattern/references/conventional-commits.md +40 -0
- package/templates/bundle-data-pipeline/skills/data-preprocessing/SKILL.md +110 -19
- package/templates/bundle-data-pipeline/skills/data-preprocessing/references/pandas-cheatsheet.md +63 -0
- package/templates/bundle-data-pipeline/skills/data-preprocessing/references/pandera-schemas.md +44 -0
- package/templates/bundle-data-pipeline/skills/docker-containerization/SKILL.md +132 -16
- package/templates/bundle-data-pipeline/skills/docker-containerization/references/compose-patterns.md +82 -0
- package/templates/bundle-data-pipeline/skills/docker-containerization/references/dockerfile-best-practices.md +57 -0
- package/templates/bundle-data-pipeline/skills/feature-engineering/SKILL.md +143 -45
- package/templates/bundle-data-pipeline/skills/feature-engineering/references/encoding-guide.md +41 -0
- package/templates/bundle-data-pipeline/skills/feature-engineering/references/scaling-guide.md +38 -0
- package/templates/bundle-data-pipeline/skills/mlops-pipeline/SKILL.md +156 -37
- package/templates/bundle-data-pipeline/skills/mlops-pipeline/references/mlflow-commands.md +69 -0
- package/templates/bundle-data-pipeline/skills/model-training/SKILL.md +152 -33
- package/templates/bundle-data-pipeline/skills/model-training/references/evaluation-metrics.md +52 -0
- package/templates/bundle-data-pipeline/skills/model-training/references/model-selection-guide.md +41 -0
- package/templates/bundle-data-pipeline/skills/rag-pipeline/SKILL.md +127 -39
- package/templates/bundle-data-pipeline/skills/rag-pipeline/references/chunking-strategies.md +51 -0
- package/templates/bundle-data-pipeline/skills/rag-pipeline/references/embedding-models.md +49 -0
- package/templates/bundle-frontend-spa/skills/authentication/SKILL.md +196 -13
- package/templates/bundle-frontend-spa/skills/authentication/references/jwt-security.md +41 -0
- package/templates/bundle-frontend-spa/skills/component-design/SKILL.md +191 -41
- package/templates/bundle-frontend-spa/skills/component-design/references/accessibility-checklist.md +41 -0
- package/templates/bundle-frontend-spa/skills/component-design/references/tailwind-patterns.md +65 -0
- package/templates/bundle-frontend-spa/skills/e2e-testing/SKILL.md +241 -79
- package/templates/bundle-frontend-spa/skills/e2e-testing/references/playwright-selectors.md +66 -0
- package/templates/bundle-frontend-spa/skills/e2e-testing/references/test-patterns.md +82 -0
- package/templates/bundle-frontend-spa/skills/integration-api/SKILL.md +221 -31
- package/templates/bundle-frontend-spa/skills/integration-api/references/api-patterns.md +81 -0
- package/templates/bundle-frontend-spa/skills/react-patterns/SKILL.md +195 -70
- package/templates/bundle-frontend-spa/skills/react-patterns/references/component-checklist.md +22 -0
- package/templates/bundle-frontend-spa/skills/react-patterns/references/hook-patterns.md +63 -0
- package/templates/bundle-frontend-spa/skills/responsive-layout/SKILL.md +162 -22
- package/templates/bundle-frontend-spa/skills/responsive-layout/references/breakpoint-guide.md +63 -0
- package/templates/bundle-frontend-spa/skills/state-management/SKILL.md +158 -30
- package/templates/bundle-frontend-spa/skills/state-management/references/react-query-config.md +64 -0
- package/templates/bundle-frontend-spa/skills/state-management/references/state-patterns.md +78 -0
- package/templates/bundle-jhipster-microservices/skills/ci-cd-pipeline/SKILL.md +135 -45
- package/templates/bundle-jhipster-microservices/skills/ci-cd-pipeline/references/gitlab-ci-templates.md +93 -0
- package/templates/bundle-jhipster-microservices/skills/clean-architecture/SKILL.md +87 -21
- package/templates/bundle-jhipster-microservices/skills/clean-architecture/references/layer-rules.md +78 -0
- package/templates/bundle-jhipster-microservices/skills/ddd-tactical/SKILL.md +94 -25
- package/templates/bundle-jhipster-microservices/skills/ddd-tactical/references/ddd-patterns.md +48 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-angular/SKILL.md +63 -21
- package/templates/bundle-jhipster-microservices/skills/jhipster-angular/references/angular-microservices.md +40 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-angular/references/angular-structure.md +59 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-docker-k8s/SKILL.md +125 -91
- package/templates/bundle-jhipster-microservices/skills/jhipster-docker-k8s/references/docker-k8s-commands.md +68 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-entities/SKILL.md +72 -20
- package/templates/bundle-jhipster-microservices/skills/jhipster-entities/references/cross-service-entities.md +36 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-entities/references/jdl-types.md +56 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-gateway/SKILL.md +80 -8
- package/templates/bundle-jhipster-microservices/skills/jhipster-gateway/references/gateway-config.md +43 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-kafka/SKILL.md +115 -22
- package/templates/bundle-jhipster-microservices/skills/jhipster-kafka/references/kafka-events.md +39 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-registry/SKILL.md +92 -23
- package/templates/bundle-jhipster-microservices/skills/jhipster-registry/references/consul-config.md +61 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-service/SKILL.md +81 -18
- package/templates/bundle-jhipster-microservices/skills/jhipster-service/references/service-patterns.md +40 -0
- package/templates/bundle-jhipster-microservices/skills/testing-strategy/SKILL.md +101 -20
- package/templates/bundle-jhipster-microservices/skills/testing-strategy/references/test-naming.md +55 -0
- package/templates/bundle-jhipster-monorepo/skills/clean-architecture/SKILL.md +87 -21
- package/templates/bundle-jhipster-monorepo/skills/clean-architecture/references/layer-rules.md +78 -0
- package/templates/bundle-jhipster-monorepo/skills/ddd-tactical/SKILL.md +94 -25
- package/templates/bundle-jhipster-monorepo/skills/ddd-tactical/references/ddd-patterns.md +48 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-angular/SKILL.md +99 -52
- package/templates/bundle-jhipster-monorepo/skills/jhipster-angular/references/angular-structure.md +59 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-entities/SKILL.md +89 -36
- package/templates/bundle-jhipster-monorepo/skills/jhipster-entities/references/jdl-types.md +56 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-liquibase/SKILL.md +123 -23
- package/templates/bundle-jhipster-monorepo/skills/jhipster-liquibase/references/liquibase-operations.md +95 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-security/SKILL.md +106 -19
- package/templates/bundle-jhipster-monorepo/skills/jhipster-security/references/security-checklist.md +47 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-spring/SKILL.md +84 -16
- package/templates/bundle-jhipster-monorepo/skills/jhipster-spring/references/spring-layers.md +41 -0
- package/templates/bundle-jhipster-monorepo/skills/testing-strategy/SKILL.md +101 -20
- package/templates/bundle-jhipster-monorepo/skills/testing-strategy/references/test-naming.md +55 -0
|
@@ -1,101 +1,263 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: e2e-testing
|
|
3
|
-
description:
|
|
3
|
+
description: Create end-to-end tests with Playwright for complete user flows in web applications. Use when you need to test user flows, validate frontend-backend integration, automate UI testing, or set up a Playwright test suite. Supports Playwright MCP tools for interactive testing.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Maestro
|
|
4
6
|
---
|
|
5
7
|
|
|
6
|
-
# E2E Testing
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
8
|
+
# E2E Testing with Playwright
|
|
9
|
+
|
|
10
|
+
Write and run end-to-end tests for full user flows using Playwright, with support for both the Playwright test framework and Playwright MCP tools for interactive browser automation.
|
|
11
|
+
|
|
12
|
+
## When to Use
|
|
13
|
+
- User needs to test a complete user flow (login, create, edit, delete)
|
|
14
|
+
- User wants to validate frontend-backend integration
|
|
15
|
+
- User needs to set up a Playwright test suite from scratch
|
|
16
|
+
- User wants to automate visual testing or screenshots
|
|
17
|
+
- User needs to debug a failing E2E test
|
|
18
|
+
|
|
19
|
+
## Available Operations
|
|
20
|
+
1. Set up Playwright in a project
|
|
21
|
+
2. Write tests for user flows (login, CRUD, navigation)
|
|
22
|
+
3. Create Page Object Models for complex tests
|
|
23
|
+
4. Run tests and debug failures
|
|
24
|
+
5. Use Playwright MCP tools for interactive browser testing
|
|
25
|
+
|
|
26
|
+
## Multi-Step Workflow
|
|
27
|
+
|
|
28
|
+
### Step 1: Install and Set Up Playwright
|
|
29
|
+
```bash
|
|
30
|
+
npm init playwright@latest
|
|
31
|
+
# Select TypeScript, tests folder, GitHub Actions workflow
|
|
32
|
+
|
|
33
|
+
# Or add to existing project:
|
|
34
|
+
npm install -D @playwright/test
|
|
35
|
+
npx playwright install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Verify installation:
|
|
39
|
+
```bash
|
|
40
|
+
npx playwright --version
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Step 2: Configure Playwright
|
|
44
|
+
```typescript
|
|
45
|
+
// playwright.config.ts
|
|
46
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
47
|
+
|
|
48
|
+
export default defineConfig({
|
|
49
|
+
testDir: './tests/e2e',
|
|
50
|
+
fullyParallel: true,
|
|
51
|
+
retries: process.env.CI ? 2 : 0,
|
|
52
|
+
workers: process.env.CI ? 1 : undefined,
|
|
53
|
+
reporter: 'html',
|
|
54
|
+
use: {
|
|
55
|
+
baseURL: 'http://localhost:5173',
|
|
56
|
+
trace: 'on-first-retry',
|
|
57
|
+
screenshot: 'only-on-failure',
|
|
58
|
+
},
|
|
59
|
+
projects: [
|
|
60
|
+
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
|
61
|
+
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
|
|
62
|
+
{ name: 'mobile', use: { ...devices['iPhone 13'] } },
|
|
63
|
+
],
|
|
64
|
+
webServer: {
|
|
65
|
+
command: 'npm run dev',
|
|
66
|
+
url: 'http://localhost:5173',
|
|
67
|
+
reuseExistingServer: !process.env.CI,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Step 3: Create Auth Setup (Reusable Login)
|
|
73
|
+
```typescript
|
|
74
|
+
// tests/e2e/auth.setup.ts
|
|
75
|
+
import { test as setup, expect } from '@playwright/test';
|
|
76
|
+
|
|
77
|
+
setup('authenticate', async ({ page }) => {
|
|
78
|
+
await page.goto('/login');
|
|
79
|
+
await page.fill('[name="email"]', 'admin@example.com');
|
|
80
|
+
await page.fill('[name="password"]', 'admin123');
|
|
81
|
+
await page.click('button[type="submit"]');
|
|
82
|
+
await page.waitForURL('**/dashboard');
|
|
83
|
+
|
|
84
|
+
// Save auth state for other tests to reuse
|
|
85
|
+
await page.context().storageState({ path: 'tests/e2e/.auth/user.json' });
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Step 4: Write a User Flow Test
|
|
90
|
+
```typescript
|
|
91
|
+
// tests/e2e/items.spec.ts
|
|
92
|
+
import { test, expect } from '@playwright/test';
|
|
93
|
+
|
|
94
|
+
test.describe('Item Management', () => {
|
|
95
|
+
test.use({ storageState: 'tests/e2e/.auth/user.json' });
|
|
96
|
+
|
|
97
|
+
test('should create a new item from the dashboard', async ({ page }) => {
|
|
98
|
+
// Navigate to items page
|
|
99
|
+
await page.goto('/items');
|
|
100
|
+
await expect(page.locator('h1')).toHaveText('Items');
|
|
101
|
+
|
|
102
|
+
// Click "New" button
|
|
103
|
+
await page.click('button:has-text("New")');
|
|
104
|
+
await expect(page.locator('dialog')).toBeVisible();
|
|
105
|
+
|
|
106
|
+
// Fill the form
|
|
107
|
+
await page.fill('[name="title"]', 'Test Item Created by E2E');
|
|
108
|
+
await page.fill('[name="description"]', 'This item was created during end-to-end testing');
|
|
109
|
+
await page.selectOption('[name="priority"]', 'high');
|
|
110
|
+
|
|
111
|
+
// Submit
|
|
112
|
+
await page.click('button:has-text("Create")');
|
|
113
|
+
|
|
114
|
+
// Verify creation
|
|
115
|
+
await expect(page.locator('text=Item created')).toBeVisible();
|
|
116
|
+
await expect(page.locator('text=Test Item Created by E2E')).toBeVisible();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('should search and filter items', async ({ page }) => {
|
|
120
|
+
await page.goto('/items');
|
|
121
|
+
|
|
122
|
+
// Search
|
|
123
|
+
await page.fill('[data-testid="search"]', 'Test Item');
|
|
124
|
+
await page.press('[data-testid="search"]', 'Enter');
|
|
125
|
+
|
|
126
|
+
// Verify results
|
|
127
|
+
await expect(page.locator('[data-testid="item-card"]')).toHaveCount(1);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test('should show dashboard metrics', async ({ page }) => {
|
|
131
|
+
await page.goto('/dashboard');
|
|
132
|
+
|
|
133
|
+
// Verify key elements are visible
|
|
134
|
+
await expect(page.locator('[data-testid="metric-active-items"]')).toBeVisible();
|
|
135
|
+
await expect(page.locator('[data-testid="activity-feed"]')).toBeVisible();
|
|
136
|
+
});
|
|
137
|
+
});
|
|
37
138
|
```
|
|
38
139
|
|
|
39
|
-
|
|
140
|
+
### Step 5: Create Page Object Model (for complex flows)
|
|
141
|
+
```typescript
|
|
142
|
+
// tests/e2e/pages/ItemPage.ts
|
|
143
|
+
import { Page, expect } from '@playwright/test';
|
|
144
|
+
|
|
145
|
+
export class ItemPage {
|
|
146
|
+
constructor(private page: Page) {}
|
|
147
|
+
|
|
148
|
+
async navigate() {
|
|
149
|
+
await this.page.goto('/items');
|
|
150
|
+
await expect(this.page.locator('h1')).toHaveText('Items');
|
|
151
|
+
}
|
|
40
152
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
153
|
+
async create(title: string, description: string, priority = 'medium') {
|
|
154
|
+
await this.page.click('button:has-text("New")');
|
|
155
|
+
await this.page.fill('[name="title"]', title);
|
|
156
|
+
await this.page.fill('[name="description"]', description);
|
|
157
|
+
await this.page.selectOption('[name="priority"]', priority);
|
|
158
|
+
await this.page.click('button:has-text("Create")');
|
|
159
|
+
await expect(this.page.locator('text=Item created')).toBeVisible();
|
|
160
|
+
}
|
|
45
161
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
162
|
+
async search(query: string) {
|
|
163
|
+
await this.page.fill('[data-testid="search"]', query);
|
|
164
|
+
await this.page.press('[data-testid="search"]', 'Enter');
|
|
165
|
+
}
|
|
49
166
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
167
|
+
async getItemCount(): Promise<number> {
|
|
168
|
+
return this.page.locator('[data-testid="item-card"]').count();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Usage in test:
|
|
173
|
+
// const itemPage = new ItemPage(page);
|
|
174
|
+
// await itemPage.navigate();
|
|
175
|
+
// await itemPage.create('My Item', 'Description', 'high');
|
|
176
|
+
```
|
|
53
177
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
178
|
+
### Step 6: Run Tests
|
|
179
|
+
```bash
|
|
180
|
+
# Run all tests
|
|
181
|
+
npx playwright test
|
|
58
182
|
|
|
59
|
-
|
|
60
|
-
|
|
183
|
+
# Run specific test file
|
|
184
|
+
npx playwright test tests/e2e/items.spec.ts
|
|
61
185
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
assert page.locator('text=Criar CRUD de usuários').is_visible()
|
|
186
|
+
# Run in headed mode (visible browser)
|
|
187
|
+
npx playwright test --headed
|
|
65
188
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
page.goto("http://localhost:3000/dashboard")
|
|
189
|
+
# Run with UI mode (interactive)
|
|
190
|
+
npx playwright test --ui
|
|
69
191
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
assert feed.is_visible()
|
|
192
|
+
# Run specific browser only
|
|
193
|
+
npx playwright test --project=chromium
|
|
73
194
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
assert page.locator('[data-testid="metric-compliance-rate"]').is_visible()
|
|
195
|
+
# Show HTML report
|
|
196
|
+
npx playwright show-report
|
|
77
197
|
```
|
|
78
198
|
|
|
79
|
-
|
|
199
|
+
### Step 7: Debug Failing Tests
|
|
200
|
+
```bash
|
|
201
|
+
# Run with step-by-step debugging
|
|
202
|
+
npx playwright test --debug
|
|
80
203
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def __init__(self, page):
|
|
84
|
-
self.page = page
|
|
204
|
+
# Show trace viewer for last failed run
|
|
205
|
+
npx playwright show-trace test-results/*/trace.zip
|
|
85
206
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
207
|
+
# Generate screenshots for visual comparison
|
|
208
|
+
npx playwright test --update-snapshots
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Using Playwright MCP Tools (Interactive Testing)
|
|
212
|
+
For interactive browser testing during development, use the Playwright MCP tools:
|
|
213
|
+
```
|
|
214
|
+
# Navigate to a URL
|
|
215
|
+
mcp__playwright__browser_navigate(url="http://localhost:5173/login")
|
|
216
|
+
|
|
217
|
+
# Take a snapshot to see current page state
|
|
218
|
+
mcp__playwright__browser_snapshot()
|
|
219
|
+
|
|
220
|
+
# Fill a form field
|
|
221
|
+
mcp__playwright__browser_fill_form(selector='[name="email"]', value="admin@example.com")
|
|
89
222
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
self.page.fill('[name="title"]', title)
|
|
93
|
-
self.page.fill('[name="description"]', description)
|
|
94
|
-
self.page.select_option('[name="priority"]', priority)
|
|
95
|
-
self.page.click('button:has-text("Criar")')
|
|
96
|
-
self.page.wait_for_selector('text=Demanda criada')
|
|
223
|
+
# Click a button
|
|
224
|
+
mcp__playwright__browser_click(selector='button[type="submit"]')
|
|
97
225
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
226
|
+
# Take a screenshot
|
|
227
|
+
mcp__playwright__browser_take_screenshot()
|
|
228
|
+
|
|
229
|
+
# Wait for navigation
|
|
230
|
+
mcp__playwright__browser_wait_for(selector='h1:has-text("Dashboard")')
|
|
101
231
|
```
|
|
232
|
+
|
|
233
|
+
## Resources
|
|
234
|
+
- `references/playwright-selectors.md` - Selector strategies and best practices
|
|
235
|
+
- `references/test-patterns.md` - Common E2E test patterns
|
|
236
|
+
|
|
237
|
+
## Examples
|
|
238
|
+
### Example 1: Test a Login Flow
|
|
239
|
+
User asks: "Write E2E tests for our login page"
|
|
240
|
+
Response approach:
|
|
241
|
+
1. Set up Playwright config with webServer pointing to dev server
|
|
242
|
+
2. Write test for successful login (fill form, submit, verify redirect)
|
|
243
|
+
3. Write test for failed login (invalid credentials, verify error message)
|
|
244
|
+
4. Write test for logout (click logout, verify redirect to login)
|
|
245
|
+
5. Run tests with `npx playwright test --headed`
|
|
246
|
+
|
|
247
|
+
### Example 2: Test CRUD Operations
|
|
248
|
+
User asks: "Add E2E tests for creating, editing, and deleting items"
|
|
249
|
+
Response approach:
|
|
250
|
+
1. Create auth setup to reuse login state
|
|
251
|
+
2. Write create test: navigate, fill form, submit, verify
|
|
252
|
+
3. Write edit test: click item, modify fields, save, verify
|
|
253
|
+
4. Write delete test: click delete, confirm, verify removal
|
|
254
|
+
5. Use Page Object Model if flows are complex
|
|
255
|
+
6. Run with `npx playwright test`
|
|
256
|
+
|
|
257
|
+
## Notes
|
|
258
|
+
- Always use `data-testid` attributes for test selectors -- more stable than CSS classes
|
|
259
|
+
- Use auth setup with storage state to avoid logging in every test
|
|
260
|
+
- Run tests in parallel by default, use `test.describe.serial` only when order matters
|
|
261
|
+
- Enable trace recording on CI for debugging remote failures
|
|
262
|
+
- Keep tests independent: each test should set up its own data, not depend on other tests
|
|
263
|
+
- Use `expect` assertions (not raw conditionals) for clear failure messages
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Playwright Selector Strategies
|
|
2
|
+
|
|
3
|
+
## Recommended Priority Order
|
|
4
|
+
1. `data-testid` attributes (most stable)
|
|
5
|
+
2. ARIA roles and labels
|
|
6
|
+
3. Text content
|
|
7
|
+
4. CSS selectors (least stable)
|
|
8
|
+
|
|
9
|
+
## data-testid (Best Practice)
|
|
10
|
+
```typescript
|
|
11
|
+
// HTML: <button data-testid="submit-btn">Submit</button>
|
|
12
|
+
await page.click('[data-testid="submit-btn"]');
|
|
13
|
+
await page.locator('[data-testid="item-list"]');
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Text Selectors
|
|
17
|
+
```typescript
|
|
18
|
+
await page.click('text=Submit');
|
|
19
|
+
await page.click('button:has-text("Submit")');
|
|
20
|
+
await page.locator('h1:has-text("Dashboard")');
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## ARIA Selectors
|
|
24
|
+
```typescript
|
|
25
|
+
await page.getByRole('button', { name: 'Submit' });
|
|
26
|
+
await page.getByRole('heading', { name: 'Dashboard' });
|
|
27
|
+
await page.getByLabel('Email');
|
|
28
|
+
await page.getByPlaceholder('Enter your email');
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Form Interactions
|
|
32
|
+
```typescript
|
|
33
|
+
// Fill input by name attribute
|
|
34
|
+
await page.fill('[name="email"]', 'user@example.com');
|
|
35
|
+
|
|
36
|
+
// Select dropdown option
|
|
37
|
+
await page.selectOption('[name="priority"]', 'high');
|
|
38
|
+
|
|
39
|
+
// Check/uncheck checkbox
|
|
40
|
+
await page.check('[name="agree"]');
|
|
41
|
+
await page.uncheck('[name="newsletter"]');
|
|
42
|
+
|
|
43
|
+
// Upload file
|
|
44
|
+
await page.setInputFiles('[type="file"]', 'path/to/file.pdf');
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Waiting Strategies
|
|
48
|
+
```typescript
|
|
49
|
+
// Wait for element to be visible
|
|
50
|
+
await page.waitForSelector('[data-testid="results"]');
|
|
51
|
+
|
|
52
|
+
// Wait for URL change
|
|
53
|
+
await page.waitForURL('**/dashboard');
|
|
54
|
+
|
|
55
|
+
// Wait for network idle
|
|
56
|
+
await page.waitForLoadState('networkidle');
|
|
57
|
+
|
|
58
|
+
// Wait for specific response
|
|
59
|
+
await page.waitForResponse('**/api/items');
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Anti-Patterns to Avoid
|
|
63
|
+
- Do NOT use CSS class selectors (`.btn-primary`) -- they change with styling
|
|
64
|
+
- Do NOT use complex XPath -- hard to maintain
|
|
65
|
+
- Do NOT use `page.waitForTimeout(ms)` -- use explicit waits instead
|
|
66
|
+
- Do NOT rely on element index (`:nth-child`) -- fragile
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# E2E Test Patterns
|
|
2
|
+
|
|
3
|
+
## Authentication Setup (Shared Login State)
|
|
4
|
+
```typescript
|
|
5
|
+
// auth.setup.ts
|
|
6
|
+
import { test as setup } from '@playwright/test';
|
|
7
|
+
|
|
8
|
+
setup('login', async ({ page }) => {
|
|
9
|
+
await page.goto('/login');
|
|
10
|
+
await page.fill('[name="email"]', 'admin@example.com');
|
|
11
|
+
await page.fill('[name="password"]', 'admin123');
|
|
12
|
+
await page.click('button[type="submit"]');
|
|
13
|
+
await page.waitForURL('**/dashboard');
|
|
14
|
+
await page.context().storageState({ path: '.auth/user.json' });
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// In tests:
|
|
18
|
+
test.use({ storageState: '.auth/user.json' });
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## CRUD Test Pattern
|
|
22
|
+
```typescript
|
|
23
|
+
test.describe('Items CRUD', () => {
|
|
24
|
+
test('create', async ({ page }) => {
|
|
25
|
+
await page.goto('/items');
|
|
26
|
+
await page.click('button:has-text("New")');
|
|
27
|
+
await page.fill('[name="title"]', 'E2E Test Item');
|
|
28
|
+
await page.click('button:has-text("Save")');
|
|
29
|
+
await expect(page.locator('text=E2E Test Item')).toBeVisible();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('read', async ({ page }) => {
|
|
33
|
+
await page.goto('/items');
|
|
34
|
+
await expect(page.locator('[data-testid="item-card"]').first()).toBeVisible();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('update', async ({ page }) => {
|
|
38
|
+
await page.goto('/items');
|
|
39
|
+
await page.click('[data-testid="item-card"]');
|
|
40
|
+
await page.fill('[name="title"]', 'Updated Title');
|
|
41
|
+
await page.click('button:has-text("Save")');
|
|
42
|
+
await expect(page.locator('text=Updated Title')).toBeVisible();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('delete', async ({ page }) => {
|
|
46
|
+
await page.goto('/items');
|
|
47
|
+
const count = await page.locator('[data-testid="item-card"]').count();
|
|
48
|
+
await page.click('[data-testid="delete-btn"]');
|
|
49
|
+
await page.click('button:has-text("Confirm")');
|
|
50
|
+
await expect(page.locator('[data-testid="item-card"]')).toHaveCount(count - 1);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Page Object Model Pattern
|
|
56
|
+
```typescript
|
|
57
|
+
class LoginPage {
|
|
58
|
+
constructor(private page: Page) {}
|
|
59
|
+
|
|
60
|
+
async login(email: string, password: string) {
|
|
61
|
+
await this.page.goto('/login');
|
|
62
|
+
await this.page.fill('[name="email"]', email);
|
|
63
|
+
await this.page.fill('[name="password"]', password);
|
|
64
|
+
await this.page.click('button[type="submit"]');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async expectError(message: string) {
|
|
68
|
+
await expect(this.page.locator('[data-testid="error"]')).toHaveText(message);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## API Mocking Pattern
|
|
74
|
+
```typescript
|
|
75
|
+
test('shows empty state when API returns no items', async ({ page }) => {
|
|
76
|
+
await page.route('**/api/items', (route) => {
|
|
77
|
+
route.fulfill({ status: 200, body: JSON.stringify({ items: [], total: 0 }) });
|
|
78
|
+
});
|
|
79
|
+
await page.goto('/items');
|
|
80
|
+
await expect(page.locator('text=No items found')).toBeVisible();
|
|
81
|
+
});
|
|
82
|
+
```
|