openspec-playwright 0.1.16
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/opsx/e2e.md +8 -0
- package/.claude/skills/openspec-e2e/SKILL.md +138 -0
- package/.github/workflows/release.yml +41 -0
- package/README.md +133 -0
- package/README.zh-CN.md +118 -0
- package/bin/openspec-pw +4 -0
- package/bin/openspec-pw.js +2 -0
- package/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.js +110 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.js +174 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/run.d.ts +5 -0
- package/dist/commands/run.js +135 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/update.d.ts +5 -0
- package/dist/commands/update.js +91 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/docs/plans/2026-03-26-openspec-playwright-design.md +180 -0
- package/package.json +39 -0
- package/schemas/playwright-e2e/schema.yaml +56 -0
- package/schemas/playwright-e2e/templates/e2e-test.ts +55 -0
- package/schemas/playwright-e2e/templates/playwright.config.ts +52 -0
- package/schemas/playwright-e2e/templates/report.md +27 -0
- package/schemas/playwright-e2e/templates/test-plan.md +24 -0
- package/src/commands/doctor.ts +114 -0
- package/src/commands/init.ts +209 -0
- package/src/commands/run.ts +172 -0
- package/src/commands/update.ts +130 -0
- package/src/index.ts +47 -0
- package/templates/auth.setup.ts +77 -0
- package/templates/credentials.yaml +33 -0
- package/templates/seed.spec.ts +63 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: openspec-e2e
|
|
3
|
+
description: Run Playwright E2E verification for an OpenSpec change. Use when the user wants to validate that the implementation works end-to-end by running Playwright tests generated from the specs.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Requires openspec CLI, Playwright (with browsers installed), and @playwright/mcp (globally installed via claude mcp add).
|
|
6
|
+
metadata:
|
|
7
|
+
author: openspec-playwright
|
|
8
|
+
version: "2.0"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Run Playwright E2E verification for an OpenSpec change. This skill reads specs from `openspec/changes/<name>/specs/`, generates test files, detects auth requirements, and delegates test execution to the `openspec-pw run` CLI.
|
|
12
|
+
|
|
13
|
+
**Architecture**: Schema owns templates. CLI handles execution. Skill handles cognitive work.
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
|
|
17
|
+
### 1. Select the change
|
|
18
|
+
|
|
19
|
+
If a name is provided (e.g., `/opsx:e2e add-auth`), use it. Otherwise:
|
|
20
|
+
- Infer from conversation context if the user mentioned a change
|
|
21
|
+
- Auto-select if only one active change exists
|
|
22
|
+
- If ambiguous, run `openspec list --json` and use the **AskUserQuestion tool** to let the user select
|
|
23
|
+
|
|
24
|
+
After selecting, announce: "Using change: `<name>`" and how to override.
|
|
25
|
+
|
|
26
|
+
Verify specs exist:
|
|
27
|
+
```bash
|
|
28
|
+
openspec status --change "<name>" --json
|
|
29
|
+
```
|
|
30
|
+
If `openspec/changes/<name>/specs/` is empty, inform the user and stop. E2E requires specs.
|
|
31
|
+
|
|
32
|
+
### 2. Read specs and detect auth
|
|
33
|
+
|
|
34
|
+
Read all files from `openspec/changes/<name>/specs/*.md`. Extract functional requirements.
|
|
35
|
+
|
|
36
|
+
Detect if auth is required. Mark as **auth required** only when BOTH conditions are met:
|
|
37
|
+
|
|
38
|
+
**Condition A — Explicit markers**: "login", "signin", "logout", "authenticate", "protected", "authenticated", "session", "unauthorized"
|
|
39
|
+
|
|
40
|
+
**Condition B — Context indicators**: Protected routes ("/dashboard", "/profile", "/admin"), role mentions ("admin", "user"), redirect flows
|
|
41
|
+
|
|
42
|
+
**Exclude false positives** — HTTP header examples (`Authorization: Bearer ...`) and code snippets do not count.
|
|
43
|
+
|
|
44
|
+
**Confidence levels**:
|
|
45
|
+
- High (auto-proceed): Multiple explicit markers AND context indicators
|
|
46
|
+
- Medium (proceed with note): Single explicit marker, context unclear
|
|
47
|
+
- Low (skip auth): No explicit markers found
|
|
48
|
+
|
|
49
|
+
### 3. Generate test plan
|
|
50
|
+
|
|
51
|
+
Create `openspec/changes/<name>/specs/playwright/test-plan.md` by:
|
|
52
|
+
- Listing each functional requirement as a test case
|
|
53
|
+
- Marking each with `@role(user|admin|guest|none)` and `@auth(required|none)`
|
|
54
|
+
- Including happy path AND key error paths
|
|
55
|
+
- Referencing the route/page each test targets
|
|
56
|
+
|
|
57
|
+
**Idempotency**: If test-plan.md already exists → read it, use it, do NOT regenerate unless user explicitly asks.
|
|
58
|
+
|
|
59
|
+
### 4. Generate test file
|
|
60
|
+
|
|
61
|
+
Create `tests/playwright/<name>.spec.ts`:
|
|
62
|
+
- Follow the page object pattern from `tests/playwright/seed.spec.ts`
|
|
63
|
+
- Prefer `data-testid` selectors, fall back to semantic selectors
|
|
64
|
+
- Each test maps to one test case from the test-plan
|
|
65
|
+
- Use `@project(admin)` / `@project(user)` for role-specific tests
|
|
66
|
+
- Cover happy path AND key error paths
|
|
67
|
+
|
|
68
|
+
**Idempotency**: If test file exists → diff against test-plan, add only missing test cases, preserve existing implementations.
|
|
69
|
+
|
|
70
|
+
### 5. Configure auth (if required)
|
|
71
|
+
|
|
72
|
+
If auth is required:
|
|
73
|
+
|
|
74
|
+
**API login**: If specs mention `/api/auth/login` or similar → generate `tests/playwright/auth.setup.ts` using API login with `E2E_USERNAME`/`E2E_PASSWORD`.
|
|
75
|
+
|
|
76
|
+
**UI login**: Otherwise → generate `tests/playwright/auth.setup.ts` using UI login. Update selectors to match the login page (look for `data-testid` attributes or fallback to `input[name="..."]`).
|
|
77
|
+
|
|
78
|
+
**Multi-user**: If specs mention multiple roles (admin + user) → generate separate `auth.setup.ts` blocks for each role with different `storageState` paths.
|
|
79
|
+
|
|
80
|
+
**Prompt user** with:
|
|
81
|
+
```
|
|
82
|
+
Auth required. To set up credentials:
|
|
83
|
+
|
|
84
|
+
1. Customize tests/playwright/credentials.yaml with your test user
|
|
85
|
+
2. Export: export E2E_USERNAME=xxx E2E_PASSWORD=yyy
|
|
86
|
+
3. Run auth: npx playwright test --project=setup
|
|
87
|
+
4. Then re-run /opsx:e2e to execute tests
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Idempotency**: If `auth.setup.ts` already exists → verify format, update only if stale.
|
|
91
|
+
|
|
92
|
+
### 6. Configure playwright.config.ts (non-destructive)
|
|
93
|
+
|
|
94
|
+
If `playwright.config.ts` does not exist → generate it from the schema template at `openspec/schemas/playwright-e2e/templates/playwright.config.ts`. The template auto-detects:
|
|
95
|
+
- **BASE_URL**: from `process.env.BASE_URL`, falling back to `tests/playwright/seed.spec.ts` → `BASE_URL` value, then `http://localhost:3000`
|
|
96
|
+
- **Dev command**: from `package.json` → scripts in order: `dev` → `start` → `serve` → `preview` → `npm run dev`
|
|
97
|
+
|
|
98
|
+
If `playwright.config.ts` exists → READ it first. Extract existing `webServer`, `use.baseURL`, and `projects`. Preserve ALL existing fields. Add `webServer` block if missing. Do NOT replace existing config values.
|
|
99
|
+
|
|
100
|
+
### 7. Execute tests via CLI
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
openspec-pw run <name> --project=<role>
|
|
104
|
+
```
|
|
105
|
+
(Add `--project=user` or `--project=admin` for role-specific tests.)
|
|
106
|
+
|
|
107
|
+
The CLI handles:
|
|
108
|
+
- Server lifecycle (start → wait for HTTP → test → stop)
|
|
109
|
+
- Port mismatch detection
|
|
110
|
+
- Report generation at `openspec/reports/playwright-e2e-<name>-<timestamp>.md`
|
|
111
|
+
|
|
112
|
+
If tests fail → analyze failures, use Playwright MCP tools to inspect UI state, fix selectors in the test file, and re-run.
|
|
113
|
+
|
|
114
|
+
**Cap auto-heal attempts at 3** to prevent infinite loops.
|
|
115
|
+
|
|
116
|
+
### 8. Report results
|
|
117
|
+
|
|
118
|
+
Read the report generated by `openspec-pw run` and present it to the user:
|
|
119
|
+
- Summary table (tests run, passed, failed, duration, final status)
|
|
120
|
+
- Any auto-heal notes
|
|
121
|
+
- Recommendations for failed tests (with specific file:line references)
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Verification Heuristics
|
|
126
|
+
|
|
127
|
+
- **Coverage**: Every functional requirement → at least one test
|
|
128
|
+
- **Selector robustness**: Prefer `data-testid`, fallback to semantic selectors
|
|
129
|
+
- **False positives**: If test fails due to test bug (not app bug) → fix the test
|
|
130
|
+
- **Actionability**: Every failed test needs a specific recommendation
|
|
131
|
+
|
|
132
|
+
## Guardrails
|
|
133
|
+
|
|
134
|
+
- Read specs from `openspec/changes/<name>/specs/` as source of truth
|
|
135
|
+
- Do NOT generate tests that contradict the specs
|
|
136
|
+
- Do NOT overwrite files outside: `specs/playwright/`, `tests/playwright/`, `openspec/reports/`, `playwright.config.ts`, `tests/auth.setup.ts`
|
|
137
|
+
- Cap auto-heal at 3 attempts
|
|
138
|
+
- If no change specified → always ask user to select
|
|
@@ -0,0 +1,41 @@
|
|
|
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: Create GitHub Release
|
|
31
|
+
uses: softprops/action-gh-release@v2
|
|
32
|
+
with:
|
|
33
|
+
generate_release_notes: true
|
|
34
|
+
files: dist/**/*
|
|
35
|
+
env:
|
|
36
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
37
|
+
|
|
38
|
+
- name: Publish to npm
|
|
39
|
+
run: npm publish --access public
|
|
40
|
+
env:
|
|
41
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# OpenSpec + Playwright E2E Verification
|
|
2
|
+
|
|
3
|
+
[中文说明](./README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
A setup tool that integrates OpenSpec's spec-driven development with Playwright's three-agent test pipeline for automated E2E verification.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g https://github.com/wxhou/openspec-playwright/archive/refs/heads/main.tar.gz
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# In your project directory
|
|
17
|
+
openspec init # Initialize OpenSpec
|
|
18
|
+
openspec-pw init # Install Playwright E2E integration
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### In Claude Code
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
/opsx:e2e my-feature # Primary command (OpenSpec convention)
|
|
27
|
+
/openspec-e2e # Alternative from skill
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### CLI Commands
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
openspec-pw init # Initialize integration (one-time setup)
|
|
34
|
+
openspec-pw update # Update CLI and skill to latest version
|
|
35
|
+
openspec-pw doctor # Check prerequisites
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## How It Works
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
/openspec-e2e <change-name>
|
|
42
|
+
│
|
|
43
|
+
├── 1. Read OpenSpec specs from openspec/changes/<name>/specs/
|
|
44
|
+
│
|
|
45
|
+
├── 2. Planner Agent → generates test-plan.md
|
|
46
|
+
│
|
|
47
|
+
├── 3. Generator Agent → creates tests/playwright/<name>.spec.ts
|
|
48
|
+
│
|
|
49
|
+
└── 4. Healer Agent → runs tests + auto-heals failures
|
|
50
|
+
│
|
|
51
|
+
└── Report: openspec/reports/playwright-e2e-<name>.md
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Two Verification Layers
|
|
55
|
+
|
|
56
|
+
| Layer | Command | What it checks |
|
|
57
|
+
|-------|---------|----------------|
|
|
58
|
+
| Static | `/opsx:verify` | Implementation matches artifacts |
|
|
59
|
+
| E2E | `/opsx:e2e` | App works when running |
|
|
60
|
+
|
|
61
|
+
## Prerequisites
|
|
62
|
+
|
|
63
|
+
1. **Node.js >= 20**
|
|
64
|
+
2. **OpenSpec** initialized: `npm install -g @fission-ai/openspec && openspec init`
|
|
65
|
+
3. **Claude Code** with Playwright MCP configured
|
|
66
|
+
|
|
67
|
+
## What `openspec-pw init` Does
|
|
68
|
+
|
|
69
|
+
1. Installs Playwright MCP globally via `claude mcp add`
|
|
70
|
+
2. Installs `/opsx:e2e` command and `/openspec-e2e` skill
|
|
71
|
+
3. Generates `tests/playwright/seed.spec.ts`, `auth.setup.ts`, `credentials.yaml`
|
|
72
|
+
|
|
73
|
+
> **Note**: After running `openspec-pw init`, manually install Playwright browsers: `npx playwright install --with-deps`
|
|
74
|
+
|
|
75
|
+
## Authentication
|
|
76
|
+
|
|
77
|
+
If your app requires login, set up credentials once, then all tests run authenticated automatically.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# 1. Edit credentials
|
|
81
|
+
vim tests/playwright/credentials.yaml
|
|
82
|
+
|
|
83
|
+
# 2. Set environment variables
|
|
84
|
+
export E2E_USERNAME=your-email@example.com
|
|
85
|
+
export E2E_PASSWORD=your-password
|
|
86
|
+
|
|
87
|
+
# 3. Record login (one-time — opens browser, log in manually)
|
|
88
|
+
npx playwright test --project=setup
|
|
89
|
+
|
|
90
|
+
# 4. All subsequent tests use the saved session
|
|
91
|
+
/opsx:e2e my-feature
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Supports **API login** (preferred) and **UI login** (fallback). For multi-user tests (admin vs user), add multiple users in `credentials.yaml` and run `/opsx:e2e` — it auto-detects roles from specs.
|
|
95
|
+
|
|
96
|
+
## Customization
|
|
97
|
+
|
|
98
|
+
### Customize seed test
|
|
99
|
+
|
|
100
|
+
Edit `tests/playwright/seed.spec.ts` to match your app's:
|
|
101
|
+
- Base URL
|
|
102
|
+
- Common selectors
|
|
103
|
+
- Page object methods
|
|
104
|
+
|
|
105
|
+
### Authentication credentials
|
|
106
|
+
|
|
107
|
+
Edit `tests/playwright/credentials.yaml`:
|
|
108
|
+
- Set login API endpoint (or leave empty for UI login)
|
|
109
|
+
- Configure test user credentials
|
|
110
|
+
- Add multiple users for role-based tests
|
|
111
|
+
|
|
112
|
+
### MCP server
|
|
113
|
+
|
|
114
|
+
Playwright MCP is installed globally via `claude mcp add`. Restart Claude Code after setup to activate.
|
|
115
|
+
|
|
116
|
+
## Architecture
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
openspec-pw (CLI - setup only)
|
|
120
|
+
├── Installs Playwright agents (.github/)
|
|
121
|
+
├── Installs Playwright MCP globally via claude mcp add
|
|
122
|
+
├── Installs Claude Code skill (/openspec-e2e)
|
|
123
|
+
└── Installs command (/opsx:e2e)
|
|
124
|
+
|
|
125
|
+
/openspec-e2e (Claude Code skill - runs in Claude)
|
|
126
|
+
├── Reads OpenSpec specs
|
|
127
|
+
├── Triggers Playwright agents via MCP
|
|
128
|
+
└── Generates E2E verification report
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# OpenSpec + Playwright E2E 验证
|
|
2
|
+
|
|
3
|
+
[English version](./README.md)
|
|
4
|
+
|
|
5
|
+
将 OpenSpec 的规格驱动开发工作流与 Playwright 三 Agent 测试管道集成,实现自动化 E2E 验证。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g https://github.com/wxhou/openspec-playwright/archive/refs/heads/main.tar.gz
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 初始化
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# 在项目目录下
|
|
17
|
+
openspec init # 初始化 OpenSpec
|
|
18
|
+
openspec-pw init # 安装 Playwright E2E 集成
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 使用
|
|
22
|
+
|
|
23
|
+
### 在 Claude Code 中
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
/opsx:e2e my-feature # 主命令(遵循 OpenSpec 规范)
|
|
27
|
+
/openspec-e2e # 来自 skill 的别名
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### CLI 命令
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
openspec-pw init # 初始化集成(一次性设置)
|
|
34
|
+
openspec-pw update # 更新 CLI 和 skill 到最新版本
|
|
35
|
+
openspec-pw doctor # 检查前置条件
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 工作原理
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
/openspec-e2e <change-name>
|
|
42
|
+
│
|
|
43
|
+
├── 1. 从 openspec/changes/<name>/specs/ 读取 OpenSpec specs
|
|
44
|
+
│
|
|
45
|
+
├── 2. Planner Agent → 生成 test-plan.md
|
|
46
|
+
│
|
|
47
|
+
├── 3. Generator Agent → 创建 tests/playwright/<name>.spec.ts
|
|
48
|
+
│
|
|
49
|
+
└── 4. Healer Agent → 运行测试 + 自动修复失败
|
|
50
|
+
│
|
|
51
|
+
└── 报告: openspec/reports/playwright-e2e-<name>.md
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 两层验证
|
|
55
|
+
|
|
56
|
+
| 层级 | 命令 | 验证内容 |
|
|
57
|
+
|------|------|---------|
|
|
58
|
+
| 静态验证 | `/opsx:verify` | 实现是否符合 artifacts |
|
|
59
|
+
| E2E 验证 | `/opsx:e2e` | 应用运行是否正常 |
|
|
60
|
+
|
|
61
|
+
## 前置条件
|
|
62
|
+
|
|
63
|
+
1. **Node.js >= 20**
|
|
64
|
+
2. **OpenSpec** 已初始化: `npm install -g @fission-ai/openspec && openspec init`
|
|
65
|
+
3. **Claude Code** 已配置 Playwright MCP
|
|
66
|
+
|
|
67
|
+
## `openspec-pw init` 做了什么
|
|
68
|
+
|
|
69
|
+
1. 通过 `claude mcp add` 全局安装 Playwright MCP
|
|
70
|
+
2. 安装 `/opsx:e2e` 命令和 `/openspec-e2e` skill
|
|
71
|
+
3. 生成 `tests/playwright/seed.spec.ts`、`auth.setup.ts`、`credentials.yaml`
|
|
72
|
+
|
|
73
|
+
> **注意**:运行 `openspec-pw init` 后,手动安装 Playwright 浏览器:`npx playwright install --with-deps`
|
|
74
|
+
|
|
75
|
+
## 认证
|
|
76
|
+
|
|
77
|
+
如果你的应用需要登录,配置一次凭证后,所有测试自动以已登录状态运行。
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# 1. 编辑凭证
|
|
81
|
+
vim tests/playwright/credentials.yaml
|
|
82
|
+
|
|
83
|
+
# 2. 设置环境变量
|
|
84
|
+
export E2E_USERNAME=your-email@example.com
|
|
85
|
+
export E2E_PASSWORD=your-password
|
|
86
|
+
|
|
87
|
+
# 3. 录制登录(一次性 — 打开浏览器,手动登录一次)
|
|
88
|
+
npx playwright test --project=setup
|
|
89
|
+
|
|
90
|
+
# 4. 后续所有测试自动复用登录状态
|
|
91
|
+
/opsx:e2e my-feature
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
支持 **API 登录**(推荐)和 **UI 登录**(备选)。多用户测试(管理员 vs 普通用户)在 `credentials.yaml` 中添加多个用户,`/opsx:e2e` 会从 specs 自动检测角色。
|
|
95
|
+
|
|
96
|
+
## 自定义
|
|
97
|
+
|
|
98
|
+
### 自定义 seed 测试
|
|
99
|
+
|
|
100
|
+
编辑 `tests/playwright/seed.spec.ts` 以匹配你的应用:
|
|
101
|
+
- 基础 URL
|
|
102
|
+
- 常用选择器
|
|
103
|
+
- Page Object 方法
|
|
104
|
+
|
|
105
|
+
### 认证凭证
|
|
106
|
+
|
|
107
|
+
编辑 `tests/playwright/credentials.yaml`:
|
|
108
|
+
- 设置登录 API 端点(或留空使用 UI 登录)
|
|
109
|
+
- 配置测试用户凭证
|
|
110
|
+
- 为角色测试添加多用户
|
|
111
|
+
|
|
112
|
+
### MCP 服务器
|
|
113
|
+
|
|
114
|
+
Playwright MCP 通过 `claude mcp add` 全局安装。设置后需重启 Claude Code 生效。
|
|
115
|
+
|
|
116
|
+
## 许可
|
|
117
|
+
|
|
118
|
+
MIT
|
package/bin/openspec-pw
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function doctor(): Promise<void>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
export async function doctor() {
|
|
6
|
+
console.log(chalk.blue('\n🔍 OpenSpec + Playwright E2E Prerequisites Check\n'));
|
|
7
|
+
const projectRoot = process.cwd();
|
|
8
|
+
let allOk = true;
|
|
9
|
+
// Node.js
|
|
10
|
+
console.log(chalk.blue('─── Node.js ───'));
|
|
11
|
+
try {
|
|
12
|
+
const node = execSync('node --version', { encoding: 'utf-8' }).trim();
|
|
13
|
+
console.log(chalk.green(` ✓ Node.js ${node}`));
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
console.log(chalk.red(' ✗ Node.js not found'));
|
|
17
|
+
allOk = false;
|
|
18
|
+
}
|
|
19
|
+
// npm
|
|
20
|
+
console.log(chalk.blue('\n─── npm ───'));
|
|
21
|
+
try {
|
|
22
|
+
const npm = execSync('npm --version', { encoding: 'utf-8' }).trim();
|
|
23
|
+
console.log(chalk.green(` ✓ npm ${npm}`));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
console.log(chalk.red(' ✗ npm not found'));
|
|
27
|
+
allOk = false;
|
|
28
|
+
}
|
|
29
|
+
// OpenSpec
|
|
30
|
+
console.log(chalk.blue('\n─── OpenSpec ───'));
|
|
31
|
+
const hasOpenSpec = existsSync(join(projectRoot, 'openspec'));
|
|
32
|
+
if (hasOpenSpec) {
|
|
33
|
+
console.log(chalk.green(' ✓ OpenSpec initialized'));
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.log(chalk.red(' ✗ OpenSpec not initialized'));
|
|
37
|
+
console.log(chalk.gray(' Run: openspec init'));
|
|
38
|
+
allOk = false;
|
|
39
|
+
}
|
|
40
|
+
// Playwright browsers
|
|
41
|
+
console.log(chalk.blue('\n─── Playwright Browsers ───'));
|
|
42
|
+
try {
|
|
43
|
+
const pw = execSync('npx playwright --version', { encoding: 'utf-8' }).trim();
|
|
44
|
+
console.log(chalk.green(` ✓ Playwright ${pw}`));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
console.log(chalk.red(' ✗ Playwright browsers not installed'));
|
|
48
|
+
console.log(chalk.gray(' Run: npx playwright install --with-deps'));
|
|
49
|
+
allOk = false;
|
|
50
|
+
}
|
|
51
|
+
// Playwright MCP (global)
|
|
52
|
+
console.log(chalk.blue('\n─── Playwright MCP ───'));
|
|
53
|
+
const homeDir = process.env.HOME ?? '';
|
|
54
|
+
const claudeJsonPath = join(homeDir, '.claude.json');
|
|
55
|
+
let mcpInstalled = false;
|
|
56
|
+
if (existsSync(claudeJsonPath)) {
|
|
57
|
+
try {
|
|
58
|
+
const claudeJson = JSON.parse(readFileSync(claudeJsonPath, 'utf-8'));
|
|
59
|
+
const globalMcp = claudeJson?.mcpServers ?? {};
|
|
60
|
+
const localMcp = claudeJson?.projects?.[projectRoot]?.mcpServers ?? {};
|
|
61
|
+
if (globalMcp['playwright'] || localMcp['playwright']) {
|
|
62
|
+
mcpInstalled = true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// ignore
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (mcpInstalled) {
|
|
70
|
+
console.log(chalk.green(' ✓ Playwright MCP installed globally'));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
console.log(chalk.red(' ✗ Playwright MCP not configured'));
|
|
74
|
+
console.log(chalk.gray(' Run: openspec-pw init'));
|
|
75
|
+
allOk = false;
|
|
76
|
+
}
|
|
77
|
+
// Skill
|
|
78
|
+
console.log(chalk.blue('\n─── Claude Code Skill ───'));
|
|
79
|
+
const hasSkill = existsSync(join(projectRoot, '.claude', 'skills', 'openspec-e2e', 'SKILL.md'));
|
|
80
|
+
if (hasSkill) {
|
|
81
|
+
console.log(chalk.green(' ✓ /openspec-e2e skill installed'));
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.log(chalk.red(' ✗ Skill not installed'));
|
|
85
|
+
console.log(chalk.gray(' Run: openspec-pw init'));
|
|
86
|
+
allOk = false;
|
|
87
|
+
}
|
|
88
|
+
// Seed test
|
|
89
|
+
console.log(chalk.blue('\n─── Seed Test ───'));
|
|
90
|
+
const hasSeed = existsSync(join(projectRoot, 'tests', 'playwright', 'seed.spec.ts'));
|
|
91
|
+
if (hasSeed) {
|
|
92
|
+
console.log(chalk.green(' ✓ seed.spec.ts found'));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
console.log(chalk.yellow(' ⚠ seed.spec.ts not found (optional)'));
|
|
96
|
+
console.log(chalk.gray(' Run: openspec-pw init'));
|
|
97
|
+
}
|
|
98
|
+
// Summary
|
|
99
|
+
console.log(chalk.blue('\n─── Summary ───'));
|
|
100
|
+
if (allOk) {
|
|
101
|
+
console.log(chalk.green(' ✅ All prerequisites met!\n'));
|
|
102
|
+
console.log(chalk.gray(' Run: /opsx:e2e <change-name> in Claude Code\n'));
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
console.log(chalk.red(' ❌ Some prerequisites are missing\n'));
|
|
106
|
+
console.log(chalk.gray(' Run: openspec-pw init to fix\n'));
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC,CAAC;IAEhF,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAClC,IAAI,KAAK,GAAG,IAAI,CAAC;IAEjB,UAAU;IACV,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,CAAC;QAChD,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;IAED,MAAM;IACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAAC,eAAe,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAC5C,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;IAED,WAAW;IACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;IAC9D,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC;QAClD,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;IAED,sBAAsB;IACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,QAAQ,CAAC,0BAA0B,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC,CAAC;QACvE,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;IAED,0BAA0B;IAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IACvC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACrD,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;YACrE,MAAM,SAAS,GAAG,UAAU,EAAE,UAAU,IAAI,EAAE,CAAC;YAC/C,MAAM,QAAQ,GAAG,UAAU,EAAE,QAAQ,EAAE,CAAC,WAAW,CAAC,EAAE,UAAU,IAAI,EAAE,CAAC;YACvE,IAAI,SAAS,CAAC,YAAY,CAAC,IAAI,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBACtD,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACrD,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;IAED,QAAQ;IACR,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,UAAU,CACzB,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,CAAC,CACnE,CAAC;IACF,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC;IAChE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACrD,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;IAED,YAAY;IACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,UAAU,CACxB,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,CAAC,CACzD,CAAC;IACF,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC;IACrD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,uCAAuC,CAAC,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,UAAU;IACV,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC7C,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC,CAAC;IAC7E,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|