openspec-playwright 0.1.62 → 0.1.64
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/commands/CLAUDE.md +12 -0
- package/.claude/commands/opsx/CLAUDE.md +12 -0
- package/.claude/commands/opsx/e2e-body.md +5 -0
- package/.claude/commands/opsx/e2e.md +5 -1
- package/.claude/skills/CLAUDE.md +12 -0
- package/.claude/skills/openspec-e2e/CLAUDE.md +14 -0
- package/.claude/skills/openspec-e2e/SKILL.md +101 -77
- package/LICENSE +21 -0
- package/README.md +4 -3
- package/README.zh-CN.md +4 -3
- package/bin/CLAUDE.md +11 -0
- package/dist/CLAUDE.md +17 -0
- package/dist/commands/doctor.d.ts +4 -1
- package/dist/commands/doctor.js +110 -73
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/editors.js +149 -95
- package/dist/commands/editors.js.map +1 -1
- package/dist/commands/init.js +105 -97
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcpSync.js +46 -31
- package/dist/commands/mcpSync.js.map +1 -1
- package/dist/commands/run.d.ts +13 -0
- package/dist/commands/run.js +74 -51
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/uninstall.d.ts +1 -0
- package/dist/commands/uninstall.js +133 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.js +79 -68
- package/dist/commands/update.js.map +1 -1
- package/dist/index.js +33 -26
- package/dist/index.js.map +1 -1
- package/employee-standards.md +3 -3
- package/package.json +21 -1
- package/schemas/playwright-e2e/templates/playwright.config.ts +22 -22
- package/templates/CLAUDE.md +15 -0
- package/templates/seed.spec.ts +5 -3
- package/.github/workflows/release.yml +0 -81
- package/docs/plans/2026-03-26-openspec-playwright-design.md +0 -180
- package/openspec/schemas/playwright-e2e/schema.yaml +0 -56
- package/openspec/schemas/playwright-e2e/templates/e2e-test.ts +0 -55
- package/openspec/schemas/playwright-e2e/templates/playwright.config.ts +0 -52
- package/openspec/schemas/playwright-e2e/templates/report.md +0 -27
- package/openspec/schemas/playwright-e2e/templates/test-plan.md +0 -24
- package/openspec-playwright-0.1.62.tgz +0 -0
- package/release-notes.md +0 -5
- package/src/commands/doctor.ts +0 -115
- package/src/commands/editors.ts +0 -606
- package/src/commands/init.ts +0 -252
- package/src/commands/mcpSync.ts +0 -160
- package/src/commands/run.ts +0 -172
- package/src/commands/update.ts +0 -192
- package/src/index.ts +0 -47
- package/tests/editors.test.ts +0 -180
- package/tsconfig.json +0 -18
- package/vitest.config.ts +0 -9
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,40 +1,47 @@
|
|
|
1
|
-
import { readFileSync } from
|
|
2
|
-
import { join, dirname } from
|
|
3
|
-
import { fileURLToPath } from
|
|
4
|
-
import { Command } from
|
|
5
|
-
import { init } from
|
|
6
|
-
import { update } from
|
|
7
|
-
import { doctor } from
|
|
8
|
-
import { run } from
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { join, dirname } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import { init } from "./commands/init.js";
|
|
6
|
+
import { update } from "./commands/update.js";
|
|
7
|
+
import { doctor } from "./commands/doctor.js";
|
|
8
|
+
import { run } from "./commands/run.js";
|
|
9
|
+
import { uninstall } from "./commands/uninstall.js";
|
|
9
10
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
-
const pkg = JSON.parse(readFileSync(join(__dirname,
|
|
11
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
|
|
11
12
|
const program = new Command();
|
|
12
13
|
program
|
|
13
|
-
.name(
|
|
14
|
-
.description(
|
|
14
|
+
.name("openspec-pw")
|
|
15
|
+
.description("OpenSpec + Playwright E2E verification setup tool")
|
|
15
16
|
.version(pkg.version);
|
|
16
17
|
program
|
|
17
|
-
.command(
|
|
18
|
-
.description(
|
|
19
|
-
.option(
|
|
20
|
-
.option(
|
|
21
|
-
.option(
|
|
18
|
+
.command("init")
|
|
19
|
+
.description("Initialize OpenSpec + Playwright E2E integration in the current project")
|
|
20
|
+
.option("-c, --change <name>", "default change name", "default")
|
|
21
|
+
.option("--no-mcp", "skip Playwright MCP configuration")
|
|
22
|
+
.option("--no-seed", "skip seed test generation")
|
|
22
23
|
.action(init);
|
|
23
24
|
program
|
|
24
|
-
.command(
|
|
25
|
-
.description(
|
|
25
|
+
.command("doctor")
|
|
26
|
+
.description("Check if all prerequisites are installed")
|
|
27
|
+
.option("--json", "Output results as JSON")
|
|
26
28
|
.action(doctor);
|
|
27
29
|
program
|
|
28
|
-
.command(
|
|
29
|
-
.description(
|
|
30
|
-
.option(
|
|
31
|
-
.option(
|
|
30
|
+
.command("update")
|
|
31
|
+
.description("Update the CLI tool and skill to the latest version")
|
|
32
|
+
.option("--no-cli", "skip CLI update")
|
|
33
|
+
.option("--no-skill", "skip skill/command update")
|
|
32
34
|
.action(update);
|
|
33
35
|
program
|
|
34
|
-
.command(
|
|
35
|
-
.description(
|
|
36
|
-
.option(
|
|
37
|
-
.option(
|
|
36
|
+
.command("run <change-name>")
|
|
37
|
+
.description("Run Playwright E2E tests for an OpenSpec change")
|
|
38
|
+
.option("-p, --project <name>", "Playwright project to run (e.g., user, admin)")
|
|
39
|
+
.option("-t, --timeout <seconds>", "Test timeout in seconds", "300")
|
|
40
|
+
.option("--json", "Output results as JSON")
|
|
38
41
|
.action(run);
|
|
42
|
+
program
|
|
43
|
+
.command("uninstall")
|
|
44
|
+
.description("Remove OpenSpec + Playwright E2E integration from the current project")
|
|
45
|
+
.action(uninstall);
|
|
39
46
|
program.parse();
|
|
40
47
|
//# sourceMappingURL=index.js.map
|
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;
|
|
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,WAAW,EAAE,2BAA2B,CAAC;KAChD,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"}
|
package/employee-standards.md
CHANGED
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
|
|
8
8
|
## 一、代码质量
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
**验证后才算成功**。动手前,先探索项目用什么工具:查看 `package.json` scripts、`Makefile`、`pyproject.toml`、`justfile` 等,找到该语言的 lint + type check 命令并执行。工具不存在时,明确告知用户,不得假装成功。
|
|
11
11
|
|
|
12
|
-
**拒绝'够用就行'
|
|
12
|
+
**拒绝'够用就行'**。架构缺陷、状态重复、模式不一致——说出来并修复。
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
**安全防护因语言/场景而异**。写 Go 时想内存安全,写 Python 时想反序列化,写 Web 时参考 [OWASP Top 10](https://owasp.org/Top10/),写 API 时参考 [OWASP API Top 10](https://owasp.org/API-Security/)。先了解所用场景的风险模型。
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openspec-playwright",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.64",
|
|
4
4
|
"description": "OpenSpec + Playwright E2E verification setup tool for Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,8 +8,13 @@
|
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "tsc",
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"lint": "eslint src/ tests/",
|
|
13
|
+
"lint:fix": "eslint src/ tests/ --fix",
|
|
14
|
+
"format": "prettier --write src/ tests/",
|
|
11
15
|
"test": "vitest",
|
|
12
16
|
"test:run": "vitest run",
|
|
17
|
+
"test:smoke": "npm run build && vitest run tests/smoke.test.ts",
|
|
13
18
|
"prepublishOnly": "npm run build",
|
|
14
19
|
"release": "npm version patch && npm run build && git push && git push --tags && npm publish"
|
|
15
20
|
},
|
|
@@ -21,12 +26,27 @@
|
|
|
21
26
|
},
|
|
22
27
|
"devDependencies": {
|
|
23
28
|
"@types/node": "^22.0.0",
|
|
29
|
+
"@typescript-eslint/eslint-plugin": "^8.58.0",
|
|
30
|
+
"@typescript-eslint/parser": "^8.58.0",
|
|
31
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
32
|
+
"eslint": "^10.1.0",
|
|
33
|
+
"prettier": "^3.8.1",
|
|
24
34
|
"typescript": "^5.6.0",
|
|
25
35
|
"vitest": "^4.1.2"
|
|
26
36
|
},
|
|
27
37
|
"engines": {
|
|
28
38
|
"node": ">=20"
|
|
29
39
|
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"bin",
|
|
43
|
+
"templates",
|
|
44
|
+
"schemas",
|
|
45
|
+
".claude",
|
|
46
|
+
"employee-standards.md",
|
|
47
|
+
"README.md",
|
|
48
|
+
"README.zh-CN.md"
|
|
49
|
+
],
|
|
30
50
|
"keywords": [
|
|
31
51
|
"openspec",
|
|
32
52
|
"playwright",
|
|
@@ -15,30 +15,30 @@ function findProjectRoot(start: string): string {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
// ─── Find the npm project root (where package.json with scripts lives) ───
|
|
18
|
-
//
|
|
19
|
-
function findNpmRoot(projectRoot: string): string {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
const entries = readdirSync(projectRoot, { withFileTypes: true });
|
|
30
|
-
for (const entry of entries) {
|
|
31
|
-
if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'node_modules') continue;
|
|
32
|
-
const subPkg = join(projectRoot, entry.name, 'package.json');
|
|
33
|
-
if (existsSync(subPkg)) {
|
|
34
|
-
const sub = JSON.parse(readFileSync(subPkg, 'utf-8'));
|
|
35
|
-
if (sub.scripts?.dev || sub.scripts?.start) {
|
|
36
|
-
return join(projectRoot, entry.name);
|
|
18
|
+
// Searches recursively up to maxDepth levels to support nested monorepos
|
|
19
|
+
function findNpmRoot(projectRoot: string, maxDepth = 5): string {
|
|
20
|
+
function search(dir: string, depth: number): string | null {
|
|
21
|
+
if (depth > maxDepth) return null;
|
|
22
|
+
const pkgPath = join(dir, 'package.json');
|
|
23
|
+
if (existsSync(pkgPath)) {
|
|
24
|
+
try {
|
|
25
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
26
|
+
if (pkg.scripts?.dev || pkg.scripts?.start || pkg.scripts?.serve || pkg.scripts?.preview) {
|
|
27
|
+
return dir;
|
|
37
28
|
}
|
|
38
|
-
}
|
|
29
|
+
} catch {}
|
|
39
30
|
}
|
|
40
|
-
|
|
41
|
-
|
|
31
|
+
try {
|
|
32
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
33
|
+
for (const entry of entries) {
|
|
34
|
+
if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'node_modules') continue;
|
|
35
|
+
const found = search(join(dir, entry.name), depth + 1);
|
|
36
|
+
if (found) return found;
|
|
37
|
+
}
|
|
38
|
+
} catch {}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return search(projectRoot, 0) ?? projectRoot;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
const projectRoot = findProjectRoot(__dirname);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<claude-mem-context>
|
|
2
|
+
# Recent Activity
|
|
3
|
+
|
|
4
|
+
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
|
|
5
|
+
|
|
6
|
+
### Mar 27, 2026
|
|
7
|
+
|
|
8
|
+
| ID | Time | T | Title | Read |
|
|
9
|
+
|----|------|---|-------|------|
|
|
10
|
+
| #5522 | 11:25 AM | 🔵 | Playwright auth setup template supports API and UI login | ~261 |
|
|
11
|
+
| #5514 | 11:22 AM | 🟣 | Created credentials.yaml template for E2E test authentication | ~227 |
|
|
12
|
+
| #5513 | " | 🟣 | Created auth.setup.ts template for Playwright Test Agents | ~276 |
|
|
13
|
+
| #5390 | 9:48 AM | 🔄 | Refactored openspec-playwright from CLI to setup tool + Claude Code skill | ~209 |
|
|
14
|
+
| #5375 | 9:44 AM | 🟣 | Created Playwright seed test template | ~224 |
|
|
15
|
+
</claude-mem-context>
|
package/templates/seed.spec.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copy this to tests/playwright/seed.spec.ts after running openspec-pw init
|
|
3
3
|
// Customize the page object and base URL for your application
|
|
4
4
|
|
|
5
|
-
import { test, expect, Page } from '@playwright/test';
|
|
5
|
+
import { test, expect, Page, ConsoleMessage } from '@playwright/test';
|
|
6
6
|
import { existsSync } from 'fs';
|
|
7
7
|
|
|
8
8
|
// Customize these for your application
|
|
@@ -49,11 +49,13 @@ test.describe('Application smoke tests', () => {
|
|
|
49
49
|
|
|
50
50
|
test('no console errors', async ({ page }) => {
|
|
51
51
|
const errors: string[] = [];
|
|
52
|
-
|
|
52
|
+
const handler = (msg: ConsoleMessage) => {
|
|
53
53
|
if (msg.type() === 'error') {
|
|
54
54
|
errors.push(msg.text());
|
|
55
55
|
}
|
|
56
|
-
}
|
|
56
|
+
};
|
|
57
|
+
page.on('console', handler);
|
|
58
|
+
test.afterEach(() => page.off('console', handler));
|
|
57
59
|
await page.reload();
|
|
58
60
|
await page.waitForLoadState('networkidle');
|
|
59
61
|
// Filter out known non-critical errors
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
name: Release
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*'
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
release:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
permissions:
|
|
12
|
-
contents: write
|
|
13
|
-
|
|
14
|
-
steps:
|
|
15
|
-
- name: Checkout
|
|
16
|
-
uses: actions/checkout@v4
|
|
17
|
-
|
|
18
|
-
- name: Setup Node.js
|
|
19
|
-
uses: actions/setup-node@v4
|
|
20
|
-
with:
|
|
21
|
-
node-version: '20'
|
|
22
|
-
registry-url: 'https://registry.npmjs.org'
|
|
23
|
-
|
|
24
|
-
- name: Install dependencies
|
|
25
|
-
run: npm ci
|
|
26
|
-
|
|
27
|
-
- name: Build
|
|
28
|
-
run: npm run build
|
|
29
|
-
|
|
30
|
-
- name: Set version from tag
|
|
31
|
-
run: |
|
|
32
|
-
TAG_NAME="${GITHUB_REF#refs/tags/}"
|
|
33
|
-
VERSION="${TAG_NAME#v}"
|
|
34
|
-
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
35
|
-
node -e "
|
|
36
|
-
import {readFileSync, writeFileSync} from 'fs';
|
|
37
|
-
const pkg = JSON.parse(readFileSync('package.json', 'utf8'));
|
|
38
|
-
pkg.version = '$VERSION';
|
|
39
|
-
writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
- name: Generate release notes
|
|
43
|
-
id: release-notes
|
|
44
|
-
run: |
|
|
45
|
-
TAG_NAME="${GITHUB_REF#refs/tags/}"
|
|
46
|
-
# Get all tags sorted by version, find previous tag
|
|
47
|
-
PREV_TAG=$(git tag --sort=-v:refname | sed -n '2p')
|
|
48
|
-
if [ -n "$PREV_TAG" ]; then
|
|
49
|
-
CHANGES=$(git log "$PREV_TAG..HEAD" --oneline --format="- %s")
|
|
50
|
-
else
|
|
51
|
-
CHANGES=$(git log --oneline --format="- %s" -10)
|
|
52
|
-
fi
|
|
53
|
-
COMPARE_URL="https://github.com/${{ github.repository }}/compare/${PREV_TAG}...${TAG_NAME}"
|
|
54
|
-
if [ -z "$PREV_TAG" ]; then
|
|
55
|
-
COMPARE_URL="https://github.com/${{ github.repository }}/releases/tag/${TAG_NAME}"
|
|
56
|
-
fi
|
|
57
|
-
cat << NOTES > release-notes.md
|
|
58
|
-
## What's Changed
|
|
59
|
-
|
|
60
|
-
${CHANGES}
|
|
61
|
-
|
|
62
|
-
**Full Changelog**: ${COMPARE_URL}
|
|
63
|
-
NOTES
|
|
64
|
-
echo "body_path=release-notes.md" >> "$GITHUB_OUTPUT"
|
|
65
|
-
|
|
66
|
-
- name: Package for release
|
|
67
|
-
run: |
|
|
68
|
-
npm pack --pack-destination .
|
|
69
|
-
|
|
70
|
-
- name: Create GitHub Release
|
|
71
|
-
uses: softprops/action-gh-release@v2
|
|
72
|
-
with:
|
|
73
|
-
body_path: ${{ steps.release-notes.outputs.body_path }}
|
|
74
|
-
files: "*.tgz"
|
|
75
|
-
env:
|
|
76
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
77
|
-
|
|
78
|
-
- name: Publish to npm
|
|
79
|
-
run: npm publish --access public
|
|
80
|
-
env:
|
|
81
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
# OpenSpec + Playwright E2E Integration Design
|
|
2
|
-
|
|
3
|
-
**Date:** 2026-03-26
|
|
4
|
-
**Updated:** 2026-03-27
|
|
5
|
-
**Status:** Implemented (MVP)
|
|
6
|
-
|
|
7
|
-
## Overview
|
|
8
|
-
|
|
9
|
-
Integrate OpenSpec's spec-driven development workflow with Playwright Test Agents' three-agent harness (Planner / Generator / Healer) for automated E2E verification.
|
|
10
|
-
|
|
11
|
-
**Design decision:** Add a new independent command `/openspec-e2e` rather than hooking into `/opsx:verify`. This keeps concerns separated and allows each verification to be run independently.
|
|
12
|
-
|
|
13
|
-
## Architecture
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
openspec-pw (CLI - setup only)
|
|
17
|
-
openspec-pw init → installs Playwright + configures MCP + installs skill
|
|
18
|
-
openspec-pw doctor → checks prerequisites
|
|
19
|
-
|
|
20
|
-
/openspec-e2e (Claude Code skill - runs in Claude)
|
|
21
|
-
│
|
|
22
|
-
├── 1. Read OpenSpec specs from openspec/changes/<name>/specs/
|
|
23
|
-
├── 2. Planner Agent → specs/playwright/test-plan.md
|
|
24
|
-
├── 3. Generator Agent → tests/playwright/<name>.spec.ts
|
|
25
|
-
└── 4. Healer Agent → run tests + auto-heal
|
|
26
|
-
│
|
|
27
|
-
└── Report: openspec/reports/playwright-e2e-<name>-<ts>.md
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Two Verification Layers
|
|
31
|
-
|
|
32
|
-
| Layer | Command | Runs in | What it checks |
|
|
33
|
-
|-------|---------|---------|----------------|
|
|
34
|
-
| Static | `/opsx:verify` | Claude Code (OpenSpec skill) | Implementation matches artifacts |
|
|
35
|
-
| E2E | `/openspec-e2e` | Claude Code (this skill) | App works when running |
|
|
36
|
-
|
|
37
|
-
## Key Design Decisions
|
|
38
|
-
|
|
39
|
-
- **Separate command, not hook**: `/openspec-e2e` is independent from `/opsx:verify`. Users run them separately or together.
|
|
40
|
-
- **CLI as setup only**: The CLI does not run agents. It only installs/configures. Agents run in Claude Code.
|
|
41
|
-
- **Playwright MCP**: Playwright agents use the MCP protocol, configured in `.claude/settings.local.json`.
|
|
42
|
-
- **Seed test**: A `tests/playwright/seed.spec.ts` template guides the Generator agent.
|
|
43
|
-
- **No re-exploration**: Planner uses OpenSpec specs directly as the source of truth, no app exploration needed.
|
|
44
|
-
|
|
45
|
-
## CLI Commands
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
npm install -g wxhou/openspec-playwright
|
|
49
|
-
|
|
50
|
-
openspec-pw init # Setup: Playwright + MCP + skill + seed
|
|
51
|
-
openspec-pw doctor # Check prerequisites
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## What `openspec-pw init` Does
|
|
55
|
-
|
|
56
|
-
1. `npx playwright init-agents --loop=claude` — installs Playwright agents
|
|
57
|
-
2. Configure Playwright MCP in `.claude/settings.local.json`
|
|
58
|
-
3. Install skill: `.claude/skills/openspec-e2e/SKILL.md`
|
|
59
|
-
4. Install command: `.claude/commands/opsx-e2e.md`
|
|
60
|
-
5. Generate `tests/playwright/seed.spec.ts` template
|
|
61
|
-
|
|
62
|
-
## SKILL.md Format
|
|
63
|
-
|
|
64
|
-
Follows the OpenSpec standard format:
|
|
65
|
-
- YAML frontmatter: `name`, `description`, `license`, `compatibility`, `metadata`
|
|
66
|
-
- Bold step names: `**Step 1: Name**`
|
|
67
|
-
- Output fenced code blocks: `**Output During Implementation**`, `**Output On Completion**`
|
|
68
|
-
- Guardrails section
|
|
69
|
-
- Fluid Workflow Integration section
|
|
70
|
-
|
|
71
|
-
## Directory Structure
|
|
72
|
-
|
|
73
|
-
```
|
|
74
|
-
project/
|
|
75
|
-
├── .claude/
|
|
76
|
-
│ ├── skills/
|
|
77
|
-
│ │ └── openspec-e2e/
|
|
78
|
-
│ │ └── SKILL.md # The /openspec-e2e skill
|
|
79
|
-
│ ├── commands/
|
|
80
|
-
│ │ └── opsx-e2e.md # The /openspec-e2e command
|
|
81
|
-
│ └── settings.local.json # Playwright MCP config
|
|
82
|
-
├── .github/ # Playwright agent definitions
|
|
83
|
-
│ └── ...
|
|
84
|
-
├── openspec/
|
|
85
|
-
│ ├── changes/<name>/
|
|
86
|
-
│ │ ├── specs/
|
|
87
|
-
│ │ │ ├── *.md # OpenSpec propose output
|
|
88
|
-
│ │ │ └── playwright/
|
|
89
|
-
│ │ │ └── test-plan.md # Planner output
|
|
90
|
-
│ │ ├── design.md
|
|
91
|
-
│ │ └── tasks.md
|
|
92
|
-
│ └── reports/
|
|
93
|
-
│ └── playwright-e2e-<name>-<ts>.md # Healer report
|
|
94
|
-
└── tests/playwright/
|
|
95
|
-
├── seed.spec.ts # Seed test template
|
|
96
|
-
└── <name>.spec.ts # Generated tests
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## SKILL.md Sections (OpenSpec Standard)
|
|
100
|
-
|
|
101
|
-
```yaml
|
|
102
|
-
---
|
|
103
|
-
name: openspec-e2e
|
|
104
|
-
description: Run Playwright E2E verification for an OpenSpec change...
|
|
105
|
-
license: MIT
|
|
106
|
-
compatibility: Requires openspec CLI and Playwright Test Agents...
|
|
107
|
-
metadata:
|
|
108
|
-
author: openspec-playwright
|
|
109
|
-
version: "0.1.0"
|
|
110
|
-
generatedBy: "openspec-playwright"
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
Run Playwright E2E verification for an OpenSpec change...
|
|
114
|
-
|
|
115
|
-
## Step 1: Identify the Change
|
|
116
|
-
...
|
|
117
|
-
|
|
118
|
-
## Step 2: Verify Prerequisites
|
|
119
|
-
...
|
|
120
|
-
|
|
121
|
-
**Output During Implementation**
|
|
122
|
-
```markdown
|
|
123
|
-
## E2E Verification: <name>
|
|
124
|
-
Status: 🔄 In Progress
|
|
125
|
-
```
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
**Output On Completion**
|
|
129
|
-
```markdown
|
|
130
|
-
## E2E Verify Report: <name>
|
|
131
|
-
| Check | Status |
|
|
132
|
-
|-------|--------|
|
|
133
|
-
...
|
|
134
|
-
```
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
**Guardrails**
|
|
138
|
-
- Always read specs from `openspec/changes/<name>/specs/` as source of truth
|
|
139
|
-
- Do not generate tests that contradict the specs
|
|
140
|
-
- Cap auto-heal attempts at 3
|
|
141
|
-
...
|
|
142
|
-
|
|
143
|
-
**Fluid Workflow Integration**
|
|
144
|
-
- Before: /opsx:propose → /opsx:apply
|
|
145
|
-
- This skill: /openspec-e2e
|
|
146
|
-
- After: /opsx:archive
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Error Handling
|
|
150
|
-
|
|
151
|
-
| Scenario | Action |
|
|
152
|
-
|----------|--------|
|
|
153
|
-
| No specs found | Prompt to run `/opsx:propose` first |
|
|
154
|
-
| Prerequisites missing | Prompt to run `openspec-pw init` |
|
|
155
|
-
| Dev server not running | Prompt to start before proceeding |
|
|
156
|
-
| Planner fails | Log error, mark FAILED |
|
|
157
|
-
| Generator fails | Log error, mark FAILED |
|
|
158
|
-
| Healer guardrails trigger | Report failures, mark PARTIAL |
|
|
159
|
-
|
|
160
|
-
## Project Structure
|
|
161
|
-
|
|
162
|
-
```
|
|
163
|
-
openspec-playwright/
|
|
164
|
-
├── src/
|
|
165
|
-
│ ├── index.ts # CLI entry
|
|
166
|
-
│ └── commands/
|
|
167
|
-
│ ├── init.ts # openspec-pw init
|
|
168
|
-
│ └── doctor.ts # openspec-pw doctor
|
|
169
|
-
├── .claude/
|
|
170
|
-
│ ├── skills/
|
|
171
|
-
│ │ └── openspec-e2e/
|
|
172
|
-
│ │ └── SKILL.md # The Claude Code skill
|
|
173
|
-
│ └── commands/
|
|
174
|
-
│ └── opsx-e2e.md # The command file
|
|
175
|
-
├── templates/
|
|
176
|
-
│ └── seed.spec.ts # Playwright seed test template
|
|
177
|
-
├── README.md
|
|
178
|
-
├── package.json
|
|
179
|
-
└── tsconfig.json
|
|
180
|
-
```
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
name: playwright-e2e
|
|
2
|
-
version: 1
|
|
3
|
-
description: Playwright E2E verification for an OpenSpec change
|
|
4
|
-
|
|
5
|
-
artifacts:
|
|
6
|
-
- id: test-plan
|
|
7
|
-
generates: specs/playwright/test-plan.md
|
|
8
|
-
description: Test plan derived from change specs
|
|
9
|
-
template: test-plan.md
|
|
10
|
-
instruction: |
|
|
11
|
-
Generate a test plan from the change specs. Each functional requirement becomes
|
|
12
|
-
one or more test cases.
|
|
13
|
-
|
|
14
|
-
For each test case, specify:
|
|
15
|
-
- **Test name** (kebab-case): what it verifies
|
|
16
|
-
- **Route/Page**: which URL or UI component it targets
|
|
17
|
-
- **Prerequisites**: auth role needed (user/admin/guest/none)
|
|
18
|
-
- **Happy path**: main user flow to verify
|
|
19
|
-
- **Error paths**: key error conditions to verify
|
|
20
|
-
|
|
21
|
-
Mark tests with role tags: `@role(user)`, `@role(admin)`, `@role(guest)`, `@role(none)`.
|
|
22
|
-
Mark auth requirement: `@auth(required)` or `@auth(none)`.
|
|
23
|
-
|
|
24
|
-
- id: e2e-test
|
|
25
|
-
generates: tests/playwright/<change>.spec.ts
|
|
26
|
-
description: Playwright E2E test suite
|
|
27
|
-
template: e2e-test.ts
|
|
28
|
-
instruction: |
|
|
29
|
-
Generate Playwright tests from the test-plan.
|
|
30
|
-
|
|
31
|
-
Rules:
|
|
32
|
-
- Follow the page object pattern from seed.spec.ts
|
|
33
|
-
- Prefer `data-testid` selectors, fall back to semantic selectors
|
|
34
|
-
- Each test maps to one test case from the test-plan
|
|
35
|
-
- Use `@project(user)` / `@project(admin)` for role-specific tests
|
|
36
|
-
- Cover happy path AND key error paths
|
|
37
|
-
- Name tests descriptively: `test('shows error on invalid input')`
|
|
38
|
-
|
|
39
|
-
- id: playwright-config
|
|
40
|
-
generates: playwright.config.ts
|
|
41
|
-
description: Playwright config with webServer and auth projects
|
|
42
|
-
template: playwright.config.ts
|
|
43
|
-
instruction: |
|
|
44
|
-
Configure Playwright for E2E testing.
|
|
45
|
-
|
|
46
|
-
- Set webServer command and url from BASE_URL
|
|
47
|
-
- Set baseURL for all tests
|
|
48
|
-
- Add auth setup project if credentials are configured
|
|
49
|
-
- Preserve any existing config fields (browsers, retries, etc.)
|
|
50
|
-
- Do NOT overwrite existing projects unless they conflict
|
|
51
|
-
|
|
52
|
-
apply:
|
|
53
|
-
requires: [test-plan, e2e-test]
|
|
54
|
-
instruction: |
|
|
55
|
-
Run tests via: openspec-pw run <change-name>
|
|
56
|
-
Analyze results and generate report at openspec/reports/playwright-e2e-<change>-<timestamp>.md
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { test, expect, Page } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
// ──────────────────────────────────────────────
|
|
4
|
-
// Test plan: <change-name>
|
|
5
|
-
// Generated from: openspec/changes/<change-name>/specs/playwright/test-plan.md
|
|
6
|
-
// ──────────────────────────────────────────────
|
|
7
|
-
|
|
8
|
-
const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Page Object Pattern - add selectors for your app's pages
|
|
12
|
-
*/
|
|
13
|
-
class AppPage {
|
|
14
|
-
constructor(private page: Page) {}
|
|
15
|
-
|
|
16
|
-
async goto(path: string = '/') {
|
|
17
|
-
await this.page.goto(`${BASE_URL}${path}`);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async getByTestId(id: string) {
|
|
21
|
-
return this.page.locator(`[data-testid="${id}"]`);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async waitForToast(message?: string) {
|
|
25
|
-
if (message) {
|
|
26
|
-
await this.page.getByText(message, { state: 'visible' }).waitFor();
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function createPage(page: Page): AppPage {
|
|
32
|
-
return new AppPage(page);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// ──────────────────────────────────────────────
|
|
36
|
-
// Tests - generated from test-plan.md
|
|
37
|
-
// Customize selectors and assertions to match your app
|
|
38
|
-
// ──────────────────────────────────────────────
|
|
39
|
-
|
|
40
|
-
test.describe('<change-name>: E2E verification', () => {
|
|
41
|
-
|
|
42
|
-
test.beforeEach(async ({ page }) => {
|
|
43
|
-
const app = createPage(page);
|
|
44
|
-
await app.goto('/');
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// TODO: Add test cases from specs/playwright/test-plan.md
|
|
48
|
-
// Example:
|
|
49
|
-
// test('shows expected content on page load', async ({ page }) => {
|
|
50
|
-
// const app = createPage(page);
|
|
51
|
-
// await app.goto('/');
|
|
52
|
-
// await expect(app.getByTestId('main-heading')).toBeVisible();
|
|
53
|
-
// });
|
|
54
|
-
|
|
55
|
-
});
|