pdd-skills 3.1.8 → 3.1.10
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/lib/init.js +1 -1
- package/package.json +1 -1
- package/testcases/examples/asset-eval-apply.env +8 -0
- package/testcases/examples/asset-eval-apply.yaml +171 -0
- package/testcases/examples/login-flow.env +7 -0
- package/testcases/examples/login-flow.yaml +171 -0
- package/testcases/examples/yaml-format-guide.md +453 -0
- package/tests/login_manager.py +695 -0
- package/tests/testcase-ai.py +3292 -0
package/lib/init.js
CHANGED
|
@@ -499,7 +499,7 @@ export async function initProject(targetPath = '.', options = {}) {
|
|
|
499
499
|
}
|
|
500
500
|
|
|
501
501
|
// Copy AI Test Framework source files (testcase-ai.py, login_manager.py)
|
|
502
|
-
const srcRoot = path.resolve(
|
|
502
|
+
const srcRoot = path.resolve(__dirname, '..');
|
|
503
503
|
console.log(chalk.blue('\n>> Copying AI Test source files...\n'));
|
|
504
504
|
for (const rel of AI_TEST_SOURCE_FILES) {
|
|
505
505
|
const srcPath = path.join(srcRoot, 'tests', path.basename(rel));
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"pdd-skills","version":"3.1.
|
|
1
|
+
{"name":"pdd-skills","version":"3.1.10","type":"module","description":"PDD Skills - PRD驱动开发框架 | 41+技能: 核心(12)/专家(8)/熵减(4)/OpenSpec(10)/PR管理(7) | AI原生开发工作流 | Bug模式库(14) | PRD规则(30) | 4级门控引擎","main":"index.js","bin":{"pdd":"./bin/pdd.js","pdd-skills":"./bin/pdd.js"},"files":["bin/","lib/","skills/","templates/","scaffolds/","scripts/","config/","hooks/","docs/","index.js","tests/testcase-ai.py","tests/login_manager.py","testcases/examples/"],"scripts":{"start":"node bin/pdd.js","list":"node bin/pdd.js list","lint":"node bin/pdd.js linter --type code prd sql activiti","generate":"node bin/pdd.js generate","verify":"node bin/pdd.js verify","report":"node bin/pdd.js report","config":"node bin/pdd.js config --list","api":"node bin/pdd.js api","api:dev":"node bin/pdd.js api -p 3000 --cors","init":"node bin/pdd.js init","update":"node bin/pdd.js update","cso":"node bin/pdd.js cso","eval":"node bin/pdd.js eval","token":"node bin/pdd.js token","i18n":"node bin/pdd.js i18n"},"keywords":["pdd","prd-driven-development","ai","claude","skills","tdd","code-generation","linter","api-server","cli"],"author":"PDD Team","license":"MIT","engines":{"node":">=18.0.0"},"dependencies":{"chalk":"^5.3.0","commander":"^12.0.0","fs-extra":"^11.2.0","yaml":"^2.3.0"}}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# 资产评估申请 - 正常路径测试
|
|
2
|
+
# 示例用例:演示完整的 YAML 结构和最佳实践
|
|
3
|
+
|
|
4
|
+
test_id: "ASSET-EVAL-001-apply-normal"
|
|
5
|
+
title: "资产评估申请正常提交流程"
|
|
6
|
+
priority: "P0"
|
|
7
|
+
tags: ["资产评估", "申请流程", "正常路径", "E2E"]
|
|
8
|
+
author: "通过对话录入(示例)"
|
|
9
|
+
|
|
10
|
+
# 前置状态感知
|
|
11
|
+
context_check:
|
|
12
|
+
login_url: "http://uniportal.sjjk.com.cn"
|
|
13
|
+
home_indicator: "门户"
|
|
14
|
+
credentials:
|
|
15
|
+
username: "${TEST_USER}"
|
|
16
|
+
password: "${TEST_PASS}"
|
|
17
|
+
display_name: "${TEST_DISPLAY_NAME}"
|
|
18
|
+
captcha_required: false
|
|
19
|
+
|
|
20
|
+
# 测试步骤
|
|
21
|
+
steps:
|
|
22
|
+
# ===== 步骤 1:打开统一门户 =====
|
|
23
|
+
- step: 1
|
|
24
|
+
desc: "打开统一门户登录页面"
|
|
25
|
+
action: navigate
|
|
26
|
+
url: "http://uniportal.sjjk.com.cn"
|
|
27
|
+
assertion:
|
|
28
|
+
type: text_contains
|
|
29
|
+
expected: "欢迎登录"
|
|
30
|
+
|
|
31
|
+
# ===== 步骤 2:输入用户名(登录页,精确匹配)=====
|
|
32
|
+
- step: 2
|
|
33
|
+
desc: "输入用户名"
|
|
34
|
+
action: fill
|
|
35
|
+
target: "用户名输入框"
|
|
36
|
+
value: "${TEST_USER}"
|
|
37
|
+
assertion:
|
|
38
|
+
type: field_filled
|
|
39
|
+
|
|
40
|
+
# ===== 步骤 3:输入密码(登录页,精确匹配)=====
|
|
41
|
+
- step: 3
|
|
42
|
+
desc: "输入密码"
|
|
43
|
+
action: fill
|
|
44
|
+
target: "密码输入框"
|
|
45
|
+
value: "${TEST_PASS}"
|
|
46
|
+
isSensitive: true
|
|
47
|
+
assertion:
|
|
48
|
+
type: field_filled
|
|
49
|
+
|
|
50
|
+
# ===== 步骤 4:点击登录按钮(登录页,精确匹配)=====
|
|
51
|
+
- step: 4
|
|
52
|
+
desc: "点击登录按钮"
|
|
53
|
+
action: click
|
|
54
|
+
target: "登录按钮"
|
|
55
|
+
wait_after:
|
|
56
|
+
type: navigation
|
|
57
|
+
timeout: 10000
|
|
58
|
+
assertion:
|
|
59
|
+
type: text_contains
|
|
60
|
+
expected: "门户"
|
|
61
|
+
|
|
62
|
+
# ===== 步骤 5:进入资产评估系统(保留UID - 结构性入口稳定)=====
|
|
63
|
+
- step: 5
|
|
64
|
+
desc: "点击资产评估系统入口"
|
|
65
|
+
action: click
|
|
66
|
+
target: "资产处置及评估系统"
|
|
67
|
+
locator:
|
|
68
|
+
uid: "6_422"
|
|
69
|
+
wait_after:
|
|
70
|
+
type: navigation
|
|
71
|
+
timeout: 8000
|
|
72
|
+
assertion:
|
|
73
|
+
type: text_contains
|
|
74
|
+
expected: "资产处置及评估系统"
|
|
75
|
+
|
|
76
|
+
# ===== 步骤 6:展开一级菜单(保留UID - 导航结构相对稳定)=====
|
|
77
|
+
- step: 6
|
|
78
|
+
desc: "展开左侧菜单'资产评估'"
|
|
79
|
+
action: click
|
|
80
|
+
target: "资产评估"
|
|
81
|
+
locator:
|
|
82
|
+
uid: "7_22"
|
|
83
|
+
assertion:
|
|
84
|
+
type: element_visible
|
|
85
|
+
expected: "资产评估核准"
|
|
86
|
+
|
|
87
|
+
# ===== 步骤 7:展开二级菜单(保留UID - 导航结构相对稳定)=====
|
|
88
|
+
- step: 7
|
|
89
|
+
desc: "展开子菜单'资产评估核准'"
|
|
90
|
+
action: click
|
|
91
|
+
target: "资产评估核准"
|
|
92
|
+
locator:
|
|
93
|
+
uid: "15_1"
|
|
94
|
+
assertion:
|
|
95
|
+
type: element_visible
|
|
96
|
+
expected: "核准申请"
|
|
97
|
+
|
|
98
|
+
# ===== 步骤 8:点击"核准申请"页面(保留UID - 导航链接稳定)=====
|
|
99
|
+
- step: 8
|
|
100
|
+
desc: "点击'核准申请'菜单项,打开列表页"
|
|
101
|
+
action: click
|
|
102
|
+
target: "核准申请"
|
|
103
|
+
locator:
|
|
104
|
+
uid: "23_1"
|
|
105
|
+
wait_after:
|
|
106
|
+
type: navigation
|
|
107
|
+
timeout: 5000
|
|
108
|
+
assertion:
|
|
109
|
+
type: text_contains
|
|
110
|
+
expected: "项目名称"
|
|
111
|
+
|
|
112
|
+
# ===== 步骤 9:点击"新增"按钮(去UID - 靠文本匹配)=====
|
|
113
|
+
- step: 9
|
|
114
|
+
desc: "点击新增按钮,打开申请表单"
|
|
115
|
+
action: click
|
|
116
|
+
target: "新增"
|
|
117
|
+
assertion:
|
|
118
|
+
type: element_visible
|
|
119
|
+
expected: "项目名称"
|
|
120
|
+
|
|
121
|
+
# ===== 步骤 10:填写项目名称(去UID - 靠placeholder精确匹配)=====
|
|
122
|
+
- step: 10
|
|
123
|
+
desc: "填写项目名称字段"
|
|
124
|
+
action: fill
|
|
125
|
+
target: "请输入项目名称"
|
|
126
|
+
value: "${TEST_PROJECT_NAME}"
|
|
127
|
+
assertion:
|
|
128
|
+
type: field_filled
|
|
129
|
+
|
|
130
|
+
# ===== 步骤 11:填写评估金额(去UID - 靠placeholder精确匹配)=====
|
|
131
|
+
- step: 11
|
|
132
|
+
desc: "填写评估金额"
|
|
133
|
+
action: fill
|
|
134
|
+
target: "请输入报送评估值"
|
|
135
|
+
value: "${TEST_AMOUNT}"
|
|
136
|
+
assertion:
|
|
137
|
+
type: field_filled
|
|
138
|
+
|
|
139
|
+
# ===== 步骤 12:选择评估方法(去UID - 靠placeholder精确匹配)=====
|
|
140
|
+
- step: 12
|
|
141
|
+
desc: "选择评估方法为'市场法'"
|
|
142
|
+
action: select_option
|
|
143
|
+
target: "请选择评估方法"
|
|
144
|
+
option: "市场法"
|
|
145
|
+
assertion:
|
|
146
|
+
type: element_text
|
|
147
|
+
expected: "市场法"
|
|
148
|
+
|
|
149
|
+
# ===== 步骤 13:点击提交按钮(去UID - 靠文本匹配)=====
|
|
150
|
+
- step: 13
|
|
151
|
+
desc: "点击提交按钮,保存申请信息"
|
|
152
|
+
action: click
|
|
153
|
+
target: "提交申请"
|
|
154
|
+
wait_after:
|
|
155
|
+
type: time
|
|
156
|
+
duration: 2000
|
|
157
|
+
assertions:
|
|
158
|
+
- type: toast_visible
|
|
159
|
+
expected: "请输入评估对象"
|
|
160
|
+
confidence: high
|
|
161
|
+
- type: network_called
|
|
162
|
+
url_pattern: "/api/asset-eval/apply*"
|
|
163
|
+
method: POST
|
|
164
|
+
response_code: 200
|
|
165
|
+
confidence: high
|
|
166
|
+
|
|
167
|
+
# 后置清理
|
|
168
|
+
teardown:
|
|
169
|
+
- action: screenshot
|
|
170
|
+
name: "apply-normal-result-{timestamp}.png"
|
|
171
|
+
fullPage: true
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# 统一门户登录流程 - 正常路径测试
|
|
2
|
+
#
|
|
3
|
+
# 📋 用途: 验证PDD Test Skill的完整执行流程
|
|
4
|
+
# 🎯 场景: 打开统一门户 → 输入凭据 → 点击登录 → 验证首页
|
|
5
|
+
# 🔗 业务系统: http://uniportal.sjjk.com.cn
|
|
6
|
+
# ⚠️ 安全提示: 所有敏感信息使用环境变量,禁止硬编码!
|
|
7
|
+
|
|
8
|
+
test_id: "LOGIN-001-portal-normal"
|
|
9
|
+
title: "统一门户登录正常流程"
|
|
10
|
+
priority: "P0"
|
|
11
|
+
tags: ["登录", "统一门户", "正常路径", "E2E", "试点验证"]
|
|
12
|
+
author: "PDD Team (v1.0.1 试点用例)"
|
|
13
|
+
|
|
14
|
+
# 前置状态感知
|
|
15
|
+
context_check:
|
|
16
|
+
login_url: "http://uniportal.sjjk.com.cn"
|
|
17
|
+
home_indicator: "统一门户(新)" # 已登录状态的标志性文本
|
|
18
|
+
credentials:
|
|
19
|
+
username: "${TEST_USER}" # 从环境变量读取用户名
|
|
20
|
+
password: "${TEST_PASS}" # 从环境变量读取密码(绝对禁止明文!)
|
|
21
|
+
display_name: "${TEST_DISPLAY_NAME}" # 中文名,用于登录状态对比
|
|
22
|
+
captcha_required: false # 测试环境通常不需要验证码
|
|
23
|
+
sso_enabled: true # 支持SSO单点登录
|
|
24
|
+
|
|
25
|
+
# 测试步骤
|
|
26
|
+
steps:
|
|
27
|
+
|
|
28
|
+
# ===== 步骤 1:打开统一门户登录页面 =====
|
|
29
|
+
- step: 1
|
|
30
|
+
desc: "打开统一门户登录页面"
|
|
31
|
+
action: navigate
|
|
32
|
+
url: "${LOGIN_URL:-http://uniportal.sjjk.com.cn}"
|
|
33
|
+
wait_after:
|
|
34
|
+
type: time
|
|
35
|
+
duration: 2000 # 等待页面完全加载
|
|
36
|
+
assertions:
|
|
37
|
+
- type: text_contains
|
|
38
|
+
expected: "欢迎登录"
|
|
39
|
+
confidence: high
|
|
40
|
+
- type: element_visible
|
|
41
|
+
target: "盛京金控统一门户平台"
|
|
42
|
+
confidence: high
|
|
43
|
+
|
|
44
|
+
# ===== 步骤 2:输入用户名 =====
|
|
45
|
+
- step: 2
|
|
46
|
+
desc: "在用户名输入框中填入用户名"
|
|
47
|
+
action: fill
|
|
48
|
+
target: "用户"
|
|
49
|
+
locator:
|
|
50
|
+
uid_cache_key: "username_input" # 缓存UID以便后续复用
|
|
51
|
+
value: "${TEST_USER}"
|
|
52
|
+
assertions:
|
|
53
|
+
- type: field_filled
|
|
54
|
+
expected: "字段已填写"
|
|
55
|
+
confidence: high
|
|
56
|
+
- type: value_equals
|
|
57
|
+
expected: "${TEST_USER}"
|
|
58
|
+
confidence: medium
|
|
59
|
+
|
|
60
|
+
# ===== 步骤 3:输入密码 =====
|
|
61
|
+
- step: 3
|
|
62
|
+
desc: "在密码输入框中填入密码"
|
|
63
|
+
action: fill
|
|
64
|
+
target: "密码"
|
|
65
|
+
locator:
|
|
66
|
+
uid_cache_key: "password_input" # 缓存UID
|
|
67
|
+
value: "${TEST_PASS}"
|
|
68
|
+
assertions:
|
|
69
|
+
- type: field_filled
|
|
70
|
+
expected: "字段已填写"
|
|
71
|
+
confidence: high
|
|
72
|
+
# 注意:不验证密码值本身(安全原因),只验证字段非空
|
|
73
|
+
|
|
74
|
+
# ===== 步骤 4:点击登录按钮 =====
|
|
75
|
+
- step: 4
|
|
76
|
+
desc: "点击登录按钮提交登录信息"
|
|
77
|
+
action: click
|
|
78
|
+
target: "登录"
|
|
79
|
+
locator:
|
|
80
|
+
uid_cache_key: "login_button" # 缓存UID
|
|
81
|
+
wait_after:
|
|
82
|
+
type: navigation # 等待页面跳转
|
|
83
|
+
timeout: 10000 # 最长等待10秒
|
|
84
|
+
assertions:
|
|
85
|
+
# 断言 1:页面跳转到首页
|
|
86
|
+
- type: url_contains
|
|
87
|
+
expected: "/sys-portal" # 或其他首页URL特征
|
|
88
|
+
confidence: high
|
|
89
|
+
# 断言 2:显示登录成功的标志
|
|
90
|
+
- type: text_contains
|
|
91
|
+
expected: "统一门户" # 首页标题或欢迎信息
|
|
92
|
+
confidence: high
|
|
93
|
+
# 断言 3:网络校验(深度验证!)
|
|
94
|
+
- type: network_called
|
|
95
|
+
url_pattern: "/api/login*" # 登录接口
|
|
96
|
+
method: POST
|
|
97
|
+
response_code: 200 # 必须返回200
|
|
98
|
+
response_body_contains:
|
|
99
|
+
- '"code":0' # 或其他成功标识
|
|
100
|
+
- '"token"' # 应该返回认证token
|
|
101
|
+
confidence: high
|
|
102
|
+
|
|
103
|
+
# ===== 步骤 5:验证首页关键元素 =====
|
|
104
|
+
- step: 5
|
|
105
|
+
desc: "验证首页加载完成并显示关键元素"
|
|
106
|
+
action: assert_multiple
|
|
107
|
+
assertions:
|
|
108
|
+
# 检查用户信息显示
|
|
109
|
+
- type: element_visible
|
|
110
|
+
target: "待办"
|
|
111
|
+
confidence: high
|
|
112
|
+
# 检查导航菜单
|
|
113
|
+
- type: element_visible
|
|
114
|
+
target: "主导航菜单"
|
|
115
|
+
confidence: high
|
|
116
|
+
# 检查应用图标/快捷方式
|
|
117
|
+
- type: element_count_greater_than
|
|
118
|
+
target: "电子档案"
|
|
119
|
+
min_count: 3 # 至少有3个应用入口
|
|
120
|
+
confidence: medium
|
|
121
|
+
|
|
122
|
+
# 后置清理
|
|
123
|
+
teardown:
|
|
124
|
+
- action: screenshot
|
|
125
|
+
name: "login-success-{timestamp}.png"
|
|
126
|
+
fullPage: true # 全页截图
|
|
127
|
+
- action: log
|
|
128
|
+
message: "登录流程测试完成,当前页面: {current_url}"
|
|
129
|
+
|
|
130
|
+
# 元数据(用于报告和追踪)
|
|
131
|
+
metadata:
|
|
132
|
+
created_by: "testcase-modeler v1.0.1"
|
|
133
|
+
test_environment: "staging"
|
|
134
|
+
browser: "chromium"
|
|
135
|
+
viewport: "1920x1080"
|
|
136
|
+
estimated_duration: "15-30s"
|
|
137
|
+
dependencies:
|
|
138
|
+
- "Chrome DevTools MCP 服务可用"
|
|
139
|
+
- "环境变量 TEST_USER 和 TEST_PASS 已设置"
|
|
140
|
+
- "网络连接正常"
|
|
141
|
+
risk_level: "low" # 只读取数据,不修改任何内容
|
|
142
|
+
|
|
143
|
+
# 变体说明(供Modeler参考)
|
|
144
|
+
variants:
|
|
145
|
+
- name: "错误密码登录"
|
|
146
|
+
description: "验证错误密码时的错误提示"
|
|
147
|
+
modifications:
|
|
148
|
+
- step: 3
|
|
149
|
+
value: "wrong_password"
|
|
150
|
+
- step: 4
|
|
151
|
+
assertions:
|
|
152
|
+
- type: replace
|
|
153
|
+
target: url_contains
|
|
154
|
+
with: error_message_visible
|
|
155
|
+
expected: "用户名或密码错误"
|
|
156
|
+
|
|
157
|
+
- name: "空用户名登录"
|
|
158
|
+
description: "验证必填字段校验"
|
|
159
|
+
modifications:
|
|
160
|
+
- step: 2
|
|
161
|
+
value: ""
|
|
162
|
+
- step: 4
|
|
163
|
+
assertions:
|
|
164
|
+
- type: add
|
|
165
|
+
target: validation_error_visible
|
|
166
|
+
expected: "请输入用户名"
|
|
167
|
+
|
|
168
|
+
- name: "Session过期重登"
|
|
169
|
+
description: "验证Session过期的自动检测和重新登录"
|
|
170
|
+
pre_condition: "已登录但Session已过期"
|
|
171
|
+
expected_behavior: "Agent自动检测到未登录状态,重新执行步骤1-4"
|