openspec-playwright 0.1.35 → 0.1.37

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.
@@ -221,7 +221,12 @@ If `playwright.config.ts` exists → READ it first. Extract existing `webServer`
221
221
  ```bash
222
222
  openspec-pw run <name> --project=<role>
223
223
  ```
224
- (Add `--project=user` or `--project=admin` for role-specific tests.)
224
+
225
+ **For role-based tests using `@tag`** (recommended over `--project` filtering):
226
+ ```bash
227
+ npx playwright test tests/playwright/<name>.spec.ts --grep "@<role>"
228
+ ```
229
+ The `--project` approach runs ALL tests under each project's credentials — use `@tag` with `--grep` for precise filtering.
225
230
 
226
231
  The CLI handles:
227
232
  - Server lifecycle (start → wait for HTTP → test → stop)
@@ -255,6 +260,7 @@ If tests fail → analyze failures, use **Playwright MCP tools** to inspect UI s
255
260
  3. **Attempt heal** (up to 3 times):
256
261
  - Apply fix using `browser_snapshot` (prefer `getByRole`, `getByLabel`, `getByText`)
257
262
  - Re-run: `openspec-pw run <name> --project=<role>`
263
+
258
264
  4. **After 3 failed attempts**, collect evidence:
259
265
 
260
266
  **Evidence checklist** (in order, stop at first match):
@@ -268,31 +274,31 @@ If tests fail → analyze failures, use **Playwright MCP tools** to inspect UI s
268
274
  - **Test bug**: report with "likely selector change, verify manually at file:line"
269
275
  - Do NOT retry after evidence checklist — evidence is conclusive
270
276
 
271
- 4b. **False Pass Detection (after test run — before reporting success)**
277
+ ### 9. False Pass Detection
272
278
 
273
- Even passing tests can give false confidence. Scan test output for silent skips:
279
+ Run **after** the test suite completes (even if all tests pass). Scan for silent skips that give false confidence:
274
280
 
275
- **Indicator A — Conditional test logic:**
276
- Look for patterns in the test file:
277
- ```typescript
278
- if (await locator.isVisible().catch(() => false)) { ... }
279
- ```
280
- → If test passes, the locator might not exist → check with `browser_snapshot`
281
- → Report: "Test passed but may have skipped — conditional visibility check detected"
281
+ **Indicator A — Conditional test logic:**
282
+ Look for patterns in the test file:
283
+ ```typescript
284
+ if (await locator.isVisible().catch(() => false)) { ... }
285
+ ```
286
+ → If test passes, the locator might not exist → check with `browser_snapshot`
287
+ → Report: "Test passed but may have skipped — conditional visibility check detected"
282
288
 
283
- **Indicator B — Test ran too fast:**
284
- A test covering a complex flow that completes in < 200ms is suspicious.
285
- → Inspect with `browser_snapshot` to confirm page state
286
- → Report: "Test duration suspiciously short — verify test logic was executed"
289
+ **Indicator B — Test ran too fast:**
290
+ A test covering a complex flow that completes in < 200ms is suspicious.
291
+ → Inspect with `browser_snapshot` to confirm page state
292
+ → Report: "Test duration suspiciously short — verify test logic was executed"
287
293
 
288
- **Indicator C — Auth guard not tested:**
289
- If specs mention "protected route" or "redirect to login" but no test uses a fresh browser context:
290
- → Report: "Auth guard not verified — test uses authenticated context (cookies/storage inherited)"
291
- → Recommendation: Add a test with `browser.newContext()` (no storageState) to verify the guard
294
+ **Indicator C — Auth guard not tested:**
295
+ If specs mention "protected route" or "redirect to login" but no test uses a fresh browser context:
296
+ → Report: "Auth guard not verified — test uses authenticated context (cookies/storage inherited)"
297
+ → Recommendation: Add a test with `browser.newContext()` (no storageState) to verify the guard
292
298
 
293
- If any false-pass indicator is found → add a **⚠️ Coverage Gap** section to the report.
299
+ If any false-pass indicator is found → add a **⚠️ Coverage Gap** section to the report.
294
300
 
295
- ### 9. Report results
301
+ ### 10. Report results
296
302
 
297
303
  Read the report at `openspec/reports/playwright-e2e-<name>-<timestamp>.md`.
298
304
 
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openspec-playwright",
3
- "version": "0.1.35",
3
+ "version": "0.1.37",
4
4
  "description": "OpenSpec + Playwright E2E verification setup tool for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
package/release-notes.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ## What's Changed
2
2
 
3
- - feat(skill): add anti-pattern guidance and false-pass detection (v2.7)
3
+ - fix(seed): add waitForLoadState('networkidle') after reload
4
4
 
5
- **Full Changelog**: https://github.com/wxhou/openspec-playwright/releases/tag/v0.1.35
5
+ **Full Changelog**: https://github.com/wxhou/openspec-playwright/releases/tag/v0.1.37
@@ -54,6 +54,7 @@ test.describe('Application smoke tests', () => {
54
54
  }
55
55
  });
56
56
  await page.reload();
57
+ await page.waitForLoadState('networkidle');
57
58
  // Filter out known non-critical errors
58
59
  const criticalErrors = errors.filter(
59
60
  (e) => !e.includes('favicon') && !e.includes('404')
@@ -120,11 +121,13 @@ test.describe('Application smoke tests', () => {
120
121
  // ──────────────────────────────────────────────
121
122
 
122
123
  // 🚫 WRONG — False Pass: test silently passes if button doesn't exist
123
- // if (await page.getByRole('button', { name: '取消' }).isVisible().catch(() => false)) {
124
- // await page.getByRole('button', { name: '取消' }).click();
124
+ // const cancelBtn = page.getByRole('button', { name: '取消订阅' });
125
+ // if (await cancelBtn.isVisible().catch(() => false)) {
126
+ // await cancelBtn.click();
127
+ // await expect(page.getByText('成功')).toBeVisible();
125
128
  // }
126
129
 
127
130
  // ✅ CORRECT — Use assertion: test fails if element is missing
128
- // await expect(page.getByRole('button', { name: '取消' })).toBeVisible();
129
- // await page.getByRole('button', { name: '取消' }).click();
131
+ // await expect(page.getByRole('button', { name: '取消订阅' })).toBeVisible();
132
+ // await page.getByRole('button', { name: '取消订阅' }).click();
130
133
  // await expect(page.getByText('操作成功')).toBeVisible();
Binary file