openspec-playwright 0.2.1 → 0.2.3
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 +29 -21
- package/README.md +4 -2
- package/README.zh-CN.md +4 -2
- package/dist/commands/migrate.d.ts +5 -0
- package/dist/commands/migrate.js +116 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/run.d.ts +5 -0
- package/dist/commands/run.js +17 -8
- package/dist/commands/run.js.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -16,7 +16,7 @@ metadata:
|
|
|
16
16
|
|
|
17
17
|
## Output
|
|
18
18
|
|
|
19
|
-
- **Test file**: `tests/playwright/<name>.spec.ts`
|
|
19
|
+
- **Test file**: `tests/playwright/changes/<name>/<name>.spec.ts`
|
|
20
20
|
- **Page Objects** (all mode): `tests/playwright/pages/<Route>Page.ts`
|
|
21
21
|
- **Auth setup**: `tests/playwright/auth.setup.ts` (if auth required)
|
|
22
22
|
- **Report**: `openspec/reports/playwright-e2e-<name>-<timestamp>.md`
|
|
@@ -28,7 +28,7 @@ Two modes, same pipeline:
|
|
|
28
28
|
|
|
29
29
|
| Mode | Command | Route source | Output |
|
|
30
30
|
| ------ | ------------------ | ------------------------ | ------------------------------- |
|
|
31
|
-
| Change | `/opsx:e2e <name>` | OpenSpec specs |
|
|
31
|
+
| Change | `/opsx:e2e <name>` | OpenSpec specs | `changes/<name>/<name>.spec.ts` |
|
|
32
32
|
| All | `/opsx:e2e all` | sitemap + homepage crawl | `pages/*.ts` (Page Objects) |
|
|
33
33
|
|
|
34
34
|
Both modes update `app-knowledge.md` and `app-exploration.md`. All `.spec.ts` files run together as regression suite.
|
|
@@ -143,7 +143,7 @@ Seed test initializes the `page` context — it runs all fixtures, hooks, and gl
|
|
|
143
143
|
|
|
144
144
|
Explore to collect real DOM data before writing test plan. This eliminates blind selector guessing.
|
|
145
145
|
|
|
146
|
-
**Prerequisites**: seed test pass. If auth is required
|
|
146
|
+
**Prerequisites**: seed test pass. BASE_URL must be verified reachable (see 4.1). If auth is required and `auth.setup.ts` already exists → auth is ready. If auth is not yet configured → use the workaround below (Option B for protected routes).
|
|
147
147
|
|
|
148
148
|
#### 4.1. Verify BASE_URL + Read app-knowledge.md
|
|
149
149
|
|
|
@@ -163,8 +163,8 @@ browser_navigate → browser_console_messages → browser_snapshot → browser_t
|
|
|
163
163
|
|
|
164
164
|
| Signal | Meaning | Action |
|
|
165
165
|
| ----------------------------- | --------------------------------- | --------------------------------------------------------------------------------------------- |
|
|
166
|
-
| HTTP 5xx or unreachable | Backend/server error | **STOP** — tell user: "App has a backend error (HTTP <code>). Fix it, then re-run
|
|
167
|
-
| JS error in console | App runtime error | **STOP** — tell user: "Page has JS errors. Fix them, then re-run
|
|
166
|
+
| HTTP 5xx or unreachable | Backend/server error | **STOP** — tell user: "App has a backend error (HTTP <code>). Fix it, then re-run `/opsx:e2e <name>` to re-explore." |
|
|
167
|
+
| JS error in console | App runtime error | **STOP** — tell user: "Page has JS errors. Fix them, then re-run `/opsx:e2e <name>` to re-explore." |
|
|
168
168
|
| HTTP 404 | Route not in app (metadata issue) | Continue — mark `⚠️ route not found` in app-exploration.md |
|
|
169
169
|
| Auth required, no credentials | Missing auth setup | Continue — skip protected routes, explore login page |
|
|
170
170
|
| Suspicious network request | API returned 4xx/5xx | Continue — mark `⚠️ API error: <endpoint> returned <code>` in app-exploration.md |
|
|
@@ -328,7 +328,7 @@ After exploration, add route-level notes (redirects, dynamic content → see 4.5
|
|
|
328
328
|
| Page loads but no interactive elements | Wait longer for SPA hydration |
|
|
329
329
|
| Dynamic content (user-specific) | Record structure — use `toContainText` or regex, not `toHaveText` |
|
|
330
330
|
|
|
331
|
-
**Idempotency**: If `app-exploration.md` already exists → read it, verify routes still match
|
|
331
|
+
**Idempotency**: If `app-exploration.md` already exists → read it, verify routes still match the live app, update only new routes or changed pages.
|
|
332
332
|
|
|
333
333
|
#### 4.6. Update app-knowledge.md
|
|
334
334
|
|
|
@@ -356,7 +356,7 @@ Read `tests/playwright/app-knowledge.md` as context for cross-change patterns.
|
|
|
356
356
|
|
|
357
357
|
### 5. Generate test plan
|
|
358
358
|
|
|
359
|
-
> **"all" mode: skip
|
|
359
|
+
> **"all" mode: skip test-plan generation.** No OpenSpec specs → no test-plan to generate. Still show confirmation below, then proceed to Step 6.
|
|
360
360
|
|
|
361
361
|
**All mode — brief confirmation before Step 6:**
|
|
362
362
|
```
|
|
@@ -470,7 +470,7 @@ For each discovered route:
|
|
|
470
470
|
|
|
471
471
|
**Output priority**: Page Objects (`pages/*.ts`) are the primary asset. Smoke test is secondary. Existing Page Objects are never overwritten — only extended.
|
|
472
472
|
|
|
473
|
-
**Change mode** → `tests/playwright/<name>.spec.ts` (functional):
|
|
473
|
+
**Change mode** → `tests/playwright/changes/<name>/<name>.spec.ts` (functional):
|
|
474
474
|
|
|
475
475
|
- Read: test-plan.md, app-exploration.md, app-knowledge.md, seed.spec.ts
|
|
476
476
|
- For each test case: verify selectors in real browser, then write Playwright code
|
|
@@ -653,7 +653,7 @@ export class LoginPage extends BasePage {
|
|
|
653
653
|
```
|
|
654
654
|
|
|
655
655
|
```typescript
|
|
656
|
-
// tests/playwright/<name>.spec.ts
|
|
656
|
+
// tests/playwright/changes/<name>/<name>.spec.ts
|
|
657
657
|
import { LoginPage } from '../pages/LoginPage';
|
|
658
658
|
|
|
659
659
|
test('user can login', async ({ page }) => {
|
|
@@ -765,11 +765,13 @@ Auth required. To set up:
|
|
|
765
765
|
1. Customize tests/playwright/credentials.yaml
|
|
766
766
|
2. Export: export E2E_USERNAME=xxx E2E_PASSWORD=yyy
|
|
767
767
|
3. Run auth: npx playwright test --project=setup
|
|
768
|
-
4.
|
|
768
|
+
4. Then run tests: openspec-pw run <name> # skips to Step 9 directly (artifacts are reused)
|
|
769
769
|
```
|
|
770
770
|
|
|
771
771
|
**Idempotency**: If `auth.setup.ts` already exists → verify format, update only if stale.
|
|
772
772
|
|
|
773
|
+
**Post-auth re-exploration**: If Step 4 skipped protected routes due to missing auth, re-run exploration for those routes now that auth is configured. Navigate to each protected route with auth context → `browser_snapshot` → update `app-exploration.md`. Selectors verified now are better than guesses used during test generation.
|
|
774
|
+
|
|
773
775
|
### 8. Configure playwright.config.ts
|
|
774
776
|
|
|
775
777
|
**Output**: `playwright.config.ts` (project root; or `tests/playwright/playwright.config.ts` if config already exists there)
|
|
@@ -793,7 +795,7 @@ If playwright.config.ts exists → READ first, preserve ALL existing fields, add
|
|
|
793
795
|
### 9. Execute tests
|
|
794
796
|
|
|
795
797
|
```bash
|
|
796
|
-
openspec-pw run <name> --project
|
|
798
|
+
openspec-pw run <name> [--project <role>]
|
|
797
799
|
```
|
|
798
800
|
|
|
799
801
|
The CLI handles: server lifecycle, port mismatch, report generation.
|
|
@@ -822,13 +824,15 @@ When a test fails, classify before attempting repair:
|
|
|
822
824
|
| **Auth Expired** | Redirected to login mid-test | **Flaky** | Re-run auth.setup → re-run |
|
|
823
825
|
| **Selector Not Found** | Element not found | **Test Bug** | → Phase 2 Healer |
|
|
824
826
|
| **Assertion Mismatch** | Wrong content/value | **Ambiguous** | → Phase 2 Healer |
|
|
825
|
-
| **Timeout** | waitFor/evaluate timeout | **Flaky** | Retry isolated (1×, not counted in heal attempts). If it passes isolated but fails in suite → **RAFT**. If it consistently times out → check framework: React 19 / Next.js App Router: add `page.waitForLoadState('networkidle')`. Vue/Angular/React 18 / Plain JS / jQuery: use `waitForSelector(targetElement)` instead of timeout tuning. |
|
|
827
|
+
| **Timeout** | waitFor/evaluate timeout | **Flaky** | Retry isolated: `openspec-pw run <name> --grep "<test-name>"` (1×, not counted in heal attempts). If it passes isolated but fails in suite → **RAFT**. If it consistently times out → check framework: React 19 / Next.js App Router: add `page.waitForLoadState('networkidle')`. Vue/Angular/React 18 / Plain JS / jQuery: use `waitForSelector(targetElement)` instead of timeout tuning. |
|
|
826
828
|
| **Same test fails in suite, passes isolated** | — | **RAFT** | `test.skip()` in suite, note RAFT in report |
|
|
827
829
|
|
|
828
830
|
- **App Bug** → skip immediately (no healing needed)
|
|
829
831
|
- **Flaky** → retry once isolated
|
|
830
832
|
- **Test Bug / Ambiguous** → Phase 2
|
|
831
833
|
|
|
834
|
+
> **Global attempt guard**: Each test has an independent heal counter (max 3 per test). If the same test enters Phase 2 more than once and reaches the cap each time → treat as "consecutive escalation without progress" → Phase 3 immediately.
|
|
835
|
+
|
|
832
836
|
> **Type ≠ Blame**: "Test Bug" means the assertion or selector is wrong — it does NOT mean "blame the test author." The test was generated from the spec. Root cause may be spec ambiguity, spec→test generation error, or app→spec deviation. Only a human can determine blame.
|
|
833
837
|
|
|
834
838
|
**Healer — Phase 2: Repair**
|
|
@@ -883,18 +887,18 @@ Wait for user input before proceeding.
|
|
|
883
887
|
|
|
884
888
|
| Choice | What to do | After fix, do this |
|
|
885
889
|
|--------|-----------|-------------------|
|
|
886
|
-
| **(a)** Fix the app to match the spec | Fix the app code | Re-run: `
|
|
890
|
+
| **(a)** Fix the app to match the spec | Fix the app code | Re-run: `openspec-pw run <change-name>` to verify fix |
|
|
887
891
|
| **(b)** Update the spec to match the app | Edit the spec file | Then update the test assertion (→ option c), or regenerate the affected part of the test |
|
|
888
|
-
| **(c)** Update the test assertion | Fix the assertion in `tests/playwright/<name>.spec.ts` | Re-run: `
|
|
892
|
+
| **(c)** Update the test assertion | Fix the assertion in `tests/playwright/changes/<name>/<name>.spec.ts` | Re-run: `openspec-pw run <change-name>` to verify |
|
|
889
893
|
| **(d)** Skip with `test.skip()` | Add `test.skip()` to the test | Note in `app-knowledge.md` → `Selector Fixes` table with reason "human escalation — skipped pending resolution" |
|
|
890
894
|
|
|
891
|
-
**
|
|
895
|
+
**Stuck in escalation loop**: If 3 consecutive Phase 3 escalations result in no progress (test still failing), STOP and ask: "This test has been escalated 3 times without resolution. Are you sure the root cause is still the same, or has something changed?"
|
|
892
896
|
|
|
893
|
-
After the issue is resolved, re-run:
|
|
897
|
+
After the issue is resolved, re-run tests:
|
|
894
898
|
```
|
|
895
|
-
|
|
899
|
+
openspec-pw run <change-name>
|
|
896
900
|
```
|
|
897
|
-
|
|
901
|
+
`/opsx:e2e <change-name>` re-runs the full 11-step workflow — unnecessary after Phase 3. The test file and auth context are already correct. Use `openspec-pw run` to verify fixes directly.
|
|
898
902
|
|
|
899
903
|
### 10. False Pass Detection + RAFT Detection
|
|
900
904
|
|
|
@@ -908,7 +912,7 @@ Run after test suite completes (even if all pass).
|
|
|
908
912
|
|
|
909
913
|
**RAFT detection** (Resource-Affected Flaky Test):
|
|
910
914
|
|
|
911
|
-
- Full suite: test fails → run test
|
|
915
|
+
- Full suite: test fails → run isolated: `openspec-pw run <name> --grep "<test-name>"` → if it passes in isolation but fails in suite → **RAFT**
|
|
912
916
|
- This is **NOT** a test bug or app bug. Mark as RAFT, add `test.skip()` in suite, note in report
|
|
913
917
|
- RAFTs are infrastructure coupling issues (CPU/memory/I/O contention), not fixable by changing test or app
|
|
914
918
|
|
|
@@ -938,7 +942,7 @@ Reference: `.claude/skills/openspec-e2e/templates/report.md`
|
|
|
938
942
|
| Scenario | Behavior |
|
|
939
943
|
| ------- | ------- |
|
|
940
944
|
| No specs / app-exploration.md missing (change mode) | **STOP** |
|
|
941
|
-
| JS errors or HTTP 5xx during exploration | **STOP** |
|
|
945
|
+
| JS errors or HTTP 5xx during exploration | **STOP** → user fixes app → re-run `/opsx:e2e <name>` to re-explore from Step 4 |
|
|
942
946
|
| Sitemap fails ("all" mode) | Continue with homepage links fallback |
|
|
943
947
|
| File already exists (app-exploration, test-plan, app-all.spec.ts, Page Objects) | Read and use — never regenerate |
|
|
944
948
|
| Test fails (network/backend) | **App Bug** — `test.skip()` + report |
|
|
@@ -960,6 +964,10 @@ Reference: `.claude/skills/openspec-e2e/templates/report.md`
|
|
|
960
964
|
| Write runnable code, not TODOs | Placeholders fail CI |
|
|
961
965
|
|
|
962
966
|
**Files you can write to:**
|
|
963
|
-
`
|
|
967
|
+
`tests/playwright/`, `openspec/changes/<name>/specs/playwright/`, `openspec/reports/`, `playwright.config.ts`, `auth.setup.ts`
|
|
968
|
+
|
|
969
|
+
> `tests/playwright/` — spec files, Page Objects, auth, credentials, app-knowledge.md
|
|
970
|
+
> `openspec/changes/<name>/specs/playwright/` — app-exploration.md, test-plan.md (change mode)
|
|
971
|
+
> `openspec/reports/` — test reports
|
|
964
972
|
|
|
965
973
|
**Never write to:** any other directory
|
package/README.md
CHANGED
|
@@ -59,7 +59,7 @@ openspec-pw uninstall # Remove integration from the project
|
|
|
59
59
|
│
|
|
60
60
|
├── 5. Planner → generates test-plan.md
|
|
61
61
|
│
|
|
62
|
-
├── 6. Generator → creates tests/playwright/<name>.spec.ts
|
|
62
|
+
├── 6. Generator → creates tests/playwright/changes/<name>/<name>.spec.ts
|
|
63
63
|
│ └─ Verifies selectors in real browser before writing
|
|
64
64
|
│
|
|
65
65
|
├── 7. Configure auth → auth.setup.ts (if required)
|
|
@@ -155,7 +155,9 @@ CLI (openspec-pw)
|
|
|
155
155
|
├── init → Installs commands, skill & templates to .claude/
|
|
156
156
|
├── update → Syncs commands, skill & templates from npm
|
|
157
157
|
├── run → Executes E2E tests with server lifecycle
|
|
158
|
-
|
|
158
|
+
├── migrate → Migrates old test files to new structure
|
|
159
|
+
├── doctor → Checks prerequisites
|
|
160
|
+
└── uninstall → Removes integration from the project
|
|
159
161
|
|
|
160
162
|
Claude Code (/opsx:e2e)
|
|
161
163
|
├── .claude/commands/opsx/e2e.md → Command file
|
package/README.zh-CN.md
CHANGED
|
@@ -72,7 +72,7 @@ openspec-pw uninstall # 移除项目中的集成
|
|
|
72
72
|
│
|
|
73
73
|
├── 5. Planner → 生成 test-plan.md
|
|
74
74
|
│
|
|
75
|
-
├── 6. Generator → 创建 tests/playwright/<name>.spec.ts
|
|
75
|
+
├── 6. Generator → 创建 tests/playwright/changes/<name>/<name>.spec.ts
|
|
76
76
|
│ └─ 写测试前先在真实浏览器验证选择器
|
|
77
77
|
│
|
|
78
78
|
├── 7. 配置 auth → auth.setup.ts(如需要)
|
|
@@ -156,7 +156,9 @@ CLI (openspec-pw)
|
|
|
156
156
|
├── init → 安装命令、skill 和模板到 .claude/
|
|
157
157
|
├── update → 从 npm 同步命令、skill 和模板
|
|
158
158
|
├── run → 执行 E2E 测试并管理服务器生命周期
|
|
159
|
-
|
|
159
|
+
├── migrate → 迁移旧测试文件到新目录结构
|
|
160
|
+
├── doctor → 检查前置条件
|
|
161
|
+
└── uninstall → 移除项目中的集成
|
|
160
162
|
|
|
161
163
|
Claude Code (/opsx:e2e)
|
|
162
164
|
├── .claude/commands/opsx/e2e.md → 命令文件
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import { existsSync, mkdirSync, readdirSync, renameSync, } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
const SHARED_FILES = new Set([
|
|
6
|
+
"seed.spec.ts",
|
|
7
|
+
"app-all.spec.ts",
|
|
8
|
+
"auth.setup.ts",
|
|
9
|
+
"credentials.yaml",
|
|
10
|
+
"app-knowledge.md",
|
|
11
|
+
"playwright.config.ts",
|
|
12
|
+
"mcp-tools.md",
|
|
13
|
+
]);
|
|
14
|
+
export async function migrate(options) {
|
|
15
|
+
const projectRoot = process.cwd();
|
|
16
|
+
const testsDir = join(projectRoot, "tests", "playwright");
|
|
17
|
+
if (!existsSync(testsDir)) {
|
|
18
|
+
console.log(chalk.yellow(" tests/playwright/ not found. Is this an initialized project?"));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
console.log(chalk.blue("\n🔄 OpenSpec Playwright: Migration\n"));
|
|
22
|
+
// 1. Get list of OpenSpec changes (to validate)
|
|
23
|
+
let changeNames = [];
|
|
24
|
+
try {
|
|
25
|
+
const result = execSync("npx openspec list --json", {
|
|
26
|
+
cwd: projectRoot,
|
|
27
|
+
encoding: "utf-8",
|
|
28
|
+
timeout: 30000,
|
|
29
|
+
});
|
|
30
|
+
const data = JSON.parse(result);
|
|
31
|
+
changeNames = Array.isArray(data)
|
|
32
|
+
? data.map((c) => c.name)
|
|
33
|
+
: Object.keys(data);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// If openspec not available or no changes, proceed with empty list
|
|
37
|
+
changeNames = [];
|
|
38
|
+
}
|
|
39
|
+
// 2. Find old-style spec files in root
|
|
40
|
+
const oldFiles = readdirSync(testsDir)
|
|
41
|
+
.filter((f) => f.endsWith(".spec.ts"))
|
|
42
|
+
.filter((f) => !SHARED_FILES.has(f))
|
|
43
|
+
.filter((f) => !f.startsWith("."));
|
|
44
|
+
if (oldFiles.length === 0) {
|
|
45
|
+
console.log(chalk.green(" ✓ No old-style change spec files found. Nothing to migrate.\n"));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
console.log(chalk.blue(`─── Found ${oldFiles.length} old-style spec file(s) ───`));
|
|
49
|
+
const items = oldFiles.map((fileName) => {
|
|
50
|
+
const changeName = fileName.replace(".spec.ts", "");
|
|
51
|
+
const oldPath = join(testsDir, fileName);
|
|
52
|
+
const newDir = join(testsDir, "changes", changeName);
|
|
53
|
+
const newPath = join(newDir, fileName);
|
|
54
|
+
const valid = changeNames.includes(changeName);
|
|
55
|
+
const reason = valid
|
|
56
|
+
? undefined
|
|
57
|
+
: changeNames.length === 0
|
|
58
|
+
? "openspec not initialized or no changes found"
|
|
59
|
+
: `change "${changeName}" not found in openspec`;
|
|
60
|
+
return { fileName, changeName, oldPath, newPath, valid, reason };
|
|
61
|
+
});
|
|
62
|
+
// 4. Display findings
|
|
63
|
+
const validItems = items.filter((i) => i.valid);
|
|
64
|
+
const invalidItems = items.filter((i) => !i.valid);
|
|
65
|
+
for (const item of items) {
|
|
66
|
+
const icon = item.valid ? chalk.green("✓") : chalk.red("✗");
|
|
67
|
+
console.log(` ${icon} ${item.fileName} → changes/${item.changeName}/${item.fileName}`);
|
|
68
|
+
if (item.reason) {
|
|
69
|
+
console.log(chalk.gray(` Skip: ${item.reason}`));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (invalidItems.length > 0) {
|
|
73
|
+
console.log(chalk.yellow(`\n ⚠ ${invalidItems.length} file(s) skipped (no matching OpenSpec change)`));
|
|
74
|
+
}
|
|
75
|
+
if (validItems.length === 0) {
|
|
76
|
+
console.log(chalk.blue("\n No valid migrations to perform.\n"));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// 5. Dry run or execute
|
|
80
|
+
if (options.dryRun) {
|
|
81
|
+
console.log(chalk.blue(`\n─── Dry run — no files were moved ───`));
|
|
82
|
+
console.log(chalk.green(" All valid migrations would succeed.\n"));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
console.log(chalk.blue("\n─── Migrating ───"));
|
|
86
|
+
let migrated = 0;
|
|
87
|
+
let skipped = 0;
|
|
88
|
+
for (const item of validItems) {
|
|
89
|
+
// Check if file exists
|
|
90
|
+
if (!existsSync(item.oldPath)) {
|
|
91
|
+
console.log(chalk.yellow(` ⚠ ${item.fileName} not found, skipping`));
|
|
92
|
+
skipped++;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
// Check if new location already has a file
|
|
96
|
+
if (existsSync(item.newPath)) {
|
|
97
|
+
if (!options.force) {
|
|
98
|
+
console.log(chalk.yellow(` ⚠ ${item.newPath} already exists. Use --force to overwrite.`));
|
|
99
|
+
skipped++;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Create directory and move
|
|
104
|
+
mkdirSync(join(testsDir, "changes", item.changeName), {
|
|
105
|
+
recursive: true,
|
|
106
|
+
});
|
|
107
|
+
renameSync(item.oldPath, item.newPath);
|
|
108
|
+
migrated++;
|
|
109
|
+
}
|
|
110
|
+
// 6. Summary
|
|
111
|
+
console.log(chalk.blue("\n─── Results ───"));
|
|
112
|
+
console.log(` ${chalk.green(`✓ ${migrated} migrated`)} ${chalk.red(`✗ ${skipped} skipped`)}`);
|
|
113
|
+
console.log(chalk.blue("\n─── Next step ───"));
|
|
114
|
+
console.log(chalk.green(" Run `openspec-pw run <name>` to verify each migrated change.\n"));
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EACL,UAAU,EACV,SAAS,EACT,WAAW,EACX,UAAU,GACX,MAAM,IAAI,CAAC;AACZ,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,cAAc;IACd,iBAAiB;IACjB,eAAe;IACf,kBAAkB;IAClB,kBAAkB;IAClB,sBAAsB;IACtB,cAAc;CACf,CAAC,CAAC;AAOH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAuB;IACnD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IAE1D,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,gEAAgE,CACjE,CACF,CAAC;QACF,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC,CAAC;IAEjE,gDAAgD;IAChD,IAAI,WAAW,GAAa,EAAE,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,0BAA0B,EAAE;YAClD,GAAG,EAAE,WAAW;YAChB,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAChC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAC/B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,mEAAmE;QACnE,WAAW,GAAG,EAAE,CAAC;IACnB,CAAC;IAED,uCAAuC;IACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC;SACnC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;SACrC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACnC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAErC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAC/E,CAAC;QACF,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,MAAM,6BAA6B,CAAC,CACtE,CAAC;IAYF,MAAM,KAAK,GAAkB,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QACrD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEvC,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,KAAK;YAClB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;gBACxB,CAAC,CAAC,8CAA8C;gBAChD,CAAC,CAAC,WAAW,UAAU,yBAAyB,CAAC;QAErD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,sBAAsB;IACtB,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAEnD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CACT,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,gBAAgB,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,QAAQ,EAAE,CAC7E,CAAC;QACF,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,SAAS,YAAY,CAAC,MAAM,gDAAgD,CAC7E,CACF,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC,CAAC;QACjE,OAAO;IACT,CAAC;IAED,wBAAwB;IACxB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CACtD,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC,CAAC;QACpE,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAE/C,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,uBAAuB;QACvB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,QAAQ,sBAAsB,CAAC,CACzD,CAAC;YACF,OAAO,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QAED,2CAA2C;QAC3C,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBACnB,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,OAAO,IAAI,CAAC,OAAO,4CAA4C,CAChE,CACF,CAAC;gBACF,OAAO,EAAE,CAAC;gBACV,SAAS;YACX,CAAC;QACH,CAAC;QAED,4BAA4B;QAC5B,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE;YACpD,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;QACH,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,QAAQ,EAAE,CAAC;IACb,CAAC;IAED,aAAa;IACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CACT,KAAK,KAAK,CAAC,KAAK,CAAC,KAAK,QAAQ,WAAW,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,KAAK,OAAO,UAAU,CAAC,EAAE,CACnF,CAAC;IACF,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAClC,CAAC;IACF,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CACT,kEAAkE,CACnE,CACF,CAAC;AACJ,CAAC"}
|
package/dist/commands/run.d.ts
CHANGED
|
@@ -2,6 +2,11 @@ export interface RunOptions {
|
|
|
2
2
|
project?: string;
|
|
3
3
|
timeout?: number;
|
|
4
4
|
json?: boolean;
|
|
5
|
+
grep?: string;
|
|
6
|
+
appBugs?: number;
|
|
7
|
+
healed?: number;
|
|
8
|
+
raft?: number;
|
|
9
|
+
escalated?: number;
|
|
5
10
|
}
|
|
6
11
|
export declare function run(changeName: string, options: RunOptions): Promise<void>;
|
|
7
12
|
interface TestResults {
|
package/dist/commands/run.js
CHANGED
|
@@ -7,9 +7,15 @@ export async function run(changeName, options) {
|
|
|
7
7
|
console.log(chalk.blue(`\n🔍 OpenSpec Playwright E2E: ${changeName}\n`));
|
|
8
8
|
const projectRoot = process.cwd();
|
|
9
9
|
// 1. Verify test file exists
|
|
10
|
-
const
|
|
10
|
+
const testFileName = changeName === "all"
|
|
11
|
+
? "app-all.spec.ts"
|
|
12
|
+
: `${changeName}.spec.ts`;
|
|
13
|
+
const testFile = join(projectRoot, "tests", "playwright", changeName === "all" ? testFileName : `changes/${changeName}/${testFileName}`);
|
|
11
14
|
if (!existsSync(testFile)) {
|
|
12
|
-
|
|
15
|
+
const testFileDisplayPath = changeName === "all"
|
|
16
|
+
? `tests/playwright/${testFileName}`
|
|
17
|
+
: `tests/playwright/changes/${changeName}/${testFileName}`;
|
|
18
|
+
console.log(chalk.red(` ✗ Test file not found: ${testFileDisplayPath}`));
|
|
13
19
|
console.log(chalk.gray(" Run /opsx:e2e first to generate tests.\n"));
|
|
14
20
|
process.exit(1);
|
|
15
21
|
}
|
|
@@ -33,6 +39,9 @@ export async function run(changeName, options) {
|
|
|
33
39
|
if (options.project) {
|
|
34
40
|
args.push("--project=" + options.project);
|
|
35
41
|
}
|
|
42
|
+
if (options.grep) {
|
|
43
|
+
args.push("--grep=" + options.grep);
|
|
44
|
+
}
|
|
36
45
|
let testOutput = "";
|
|
37
46
|
try {
|
|
38
47
|
const result = execSync(args.join(" "), {
|
|
@@ -58,7 +67,7 @@ export async function run(changeName, options) {
|
|
|
58
67
|
// 7. Generate markdown report
|
|
59
68
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
60
69
|
const reportPath = join(projectRoot, REPORTS_DIR, `playwright-e2e-${changeName}-${timestamp}.md`);
|
|
61
|
-
const reportContent = generateReport(changeName, timestamp, results);
|
|
70
|
+
const reportContent = generateReport(changeName, timestamp, results, options);
|
|
62
71
|
writeFileSync(reportPath, reportContent);
|
|
63
72
|
// 8. Summary
|
|
64
73
|
if (options.json) {
|
|
@@ -171,7 +180,7 @@ export function parsePlaywrightOutput(output) {
|
|
|
171
180
|
results.duration = durationMatch[1];
|
|
172
181
|
return results;
|
|
173
182
|
}
|
|
174
|
-
function generateReport(changeName, timestamp, results) {
|
|
183
|
+
function generateReport(changeName, timestamp, results, options) {
|
|
175
184
|
const duration = timestamp.replace("T", " ").slice(0, 16);
|
|
176
185
|
const status = results.failed === 0 ? "✅ PASS" : "❌ FAIL";
|
|
177
186
|
const lines = [
|
|
@@ -187,10 +196,10 @@ function generateReport(changeName, timestamp, results) {
|
|
|
187
196
|
`| Passed | ${results.passed} |`,
|
|
188
197
|
`| Failed | ${results.failed} |`,
|
|
189
198
|
`| Duration | ${results.duration} |`,
|
|
190
|
-
`| App Bugs (skipped) | ${
|
|
191
|
-
`| Test Bugs (healed) | ${
|
|
192
|
-
`| Flaky/RAFT | ${
|
|
193
|
-
`| Human Escalations | ${
|
|
199
|
+
`| App Bugs (skipped) | ${options.appBugs ?? "—"} |`,
|
|
200
|
+
`| Test Bugs (healed) | ${options.healed ?? "—"} |`,
|
|
201
|
+
`| Flaky/RAFT | ${options.raft ?? "—"} |`,
|
|
202
|
+
`| Human Escalations | ${options.escalated ?? "—"} |`,
|
|
194
203
|
`| Final Status | ${status} |`,
|
|
195
204
|
"",
|
|
196
205
|
];
|
package/dist/commands/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { init } from "./commands/init.js";
|
|
|
6
6
|
import { update } from "./commands/update.js";
|
|
7
7
|
import { doctor } from "./commands/doctor.js";
|
|
8
8
|
import { run } from "./commands/run.js";
|
|
9
|
+
import { migrate } from "./commands/migrate.js";
|
|
9
10
|
import { uninstall } from "./commands/uninstall.js";
|
|
10
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
12
|
const pkg = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
|
|
@@ -39,7 +40,18 @@ program
|
|
|
39
40
|
.option("-p, --project <name>", "Playwright project to run (e.g., user, admin)")
|
|
40
41
|
.option("-t, --timeout <seconds>", "Test timeout in seconds", "300")
|
|
41
42
|
.option("--json", "Output results as JSON")
|
|
43
|
+
.option("-g, --grep <pattern>", "Run only tests matching pattern")
|
|
44
|
+
.option("--app-bugs <n>", "Number of app bugs (skipped tests)", (v) => parseInt(v, 10), undefined)
|
|
45
|
+
.option("--healed <n>", "Number of test bugs healed by Healer", (v) => parseInt(v, 10), undefined)
|
|
46
|
+
.option("--raft <n>", "Number of RAFTs detected", (v) => parseInt(v, 10), undefined)
|
|
47
|
+
.option("--escalated <n>", "Number of human escalations", (v) => parseInt(v, 10), undefined)
|
|
42
48
|
.action(run);
|
|
49
|
+
program
|
|
50
|
+
.command("migrate")
|
|
51
|
+
.description("Migrate old-style change spec files to the new tests/playwright/changes/<name>/ structure")
|
|
52
|
+
.option("-n, --dry-run", "Show what would be migrated without moving files")
|
|
53
|
+
.option("-f, --force", "Overwrite existing files at the new location")
|
|
54
|
+
.action(migrate);
|
|
43
55
|
program
|
|
44
56
|
.command("uninstall")
|
|
45
57
|
.description("Remove OpenSpec + Playwright E2E integration from the current project")
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAC1D,CAAC;AAEF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,mDAAmD,CAAC;KAChE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAExB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CACV,yEAAyE,CAC1E;KACA,MAAM,CAAC,qBAAqB,EAAE,qBAAqB,EAAE,SAAS,CAAC;KAC/D,MAAM,CAAC,UAAU,EAAE,mCAAmC,CAAC;KACvD,MAAM,CAAC,QAAQ,EAAE,qDAAqD,CAAC;KACvE,MAAM,CAAC,WAAW,EAAE,uCAAuC,CAAC;KAC5D,MAAM,CAAC,IAAI,CAAC,CAAC;AAEhB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,QAAQ,EAAE,wBAAwB,CAAC;KAC1C,MAAM,CAAC,MAAM,CAAC,CAAC;AAElB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,qDAAqD,CAAC;KAClE,MAAM,CAAC,UAAU,EAAE,iBAAiB,CAAC;KACrC,MAAM,CAAC,YAAY,EAAE,2BAA2B,CAAC;KACjD,MAAM,CAAC,MAAM,CAAC,CAAC;AAElB,OAAO;KACJ,OAAO,CAAC,mBAAmB,CAAC;KAC5B,WAAW,CAAC,iDAAiD,CAAC;KAC9D,MAAM,CACL,sBAAsB,EACtB,+CAA+C,CAChD;KACA,MAAM,CAAC,yBAAyB,EAAE,yBAAyB,EAAE,KAAK,CAAC;KACnE,MAAM,CAAC,QAAQ,EAAE,wBAAwB,CAAC;KAC1C,MAAM,CAAC,GAAG,CAAC,CAAC;AAEf,OAAO;KACJ,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CACV,uEAAuE,CACxE;KACA,MAAM,CAAC,SAAS,CAAC,CAAC;AAErB,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|