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
|
-
|
|
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
|
-
|
|
277
|
+
### 9. False Pass Detection
|
|
272
278
|
|
|
273
|
-
|
|
279
|
+
Run **after** the test suite completes (even if all tests pass). Scan for silent skips that give false confidence:
|
|
274
280
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
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
|
-
|
|
299
|
+
If any false-pass indicator is found → add a **⚠️ Coverage Gap** section to the report.
|
|
294
300
|
|
|
295
|
-
###
|
|
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
package/release-notes.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
## What's Changed
|
|
2
2
|
|
|
3
|
-
-
|
|
3
|
+
- fix(seed): add waitForLoadState('networkidle') after reload
|
|
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.37
|
package/templates/seed.spec.ts
CHANGED
|
@@ -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
|
-
//
|
|
124
|
-
//
|
|
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: '
|
|
129
|
-
// await page.getByRole('button', { name: '
|
|
131
|
+
// await expect(page.getByRole('button', { name: '取消订阅' })).toBeVisible();
|
|
132
|
+
// await page.getByRole('button', { name: '取消订阅' }).click();
|
|
130
133
|
// await expect(page.getByText('操作成功')).toBeVisible();
|
|
Binary file
|