openspec-playwright 0.1.60 → 0.1.62
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 +31 -3
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +27 -1
- package/dist/commands/update.js.map +1 -1
- package/employee-standards.md +13 -53
- package/openspec-playwright-0.1.62.tgz +0 -0
- package/package.json +1 -1
- package/release-notes.md +2 -2
- package/src/commands/update.ts +28 -1
- package/openspec-playwright-0.1.60.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.11"
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
## Input
|
|
@@ -32,6 +32,14 @@ Two modes, same pipeline:
|
|
|
32
32
|
|
|
33
33
|
Both modes update `app-knowledge.md` and `app-exploration.md`. All `.spec.ts` files run together as regression suite.
|
|
34
34
|
|
|
35
|
+
**Role mapping** (Playwright Test Agents terminology):
|
|
36
|
+
|
|
37
|
+
| Role | This SKILL | What it does |
|
|
38
|
+
|------|-----------|--------------|
|
|
39
|
+
| Planner | Step 4–5 | Explores app via Playwright MCP → produces test-plan.md |
|
|
40
|
+
| Generator | Step 6 | Transforms test-plan.md → `.spec.ts` with verified selectors |
|
|
41
|
+
| Healer | Step 9 | Executes tests, repairs failures via Playwright MCP |
|
|
42
|
+
|
|
35
43
|
## Testing principles
|
|
36
44
|
|
|
37
45
|
**UI first** — Test every user flow through the browser UI. E2E validates that users can accomplish tasks in the real interface, not just that the backend responds correctly.
|
|
@@ -98,7 +106,7 @@ Run the seed test before generating tests:
|
|
|
98
106
|
npx playwright test tests/playwright/seed.spec.ts --project=chromium
|
|
99
107
|
```
|
|
100
108
|
|
|
101
|
-
|
|
109
|
+
Seed test initializes the `page` context — it runs all fixtures, hooks, and globalSetup. Not just a smoke check: it also validates that auth setup, BASE_URL, and Playwright are fully functional.
|
|
102
110
|
|
|
103
111
|
**If seed test fails**: Stop and report. Fix the environment before proceeding.
|
|
104
112
|
|
|
@@ -219,6 +227,8 @@ Read `tests/playwright/app-knowledge.md` as context for cross-change patterns.
|
|
|
219
227
|
|
|
220
228
|
> **"all" mode: skip this step — go directly to Step 6.**
|
|
221
229
|
|
|
230
|
+
**Change mode — prerequisite**: If `openspec/changes/<name>/specs/playwright/app-exploration.md` does not exist → **STOP**. Run Step 4 (explore application) before generating tests. Without real DOM data from exploration, selectors are guesses and tests will be fragile.
|
|
231
|
+
|
|
222
232
|
**Change mode**: Create `openspec/changes/<name>/specs/playwright/test-plan.md`.
|
|
223
233
|
|
|
224
234
|
**Read inputs**: specs, app-exploration.md, app-knowledge.md
|
|
@@ -247,6 +257,8 @@ Template: `openspec/schemas/playwright-e2e/templates/test-plan.md`
|
|
|
247
257
|
4. Write test code with verified selectors
|
|
248
258
|
5. If selector unverifiable → note for Healer (Step 9)
|
|
249
259
|
|
|
260
|
+
**Test coverage — empty states**: For list/detail pages, explore the empty state. If the app shows a "no data" UI when the list is empty, generate a test to verify it. Empty states are often missing from specs but are real user paths.
|
|
261
|
+
|
|
250
262
|
**Output format**:
|
|
251
263
|
- Follow `seed.spec.ts` structure
|
|
252
264
|
- Use `test.describe(...)` for grouping
|
|
@@ -299,6 +311,21 @@ test('unauthenticated user redirected to login', async ({ browser }) => {
|
|
|
299
311
|
await freshPage.goto(`${BASE_URL}/dashboard`);
|
|
300
312
|
await expect(freshPage).toHaveURL(/login|auth/);
|
|
301
313
|
});
|
|
314
|
+
// ✅ Session — logout clears protected state
|
|
315
|
+
await page.getByRole('button', { name: '退出登录' }).click();
|
|
316
|
+
await expect(page).toHaveURL(/login|auth/);
|
|
317
|
+
const freshPage2 = await browser.newContext().newPage();
|
|
318
|
+
await freshPage2.goto(`${BASE_URL}/dashboard`);
|
|
319
|
+
await expect(freshPage2).toHaveURL(/login|auth/); // session revoked
|
|
320
|
+
|
|
321
|
+
// ✅ Browser history — SPA back/forward navigation
|
|
322
|
+
await page.goto(`${BASE_URL}/list`);
|
|
323
|
+
await page.getByRole('link', { name: '详情' }).first().click();
|
|
324
|
+
await expect(page).toHaveURL(/detail/);
|
|
325
|
+
await page.goBack();
|
|
326
|
+
await expect(page).toHaveURL(/list/);
|
|
327
|
+
await page.goForward();
|
|
328
|
+
await expect(page).toHaveURL(/detail/);
|
|
302
329
|
|
|
303
330
|
// ✅ File uploads — UI 操作
|
|
304
331
|
await page.locator('input[type="file"]').setInputFiles('/path/to/file.pdf');
|
|
@@ -415,7 +442,8 @@ Reference: `openspec/schemas/playwright-e2e/templates/report.md`
|
|
|
415
442
|
| Sitemap discovery fails ("all" mode) | Continue — use homepage links + common paths fallback |
|
|
416
443
|
| App has JS errors or HTTP 5xx during exploration | **STOP** — see app-knowledge.md → Architecture for restart instructions |
|
|
417
444
|
| app-all.spec.ts exists | Read and use (never regenerate — regression baseline) |
|
|
418
|
-
| app-exploration.md
|
|
445
|
+
| app-exploration.md missing (change mode) | **STOP** — Step 4 exploration is mandatory. Explore before generating tests. |
|
|
446
|
+
| app-exploration.md exists | Read and use (verify routes still match specs — re-explore if page structure changed) |
|
|
419
447
|
| app-knowledge.md exists | Read and use (append new patterns only) |
|
|
420
448
|
| test-plan.md exists (change mode) | Read and use (never regenerate) |
|
|
421
449
|
| auth.setup.ts exists | Verify format (update only if stale) |
|
package/dist/commands/update.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { execSync, exec } from 'child_process';
|
|
2
2
|
import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, readdirSync, statSync, } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
|
-
import { tmpdir } from 'os';
|
|
4
|
+
import { tmpdir, homedir } from 'os';
|
|
5
5
|
import { promisify } from 'util';
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
7
|
import chalk from 'chalk';
|
|
@@ -87,6 +87,32 @@ export async function update(options) {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
+
// 2b. Install Playwright MCP if not present (Claude Code only)
|
|
91
|
+
if (options.mcp !== false && existsSync(join(projectRoot, '.claude'))) {
|
|
92
|
+
console.log(chalk.blue('\n─── Installing Playwright MCP ───'));
|
|
93
|
+
const claudeJsonPath = join(homedir(), '.claude.json');
|
|
94
|
+
const claudeJson = existsSync(claudeJsonPath) ? JSON.parse(readFileSync(claudeJsonPath, 'utf-8')) : {};
|
|
95
|
+
const globalMcp = claudeJson?.mcpServers ?? {};
|
|
96
|
+
const localMcp = claudeJson?.projects?.[projectRoot]?.mcpServers ?? {};
|
|
97
|
+
if (globalMcp['playwright'] || localMcp['playwright']) {
|
|
98
|
+
console.log(chalk.green(' ✓ Playwright MCP already installed'));
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
try {
|
|
102
|
+
execSync('claude mcp add playwright npx @playwright/mcp@latest', {
|
|
103
|
+
cwd: projectRoot,
|
|
104
|
+
stdio: 'inherit',
|
|
105
|
+
});
|
|
106
|
+
console.log(chalk.green(' ✓ Playwright MCP installed globally'));
|
|
107
|
+
console.log(chalk.gray(' (Restart Claude Code to activate)'));
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
console.log(chalk.yellow(' ⚠ Failed to install Playwright MCP'));
|
|
111
|
+
console.log(chalk.gray(' Run manually: claude mcp add playwright npx @playwright/mcp@latest'));
|
|
112
|
+
console.log(chalk.gray(' (Restart Claude Code to activate the MCP server)'));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
90
116
|
// 3. Sync Healer tools (Claude Code only)
|
|
91
117
|
if (existsSync(join(projectRoot, '.claude', 'skills', 'openspec-e2e', 'SKILL.md'))) {
|
|
92
118
|
console.log(chalk.blue('\n─── Syncing Healer Tools ───'));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,UAAU,EACjB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,MAAM,EACN,WAAW,EACX,QAAQ,GACT,MAAM,IAAI,CAAC;AACZ,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
|
package/employee-standards.md
CHANGED
|
@@ -1,84 +1,44 @@
|
|
|
1
1
|
# Claude Code Employee-Grade Configuration
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
3
|
+
> 员工级行为规范,适用于 OpenSpec 项目。
|
|
4
|
+
> 遵循 OpenSpec 规范驱动开发流程(详见 /openspec/)。
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
## 一、代码质量
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
**验证后才能报告成功**。运行项目的 linter 和 type checker:查看 `package.json`/`pyproject.toml`/`go.mod`/`Cargo.toml` 中的 scripts,使用对应的 `lint`/`typecheck` 命令。不存在时,明确告知用户,不得假装成功。
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
**拒绝'够用就行'**。架构缺陷、状态重复、模式不一致——说出来并修复。高级工程师在 code review 中会拒绝什么?全部修掉。
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
npx tsc --noEmit && npx eslint . --quiet
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
如项目无类型检查,明确告知用户,不得假装成功。
|
|
19
|
-
|
|
20
|
-
### 高级工程师标准
|
|
21
|
-
|
|
22
|
-
不接受"最简单方案"和"不超出需求"作为偷懒的借口。如果架构有缺陷、状态重复、模式不一致——说出来并修复。问自己:**高级工程师在 code review 中会拒绝什么?** 把那些全部修掉。
|
|
14
|
+
**安全防护**:防范 XSS、SQL 注入、命令注入(OWASP Top 10)。
|
|
23
15
|
|
|
24
16
|
---
|
|
25
17
|
|
|
26
18
|
## 二、上下文管理
|
|
27
19
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
任何结构性重构(>300 LOC)之前,先删除所有死代码(未使用 import/export/prop/console.log)。单独提交清理,再做重构。
|
|
31
|
-
死代码会提前消耗 token budget,触发 auto-compaction——每次失败会浪费大量 API 调用。保持代码干净直接节省成本。
|
|
20
|
+
**文件读取完整**:超过 500 行的文件,不要假设单次读取覆盖了完整文件——根据需要分次读取相关段落,或编辑前重新读取完整文件。超过 10 条消息后,编辑任何文件前强制重新读取。
|
|
32
21
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
超过 500 行的文件,不要假设单次读取覆盖了完整文件。根据需要分次读取相关段落,或编辑前重新读取完整文件以确保上下文最新。
|
|
36
|
-
|
|
37
|
-
### 上下文衰减
|
|
38
|
-
|
|
39
|
-
超过 10 条消息后,编辑任何文件前必须重新读取。
|
|
22
|
+
**重构前清死代码**:未使用的 import/export/prop/console.log 先删掉,单独提交,再做重构。
|
|
40
23
|
|
|
41
24
|
---
|
|
42
25
|
|
|
43
|
-
##
|
|
44
|
-
|
|
45
|
-
### 子 Agent 并行化
|
|
26
|
+
## 三,大规模任务
|
|
46
27
|
|
|
47
|
-
|
|
28
|
+
**子 Agent 并行化**:任务涉及超过 5 个独立文件时,启动并行子 agent(每个 5-8 个文件),每个拥有独立 token budget。
|
|
48
29
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
不要在单次响应中完成多文件重构。每个阶段不超过 5 个文件,完成后验证,等待用户批准再继续。
|
|
30
|
+
**分阶段执行**:每个阶段不超过 5 个文件,完成后验证,等待用户批准再继续。
|
|
52
31
|
|
|
53
32
|
---
|
|
54
33
|
|
|
55
34
|
## 四、工具限制
|
|
56
35
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
搜索结果异常少时,用更窄范围重新运行。怀疑截断时告知用户。
|
|
60
|
-
|
|
61
|
-
### Grep 不是 AST
|
|
62
|
-
|
|
63
|
-
重命名函数/类型/变量时,必须分开搜索:
|
|
64
|
-
|
|
65
|
-
- 直接调用和引用
|
|
66
|
-
- 类型级引用(interface、泛型)
|
|
67
|
-
- 字符串字面量(动态引用)
|
|
68
|
-
- `require()` / `import`
|
|
69
|
-
- barrel file 和 re-export
|
|
70
|
-
- 测试文件和 mock
|
|
71
|
-
|
|
72
|
-
不得假设一次 grep 覆盖所有情况。
|
|
36
|
+
**搜索维度完整**:重命名函数/类型/变量时,必须覆盖:直接调用、类型级引用、字符串字面量、`require()`/`import`、barrel file、测试 mock。不得假设一次 grep 覆盖所有情况。
|
|
73
37
|
|
|
74
38
|
---
|
|
75
39
|
|
|
76
40
|
## 五、编辑安全
|
|
77
41
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
每次编辑前重新读取文件,编辑后再次读取确认变更正确应用。同一文件连续编辑不超过 3 次,中间必须验证读取。
|
|
81
|
-
|
|
82
|
-
### 变更完整性
|
|
42
|
+
**验证后才算完成**:编辑后再次读取确认变更正确应用。同一文件连续编辑不超过 3 次,中间必须验证。变更完成后,明确告知用户可能遗漏的区域(动态引用、测试 mock 等),提示人工复查。
|
|
83
43
|
|
|
84
|
-
|
|
44
|
+
**不主动推送**:除非用户明确要求,否则不推送代码。
|
|
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 to 0.1.62
|
|
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.62
|
package/src/commands/update.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { existsSync,
|
|
|
8
8
|
statSync,
|
|
9
9
|
} from 'fs';
|
|
10
10
|
import { join } from 'path';
|
|
11
|
-
import { tmpdir } from 'os';
|
|
11
|
+
import { tmpdir, homedir } from 'os';
|
|
12
12
|
import { promisify } from 'util';
|
|
13
13
|
import { fileURLToPath } from 'url';
|
|
14
14
|
import chalk from 'chalk';
|
|
@@ -22,6 +22,7 @@ const SCHEMA_DIR = fileURLToPath(new URL('../../schemas', import.meta.url));
|
|
|
22
22
|
export interface UpdateOptions {
|
|
23
23
|
cli?: boolean;
|
|
24
24
|
skill?: boolean;
|
|
25
|
+
mcp?: boolean;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export async function update(options: UpdateOptions) {
|
|
@@ -118,6 +119,32 @@ export async function update(options: UpdateOptions) {
|
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
// 2b. Install Playwright MCP if not present (Claude Code only)
|
|
123
|
+
if (options.mcp !== false && existsSync(join(projectRoot, '.claude'))) {
|
|
124
|
+
console.log(chalk.blue('\n─── Installing Playwright MCP ───'));
|
|
125
|
+
const claudeJsonPath = join(homedir(), '.claude.json');
|
|
126
|
+
const claudeJson = existsSync(claudeJsonPath) ? JSON.parse(readFileSync(claudeJsonPath, 'utf-8')) : {};
|
|
127
|
+
const globalMcp = claudeJson?.mcpServers ?? {};
|
|
128
|
+
const localMcp = claudeJson?.projects?.[projectRoot]?.mcpServers ?? {};
|
|
129
|
+
|
|
130
|
+
if (globalMcp['playwright'] || localMcp['playwright']) {
|
|
131
|
+
console.log(chalk.green(' ✓ Playwright MCP already installed'));
|
|
132
|
+
} else {
|
|
133
|
+
try {
|
|
134
|
+
execSync('claude mcp add playwright npx @playwright/mcp@latest', {
|
|
135
|
+
cwd: projectRoot,
|
|
136
|
+
stdio: 'inherit',
|
|
137
|
+
});
|
|
138
|
+
console.log(chalk.green(' ✓ Playwright MCP installed globally'));
|
|
139
|
+
console.log(chalk.gray(' (Restart Claude Code to activate)'));
|
|
140
|
+
} catch {
|
|
141
|
+
console.log(chalk.yellow(' ⚠ Failed to install Playwright MCP'));
|
|
142
|
+
console.log(chalk.gray(' Run manually: claude mcp add playwright npx @playwright/mcp@latest'));
|
|
143
|
+
console.log(chalk.gray(' (Restart Claude Code to activate the MCP server)'));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
121
148
|
// 3. Sync Healer tools (Claude Code only)
|
|
122
149
|
if (existsSync(join(projectRoot, '.claude', 'skills', 'openspec-e2e', 'SKILL.md'))) {
|
|
123
150
|
console.log(chalk.blue('\n─── Syncing Healer Tools ───'));
|
|
Binary file
|