openspec-playwright 0.3.47 → 0.3.49
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/README.md +15 -6
- package/README.zh-CN.md +12 -6
- package/dist/commands/audit.js +5 -3
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/coverage.d.ts +41 -0
- package/dist/commands/coverage.js +368 -0
- package/dist/commands/coverage.js.map +1 -0
- package/dist/commands/flake.d.ts +23 -0
- package/dist/commands/flake.js +311 -0
- package/dist/commands/flake.js.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/employee-standards.md +3 -5
- package/package.json +1 -1
- package/templates/e2e-command.md +1 -1
- package/dist/commands/visionCheck.d.ts +0 -35
- package/dist/commands/visionCheck.js +0 -351
- package/dist/commands/visionCheck.js.map +0 -1
- package/dist/utils/ollama.d.ts +0 -73
- package/dist/utils/ollama.js +0 -619
- package/dist/utils/ollama.js.map +0 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ openspec-pw init # Install Playwright E2E integration
|
|
|
20
20
|
|
|
21
21
|
## Supported AI Coding Assistants
|
|
22
22
|
|
|
23
|
-
**Claude Code** (Anthropic) — E2E workflow is driven by the `/opsx:e2e` command using a browser exploration tool (
|
|
23
|
+
**Claude Code** (Anthropic) — E2E workflow is driven by the `/opsx:e2e` command using a browser exploration tool (Playwright MCP or `openspec-pw explore`) + Playwright MCP (test execution).
|
|
24
24
|
|
|
25
25
|
**OpenCode** (SST) — E2E workflow is driven by the `/opsx-e2e` command (hyphenated per OpenSpec convention) using the same browser exploration + Playwright MCP stack. Playwright MCP is configured under `mcp.playwright` in `opencode.jsonc`.
|
|
26
26
|
|
|
@@ -47,6 +47,8 @@ openspec-pw init # Initialize integration (one-time setup; add --seed t
|
|
|
47
47
|
openspec-pw update # Update CLI and commands to latest version
|
|
48
48
|
openspec-pw doctor # Check prerequisites + app server diagnostics
|
|
49
49
|
openspec-pw audit # Audit tests for orphaned specs and issues
|
|
50
|
+
openspec-pw coverage # Analyze spec–test coverage for changes
|
|
51
|
+
openspec-pw flake # Detect static flake patterns in test files
|
|
50
52
|
openspec-pw migrate # Migrate old test files to new structure
|
|
51
53
|
openspec-pw explore # Explore routes in parallel with Playwright
|
|
52
54
|
openspec-pw run <name> # Execute E2E tests for a change
|
|
@@ -65,7 +67,7 @@ openspec-pw uninstall # Remove integration from the project
|
|
|
65
67
|
│
|
|
66
68
|
├── 3. Validate env → run seed.spec.ts
|
|
67
69
|
│
|
|
68
|
-
├── 4. Explore app → browser exploration (
|
|
70
|
+
├── 4. Explore app → browser exploration (Playwright MCP / `openspec-pw explore`)
|
|
69
71
|
│ ├─ Read app-knowledge.md (project-level knowledge)
|
|
70
72
|
│ ├─ Extract routes from specs
|
|
71
73
|
│ ├─ Navigate each route → snapshot → screenshot
|
|
@@ -98,9 +100,15 @@ openspec-pw uninstall # Remove integration from the project
|
|
|
98
100
|
- **Claude Code**: `claude mcp add playwright npx @playwright/mcp@latest`
|
|
99
101
|
- **OpenCode**: merged into `opencode.jsonc` under `mcp.playwright = { type: "local", command: ["npx", "@playwright/mcp@latest"] }`
|
|
100
102
|
|
|
101
|
-
**Optional** —
|
|
103
|
+
**Optional** — enhance your AI coding assistant with Superpowers methodology:
|
|
102
104
|
|
|
103
|
-
- **
|
|
105
|
+
- **Superpowers**: a complete development methodology plugin for Claude Code. It enhances the OpenSpec workflow (propose → apply → verify) with conversational spec exploration, TDD discipline, and subagent-driven implementation. Superpowers does **not** replace OpenSpec — the E2E verification pipeline (`/opsx:e2e`, `openspec-pw doctor/explore/run`) remains unchanged.
|
|
106
|
+
```bash
|
|
107
|
+
/plugin install superpowers@claude-plugins-official
|
|
108
|
+
```
|
|
109
|
+
See [github.com/obra/superpowers](https://github.com/obra/superpowers) for details.
|
|
110
|
+
|
|
111
|
+
Browser exploration is provided out of the box by Playwright MCP and `openspec-pw explore`; no extra browser tool is needed.
|
|
104
112
|
|
|
105
113
|
## What `openspec-pw init` Does
|
|
106
114
|
|
|
@@ -127,11 +135,11 @@ Run through these steps in order when using the E2E workflow for the first time:
|
|
|
127
135
|
| 8. Configure auth (if needed) | See "Authentication" below | Debug with `npx playwright test --project=setup` |
|
|
128
136
|
| 9. Run first E2E | `/opsx:e2e <change-name>` (Claude) or `/opsx-e2e <change-name>` (OpenCode) | Check `openspec/reports/` for the report |
|
|
129
137
|
|
|
130
|
-
**Optional —
|
|
138
|
+
**Optional — enhance your AI coding assistant with Superpowers methodology:**
|
|
131
139
|
|
|
132
140
|
| Step | Command | If it fails |
|
|
133
141
|
|------|---------|-------------|
|
|
134
|
-
| A. Install
|
|
142
|
+
| A. Install Superpowers | `/plugin install superpowers@claude-plugins-official` | See [github.com/obra/superpowers](https://github.com/obra/superpowers) for alternative install methods |
|
|
135
143
|
|
|
136
144
|
## App Server Detection
|
|
137
145
|
|
|
@@ -206,6 +214,7 @@ CLI (openspec-pw)
|
|
|
206
214
|
├── run → Executes E2E tests with server lifecycle
|
|
207
215
|
├── migrate → Migrates old test files to new structure
|
|
208
216
|
├── audit → Audits tests for orphaned specs and issues
|
|
217
|
+
├── flake → Detects static flake patterns in test files
|
|
209
218
|
├── doctor → Checks prerequisites
|
|
210
219
|
├── explore → Explores routes in parallel with Playwright
|
|
211
220
|
└── uninstall → Removes integration from the project
|
package/README.zh-CN.md
CHANGED
|
@@ -21,9 +21,15 @@ npm install -g openspec-playwright@latest
|
|
|
21
21
|
- **Claude Code**:`claude mcp add playwright npx @playwright/mcp@latest`
|
|
22
22
|
- **OpenCode**:合并到 `opencode.jsonc` 的 `mcp.playwright = { type: "local", command: ["npx", "@playwright/mcp@latest"] }`
|
|
23
23
|
|
|
24
|
-
**可选** —
|
|
24
|
+
**可选** — 用 Superpowers 增强 AI 编码助手的能力:
|
|
25
25
|
|
|
26
|
-
- **
|
|
26
|
+
- **Superpowers**:完整的 AI 编码助手开发方法论插件。它在 OpenSpec 工作流(propose → apply → verify)阶段增强 AI 能力:对话式 spec 探索、TDD 纪律、subagent 并行实现。Superpowers **不替换 OpenSpec**,E2E 验证管线(`/opsx:e2e`、`openspec-pw doctor/explore/run` 等)保持不变。
|
|
27
|
+
```bash
|
|
28
|
+
/plugin install superpowers@claude-plugins-official
|
|
29
|
+
```
|
|
30
|
+
详见 [github.com/obra/superpowers](https://github.com/obra/superpowers)
|
|
31
|
+
|
|
32
|
+
浏览器探索能力由 Playwright MCP 和 `openspec-pw explore` 内置提供,无需额外工具。
|
|
27
33
|
|
|
28
34
|
## 初始化
|
|
29
35
|
|
|
@@ -37,7 +43,7 @@ openspec-pw init # 安装 Playwright E2E 集成
|
|
|
37
43
|
|
|
38
44
|
## 支持的 AI 编码助手
|
|
39
45
|
|
|
40
|
-
**Claude Code**(Anthropic)— E2E 工作流由
|
|
46
|
+
**Claude Code**(Anthropic)— E2E 工作流由 `探索 + 测试执行` 两步组成:Playwright MCP + `openspec-pw explore`。
|
|
41
47
|
|
|
42
48
|
**OpenCode**(SST)— E2E 工作流由 `/opsx-e2e` 命令驱动(按 OpenSpec 惯例使用连字符),使用相同的浏览器探索 + Playwright MCP 技术栈。Playwright MCP 通过 `opencode.jsonc` 的 `mcp.playwright` 配置。
|
|
43
49
|
|
|
@@ -82,7 +88,7 @@ openspec-pw uninstall # 移除项目中的集成
|
|
|
82
88
|
│
|
|
83
89
|
├── 3. 验证环境 → 运行 seed.spec.ts
|
|
84
90
|
│
|
|
85
|
-
├── 4. 探索应用 → 浏览器探索(
|
|
91
|
+
├── 4. 探索应用 → 浏览器探索(Playwright MCP / `openspec-pw explore`)
|
|
86
92
|
│ ├─ 读取 app-knowledge.md(项目级知识)
|
|
87
93
|
│ ├─ 从 specs 提取路由
|
|
88
94
|
│ ├─ 遍历每个路由 → snapshot → screenshot
|
|
@@ -127,11 +133,11 @@ openspec-pw uninstall # 移除项目中的集成
|
|
|
127
133
|
| 8. 配置认证(如需要) | 见下方"认证配置" | `npx playwright test --project=setup` 调试 |
|
|
128
134
|
| 9. 运行第一个 E2E | `/opsx:e2e <change-name>`(Claude)或 `/opsx-e2e <change-name>`(OpenCode) | 查看 `openspec/reports/` 中的报告 |
|
|
129
135
|
|
|
130
|
-
**可选 —
|
|
136
|
+
**可选 — 用 Superpowers 增强 AI 编码助手:**
|
|
131
137
|
|
|
132
138
|
| 步骤 | 命令 | 失败时快速修复 |
|
|
133
139
|
|------|------|----------------|
|
|
134
|
-
| A. 安装
|
|
140
|
+
| A. 安装 Superpowers | `/plugin install superpowers@claude-plugins-official` | 详见 [github.com/obra/superpowers](https://github.com/obra/superpowers) |
|
|
135
141
|
|
|
136
142
|
## 认证配置
|
|
137
143
|
|
package/dist/commands/audit.js
CHANGED
|
@@ -167,9 +167,11 @@ async function getChangeNames(projectRoot) {
|
|
|
167
167
|
timeout: TIMEOUT.OPENSPEC_LIST,
|
|
168
168
|
});
|
|
169
169
|
const data = JSON.parse(result);
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
if (Array.isArray(data))
|
|
171
|
+
return data.map((c) => c.name);
|
|
172
|
+
if (data.changes && Array.isArray(data.changes))
|
|
173
|
+
return data.changes.map((c) => c.name);
|
|
174
|
+
return Object.keys(data);
|
|
173
175
|
}
|
|
174
176
|
catch {
|
|
175
177
|
return [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EACL,UAAU,EACV,WAAW,EACX,YAAY,GACb,MAAM,IAAI,CAAC;AACZ,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAQ5E,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,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,CAAC,gEAAgE,CAAC,CAC/E,CAAC;QACF,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC,CAAC;IAE7D,MAAM,OAAO,GAAkB,EAAE,CAAC;IAElC,wBAAwB;IACxB,MAAM,aAAa,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAC/C,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC;IACvC,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,+BAA+B;IAC/B,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;IAEtD,qCAAqC;IACrC,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE7C,0BAA0B;IAC1B,MAAM,YAAY,GAAG,iBAAiB,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAE5C,oBAAoB;QACpB,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAChD,IAAI,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS;QAEzC,sDAAsD;QACtD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACpD,+CAA+C;QAC/C,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBAChE,OAAO,CAAC,IAAI,CAAC;oBACX,QAAQ,EAAE,OAAO;oBACjB,KAAK,EAAE,oBAAoB;oBAC3B,MAAM,EAAE,qFAAqF,UAAU,GAAG;iBAC3G,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,8CAA8C;QAC9C,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACzD,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC7B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;gBACvC,IACE,QAAQ,KAAK,GAAG;oBAChB,SAAS,CAAC,MAAM,GAAG,CAAC;oBACpB,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC;oBAC7B,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAC9C,CAAC;oBACD,OAAO,CAAC,IAAI,CAAC;wBACX,QAAQ,EAAE,OAAO;wBACjB,KAAK,EAAE,sBAAsB;wBAC7B,MAAM,EAAE,cAAc,GAAG,EAAE;qBAC5B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAC7C,OAAO,CACL,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC3B,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;gBAC/B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;gBAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;gBACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAC/B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,SAAS,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC;YACX,QAAQ,EAAE,eAAe;YACzB,KAAK,EAAE,oBAAoB;YAC3B,MAAM,EACJ,iEAAiE;SACpE,CAAC,CAAC;IACL,CAAC;IAED,mDAAmD;IACnD,MAAM,aAAa,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAChD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CACtD,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC;YACX,QAAQ,EAAE,CAAC;YACX,KAAK,EAAE,yBAAyB;YAChC,MAAM,EAAE,mEAAmE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,GAAG;SACxG,CAAC,CAAC;IACL,CAAC;IAED,oBAAoB;IACpB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAC9D,CAAC;QACF,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,aAAa,OAAO,CAAC,MAAM,eAAe,CAAC,CACzD,CAAC;IAEF,sBAAsB;IACtB,MAAM,OAAO,GAAkC,EAAE,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAC7C,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC;QAC5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAClD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CACxC,CAAC;IACF,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QAC9D,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,2DAA2D,CAAC,CACzE,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;QACjE,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAC1E,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC;QACzE,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAChE,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC;AAED,gFAAgF;AAEhF,KAAK,UAAU,gBAAgB;IAI7B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,uBAAuB,CAAC;IAChE,MAAM,UAAU,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;QAC9E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,cAAc,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QACtF,YAAY,CAAC,SAAS,CAAC,CAAC;QAExB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO;gBACL,MAAM,EAAE,EAAE;gBACV,IAAI,EAAE,GAAG,OAAO,yBAAyB,QAAQ,CAAC,MAAM,gCAAgC;aACzF,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,sBAAsB,CAAC;QACxC,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,IAAI,KAAK,CAAC;QACV,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YAClE,IAAI,CAAC;gBACH,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YACxC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,UAAU;YACvB,CAAC,CAAC,iBAAkB,GAAa,CAAC,OAAO,EAAE;YAC3C,CAAC,CAAC,kCAAkC,OAAO,EAAE,CAAC;QAChD,OAAO;YACL,MAAM,EAAE,EAAE;YACV,IAAI,EAAE,0DAA0D,MAAM,GAAG;SAC1E,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,WAAmB;IAC/C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,UAAU;YACpF,GAAG,EAAE,WAAW;YAChB,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,OAAO,CAAC,aAAa;SAC/B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1E,IAAI,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1G,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW,EAAE,YAAsB,EAAE;IAC7D,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,+CAA+C;YAC/C,IACE,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAC3B,KAAK,CAAC,IAAI,KAAK,cAAc;gBAC7B,KAAK,CAAC,IAAI,KAAK,eAAe,EAC9B,CAAC;gBACD,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3C,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
interface CoverageChange {
|
|
2
|
+
name: string;
|
|
3
|
+
testCount: number;
|
|
4
|
+
specScenarioCount: number;
|
|
5
|
+
matchedScenarioCount: number;
|
|
6
|
+
coveragePct: number;
|
|
7
|
+
uncoveredScenarios: string[];
|
|
8
|
+
coveredRoutes: string[];
|
|
9
|
+
uncoveredRoutes: string[];
|
|
10
|
+
}
|
|
11
|
+
interface CoverageReport {
|
|
12
|
+
changes: CoverageChange[];
|
|
13
|
+
overallTestCount: number;
|
|
14
|
+
overallScenarioCount: number;
|
|
15
|
+
overallMatchedCount: number;
|
|
16
|
+
overallCoveragePct: number;
|
|
17
|
+
orphanedTests: string[];
|
|
18
|
+
recommendations: string[];
|
|
19
|
+
}
|
|
20
|
+
interface Scenario {
|
|
21
|
+
name: string;
|
|
22
|
+
tags: string[];
|
|
23
|
+
routes: string[];
|
|
24
|
+
file: string;
|
|
25
|
+
}
|
|
26
|
+
interface TestCase {
|
|
27
|
+
name: string;
|
|
28
|
+
tags: string[];
|
|
29
|
+
routes: string[];
|
|
30
|
+
file: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function coverage(changeName?: string, opts?: {
|
|
33
|
+
json?: boolean;
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
export declare function analyzeChange(name: string, projectRoot: string, testsDir: string, changesDir: string, _allTestFiles: string[]): CoverageChange;
|
|
36
|
+
export declare function computeOverall(changes: CoverageChange[], orphanedTests: string[], recommendations: string[]): CoverageReport;
|
|
37
|
+
export declare function parseScenarios(filePath: string): Scenario[];
|
|
38
|
+
export declare function parseTestCases(filePath: string): TestCase[];
|
|
39
|
+
export declare function extractKeywords(name: string): string[];
|
|
40
|
+
export declare function collectSpecFiles(dir: string, collected?: string[]): string[];
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
|
+
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { TIMEOUT, needsShell } from "../shared/index.js";
|
|
6
|
+
// ─── Main Entry Point ─────────────────────────────────────────────────
|
|
7
|
+
export async function coverage(changeName, opts) {
|
|
8
|
+
const projectRoot = process.cwd();
|
|
9
|
+
const testsDir = join(projectRoot, "tests", "playwright");
|
|
10
|
+
const changesDir = join(projectRoot, "openspec", "changes");
|
|
11
|
+
if (!existsSync(testsDir)) {
|
|
12
|
+
console.log(chalk.yellow(" tests/playwright/ not found. Run `openspec-pw init` first.\n"));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
console.log(chalk.blue("\n📊 OpenSpec Playwright: Coverage Analysis\n"));
|
|
16
|
+
// 1. Get all OpenSpec change names
|
|
17
|
+
const changeNames = await getChangeNames(projectRoot);
|
|
18
|
+
if (changeNames.length === 0) {
|
|
19
|
+
console.log(chalk.yellow(" No OpenSpec changes found. Run `openspec init` first.\n"));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
// Filter to single change if requested
|
|
23
|
+
const targetChanges = changeName
|
|
24
|
+
? changeNames.filter((n) => n === changeName)
|
|
25
|
+
: changeNames;
|
|
26
|
+
if (changeName && targetChanges.length === 0) {
|
|
27
|
+
console.log(chalk.yellow(` Change "${changeName}" not found.\n`));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// 2. Collect test files
|
|
31
|
+
const testFiles = collectTestFiles(testsDir);
|
|
32
|
+
// 3. Analyze each change
|
|
33
|
+
const changes = [];
|
|
34
|
+
const orphanedTests = [];
|
|
35
|
+
const allRecommendations = [];
|
|
36
|
+
for (const name of targetChanges) {
|
|
37
|
+
const change = analyzeChange(name, projectRoot, testsDir, changesDir, testFiles);
|
|
38
|
+
changes.push(change);
|
|
39
|
+
if (change.coveragePct === 0 && change.specScenarioCount > 0) {
|
|
40
|
+
allRecommendations.push(`Add tests for "${name}" (${change.specScenarioCount} scenarios uncovered)`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// 4. Detect orphaned tests (test file with no matching change)
|
|
44
|
+
for (const tf of testFiles) {
|
|
45
|
+
const rel = tf.replace(testsDir + "/", "");
|
|
46
|
+
const match = rel.match(/^changes\/([^/]+)\//);
|
|
47
|
+
if (match && !changeNames.includes(match[1])) {
|
|
48
|
+
orphanedTests.push(rel);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (orphanedTests.length > 0) {
|
|
52
|
+
allRecommendations.push(`${orphanedTests.length} orphaned test(s) — no matching OpenSpec change`);
|
|
53
|
+
}
|
|
54
|
+
// 5. Compute overall stats
|
|
55
|
+
const overall = computeOverall(changes, orphanedTests, allRecommendations);
|
|
56
|
+
// 6. Render
|
|
57
|
+
if (opts?.json) {
|
|
58
|
+
console.log(JSON.stringify(overall, null, 2));
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
renderReport(overall);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// ─── Analysis Functions ───────────────────────────────────────────────
|
|
65
|
+
export function analyzeChange(name, projectRoot, testsDir, changesDir, _allTestFiles) {
|
|
66
|
+
// Spec dir: openspec/changes/<name>/specs/
|
|
67
|
+
const specDir = join(changesDir, name, "specs");
|
|
68
|
+
// Test dir: tests/playwright/changes/<name>/
|
|
69
|
+
const changeTestDir = join(testsDir, "changes", name);
|
|
70
|
+
// Parse spec scenarios
|
|
71
|
+
const scenarios = [];
|
|
72
|
+
if (existsSync(specDir)) {
|
|
73
|
+
const specFiles = collectMarkdownFiles(specDir);
|
|
74
|
+
for (const sf of specFiles) {
|
|
75
|
+
scenarios.push(...parseScenarios(sf));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Parse test cases
|
|
79
|
+
const tests = [];
|
|
80
|
+
if (existsSync(changeTestDir)) {
|
|
81
|
+
const files = collectSpecFiles(changeTestDir);
|
|
82
|
+
for (const tf of files) {
|
|
83
|
+
tests.push(...parseTestCases(tf));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Route extraction
|
|
87
|
+
const specRoutes = extractRoutes(scenarios.map((s) => s.routes).flat());
|
|
88
|
+
const testRoutes = extractRoutes(tests.map((t) => t.routes).flat());
|
|
89
|
+
// L2 — Route match: spec routes covered by test routes
|
|
90
|
+
const coveredRoutes = specRoutes.filter((r) => testRoutes.some((tr) => tr === r || tr.startsWith(r)));
|
|
91
|
+
const uncoveredRoutes = specRoutes.filter((r) => !coveredRoutes.includes(r));
|
|
92
|
+
// L3 — Tag match
|
|
93
|
+
const testTags = new Set(tests.flatMap((t) => t.tags));
|
|
94
|
+
// L1+L3+L4+L5 — Scenario matching
|
|
95
|
+
let matchedCount = 0;
|
|
96
|
+
const uncoveredScenarios = [];
|
|
97
|
+
for (const sc of scenarios) {
|
|
98
|
+
// L3: tag match
|
|
99
|
+
const tagMatched = sc.tags.length > 0 && sc.tags.some((t) => testTags.has(t));
|
|
100
|
+
// L4: keyword match — extract key terms from scenario name
|
|
101
|
+
const scKeywords = extractKeywords(sc.name);
|
|
102
|
+
const keywordMatched = tests.some((t) => scKeywords.some((kw) => t.name.toLowerCase().includes(kw)));
|
|
103
|
+
// L5: name contains (or similar by overlap)
|
|
104
|
+
const nameMatched = tests.some((t) => t.name.toLowerCase().includes(sc.name.toLowerCase()) ||
|
|
105
|
+
sc.name.toLowerCase().includes(t.name.toLowerCase()));
|
|
106
|
+
if (tagMatched || keywordMatched || nameMatched) {
|
|
107
|
+
matchedCount++;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
uncoveredScenarios.push(sc.name);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const totalScenarios = scenarios.length || 1; // avoid div-by-zero
|
|
114
|
+
const pct = Math.round((matchedCount / totalScenarios) * 100);
|
|
115
|
+
return {
|
|
116
|
+
name,
|
|
117
|
+
testCount: tests.length,
|
|
118
|
+
specScenarioCount: scenarios.length,
|
|
119
|
+
matchedScenarioCount: matchedCount,
|
|
120
|
+
coveragePct: pct,
|
|
121
|
+
uncoveredScenarios,
|
|
122
|
+
coveredRoutes,
|
|
123
|
+
uncoveredRoutes,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
export function computeOverall(changes, orphanedTests, recommendations) {
|
|
127
|
+
const totalScenarios = changes.reduce((s, c) => s + c.specScenarioCount, 0);
|
|
128
|
+
const totalMatched = changes.reduce((s, c) => s + c.matchedScenarioCount, 0);
|
|
129
|
+
const totalTests = changes.reduce((s, c) => s + c.testCount, 0);
|
|
130
|
+
return {
|
|
131
|
+
changes,
|
|
132
|
+
overallTestCount: totalTests,
|
|
133
|
+
overallScenarioCount: totalScenarios,
|
|
134
|
+
overallMatchedCount: totalMatched,
|
|
135
|
+
overallCoveragePct: totalScenarios > 0
|
|
136
|
+
? Math.round((totalMatched / totalScenarios) * 100)
|
|
137
|
+
: 0,
|
|
138
|
+
orphanedTests,
|
|
139
|
+
recommendations,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// ─── Parsing Helpers ──────────────────────────────────────────────────
|
|
143
|
+
export function parseScenarios(filePath) {
|
|
144
|
+
const content = readFileSync(filePath, "utf-8");
|
|
145
|
+
const scenarios = [];
|
|
146
|
+
const lines = content.split("\n");
|
|
147
|
+
let currentScenario = null;
|
|
148
|
+
let descriptionLines = [];
|
|
149
|
+
for (const line of lines) {
|
|
150
|
+
const scenarioMatch = line.match(/^#### Scenario:\s*(.+)/);
|
|
151
|
+
if (scenarioMatch) {
|
|
152
|
+
if (currentScenario?.name) {
|
|
153
|
+
scenarios.push(buildScenario(currentScenario, descriptionLines));
|
|
154
|
+
}
|
|
155
|
+
// Capture inline tags, then strip from name
|
|
156
|
+
const rawName = scenarioMatch[1].trim();
|
|
157
|
+
const inlineTags = [...new Set((rawName.match(/@\w+/g) ?? []).map((t) => t.toLowerCase()))];
|
|
158
|
+
const cleanName = rawName.replace(/@\w+/g, "").replace(/\s{2,}/g, " ").trim();
|
|
159
|
+
currentScenario = { name: cleanName, tags: inlineTags, routes: [] };
|
|
160
|
+
descriptionLines = [];
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (currentScenario) {
|
|
164
|
+
descriptionLines.push(line);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (currentScenario?.name) {
|
|
168
|
+
scenarios.push(buildScenario(currentScenario, descriptionLines));
|
|
169
|
+
}
|
|
170
|
+
return scenarios;
|
|
171
|
+
}
|
|
172
|
+
function buildScenario(sc, descLines) {
|
|
173
|
+
const fullText = descLines.join(" ");
|
|
174
|
+
// Merge inline tags (already parsed) with description tags
|
|
175
|
+
const descTags = (fullText.match(/@\w+/g) ?? []).map((t) => t.toLowerCase());
|
|
176
|
+
const tags = [...new Set([...(sc.tags ?? []), ...descTags])];
|
|
177
|
+
// Extract routes
|
|
178
|
+
const routes = extractRoutesFromText(fullText);
|
|
179
|
+
return {
|
|
180
|
+
name: sc.name ?? "",
|
|
181
|
+
tags,
|
|
182
|
+
routes,
|
|
183
|
+
file: "",
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
export function parseTestCases(filePath) {
|
|
187
|
+
const content = readFileSync(filePath, "utf-8");
|
|
188
|
+
const tests = [];
|
|
189
|
+
const lines = content.split("\n");
|
|
190
|
+
for (const line of lines) {
|
|
191
|
+
// Match test('name', ...) or test("name", ...) or test(`name`, ...)
|
|
192
|
+
const match = line.match(/test\(['"`](.+)['"`]/);
|
|
193
|
+
if (match) {
|
|
194
|
+
const name = match[1].trim();
|
|
195
|
+
// Extract @tags
|
|
196
|
+
const tagMatches = name.match(/@\w+/g);
|
|
197
|
+
const tags = tagMatches ? [...new Set(tagMatches.map((t) => t.toLowerCase()))] : [];
|
|
198
|
+
// Extract routes from the line
|
|
199
|
+
const routes = extractRoutesFromText(name);
|
|
200
|
+
tests.push({ name, tags, routes, file: filePath });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return tests;
|
|
204
|
+
}
|
|
205
|
+
function extractRoutesFromText(text) {
|
|
206
|
+
const routes = [];
|
|
207
|
+
// Match goto('/path') or page.goto('/path')
|
|
208
|
+
const gotoPattern = /(?:page\s*\.\s*)?goto\s*\(\s*['"`](\/[^'"`]*)['"`]/g;
|
|
209
|
+
let m;
|
|
210
|
+
while ((m = gotoPattern.exec(text)) !== null) {
|
|
211
|
+
routes.push(m[1]);
|
|
212
|
+
}
|
|
213
|
+
// Also match bare paths like /login, /dashboard used in comments/specs
|
|
214
|
+
const pathPattern = /\b(\/[a-z][a-z0-9_\-/]*)/gi;
|
|
215
|
+
while ((m = pathPattern.exec(text)) !== null) {
|
|
216
|
+
const p = m[1];
|
|
217
|
+
if (!p.includes("//") && !p.includes(".") && p.split("/").length <= 4) {
|
|
218
|
+
routes.push(p);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return [...new Set(routes)];
|
|
222
|
+
}
|
|
223
|
+
function extractRoutes(routeList) {
|
|
224
|
+
return [...new Set(routeList)];
|
|
225
|
+
}
|
|
226
|
+
export function extractKeywords(name) {
|
|
227
|
+
// Extract meaningful words (≥3 chars, not common stop words)
|
|
228
|
+
const stopWords = new Set([
|
|
229
|
+
"the", "and", "for", "with", "from", "that", "this", "when",
|
|
230
|
+
"then", "user", "page", "test", "should", "can", "not",
|
|
231
|
+
]);
|
|
232
|
+
return name
|
|
233
|
+
.toLowerCase()
|
|
234
|
+
.split(/[\s\-_/]+/)
|
|
235
|
+
.filter((w) => w.length >= 3 && !stopWords.has(w));
|
|
236
|
+
}
|
|
237
|
+
// ─── File Collection ──────────────────────────────────────────────────
|
|
238
|
+
function collectTestFiles(dir, collected = []) {
|
|
239
|
+
return collectSpecFiles(dir, collected);
|
|
240
|
+
}
|
|
241
|
+
export function collectSpecFiles(dir, collected = []) {
|
|
242
|
+
if (!existsSync(dir))
|
|
243
|
+
return collected;
|
|
244
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
245
|
+
for (const entry of entries) {
|
|
246
|
+
const fullPath = join(dir, entry.name);
|
|
247
|
+
if (entry.isDirectory()) {
|
|
248
|
+
if (!entry.name.startsWith(".") &&
|
|
249
|
+
entry.name !== "node_modules" &&
|
|
250
|
+
entry.name !== "__snapshots__") {
|
|
251
|
+
collectSpecFiles(fullPath, collected);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
else if (entry.name.endsWith(".spec.ts")) {
|
|
255
|
+
collected.push(fullPath);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return collected;
|
|
259
|
+
}
|
|
260
|
+
function collectMarkdownFiles(dir, collected = []) {
|
|
261
|
+
if (!existsSync(dir))
|
|
262
|
+
return collected;
|
|
263
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
264
|
+
for (const entry of entries) {
|
|
265
|
+
const fullPath = join(dir, entry.name);
|
|
266
|
+
if (entry.isDirectory()) {
|
|
267
|
+
if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
268
|
+
collectMarkdownFiles(fullPath, collected);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else if (entry.name.endsWith(".md") && entry.name !== "test-plan.md") {
|
|
272
|
+
collected.push(fullPath);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return collected;
|
|
276
|
+
}
|
|
277
|
+
async function getChangeNames(projectRoot) {
|
|
278
|
+
try {
|
|
279
|
+
const result = execFileSync("npx", ["openspec", "list", "--json"], {
|
|
280
|
+
shell: needsShell,
|
|
281
|
+
cwd: projectRoot,
|
|
282
|
+
encoding: "utf-8",
|
|
283
|
+
timeout: TIMEOUT.OPENSPEC_LIST,
|
|
284
|
+
});
|
|
285
|
+
const data = JSON.parse(result);
|
|
286
|
+
if (Array.isArray(data))
|
|
287
|
+
return data.map((c) => c.name);
|
|
288
|
+
if (data.changes && Array.isArray(data.changes))
|
|
289
|
+
return data.changes.map((c) => c.name);
|
|
290
|
+
return Object.keys(data);
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// ─── Report Rendering ─────────────────────────────────────────────────
|
|
297
|
+
function renderReport(report) {
|
|
298
|
+
const { changes, overallCoveragePct, orphanedTests, recommendations } = report;
|
|
299
|
+
if (changes.length === 0) {
|
|
300
|
+
console.log(chalk.yellow(" No changes to analyze.\n"));
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
// Summary table (manually aligned for terminal)
|
|
304
|
+
const header = `${chalk.bold("Change".padEnd(24))} ${chalk.bold("Tests")} ${chalk.bold("Spec")} ${chalk.bold("Cov")}`;
|
|
305
|
+
const sep = "─".repeat(24) + " ───── ───── ─────";
|
|
306
|
+
console.log(` ${header}`);
|
|
307
|
+
console.log(` ${chalk.gray(sep)}`);
|
|
308
|
+
for (const c of changes) {
|
|
309
|
+
const name = c.name.padEnd(24);
|
|
310
|
+
const tests = String(c.testCount).padStart(3);
|
|
311
|
+
const specs = String(c.specScenarioCount).padStart(4);
|
|
312
|
+
const pct = formatPct(c.coveragePct);
|
|
313
|
+
console.log(` ${name} ${tests} ${specs} ${pct}`);
|
|
314
|
+
}
|
|
315
|
+
console.log();
|
|
316
|
+
// Overall
|
|
317
|
+
const overallColor = overallCoveragePct >= 80 ? chalk.green : overallCoveragePct >= 50 ? chalk.yellow : chalk.red;
|
|
318
|
+
console.log(` Overall coverage: ${overallColor(`${overallCoveragePct}%`)} (${report.overallMatchedCount}/${report.overallScenarioCount} scenarios)`);
|
|
319
|
+
console.log(` Total test cases: ${chalk.cyan(String(report.overallTestCount))}`);
|
|
320
|
+
console.log();
|
|
321
|
+
// Uncovered scenarios
|
|
322
|
+
const uncovered = changes.flatMap((c) => c.uncoveredScenarios.map((s) => ({ change: c.name, scenario: s })));
|
|
323
|
+
if (uncovered.length > 0) {
|
|
324
|
+
console.log(chalk.yellow(` 📋 Uncovered scenarios (${uncovered.length}):`));
|
|
325
|
+
for (const u of uncovered) {
|
|
326
|
+
console.log(chalk.gray(` ${u.change} → ${u.scenario}`));
|
|
327
|
+
}
|
|
328
|
+
console.log();
|
|
329
|
+
}
|
|
330
|
+
// Uncovered routes
|
|
331
|
+
const uncoveredRoutes = changes.flatMap((c) => c.uncoveredRoutes.map((r) => ({ change: c.name, route: r })));
|
|
332
|
+
if (uncoveredRoutes.length > 0) {
|
|
333
|
+
console.log(chalk.yellow(` 🛣️ Uncovered routes (${uncoveredRoutes.length}):`));
|
|
334
|
+
for (const u of uncoveredRoutes) {
|
|
335
|
+
console.log(chalk.gray(` ${u.change} → ${u.route}`));
|
|
336
|
+
}
|
|
337
|
+
console.log();
|
|
338
|
+
}
|
|
339
|
+
// Orphaned tests
|
|
340
|
+
if (orphanedTests.length > 0) {
|
|
341
|
+
console.log(chalk.red(` ⚠ Orphaned tests (${orphanedTests.length}):`));
|
|
342
|
+
for (const ot of orphanedTests) {
|
|
343
|
+
console.log(chalk.gray(` ${ot}`));
|
|
344
|
+
}
|
|
345
|
+
console.log();
|
|
346
|
+
}
|
|
347
|
+
// Recommendations
|
|
348
|
+
if (recommendations.length > 0) {
|
|
349
|
+
console.log(chalk.blue(" 💡 Recommendations:"));
|
|
350
|
+
for (const r of recommendations) {
|
|
351
|
+
console.log(chalk.gray(` • ${r}`));
|
|
352
|
+
}
|
|
353
|
+
console.log();
|
|
354
|
+
}
|
|
355
|
+
// Footer
|
|
356
|
+
if (uncovered.length === 0 && orphanedTests.length === 0) {
|
|
357
|
+
console.log(chalk.green(" ✅ Full coverage — all scenarios matched.\n"));
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function formatPct(pct) {
|
|
361
|
+
const s = `${pct}%`.padStart(4);
|
|
362
|
+
if (pct >= 80)
|
|
363
|
+
return chalk.green(s);
|
|
364
|
+
if (pct >= 50)
|
|
365
|
+
return chalk.yellow(s);
|
|
366
|
+
return chalk.red(s);
|
|
367
|
+
}
|
|
368
|
+
//# sourceMappingURL=coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../src/commands/coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface FlakeFinding {
|
|
2
|
+
pattern: string;
|
|
3
|
+
file: string;
|
|
4
|
+
line: number;
|
|
5
|
+
message: string;
|
|
6
|
+
severity: "high" | "medium";
|
|
7
|
+
}
|
|
8
|
+
export interface FlakeReport {
|
|
9
|
+
findings: FlakeFinding[];
|
|
10
|
+
patternCounts: Record<string, number>;
|
|
11
|
+
summaryText: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function flake(changeName?: string, options?: {
|
|
14
|
+
json?: boolean;
|
|
15
|
+
gate?: string;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
export declare function getConfigStorageState(projectRoot: string): boolean;
|
|
18
|
+
export declare function detectNetworkIdle(content: string, filePath: string): FlakeFinding[];
|
|
19
|
+
export declare function detectRouteAfterGoto(content: string, filePath: string): FlakeFinding[];
|
|
20
|
+
export declare function detectStorageLeakage(content: string, filePath: string, configHasStorageState: boolean): FlakeFinding[];
|
|
21
|
+
export declare function detectTestUseScope(content: string, filePath: string, configHasStorageState: boolean): FlakeFinding[];
|
|
22
|
+
export declare function buildReport(findings: FlakeFinding[]): FlakeReport;
|
|
23
|
+
export declare function computeGateExitCode(report: FlakeReport, gate: string): number;
|