openspec-playwright 0.1.44 → 0.1.46
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/.claude/skills/openspec-e2e/SKILL.md +205 -16
- package/dist/commands/init.js +18 -3
- package/dist/commands/init.js.map +1 -1
- package/openspec-playwright-0.1.46.tgz +0 -0
- package/package.json +1 -1
- package/release-notes.md +2 -2
- package/schemas/playwright-e2e/templates/app-exploration.md +51 -0
- package/schemas/playwright-e2e/templates/app-knowledge.md +73 -0
- package/src/commands/init.ts +22 -3
- package/openspec-playwright-0.1.44.tgz +0 -0
|
@@ -5,7 +5,7 @@ license: MIT
|
|
|
5
5
|
compatibility: Requires openspec CLI, Playwright (with browsers installed), and @playwright/mcp (globally installed via `claude mcp add playwright npx @playwright/mcp@latest`).
|
|
6
6
|
metadata:
|
|
7
7
|
author: openspec-playwright
|
|
8
|
-
version: "2.
|
|
8
|
+
version: "2.9"
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
## Input
|
|
@@ -23,11 +23,11 @@ metadata:
|
|
|
23
23
|
|
|
24
24
|
## Architecture
|
|
25
25
|
|
|
26
|
-
Pipeline: **Planner** (Step
|
|
26
|
+
Pipeline: **Planner** (Step 5) → **Generator** (Step 6) → **Healer** (Step 9).
|
|
27
27
|
|
|
28
|
-
Uses CLI + SKILLs (not `init-agents`). CLI is ~4x more token-efficient than loading MCP tool schemas. MCP is used
|
|
28
|
+
Uses CLI + SKILLs (not `init-agents`). CLI is ~4x more token-efficient than loading MCP tool schemas. MCP is used for **Explore** (Step 4, real DOM data) and **Healer** (UI inspection on failure).
|
|
29
29
|
|
|
30
|
-
**Schema owns templates. CLI handles execution. Skill handles cognitive work.**
|
|
30
|
+
**Schema owns templates. CLI handles execution. Skill handles cognitive work. Exploration drives generation.**
|
|
31
31
|
|
|
32
32
|
## Steps
|
|
33
33
|
|
|
@@ -74,25 +74,211 @@ This validates: app server reachable, auth fixtures initialized, Playwright work
|
|
|
74
74
|
|
|
75
75
|
**If seed test fails**: Stop and report. Fix the environment before proceeding.
|
|
76
76
|
|
|
77
|
-
### 4.
|
|
77
|
+
### 4. Explore application
|
|
78
|
+
|
|
79
|
+
**Before writing test plan, explore the app to collect real DOM data.** This is the most critical step — it eliminates blind selector guessing.
|
|
80
|
+
|
|
81
|
+
**Prerequisites**: seed test pass. If auth is required, ensure `auth.setup.ts` has been run (Step 7).
|
|
82
|
+
|
|
83
|
+
#### 4.1. Extract routes from specs
|
|
84
|
+
|
|
85
|
+
Read all files in `openspec/changes/<name>/specs/*.md`. Extract every URL, route, or path mentioned:
|
|
86
|
+
|
|
87
|
+
- Full URLs: `http://localhost:3000/dashboard`, `BASE_URL + /admin`
|
|
88
|
+
- Relative paths: `/dashboard`, `/api/auth/login`, `/admin/settings`
|
|
89
|
+
- Infer routes from text: "navigate to the dashboard" → check if `/dashboard` exists
|
|
90
|
+
|
|
91
|
+
Group routes by role:
|
|
92
|
+
- **Guest routes**: `/`, `/login`, `/about` (no auth needed)
|
|
93
|
+
- **Protected routes**: `/dashboard`, `/profile`, `/admin` (auth required)
|
|
94
|
+
|
|
95
|
+
#### 4.2. Explore each route via Playwright MCP
|
|
96
|
+
|
|
97
|
+
For each route, use these tools in order:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
browser_navigate → browser_snapshot → browser_take_screenshot
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**For guest routes** (no auth):
|
|
104
|
+
```javascript
|
|
105
|
+
// Navigate directly
|
|
106
|
+
await browser_navigate(`${BASE_URL}/<route>`)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**For protected routes** (auth required):
|
|
110
|
+
```javascript
|
|
111
|
+
// Option A: use existing storageState (recommended if auth.setup.ts already ran)
|
|
112
|
+
// Option B: navigate to /login first, fill form, then navigate to target
|
|
113
|
+
// Option C: use browser_run_code to set auth cookies directly
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Wait for page stability after navigation:
|
|
117
|
+
- Prefer waiting for a specific element: `browser_wait_for` with text or selector
|
|
118
|
+
- Avoid `networkidle` / `load` — they are too slow or unreliable
|
|
119
|
+
- Use a "page ready" signal: look for a heading, a loading spinner disappearing, or a URL change
|
|
120
|
+
|
|
121
|
+
#### 4.3. Parse the snapshot
|
|
122
|
+
|
|
123
|
+
From `browser_snapshot` output, extract **interactive elements** for each route:
|
|
124
|
+
|
|
125
|
+
| Element type | What to capture | Priority |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| **Buttons** | text, selector (`getByRole`, `getByLabel`, `data-testid`) | data-testid > role > label > text |
|
|
128
|
+
| **Form fields** | name, type, label, selector | data-testid > name > label |
|
|
129
|
+
| **Navigation links** | text, href, selector | text > href |
|
|
130
|
+
| **Headings** | text content, selector | for assertions |
|
|
131
|
+
| **Error messages** | text patterns, selector | for error path testing |
|
|
132
|
+
| **Dynamic content** | structure (not content) — row counts, card layouts | for data-driven tests |
|
|
133
|
+
|
|
134
|
+
**Selector strategy** (in priority order):
|
|
135
|
+
1. `[data-testid="..."]` — most stable, prefer these
|
|
136
|
+
2. `getByRole('button', { name: '...' })` — semantic, stable
|
|
137
|
+
3. `getByLabel('...')` — for form fields
|
|
138
|
+
4. `getByText('...')` — fallback, fragile
|
|
139
|
+
5. CSS selectors — last resort
|
|
140
|
+
|
|
141
|
+
#### 4.4. Write app-exploration.md
|
|
142
|
+
|
|
143
|
+
Output: `openspec/changes/<name>/specs/playwright/app-exploration.md`
|
|
144
|
+
|
|
145
|
+
```markdown
|
|
146
|
+
# App Exploration — <name>
|
|
147
|
+
Generated: <timestamp>
|
|
148
|
+
BASE_URL: <from env or seed.spec.ts>
|
|
149
|
+
|
|
150
|
+
## Route: /
|
|
151
|
+
- **Auth**: none
|
|
152
|
+
- **URL**: ${BASE_URL}/
|
|
153
|
+
- **Ready signal**: page has heading
|
|
154
|
+
- **Elements**:
|
|
155
|
+
- login link: `a:text("登录")`
|
|
156
|
+
- signup link: `[data-testid="signup-link"]`
|
|
157
|
+
- **Screenshot**: `__screenshots__/index.png`
|
|
158
|
+
|
|
159
|
+
## Route: /dashboard (user)
|
|
160
|
+
- **Auth**: required (storageState: playwright/.auth/user.json)
|
|
161
|
+
- **URL**: ${BASE_URL}/dashboard
|
|
162
|
+
- **Ready signal**: [data-testid="dashboard-heading"] visible
|
|
163
|
+
- **Elements**:
|
|
164
|
+
- heading: `[data-testid="page-title"]`
|
|
165
|
+
- logout btn: `[data-testid="logout-btn"]`
|
|
166
|
+
- profile form: `form >> input[name="displayName"]`
|
|
167
|
+
- settings link: `nav >> text=Settings`
|
|
168
|
+
- **Screenshot**: `__screenshots__/dashboard-user.png`
|
|
169
|
+
|
|
170
|
+
## Route: /admin (admin)
|
|
171
|
+
- **Auth**: required (storageState: playwright/.auth/admin.json)
|
|
172
|
+
- **URL**: ${BASE_URL}/admin
|
|
173
|
+
- **Ready signal**: [data-testid="admin-panel"] visible
|
|
174
|
+
- **Elements**:
|
|
175
|
+
- admin panel: `[data-testid="admin-panel"]`
|
|
176
|
+
- user table: `table#user-table tbody tr`
|
|
177
|
+
- add user btn: `[data-testid="add-user-btn"]`
|
|
178
|
+
- delete btn: `button:has-text("Delete")`
|
|
179
|
+
- **Screenshot**: `__screenshots__/admin-panel.png`
|
|
180
|
+
|
|
181
|
+
## Exploration Notes
|
|
182
|
+
- Route /admin → user gets redirected to /login (no admin role)
|
|
183
|
+
- /dashboard loads user-specific data (test assertions should use toContainText, not toHaveText)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### 4.5. Edge cases
|
|
187
|
+
|
|
188
|
+
| Situation | What to do |
|
|
189
|
+
|-----------|-----------|
|
|
190
|
+
| Route 404 | Mark as "⚠️ route not found — verify URL in specs" |
|
|
191
|
+
| Network error | Mark as "⚠️ unreachable — check if server is running" |
|
|
192
|
+
| Auth required, no storageState | Skip protected routes → note which routes need auth |
|
|
193
|
+
| SPA routing (URL changes but page doesn't reload) | Explore via navigation clicks from known routes, not direct URLs |
|
|
194
|
+
| Page loads but no interactive elements | Try waiting longer for SPA hydration |
|
|
195
|
+
| Dynamic content (user-specific) | Record structure, not content — use `toContainText`, not `toHaveText` |
|
|
196
|
+
|
|
197
|
+
**Idempotency**: If `app-exploration.md` already exists → read it, verify routes still match specs, update only new routes or changed pages.
|
|
198
|
+
|
|
199
|
+
#### 4.6. Update app-knowledge.md
|
|
200
|
+
|
|
201
|
+
After writing `app-exploration.md`, extract **project-level shared knowledge** and append to `tests/playwright/app-knowledge.md`:
|
|
202
|
+
|
|
203
|
+
| Section | What to extract |
|
|
204
|
+
|---------|----------------|
|
|
205
|
+
| Credential Format | Login endpoint, username format (email vs username) |
|
|
206
|
+
| Common Selector Patterns | New patterns discovered that apply across routes |
|
|
207
|
+
| SPA Routing | SPA framework, routing behavior |
|
|
208
|
+
| Project Conventions | BASE_URL, auth method, multi-user roles |
|
|
209
|
+
|
|
210
|
+
Append only new/changed items — preserve existing content.
|
|
211
|
+
|
|
212
|
+
#### 4.7. After exploration
|
|
213
|
+
|
|
214
|
+
Pass `app-exploration.md` to:
|
|
215
|
+
- **Step 5 (Planner)**: reference real routes, auth states, and elements in test-plan.md
|
|
216
|
+
- **Step 6 (Generator)**: use verified selectors instead of inferring
|
|
217
|
+
|
|
218
|
+
Read `tests/playwright/app-knowledge.md` as context for cross-change patterns.
|
|
219
|
+
|
|
220
|
+
### 5. Generate test plan
|
|
78
221
|
|
|
79
222
|
Create `openspec/changes/<name>/specs/playwright/test-plan.md`:
|
|
223
|
+
|
|
224
|
+
**Read inputs first**:
|
|
225
|
+
- `openspec/changes/<name>/specs/*.md` — functional requirements
|
|
226
|
+
- `openspec/changes/<name>/specs/playwright/app-exploration.md` — **real routes and verified selectors**
|
|
227
|
+
- `tests/playwright/app-knowledge.md` — project-level shared knowledge
|
|
228
|
+
|
|
229
|
+
Create test cases:
|
|
80
230
|
- List each functional requirement as a test case
|
|
81
231
|
- Mark with `@role(user|admin|guest|none)` and `@auth(required|none)`
|
|
82
232
|
- Include happy path AND error paths
|
|
83
|
-
- Reference the route
|
|
233
|
+
- Reference the **real route URL** from app-exploration.md for each test
|
|
234
|
+
- Reference **verified selectors** from app-exploration.md instead of inferring
|
|
235
|
+
|
|
236
|
+
```markdown
|
|
237
|
+
### User can view dashboard
|
|
238
|
+
- **Route**: /dashboard (from app-exploration.md)
|
|
239
|
+
- **Auth**: required (user storageState)
|
|
240
|
+
- **Test steps**:
|
|
241
|
+
1. Go to `/dashboard`
|
|
242
|
+
2. Assert page heading: `[data-testid="page-title"]` contains "Dashboard"
|
|
243
|
+
3. Assert logout button visible: `[data-testid="logout-btn"]`
|
|
244
|
+
```
|
|
84
245
|
|
|
85
246
|
**Idempotency**: If test-plan.md already exists → read it, use it, do NOT regenerate.
|
|
86
247
|
|
|
87
|
-
###
|
|
248
|
+
### 6. Generate test file
|
|
88
249
|
|
|
89
250
|
Create `tests/playwright/<name>.spec.ts`:
|
|
90
251
|
|
|
91
252
|
**Read inputs first**:
|
|
92
|
-
- `openspec/changes/<name>/specs/playwright/test-plan.md`
|
|
93
|
-
- `
|
|
253
|
+
- `openspec/changes/<name>/specs/playwright/test-plan.md` — test cases
|
|
254
|
+
- `openspec/changes/<name>/specs/playwright/app-exploration.md` — **verified routes and selectors**
|
|
255
|
+
- `tests/playwright/app-knowledge.md` — project-level patterns and conventions
|
|
256
|
+
- `tests/playwright/seed.spec.ts` — code pattern and page object structure
|
|
257
|
+
|
|
258
|
+
#### Verify selectors before writing
|
|
259
|
+
|
|
260
|
+
**For each test case, verify selectors in a real browser BEFORE writing the test code.** This is the most important step — do not skip it.
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
For each test case in test-plan.md:
|
|
264
|
+
|
|
265
|
+
1. Determine target route (from app-exploration.md)
|
|
266
|
+
2. Determine auth state (load storageState if @auth(required))
|
|
267
|
+
3. Navigate: browser_navigate to the route
|
|
268
|
+
4. Wait for page ready: browser_wait_for with a key element
|
|
269
|
+
5. Verify: browser_snapshot to confirm page loaded
|
|
270
|
+
6. For each selector in the test case:
|
|
271
|
+
a. Check if selector exists in app-exploration.md
|
|
272
|
+
b. If yes → verify it's still valid via browser_snapshot
|
|
273
|
+
c. If no → find equivalent from current snapshot
|
|
274
|
+
d. Selector priority: data-testid > getByRole > getByLabel > getByText
|
|
275
|
+
7. Write test code with verified selectors
|
|
276
|
+
8. If selector cannot be verified → note it for Healer (Step 9)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
This ensures every selector in the generated test code has been validated against the live DOM.
|
|
94
280
|
|
|
95
|
-
**Generate** Playwright code for each test case:
|
|
281
|
+
**Generate** Playwright code for each verified test case:
|
|
96
282
|
- Follow `seed.spec.ts` structure
|
|
97
283
|
- Prefer `data-testid`; fallback to `getByRole`, `getByLabel`, `getByText`
|
|
98
284
|
- Include happy path AND error/edge cases
|
|
@@ -183,7 +369,7 @@ await page.getByRole('button', { name: 'Submit' }).click();
|
|
|
183
369
|
|
|
184
370
|
If the file exists → diff against test-plan, add only missing test cases.
|
|
185
371
|
|
|
186
|
-
###
|
|
372
|
+
### 7. Configure auth (if required)
|
|
187
373
|
|
|
188
374
|
- **API login**: Generate `auth.setup.ts` using `E2E_USERNAME`/`E2E_PASSWORD` + POST to login endpoint
|
|
189
375
|
- **UI login**: Generate `auth.setup.ts` using browser form fill. Update selectors to match your login page
|
|
@@ -206,7 +392,7 @@ Auth required. To set up:
|
|
|
206
392
|
|
|
207
393
|
**Idempotency**: If `auth.setup.ts` already exists → verify format, update only if stale.
|
|
208
394
|
|
|
209
|
-
###
|
|
395
|
+
### 8. Configure playwright.config.ts
|
|
210
396
|
|
|
211
397
|
If missing → generate from `openspec/schemas/playwright-e2e/templates/playwright.config.ts`.
|
|
212
398
|
|
|
@@ -222,7 +408,7 @@ If missing → generate from `openspec/schemas/playwright-e2e/templates/playwrig
|
|
|
222
408
|
|
|
223
409
|
If playwright.config.ts exists → READ first, preserve ALL existing fields, add only missing `webServer` block.
|
|
224
410
|
|
|
225
|
-
###
|
|
411
|
+
### 9. Execute tests
|
|
226
412
|
|
|
227
413
|
```bash
|
|
228
414
|
openspec-pw run <name> --project=<role>
|
|
@@ -260,7 +446,7 @@ If tests fail → use Playwright MCP tools to inspect UI, fix selectors, re-run.
|
|
|
260
446
|
3. **Attempt heal** (≤3 times): snapshot → fix → re-run
|
|
261
447
|
4. **After 3 failures**: collect evidence checklist → `test.skip()` if app bug, report recommendation if test bug
|
|
262
448
|
|
|
263
|
-
###
|
|
449
|
+
### 10. False Pass Detection
|
|
264
450
|
|
|
265
451
|
Run after test suite completes (even if all pass):
|
|
266
452
|
|
|
@@ -270,7 +456,7 @@ Run after test suite completes (even if all pass):
|
|
|
270
456
|
|
|
271
457
|
Report any gaps in a **⚠️ Coverage Gap** section.
|
|
272
458
|
|
|
273
|
-
###
|
|
459
|
+
### 11. Report results
|
|
274
460
|
|
|
275
461
|
Read report at `openspec/reports/playwright-e2e-<name>-<timestamp>.md`. Present:
|
|
276
462
|
- Summary table (tests, passed, failed, duration, status)
|
|
@@ -324,6 +510,8 @@ Read report at `openspec/reports/playwright-e2e-<name>-<timestamp>.md`. Present:
|
|
|
324
510
|
| No specs | Stop — E2E requires specs |
|
|
325
511
|
| Seed test fails | Stop — fix environment |
|
|
326
512
|
| No auth required | Skip auth setup |
|
|
513
|
+
| app-exploration.md exists | Read and use (never regenerate) |
|
|
514
|
+
| app-knowledge.md exists | Read and use (append new patterns only) |
|
|
327
515
|
| test-plan.md exists | Read and use (never regenerate) |
|
|
328
516
|
| auth.setup.ts exists | Verify format (update only if stale) |
|
|
329
517
|
| playwright.config.ts exists | Preserve all fields (add only missing) |
|
|
@@ -337,6 +525,7 @@ Read report at `openspec/reports/playwright-e2e-<name>-<timestamp>.md`. Present:
|
|
|
337
525
|
- Read specs from `openspec/changes/<name>/specs/` as source of truth
|
|
338
526
|
- Do NOT generate tests that contradict the specs
|
|
339
527
|
- **DO generate real, runnable Playwright test code** — not placeholders or TODOs
|
|
340
|
-
- Do NOT overwrite files outside: `specs/playwright/`, `tests/playwright/`, `openspec/reports/`, `playwright.config.ts`
|
|
528
|
+
- Do NOT overwrite files outside: `specs/playwright/`, `tests/playwright/`, `openspec/reports/`, `playwright.config.ts`, `auth.setup.ts`, `app-exploration.md`, `app-knowledge.md`
|
|
529
|
+
- **Always explore before generating** — Step 4 is mandatory for accurate selectors
|
|
341
530
|
- Cap auto-heal at 3 attempts
|
|
342
531
|
- If no change specified → always ask user to select
|
package/dist/commands/init.js
CHANGED
|
@@ -99,13 +99,16 @@ export async function init(options) {
|
|
|
99
99
|
console.log(chalk.blue('\n─── Generating Seed Test ───'));
|
|
100
100
|
await generateSeedTest(projectRoot);
|
|
101
101
|
}
|
|
102
|
-
// 8.
|
|
102
|
+
// 8. Generate app-knowledge.md
|
|
103
|
+
console.log(chalk.blue('\n─── Generating App Knowledge ───'));
|
|
104
|
+
await generateAppKnowledge(projectRoot);
|
|
105
|
+
// 9. Install employee-grade CLAUDE.md
|
|
103
106
|
console.log(chalk.blue('\n─── Installing Employee Standards ───'));
|
|
104
107
|
const standards = readEmployeeStandards(EMPLOYEE_STANDARDS_SRC);
|
|
105
108
|
if (standards) {
|
|
106
109
|
installProjectClaudeMd(projectRoot, standards);
|
|
107
110
|
}
|
|
108
|
-
//
|
|
111
|
+
// 10. Summary
|
|
109
112
|
console.log(chalk.blue('\n─── Summary ───'));
|
|
110
113
|
console.log(chalk.green(' ✓ Setup complete!\n'));
|
|
111
114
|
console.log(chalk.bold('Next steps:'));
|
|
@@ -158,6 +161,18 @@ async function generateSeedTest(projectRoot) {
|
|
|
158
161
|
}
|
|
159
162
|
console.log(chalk.gray(' (Customize BASE_URL and credentials for your app)'));
|
|
160
163
|
}
|
|
164
|
+
async function generateAppKnowledge(projectRoot) {
|
|
165
|
+
const src = join(SCHEMA_DIR, 'playwright-e2e', 'templates', 'app-knowledge.md');
|
|
166
|
+
const dest = join(projectRoot, 'tests', 'playwright', 'app-knowledge.md');
|
|
167
|
+
if (existsSync(dest)) {
|
|
168
|
+
console.log(chalk.gray(' - app-knowledge.md already exists, skipping'));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (existsSync(src)) {
|
|
172
|
+
writeFileSync(dest, readFileSync(src));
|
|
173
|
+
console.log(chalk.green(' ✓ Generated: tests/playwright/app-knowledge.md'));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
161
176
|
async function installSchema(projectRoot) {
|
|
162
177
|
const schemaSrc = SCHEMA_DIR + '/playwright-e2e';
|
|
163
178
|
const schemaDest = join(projectRoot, 'openspec', 'schemas', 'playwright-e2e');
|
|
@@ -174,7 +189,7 @@ async function installSchema(projectRoot) {
|
|
|
174
189
|
const templatesSrc = join(schemaSrc, 'templates');
|
|
175
190
|
const templatesDest = join(schemaDest, 'templates');
|
|
176
191
|
mkdirSync(templatesDest, { recursive: true });
|
|
177
|
-
const templateFiles = ['test-plan.md', 'report.md', 'e2e-test.ts', 'playwright.config.ts'];
|
|
192
|
+
const templateFiles = ['test-plan.md', 'report.md', 'e2e-test.ts', 'playwright.config.ts', 'app-knowledge.md'];
|
|
178
193
|
for (const file of templateFiles) {
|
|
179
194
|
const src = join(templatesSrc, file);
|
|
180
195
|
const dest = join(templatesDest, file);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EACL,UAAU,EACV,YAAY,EACZ,aAAa,EACb,SAAS,GACV,MAAM,IAAI,CAAC;AACZ,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,oBAAoB,EAAE,YAAY,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE5J,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAChF,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC5E,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,4CAA4C,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACxG,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,yCAAyC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACxG,MAAM,sBAAsB,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,6BAA6B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAQtG,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAAoB;IAC7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC,CAAC;IAElE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAElC,yBAAyB;IACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAEjD,MAAM,OAAO,GAAG,OAAO,CAAC,gBAAgB,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IACrD,MAAM,WAAW,GAAG,OAAO,CAAC,wDAAwD,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IAExG,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAEtD,oBAAoB;IACpB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,yDAAyD,CAAC,CAAC,CAAC;QACrF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC,CAAC;QAChE,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;IAErD,qCAAqC;IACrC,IAAI,OAAO,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC,CAAC;QAE/D,0DAA0D;QAC1D,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;QACvD,MAAM,UAAU,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvG,MAAM,SAAS,GAAG,UAAU,EAAE,UAAU,IAAI,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAG,UAAU,EAAE,QAAQ,EAAE,CAAC,WAAW,CAAC,EAAE,UAAU,IAAI,EAAE,CAAC;QAEvE,IAAI,SAAS,CAAC,YAAY,CAAC,IAAI,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,CAAC;QACnE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC;gBACH,QAAQ,CAAC,sDAAsD,EAAE;oBAC/D,GAAG,EAAE,WAAW;oBAChB,KAAK,EAAE,SAAS;iBACjB,CAAC,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;gBAClE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC,CAAC;YACjE,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,kCAAkC,CAAC,CAAC,CAAC;gBAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC,CAAC;gBAChG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC,CAAC;YAChF,CAAC;QACH,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACzD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACnD,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACnD,oBAAoB,CAAC,IAAI,EAAE,CAAC,aAAa,CAAC,EAAE,WAAW,CAAC,CAAC;IAC3D,CAAC;IAED,qCAAqC;IACrC,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;QAC7C,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACxD,YAAY,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC1C,CAAC;IAED,sEAAsE;IACtE,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;QACrF,MAAM,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,6BAA6B;IAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC,CAAC;IAChE,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IAEjC,wBAAwB;IACxB,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAC1D,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC;IAED,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,qBAAqB,CAAC,sBAAsB,CAAC,CAAC;IAChE,IAAI,SAAS,EAAE,CAAC;QACd,sBAAsB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACjD,CAAC;IAED,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
Binary file
|
package/package.json
CHANGED
package/release-notes.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
## What's Changed
|
|
2
2
|
|
|
3
|
-
-
|
|
3
|
+
- chore: bump version
|
|
4
4
|
|
|
5
|
-
**Full Changelog**: https://github.com/wxhou/openspec-playwright/releases/tag/v0.1.
|
|
5
|
+
**Full Changelog**: https://github.com/wxhou/openspec-playwright/releases/tag/v0.1.46
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# App Exploration — <change-name>
|
|
2
|
+
|
|
3
|
+
Generated: <timestamp>
|
|
4
|
+
BASE_URL: <from env or seed.spec.ts>
|
|
5
|
+
|
|
6
|
+
## Exploration Summary
|
|
7
|
+
|
|
8
|
+
| Route | Auth | Status | Ready Signal |
|
|
9
|
+
|-------|------|--------|-------------|
|
|
10
|
+
| / | none | ✅ explored | page has heading |
|
|
11
|
+
| /login | none | ✅ explored | [data-testid="login-form"] visible |
|
|
12
|
+
| /dashboard | required (user) | ✅ explored | [data-testid="page-title"] visible |
|
|
13
|
+
| /admin | required (admin) | ✅ explored | [data-testid="admin-panel"] visible |
|
|
14
|
+
|
|
15
|
+
## Route: <path>
|
|
16
|
+
|
|
17
|
+
- **Auth**: none / required (storageState: <path>)
|
|
18
|
+
- **URL**: ${BASE_URL}<path>
|
|
19
|
+
- **Ready signal**: <how to know page is loaded>
|
|
20
|
+
- **Screenshot**: `__screenshots__/<path-slug>.png`
|
|
21
|
+
|
|
22
|
+
### Interactive Elements (from real DOM)
|
|
23
|
+
|
|
24
|
+
| Element | Selector | Notes |
|
|
25
|
+
|---------|----------|-------|
|
|
26
|
+
| heading | `[data-testid="..."]` or `h1` | |
|
|
27
|
+
| submit btn | `getByRole('button', { name: '...' })` | |
|
|
28
|
+
| logout btn | `[data-testid="logout-btn"]` | |
|
|
29
|
+
| form | `form >> input[name="..."]` | |
|
|
30
|
+
| nav link | `a:text("...")` or `nav >> text=...` | |
|
|
31
|
+
|
|
32
|
+
### Navigation Context
|
|
33
|
+
|
|
34
|
+
- How to reach this page: <from homepage / from dashboard / etc.>
|
|
35
|
+
- Redirects: <any redirects observed>
|
|
36
|
+
|
|
37
|
+
### Dynamic Content Notes
|
|
38
|
+
|
|
39
|
+
- <any dynamic content that was observed>
|
|
40
|
+
- <test assertions should use toContainText, not toHaveText for user-specific data>
|
|
41
|
+
|
|
42
|
+
## Exploration Failures
|
|
43
|
+
|
|
44
|
+
| Route | Error | Notes |
|
|
45
|
+
|-------|-------|-------|
|
|
46
|
+
| | | |
|
|
47
|
+
|
|
48
|
+
## Next Steps
|
|
49
|
+
|
|
50
|
+
After exploration, pass this file to Step 5 (Planner) and Step 6 (Generator).
|
|
51
|
+
Also extract project-level patterns → append to `tests/playwright/app-knowledge.md`.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# App Knowledge — <project-name>
|
|
2
|
+
|
|
3
|
+
Generated: <timestamp>
|
|
4
|
+
Last updated: <timestamp>
|
|
5
|
+
|
|
6
|
+
Cross-change E2E knowledge. Updated by Step 4 exploration, read by Step 5/6.
|
|
7
|
+
|
|
8
|
+
## Credential Format
|
|
9
|
+
|
|
10
|
+
| Field | Format | Source |
|
|
11
|
+
|-------|--------|--------|
|
|
12
|
+
| username | `<pattern>` | e.g. `email@example.com` or `test_user_001` |
|
|
13
|
+
| password | `<pattern>` | |
|
|
14
|
+
| login endpoint | `<path>` | e.g. `/api/auth/login` |
|
|
15
|
+
|
|
16
|
+
## Common Selector Patterns
|
|
17
|
+
|
|
18
|
+
Priority: `[data-testid]` > `getByRole` > `getByLabel` > `getByText` > CSS
|
|
19
|
+
|
|
20
|
+
### Forms
|
|
21
|
+
|
|
22
|
+
| Element | Selector | Notes |
|
|
23
|
+
|---------|----------|-------|
|
|
24
|
+
| submit btn | `[data-testid="..."]` or `getByRole('button', { name: '...' })` | |
|
|
25
|
+
| text input | `getByLabel('...')` or `[data-testid="..."]` | |
|
|
26
|
+
| password input | `getByLabel('...')` or `[name="..."]` | |
|
|
27
|
+
|
|
28
|
+
### Navigation
|
|
29
|
+
|
|
30
|
+
| Element | Selector | Notes |
|
|
31
|
+
|---------|----------|-------|
|
|
32
|
+
| nav link | `a:text("...")` or `nav >> text=...` | |
|
|
33
|
+
| logout btn | `[data-testid="logout-btn"]` | |
|
|
34
|
+
|
|
35
|
+
### Feedback
|
|
36
|
+
|
|
37
|
+
| Element | Selector | Notes |
|
|
38
|
+
|---------|----------|-------|
|
|
39
|
+
| error msg | `[data-testid="error-msg"]` or `.error` | |
|
|
40
|
+
| success msg | `[data-testid="success-msg"]` | |
|
|
41
|
+
| loading spinner | `[data-testid="loading"]` | |
|
|
42
|
+
|
|
43
|
+
## SPA Routing
|
|
44
|
+
|
|
45
|
+
- Framework: <e.g. React Router / Vue Router / Next.js>
|
|
46
|
+
- URL changes without page reload: <yes/no>
|
|
47
|
+
- History API: <yes/no>
|
|
48
|
+
- Hash routing: <yes/no>
|
|
49
|
+
|
|
50
|
+
## Dynamic Content Conventions
|
|
51
|
+
|
|
52
|
+
- User-specific data: use `toContainText`, never `toHaveText`
|
|
53
|
+
- Timestamps: normalize or use regex
|
|
54
|
+
- Random IDs: avoid asserting on auto-generated values
|
|
55
|
+
- Pagination: test first/last page, boundary conditions
|
|
56
|
+
|
|
57
|
+
## Project Conventions
|
|
58
|
+
|
|
59
|
+
| Convention | Value | Notes |
|
|
60
|
+
|------------|-------|-------|
|
|
61
|
+
| BASE_URL | `<default>` | Override with env |
|
|
62
|
+
| auth method | API / UI | See auth.setup.ts |
|
|
63
|
+
| multi-user roles | `<roles>` | e.g. admin, user, guest |
|
|
64
|
+
|
|
65
|
+
## Changelog
|
|
66
|
+
|
|
67
|
+
| Date | Change | By |
|
|
68
|
+
|------|--------|-----|
|
|
69
|
+
| | | |
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
> **Updating this file**: After each E2E exploration (Step 4), extract new shared patterns and update this file. Generator (Step 6) reads this before writing tests.
|
package/src/commands/init.ts
CHANGED
|
@@ -122,14 +122,18 @@ export async function init(options: InitOptions) {
|
|
|
122
122
|
await generateSeedTest(projectRoot);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
// 8.
|
|
125
|
+
// 8. Generate app-knowledge.md
|
|
126
|
+
console.log(chalk.blue('\n─── Generating App Knowledge ───'));
|
|
127
|
+
await generateAppKnowledge(projectRoot);
|
|
128
|
+
|
|
129
|
+
// 9. Install employee-grade CLAUDE.md
|
|
126
130
|
console.log(chalk.blue('\n─── Installing Employee Standards ───'));
|
|
127
131
|
const standards = readEmployeeStandards(EMPLOYEE_STANDARDS_SRC);
|
|
128
132
|
if (standards) {
|
|
129
133
|
installProjectClaudeMd(projectRoot, standards);
|
|
130
134
|
}
|
|
131
135
|
|
|
132
|
-
//
|
|
136
|
+
// 10. Summary
|
|
133
137
|
console.log(chalk.blue('\n─── Summary ───'));
|
|
134
138
|
console.log(chalk.green(' ✓ Setup complete!\n'));
|
|
135
139
|
|
|
@@ -187,6 +191,21 @@ async function generateSeedTest(projectRoot: string) {
|
|
|
187
191
|
console.log(chalk.gray(' (Customize BASE_URL and credentials for your app)'));
|
|
188
192
|
}
|
|
189
193
|
|
|
194
|
+
async function generateAppKnowledge(projectRoot: string) {
|
|
195
|
+
const src = join(SCHEMA_DIR, 'playwright-e2e', 'templates', 'app-knowledge.md');
|
|
196
|
+
const dest = join(projectRoot, 'tests', 'playwright', 'app-knowledge.md');
|
|
197
|
+
|
|
198
|
+
if (existsSync(dest)) {
|
|
199
|
+
console.log(chalk.gray(' - app-knowledge.md already exists, skipping'));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (existsSync(src)) {
|
|
204
|
+
writeFileSync(dest, readFileSync(src));
|
|
205
|
+
console.log(chalk.green(' ✓ Generated: tests/playwright/app-knowledge.md'));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
190
209
|
async function installSchema(projectRoot: string) {
|
|
191
210
|
const schemaSrc = SCHEMA_DIR + '/playwright-e2e';
|
|
192
211
|
const schemaDest = join(projectRoot, 'openspec', 'schemas', 'playwright-e2e');
|
|
@@ -205,7 +224,7 @@ async function installSchema(projectRoot: string) {
|
|
|
205
224
|
const templatesSrc = join(schemaSrc, 'templates');
|
|
206
225
|
const templatesDest = join(schemaDest, 'templates');
|
|
207
226
|
mkdirSync(templatesDest, { recursive: true });
|
|
208
|
-
const templateFiles = ['test-plan.md', 'report.md', 'e2e-test.ts', 'playwright.config.ts'];
|
|
227
|
+
const templateFiles = ['test-plan.md', 'report.md', 'e2e-test.ts', 'playwright.config.ts', 'app-knowledge.md'];
|
|
209
228
|
for (const file of templateFiles) {
|
|
210
229
|
const src = join(templatesSrc, file);
|
|
211
230
|
const dest = join(templatesDest, file);
|
|
Binary file
|