speccore 8.3.149 → 8.3.150

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.
@@ -1,76 +1,70 @@
1
- # VERIFY_SPEC.yaml — 企业级 UI 冒烟测试规格(完整示例)
1
+ # VERIFY_SPEC.yaml — UI 冒烟测试规格(真实值示例版)
2
2
  # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
3
3
  # 格式类型: VERIFY_SPEC 格式(scenarios + actions + assertions 结构)
4
- # 适用场景: 精细 UI 交互测试(填写表单、点击按钮、断言元素状态)
5
4
  # 对应命令:
6
- # • speccore verify --ui --spec ./tests/smoke.yaml ← 推荐,原生支持完整交互逻辑
7
- # • speccore verify --ui --config ./tests/smoke.yaml ← 兼容,自动转换为批量页面测试
8
- # 按模块过滤: speccore verify --ui --spec ./tests/smoke.yaml --module=auth
5
+ # • speccore verify --ui --spec ./tests/smoke.yaml ← 推荐
6
+ # • speccore verify --ui --config ./tests/smoke.yaml ← 兼容
7
+ # 按模块过滤: speccore verify --ui --spec ./tests/smoke.yaml --module=login
9
8
  #
10
- # ⚠️ 格式说明:
11
- # VERIFY_SPEC 格式 = scenarios + actions + assertions(本文件,支持完整交互)
12
- # TestConfig 格式 = tests + routes + type(用于批量页面/API测试,见 pr.yaml/release.yaml)
13
- # 两种格式 speccore verify --config 均可自动识别。
14
- #
15
- # 本示例覆盖:
16
- # • 全部 ActionType: fill, click, select, check, uncheck, hover, focus, blur, press,
17
- # wait, navigate, screenshot, cookie, localStorage, script, scroll, upload, iframe,
18
- # waitForRequest, waitForResponse, drag
19
- # • 全部 AssertionType: visible, hidden, text, value, url, count, attribute, style, visual
20
- # • 业务模块: 登录认证 / 用户中心 / 商品 / 购物车 / 订单 / 消息通知 / 后台管理
21
- #
22
- # v8.3.95+ 支持: cookie / localStorage / script / scroll / upload / iframe / waitForRequest / waitForResponse / drag
9
+ # 本文件所有 value / selector 均为真实示例值,使用时替换为你的实际值即可。
10
+ # 选择器建议优先使用 data-testid(最稳定),其次 name / id,避免随机 class。
23
11
 
24
- name: 示例项目冒烟测试(完整版)
12
+ name: 示例项目冒烟测试
25
13
  platform: h5-mobile
26
14
  url: /
27
15
 
28
- # ─────────────────────────────────────────────────────────────────────────────
29
- # 一、登录认证模块 (auth)
30
- # ─────────────────────────────────────────────────────────────────────────────
31
16
  scenarios:
17
+
18
+ # ═══════════════════════════════════════════════════════════════════════════
19
+ # 一、登录认证 (auth)
20
+ # ═══════════════════════════════════════════════════════════════════════════
21
+
32
22
  # ── 场景1: 账号密码登录 ──
23
+ # 说明: 最基础的登录方式,填写用户名密码后点击登录
24
+ # 如何替换: 把 selector 换成你页面上的真实选择器,value 换成你的测试账号
33
25
  - name: 登录-账号密码登录
34
26
  description: 模块:auth 页面:/login
35
27
  actions:
36
28
  - type: navigate
37
- value: /login
29
+ value: /login # 登录页路由
38
30
  - type: fill
39
- selector: 'input[name="username"]'
40
- value: test_user
31
+ selector: 'input[name="username"]' # 用户名输入框(换成你实际的,如 '#username' / '[data-testid="user-input"]')
32
+ value: test_user # 测试账号用户名
41
33
  - type: fill
42
- selector: 'input[name="password"]'
43
- value: test_password
34
+ selector: 'input[name="password"]' # 密码输入框
35
+ value: Test@123456 # 测试账号密码
44
36
  - type: click
45
- selector: 'button[type="submit"]'
46
- waitFor: '.dashboard-container'
37
+ selector: 'button[type="submit"]' # 登录按钮
38
+ waitFor: '.dashboard-container' # 登录成功后出现的元素(用于等待跳转完成)
47
39
  assertions:
48
40
  - type: url
49
- contains: /dashboard
41
+ contains: /dashboard # 断言 URL 跳转到控制台
50
42
  - type: visible
51
- selector: '.dashboard-container'
43
+ selector: '.dashboard-container' # 断言控制台容器可见
52
44
  - type: text
53
- selector: '.user-name'
54
- contains: test_user
45
+ selector: '.user-name' # 断言页面显示用户名
46
+ contains: test_user # 预期显示的用户名
55
47
 
56
48
  # ── 场景2: 手机号+验证码登录 ──
49
+ # 说明: 输入手机号 → 点击获取验证码 → 输入验证码 → 登录
50
+ # 如何替换: 测试环境通常有固定验证码(如123456),或需要 mock 验证码接口
57
51
  - name: 登录-手机号验证码
58
52
  description: 模块:auth 页面:/login/phone
59
53
  actions:
60
54
  - type: navigate
61
- value: /login/phone
55
+ value: /login/phone # 手机号登录页路由
62
56
  - type: fill
63
- selector: 'input[name="phone"]'
64
- value: '13800138000'
57
+ selector: 'input[name="phone"]' # 手机号输入框
58
+ value: '13800138000' # 测试手机号
65
59
  - type: click
66
- selector: '.send-code-btn'
60
+ selector: '.send-code-btn' # 获取验证码按钮
67
61
  - type: wait
68
- delay: 2000
62
+ delay: 2000 # 等待短信发送(测试环境可缩短)
69
63
  - type: fill
70
- selector: 'input[name="verifyCode"]'
71
- value: '123456'
64
+ selector: 'input[name="verifyCode"]' # 验证码输入框
65
+ value: '123456' # 测试环境固定验证码
72
66
  - type: click
73
- selector: 'button[type="submit"]'
67
+ selector: 'button[type="submit"]' # 登录按钮
74
68
  waitFor: '.dashboard-container'
75
69
  assertions:
76
70
  - type: url
@@ -79,35 +73,39 @@ scenarios:
79
73
  selector: '.dashboard-container'
80
74
 
81
75
  # ── 场景3: 微信 OAuth 登录 ──
76
+ # 说明: 点击微信登录按钮 → 跳转微信授权页 → 授权后回调
77
+ # 如何替换: 需配置微信开放平台测试账号,回调域名需与测试环境一致
82
78
  - name: 登录-微信OAuth
83
79
  description: 模块:auth 页面:/login 第三方登录
84
80
  actions:
85
81
  - type: navigate
86
- value: /login
82
+ value: /login # 登录页
87
83
  - type: click
88
- selector: '.wechat-login-btn'
84
+ selector: '.wechat-login-btn' # 微信登录按钮(如 [data-testid="wechat-login"])
89
85
  - type: waitForRequest
90
- selector: 'https://open.weixin.qq.com/connect/oauth2/authorize'
86
+ selector: 'https://open.weixin.qq.com/connect/oauth2/authorize' # 等待跳转微信授权页
91
87
  timeout: 5000
92
88
  - type: wait
93
- delay: 3000
89
+ delay: 3000 # 等待授权回调
94
90
  assertions:
95
91
  - type: url
96
- contains: wechat
92
+ contains: wechat # 断言 URL 包含微信域名
97
93
 
98
94
  # ── 场景4: 企业微信 SSO 登录 ──
95
+ # 说明: 页面内嵌 iframe 展示企业微信登录 → 填写企业 ID → 授权
96
+ # 如何替换: 企业 ID 从企业微信管理后台获取(格式: wwxxxxxxxxxxxxxxxx)
99
97
  - name: 登录-企业微信SSO
100
98
  description: 模块:auth 页面:/login/sso
101
99
  actions:
102
100
  - type: navigate
103
- value: /login/sso
101
+ value: /login/sso # SSO 登录页
104
102
  - type: iframe
105
- selector: '#sso-frame'
103
+ selector: '#sso-frame' # iframe 选择器(切换上下文到 iframe 内部)
106
104
  - type: fill
107
- selector: 'input[name="corpId"]'
108
- value: 'ww1234567890abcdef'
105
+ selector: 'input[name="corpId"]' # 企业 ID 输入框(在 iframe 内)
106
+ value: 'ww1234567890abcdef' # 企业微信企业 ID
109
107
  - type: click
110
- selector: '.sso-submit-btn'
108
+ selector: '.sso-submit-btn' # 确认按钮(在 iframe 内)
111
109
  waitFor: '.dashboard-container'
112
110
  assertions:
113
111
  - type: url
@@ -116,24 +114,28 @@ scenarios:
116
114
  selector: '.dashboard-container'
117
115
 
118
116
  # ── 场景5: 扫码登录 ──
117
+ # 说明: 进入扫码页 → 二维码渲染 → 等待扫码 → 登录成功
118
+ # 如何替换: 测试环境可用 mock 接口模拟扫码成功,避免人工操作
119
119
  - name: 登录-扫码登录
120
120
  description: 模块:auth 页面:/login/qrcode
121
121
  actions:
122
122
  - type: navigate
123
- value: /login/qrcode
123
+ value: /login/qrcode # 扫码登录页
124
124
  - type: visible
125
- selector: '.qrcode-img'
125
+ selector: '.qrcode-img' # 断言二维码图片已渲染
126
126
  - type: wait
127
- delay: 5000
127
+ delay: 5000 # 等待扫码(测试环境可 mock 缩短)
128
128
  assertions:
129
129
  - type: visible
130
130
  selector: '.qrcode-img'
131
131
  - type: attribute
132
- selector: '.qrcode-img'
133
- attribute: src
134
- contains: data:image
132
+ selector: '.qrcode-img' # 断言二维码图片
133
+ attribute: src # 检查 src 属性
134
+ contains: data:image # 包含 base64 图片数据
135
135
 
136
136
  # ── 场景6: 登录失败-密码错误 ──
137
+ # 说明: 故意输错密码,验证错误提示是否正确
138
+ # 如何替换: value 填存在的账号 + 错误的密码
137
139
  - name: 登录-密码错误提示
138
140
  description: 模块:auth 页面:/login 异常场景
139
141
  actions:
@@ -141,22 +143,23 @@ scenarios:
141
143
  value: /login
142
144
  - type: fill
143
145
  selector: 'input[name="username"]'
144
- value: test_user
146
+ value: test_user # 存在的用户名
145
147
  - type: fill
146
148
  selector: 'input[name="password"]'
147
- value: wrong_password
149
+ value: wrong_password # 故意填错密码
148
150
  - type: click
149
151
  selector: 'button[type="submit"]'
150
152
  - type: wait
151
- delay: 1000
153
+ delay: 1000 # 等待错误提示出现
152
154
  assertions:
153
155
  - type: visible
154
- selector: '.error-message'
156
+ selector: '.error-message' # 错误提示元素
155
157
  - type: text
156
158
  selector: '.error-message'
157
- contains: 密码错误
159
+ contains: 密码错误 # 根据实际文案调整(如"用户名或密码错误")
158
160
 
159
161
  # ── 场景7: 登录失败-账号锁定 ──
162
+ # 说明: 使用被锁定的账号登录,验证锁定提示
160
163
  - name: 登录-账号锁定提示
161
164
  description: 模块:auth 页面:/login 异常场景
162
165
  actions:
@@ -164,10 +167,10 @@ scenarios:
164
167
  value: /login
165
168
  - type: fill
166
169
  selector: 'input[name="username"]'
167
- value: locked_user
170
+ value: locked_user # 被锁定的测试账号
168
171
  - type: fill
169
172
  selector: 'input[name="password"]'
170
- value: any_password
173
+ value: any_password # 任意密码
171
174
  - type: click
172
175
  selector: 'button[type="submit"]'
173
176
  - type: wait
@@ -177,114 +180,121 @@ scenarios:
177
180
  selector: '.error-message'
178
181
  - type: text
179
182
  selector: '.error-message'
180
- contains: 账号已被锁定
183
+ contains: 账号已被锁定 # 根据实际文案调整
181
184
 
182
- # ── 场景8: 记住密码功能 ──
185
+ # ── 场景8: 记住密码 ──
186
+ # 说明: 勾选记住密码 → 登录 → 验证 Cookie 中写入记住密码标记
183
187
  - name: 登录-记住密码
184
188
  description: 模块:auth 页面:/login 记住密码勾选
185
189
  actions:
186
190
  - type: navigate
187
191
  value: /login
188
192
  - type: check
189
- selector: 'input[name="rememberMe"]'
193
+ selector: 'input[name="rememberMe"]' # 记住密码复选框
190
194
  - type: fill
191
195
  selector: 'input[name="username"]'
192
196
  value: test_user
193
197
  - type: fill
194
198
  selector: 'input[name="password"]'
195
- value: test_password
199
+ value: Test@123456
196
200
  - type: click
197
201
  selector: 'button[type="submit"]'
198
202
  waitFor: '.dashboard-container'
199
203
  assertions:
200
204
  - type: cookie
201
- selector: remember_me
202
- contains: 'true'
205
+ selector: remember_me # Cookie 名称
206
+ contains: 'true' # Cookie 值包含 true
203
207
 
204
208
  # ── 场景9: 退出登录 ──
209
+ # 说明: 点击用户头像展开菜单 → 点击退出 → 验证跳回登录页
205
210
  - name: 登录-退出登录
206
211
  description: 模块:auth 页面:/dashboard
207
212
  actions:
208
213
  - type: navigate
209
- value: /dashboard
214
+ value: /dashboard # 已登录后的首页
210
215
  - type: click
211
- selector: '.user-avatar'
216
+ selector: '.user-avatar' # 用户头像/菜单触发器
212
217
  - type: click
213
- selector: '.logout-btn'
218
+ selector: '.logout-btn' # 退出按钮
214
219
  - type: wait
215
- delay: 1000
220
+ delay: 1000 # 等待跳转
216
221
  assertions:
217
222
  - type: url
218
- contains: /login
223
+ contains: /login # 断言回到登录页
219
224
  - type: visible
220
- selector: '.login-form'
225
+ selector: '.login-form' # 断言登录表单可见
221
226
 
222
- # ─────────────────────────────────────────────────────────────────────────────
223
- # 二、用户中心模块 (user)
224
- # ─────────────────────────────────────────────────────────────────────────────
227
+ # ═══════════════════════════════════════════════════════════════════════════
228
+ # 二、用户中心 (user)
229
+ # ═══════════════════════════════════════════════════════════════════════════
225
230
 
226
- # ── 场景10: 个人资料修改 ──
231
+ # ── 场景10: 修改个人资料 ──
232
+ # 说明: 修改昵称、性别、邮箱,点击保存
233
+ # select 说明: value 填 option 的 value 属性(不是显示文本)
227
234
  - name: 用户-修改个人资料
228
235
  description: 模块:user 页面:/profile/edit
229
236
  actions:
230
237
  - type: navigate
231
- value: /profile/edit
238
+ value: /profile/edit # 个人资料编辑页
232
239
  - type: fill
233
- selector: 'input[name="nickname"]'
234
- value: 新昵称测试
240
+ selector: 'input[name="nickname"]' # 昵称输入框
241
+ value: 新昵称测试 # 新昵称
235
242
  - type: select
236
- selector: 'select[name="gender"]'
237
- value: female
243
+ selector: 'select[name="gender"]' # 性别下拉框
244
+ value: female # option 的 value 值(如 female/male/unknown)
238
245
  - type: fill
239
- selector: 'input[name="email"]'
240
- value: 'newemail@example.com'
246
+ selector: 'input[name="email"]' # 邮箱输入框
247
+ value: 'newemail@example.com' # 新邮箱
241
248
  - type: click
242
- selector: '.save-profile-btn'
249
+ selector: '.save-profile-btn' # 保存按钮
243
250
  - type: wait
244
- delay: 1500
251
+ delay: 1500 # 等待保存接口返回
245
252
  assertions:
246
253
  - type: visible
247
- selector: '.toast-success'
254
+ selector: '.toast-success' # 成功提示元素
248
255
  - type: text
249
256
  selector: '.toast-success'
250
- contains: 保存成功
257
+ contains: 保存成功 # 预期提示文案
251
258
 
252
- # ── 场景11: 头像上传 ──
259
+ # ── 场景11: 上传头像 ──
260
+ # 说明: 选择本地图片文件上传,验证预览图更新
261
+ # upload 说明: value 为本地文件路径(相对项目根目录或绝对路径)
253
262
  - name: 用户-上传头像
254
263
  description: 模块:user 页面:/profile/edit 头像上传
255
264
  actions:
256
265
  - type: navigate
257
266
  value: /profile/edit
258
267
  - type: upload
259
- selector: 'input[type="file"].avatar-upload'
260
- value: ./fixtures/test-avatar.png
268
+ selector: 'input[type="file"].avatar-upload' # 文件输入框
269
+ value: ./fixtures/test-avatar.png # 本地图片路径(确保文件存在)
261
270
  - type: wait
262
- delay: 2000
271
+ delay: 2000 # 等待上传完成
263
272
  assertions:
264
273
  - type: visible
265
- selector: '.avatar-preview img'
274
+ selector: '.avatar-preview img' # 头像预览图
266
275
  - type: attribute
267
276
  selector: '.avatar-preview img'
268
- attribute: src
269
- contains: avatar
277
+ attribute: src # 断言 src 属性已更新
278
+ contains: avatar # 包含 avatar 路径
270
279
 
271
280
  # ── 场景12: 修改密码 ──
281
+ # 说明: 填写旧密码 + 新密码 + 确认密码,点击修改
272
282
  - name: 用户-修改密码
273
283
  description: 模块:user 页面:/profile/security
274
284
  actions:
275
285
  - type: navigate
276
- value: /profile/security
286
+ value: /profile/security # 安全设置页
277
287
  - type: fill
278
- selector: 'input[name="oldPassword"]'
279
- value: old_pass_123
288
+ selector: 'input[name="oldPassword"]' # 旧密码
289
+ value: OldPass123 # 当前密码
280
290
  - type: fill
281
- selector: 'input[name="newPassword"]'
282
- value: new_pass_456
291
+ selector: 'input[name="newPassword"]' # 新密码
292
+ value: NewPass456 # 新密码
283
293
  - type: fill
284
- selector: 'input[name="confirmPassword"]'
285
- value: new_pass_456
294
+ selector: 'input[name="confirmPassword"]' # 确认密码
295
+ value: NewPass456 # 与新密码保持一致
286
296
  - type: click
287
- selector: '.change-password-btn'
297
+ selector: '.change-password-btn' # 确认修改按钮
288
298
  - type: wait
289
299
  delay: 1500
290
300
  assertions:
@@ -294,100 +304,106 @@ scenarios:
294
304
  selector: '.toast-success'
295
305
  contains: 密码修改成功
296
306
 
297
- # ── 场景13: Token 注入免登录(localStorage) ──
307
+ # ── 场景13: Token 注入免登录 ──
308
+ # 说明: 直接通过 localStorage 注入 JWT,跳过登录流程
309
+ # 适用场景: 测试环境已有固定账号,不需重复测试登录
298
310
  - name: 用户-Token注入免登录
299
311
  description: 模块:user 页面:/profile Token注入方式
300
312
  actions:
301
313
  - type: localStorage
302
- selector: accessToken
303
- value: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
314
+ selector: accessToken # localStorage key 名
315
+ value: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEwMDg2fQ.test' # JWT Token
304
316
  - type: localStorage
305
- selector: refreshToken
306
- value: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
317
+ selector: refreshToken # 同时注入 refreshToken
318
+ value: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoicmVmcmVzaCJ9.test'
307
319
  - type: navigate
308
- value: /profile
320
+ value: /profile # 直接访问需要登录的页面
309
321
  - type: wait
310
322
  delay: 800
311
323
  assertions:
312
324
  - type: visible
313
- selector: '.profile-header'
325
+ selector: '.profile-header' # 断言个人中心头部可见
314
326
  - type: text
315
- selector: '.username'
327
+ selector: '.username' # 断言显示用户名
316
328
  contains: test_user
317
329
 
318
- # ─────────────────────────────────────────────────────────────────────────────
319
- # 三、商品模块 (product)
320
- # ─────────────────────────────────────────────────────────────────────────────
330
+ # ═══════════════════════════════════════════════════════════════════════════
331
+ # 三、商品模块 (product)
332
+ # ═══════════════════════════════════════════════════════════════════════════
321
333
 
322
334
  # ── 场景14: 商品列表浏览 ──
335
+ # 说明: 进入商品列表 → 滚动到底部 → 验证商品数量
323
336
  - name: 商品-列表浏览
324
337
  description: 模块:product 页面:/products
325
338
  actions:
326
339
  - type: navigate
327
- value: /products
340
+ value: /products # 商品列表页
328
341
  - type: scroll
329
- selector: bottom
342
+ selector: bottom # 滚动到页面底部(触发懒加载)
330
343
  - type: wait
331
344
  delay: 1000
332
345
  assertions:
333
346
  - type: visible
334
- selector: '.product-list'
347
+ selector: '.product-list' # 商品列表容器
335
348
  - type: count
336
- selector: '.product-item'
337
- count: 10
349
+ selector: '.product-item' # 商品卡片
350
+ count: 10 # 预期至少 10 个商品
338
351
 
339
352
  # ── 场景15: 商品搜索 ──
353
+ # 说明: 输入关键词 → 按回车 → 验证搜索结果
340
354
  - name: 商品-搜索
341
355
  description: 模块:product 页面:/products 搜索功能
342
356
  actions:
343
357
  - type: navigate
344
358
  value: /products
345
359
  - type: fill
346
- selector: 'input[name="keyword"]'
347
- value: iPhone
360
+ selector: 'input[name="keyword"]' # 搜索框
361
+ value: iPhone # 搜索关键词
348
362
  - type: press
349
- key: Enter
363
+ key: Enter # 按回车触发搜索
350
364
  - type: wait
351
- delay: 1500
365
+ delay: 1500 # 等待搜索结果返回
352
366
  assertions:
353
367
  - type: visible
354
- selector: '.search-result-list'
368
+ selector: '.search-result-list' # 搜索结果列表
355
369
  - type: count
356
370
  selector: '.product-item'
357
- count: 3
371
+ count: 3 # 预期至少 3 个结果
358
372
 
359
373
  # ── 场景16: 商品详情 ──
374
+ # 说明: 点击商品标题进入详情页,验证详情信息展示
360
375
  - name: 商品-详情页
361
376
  description: 模块:product 页面:/products/:id
362
377
  actions:
363
378
  - type: navigate
364
379
  value: /products
365
380
  - type: click
366
- selector: '.product-item:first-child .product-title'
381
+ selector: '.product-item:first-child .product-title' # 点击第一个商品的标题
367
382
  - type: wait
368
383
  delay: 1000
369
384
  assertions:
370
385
  - type: visible
371
- selector: '.product-detail'
386
+ selector: '.product-detail' # 详情页容器
372
387
  - type: text
373
- selector: '.product-name'
374
- contains: iPhone
388
+ selector: '.product-name' # 商品名称
389
+ contains: iPhone # 包含搜索关键词
375
390
  - type: visible
376
- selector: '.product-price'
391
+ selector: '.product-price' # 价格元素
377
392
 
378
- # ── 场景17: 商品筛选 ──
393
+ # ── 场景17: 商品多条件筛选 ──
394
+ # 说明: 同时选择分类 + 库存状态,验证筛选结果
379
395
  - name: 商品-多条件筛选
380
396
  description: 模块:product 页面:/products 筛选功能
381
397
  actions:
382
398
  - type: navigate
383
399
  value: /products
384
400
  - type: select
385
- selector: 'select[name="category"]'
386
- value: electronics
401
+ selector: 'select[name="category"]' # 分类下拉框
402
+ value: electronics # option value(如 electronics/clothing/food)
387
403
  - type: check
388
- selector: 'input[value="inStock"]'
404
+ selector: 'input[value="inStock"]' # 仅看有库存(复选框)
389
405
  - type: click
390
- selector: '.filter-submit-btn'
406
+ selector: '.filter-submit-btn' # 确认筛选按钮
391
407
  - type: wait
392
408
  delay: 1200
393
409
  assertions:
@@ -395,155 +411,162 @@ scenarios:
395
411
  selector: '.product-list'
396
412
  - type: count
397
413
  selector: '.product-item'
398
- count: 5
414
+ count: 5 # 筛选后预期 5 个商品
399
415
 
400
416
  # ── 场景18: 商品收藏 ──
417
+ # 说明: 点击收藏按钮,验证按钮颜色变为红色(已收藏状态)
401
418
  - name: 商品-收藏/取消收藏
402
419
  description: 模块:product 页面:/products/:id 收藏功能
403
420
  actions:
404
421
  - type: navigate
405
- value: /products/123
422
+ value: /products/123 # 某个商品详情页(123 为商品 ID)
406
423
  - type: click
407
- selector: '.favorite-btn'
424
+ selector: '.favorite-btn' # 收藏按钮(空心)
408
425
  - type: wait
409
426
  delay: 500
410
427
  assertions:
411
428
  - type: style
412
- selector: '.favorite-btn'
413
- style: color
414
- value: rgb(255, 77, 79)
429
+ selector: '.favorite-btn' # 断言按钮样式变化
430
+ style: color # CSS 属性: 颜色
431
+ value: rgb(255, 77, 79) # 预期变为红色(根据实际样式调整)
415
432
 
416
- # ─────────────────────────────────────────────────────────────────────────────
417
- # 四、购物车模块 (cart)
418
- # ─────────────────────────────────────────────────────────────────────────────
433
+ # ═══════════════════════════════════════════════════════════════════════════
434
+ # 四、购物车 (cart)
435
+ # ═══════════════════════════════════════════════════════════════════════════
419
436
 
420
437
  # ── 场景19: 添加商品到购物车 ──
438
+ # 说明: 商品详情页点击加购,验证购物车角标数字更新
421
439
  - name: 购物车-添加商品
422
440
  description: 模块:cart 页面:/products/:id
423
441
  actions:
424
442
  - type: navigate
425
- value: /products/123
443
+ value: /products/123 # 商品详情页
426
444
  - type: click
427
- selector: '.add-to-cart-btn'
445
+ selector: '.add-to-cart-btn' # 加入购物车按钮
428
446
  - type: wait
429
- delay: 800
447
+ delay: 800 # 等待加购动画/接口
430
448
  assertions:
431
449
  - type: visible
432
- selector: '.cart-badge'
450
+ selector: '.cart-badge' # 购物车角标
433
451
  - type: text
434
452
  selector: '.cart-badge'
435
- contains: '1'
453
+ contains: '1' # 角标显示 1
436
454
 
437
- # ── 场景20: 购物车数量修改 ──
455
+ # ── 场景20: 修改购物车商品数量 ──
456
+ # 说明: 修改数量输入框 → 失去焦点触发计算 → 验证小计金额更新
438
457
  - name: 购物车-修改数量
439
458
  description: 模块:cart 页面:/cart
440
459
  actions:
441
460
  - type: navigate
442
- value: /cart
461
+ value: /cart # 购物车页面
443
462
  - type: fill
444
- selector: '.cart-item:first-child .quantity-input'
445
- value: '3'
463
+ selector: '.cart-item:first-child .quantity-input' # 第一个商品的数量输入框
464
+ value: '3' # 修改为 3 件
446
465
  - type: blur
447
- selector: '.cart-item:first-child .quantity-input'
466
+ selector: '.cart-item:first-child .quantity-input' # 触发 blur 事件(触发价格重算)
448
467
  - type: wait
449
468
  delay: 800
450
469
  assertions:
451
470
  - type: text
452
- selector: '.cart-item:first-child .subtotal'
453
- contains: '¥'
471
+ selector: '.cart-item:first-child .subtotal' # 小计金额
472
+ contains: '¥' # 包含人民币符号(断言金额已更新)
454
473
 
455
- # ── 场景21: 购物车结算 ──
474
+ # ── 场景21: 购物车去结算 ──
475
+ # 说明: 勾选商品 → 点击结算 → 验证跳转到结算页
456
476
  - name: 购物车-去结算
457
477
  description: 模块:cart 页面:/cart
458
478
  actions:
459
479
  - type: navigate
460
480
  value: /cart
461
481
  - type: check
462
- selector: '.cart-item:first-child .item-checkbox'
482
+ selector: '.cart-item:first-child .item-checkbox' # 勾选第一个商品
463
483
  - type: click
464
- selector: '.checkout-btn'
484
+ selector: '.checkout-btn' # 去结算按钮
465
485
  - type: wait
466
486
  delay: 1500
467
487
  assertions:
468
488
  - type: url
469
- contains: /checkout
489
+ contains: /checkout # 断言跳转到结算页
470
490
  - type: visible
471
- selector: '.checkout-form'
491
+ selector: '.checkout-form' # 结算表单
472
492
 
473
- # ── 场景22: 购物车删除商品 ──
493
+ # ── 场景22: 删除购物车商品 ──
494
+ # 说明: 点击删除按钮,验证商品被移除
474
495
  - name: 购物车-删除商品
475
496
  description: 模块:cart 页面:/cart
476
497
  actions:
477
498
  - type: navigate
478
499
  value: /cart
479
500
  - type: click
480
- selector: '.cart-item:first-child .delete-btn'
501
+ selector: '.cart-item:first-child .delete-btn' # 删除按钮
481
502
  - type: wait
482
503
  delay: 800
483
504
  assertions:
484
505
  - type: count
485
- selector: '.cart-item'
486
- count: 0
506
+ selector: '.cart-item' # 断言购物车商品数量
507
+ count: 0 # 预期为 0(空购物车)
487
508
 
488
- # ─────────────────────────────────────────────────────────────────────────────
489
- # 五、订单模块 (order)
490
- # ─────────────────────────────────────────────────────────────────────────────
509
+ # ═══════════════════════════════════════════════════════════════════════════
510
+ # 五、订单模块 (order)
511
+ # ═══════════════════════════════════════════════════════════════════════════
491
512
 
492
- # ── 场景23: 订单创建 ──
513
+ # ── 场景23: 创建订单 ──
514
+ # 说明: 填写收货信息 → 提交订单 → 验证订单创建成功
493
515
  - name: 订单-创建订单
494
516
  description: 模块:order 页面:/checkout
495
517
  actions:
496
518
  - type: navigate
497
- value: /checkout
519
+ value: /checkout # 结算页
498
520
  - type: fill
499
- selector: 'input[name="receiverName"]'
500
- value: 张三
521
+ selector: 'input[name="receiverName"]' # 收货人姓名
522
+ value: 张三 # 真实姓名或测试姓名
501
523
  - type: fill
502
- selector: 'input[name="phone"]'
524
+ selector: 'input[name="phone"]' # 手机号
503
525
  value: '13800138000'
504
526
  - type: fill
505
- selector: 'input[name="address"]'
506
- value: 北京市朝阳区测试街道123号
527
+ selector: 'input[name="address"]' # 详细地址
528
+ value: 北京市朝阳区测试街道123号 # 测试地址
507
529
  - type: click
508
- selector: '.submit-order-btn'
530
+ selector: '.submit-order-btn' # 提交订单按钮
509
531
  - type: wait
510
- delay: 2000
532
+ delay: 2000 # 等待订单创建接口
511
533
  assertions:
512
534
  - type: url
513
- contains: /order/success
535
+ contains: /order/success # 断言跳转到成功页
514
536
  - type: visible
515
- selector: '.order-success'
537
+ selector: '.order-success' # 成功提示
516
538
  - type: text
517
539
  selector: '.order-success'
518
540
  contains: 订单提交成功
519
541
 
520
542
  # ── 场景24: 订单支付 ──
543
+ # 说明: 选择支付方式 → 确认支付 → 等待支付接口返回 → 验证成功
521
544
  - name: 订单-支付订单
522
545
  description: 模块:order 页面:/pay/:orderId
523
546
  actions:
524
547
  - type: navigate
525
- value: /pay/ORD202409110001
548
+ value: /pay/ORD202409110001 # 支付页(ORD202409110001 为订单号)
526
549
  - type: click
527
- selector: '.pay-method-wechat'
550
+ selector: '.pay-method-wechat' # 选择微信支付
528
551
  - type: click
529
- selector: '.confirm-pay-btn'
552
+ selector: '.confirm-pay-btn' # 确认支付按钮
530
553
  - type: waitForResponse
531
- selector: '/api/pay/create'
532
- timeout: 10000
554
+ selector: '/api/pay/create' # 等待支付创建接口返回
555
+ timeout: 10000 # 支付接口较慢,超时设 10 秒
533
556
  - type: wait
534
557
  delay: 2000
535
558
  assertions:
536
559
  - type: url
537
- contains: /pay/success
560
+ contains: /pay/success # 断言跳转到支付成功页
538
561
  - type: visible
539
562
  selector: '.pay-success'
540
563
 
541
- # ── 场景25: 订单列表 ──
564
+ # ── 场景25: 订单列表查询 ──
542
565
  - name: 订单-列表查询
543
566
  description: 模块:order 页面:/orders
544
567
  actions:
545
568
  - type: navigate
546
- value: /orders
569
+ value: /orders # 订单列表页
547
570
  - type: wait
548
571
  delay: 1000
549
572
  assertions:
@@ -551,54 +574,55 @@ scenarios:
551
574
  selector: '.order-list'
552
575
  - type: count
553
576
  selector: '.order-item'
554
- count: 5
577
+ count: 5 # 预期至少 5 个订单
555
578
 
556
- # ── 场景26: 订单详情 ──
579
+ # ── 场景26: 订单详情查看 ──
557
580
  - name: 订单-详情查看
558
581
  description: 模块:order 页面:/orders/:id
559
582
  actions:
560
583
  - type: navigate
561
584
  value: /orders
562
585
  - type: click
563
- selector: '.order-item:first-child .view-detail-btn'
586
+ selector: '.order-item:first-child .view-detail-btn' # 查看第一个订单详情
564
587
  - type: wait
565
588
  delay: 800
566
589
  assertions:
567
590
  - type: visible
568
591
  selector: '.order-detail'
569
592
  - type: text
570
- selector: '.order-status'
571
- contains: 待付款
593
+ selector: '.order-status' # 订单状态
594
+ contains: 待付款 # 预期状态文案
572
595
 
573
- # ── 场景27: 订单取消 ──
596
+ # ── 场景27: 取消订单 ──
597
+ # 说明: 点击取消 → 确认取消 → 验证状态变为已取消
574
598
  - name: 订单-取消订单
575
599
  description: 模块:order 页面:/orders/:id
576
600
  actions:
577
601
  - type: navigate
578
- value: /orders/ORD202409110001
602
+ value: /orders/ORD202409110001 # 某个待付款订单
579
603
  - type: click
580
- selector: '.cancel-order-btn'
604
+ selector: '.cancel-order-btn' # 取消订单按钮
581
605
  - type: wait
582
- delay: 500
606
+ delay: 500 # 等待确认弹窗
583
607
  - type: click
584
- selector: '.confirm-cancel-btn'
608
+ selector: '.confirm-cancel-btn' # 确认取消按钮
585
609
  - type: wait
586
- delay: 1500
610
+ delay: 1500 # 等待取消接口返回
587
611
  assertions:
588
612
  - type: text
589
613
  selector: '.order-status'
590
- contains: 已取消
614
+ contains: 已取消 # 状态变为已取消
591
615
 
592
- # ─────────────────────────────────────────────────────────────────────────────
593
- # 六、消息通知模块 (notification)
594
- # ─────────────────────────────────────────────────────────────────────────────
616
+ # ═══════════════════════════════════════════════════════════════════════════
617
+ # 六、消息通知 (notification)
618
+ # ═══════════════════════════════════════════════════════════════════════════
595
619
 
596
- # ── 场景28: 消息列表 ──
620
+ # ── 场景28: 消息列表查看 ──
597
621
  - name: 消息-列表查看
598
622
  description: 模块:notification 页面:/notifications
599
623
  actions:
600
624
  - type: navigate
601
- value: /notifications
625
+ value: /notifications # 消息中心
602
626
  - type: wait
603
627
  delay: 1000
604
628
  assertions:
@@ -606,98 +630,103 @@ scenarios:
606
630
  selector: '.notification-list'
607
631
  - type: count
608
632
  selector: '.notification-item'
609
- count: 3
633
+ count: 3 # 预期 3 条未读消息
610
634
 
611
635
  # ── 场景29: 消息标记已读 ──
636
+ # 说明: 点击消息 → 验证字体从粗体变为正常(已读状态)
612
637
  - name: 消息-标记已读
613
638
  description: 模块:notification 页面:/notifications
614
639
  actions:
615
640
  - type: navigate
616
641
  value: /notifications
617
642
  - type: click
618
- selector: '.notification-item:first-child'
643
+ selector: '.notification-item:first-child' # 点击第一条消息
619
644
  - type: wait
620
645
  delay: 500
621
646
  assertions:
622
647
  - type: style
623
648
  selector: '.notification-item:first-child'
624
- style: font-weight
625
- value: '400'
649
+ style: font-weight # CSS 属性: 字重
650
+ value: '400' # 400 = normal(已读),700 = bold(未读)
626
651
 
627
- # ─────────────────────────────────────────────────────────────────────────────
628
- # 七、后台管理模块 (admin)
629
- # ─────────────────────────────────────────────────────────────────────────────
652
+ # ═══════════════════════════════════════════════════════════════════════════
653
+ # 七、后台管理 (admin)
654
+ # ═══════════════════════════════════════════════════════════════════════════
630
655
 
631
656
  # ── 场景30: 用户管理列表 ──
632
657
  - name: 后台-用户管理
633
658
  description: 模块:admin 页面:/admin/users
634
659
  actions:
635
660
  - type: navigate
636
- value: /admin/users
661
+ value: /admin/users # 后台用户管理页
637
662
  - type: wait
638
- delay: 1500
663
+ delay: 1500 # 等待表格数据加载
639
664
  assertions:
640
665
  - type: visible
641
- selector: '.user-table'
666
+ selector: '.user-table' # 用户表格
642
667
  - type: count
643
- selector: '.user-table tbody tr'
644
- count: 10
668
+ selector: '.user-table tbody tr' # 表格行数
669
+ count: 10 # 预期 10 条用户数据
645
670
 
646
671
  # ── 场景31: 数据报表(iframe 嵌入) ──
672
+ # 说明: 后台报表通常用 iframe 嵌入第三方 BI 工具(如帆软、Tableau)
647
673
  - name: 后台-数据报表iframe
648
674
  description: 模块:admin 页面:/admin/reports iframe嵌入
649
675
  actions:
650
676
  - type: navigate
651
- value: /admin/reports
677
+ value: /admin/reports # 报表页面
652
678
  - type: iframe
653
- selector: '#report-frame'
679
+ selector: '#report-frame' # 报表 iframe
654
680
  - type: wait
655
- delay: 2000
681
+ delay: 2000 # 等待 iframe 内报表加载
656
682
  assertions:
657
683
  - type: visible
658
- selector: '.chart-container'
684
+ selector: '.chart-container' # 图表容器(在 iframe 内)
659
685
  - type: count
660
- selector: '.chart-item'
661
- count: 4
686
+ selector: '.chart-item' # 图表数量
687
+ count: 4 # 预期 4 个图表
662
688
 
663
689
  # ── 场景32: 拖拽排序 ──
690
+ # 说明: 拖拽分类/菜单项调整顺序
664
691
  - name: 后台-拖拽排序
665
692
  description: 模块:admin 页面:/admin/categories 拖拽排序
666
693
  actions:
667
694
  - type: navigate
668
- value: /admin/categories
695
+ value: /admin/categories # 分类管理页
669
696
  - type: drag
670
- selector: '.category-item:first-child'
671
- toSelector: '.category-item:last-child'
697
+ selector: '.category-item:first-child' # 拖拽第一个分类
698
+ toSelector: '.category-item:last-child' # 放到最后一个位置
672
699
  - type: wait
673
- delay: 1000
700
+ delay: 1000 # 等待保存接口
674
701
  assertions:
675
702
  - type: text
676
- selector: '.category-item:last-child .category-name'
677
- contains: 原第一个分类
703
+ selector: '.category-item:last-child .category-name' # 断言最后一个分类的名称
704
+ contains: 原第一个分类 # 确认拖拽成功
678
705
 
679
- # ─────────────────────────────────────────────────────────────────────────────
680
- # 八、通用能力与高级特性
681
- # ─────────────────────────────────────────────────────────────────────────────
706
+ # ═══════════════════════════════════════════════════════════════════════════
707
+ # 八、通用能力
708
+ # ═══════════════════════════════════════════════════════════════════════════
682
709
 
683
710
  # ── 场景33: Cookie 注入免登录 ──
711
+ # 说明: 直接注入 session Cookie,跳过登录页,适合批量测试业务模块
712
+ # 如何获取 Cookie: 在浏览器开发者工具 → Application → Cookies 中复制
684
713
  - name: 通用-Cookie注入免登录
685
714
  description: 模块:common Cookie注入跳过登录
686
715
  actions:
687
716
  - type: cookie
688
- selector: session_token
689
- value: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
690
- domain: example.com
691
- path: /
692
- secure: true
693
- httpOnly: true
717
+ selector: session_token # Cookie 名称
718
+ value: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEwMDg2fQ.test' # Cookie 值
719
+ domain: example.com # Cookie 域名(必须与测试站点一致)
720
+ path: / # Cookie 路径
721
+ secure: true # 仅 HTTPS 传输
722
+ httpOnly: true # 禁止 JS 读取
694
723
  - type: cookie
695
- selector: user_id
724
+ selector: user_id # 同时注入 user_id
696
725
  value: '10086'
697
726
  domain: example.com
698
727
  path: /
699
728
  - type: navigate
700
- value: /dashboard
729
+ value: /dashboard # 直接访问需登录页面
701
730
  - type: wait
702
731
  delay: 1000
703
732
  assertions:
@@ -714,21 +743,22 @@ scenarios:
714
743
  - type: navigate
715
744
  value: /
716
745
  - type: scroll
717
- selector: bottom
746
+ selector: bottom # 滚动到底部
718
747
  - type: wait
719
748
  delay: 1500
720
749
  - type: scroll
721
- selector: bottom
750
+ selector: bottom # 再次滚动(触发第二轮加载)
722
751
  - type: wait
723
752
  delay: 1500
724
753
  assertions:
725
754
  - type: visible
726
- selector: '.load-more-btn'
755
+ selector: '.load-more-btn' # 加载更多按钮
727
756
  - type: count
728
- selector: '.product-card'
729
- count: 20
757
+ selector: '.product-card' # 商品卡片总数
758
+ count: 20 # 预期加载了 20 个商品
730
759
 
731
760
  # ── 场景35: 样式断言 ──
761
+ # 说明: 验证按钮颜色、圆角等样式是否符合设计稿
732
762
  - name: 通用-按钮样式检查
733
763
  description: 模块:ui 页面:/
734
764
  actions:
@@ -736,39 +766,42 @@ scenarios:
736
766
  value: /
737
767
  assertions:
738
768
  - type: style
739
- selector: '.primary-btn'
740
- style: background-color
741
- value: rgb(24, 144, 255)
769
+ selector: '.primary-btn' # 主按钮
770
+ style: background-color # CSS 属性: 背景色
771
+ value: rgb(24, 144, 255) # 预期颜色(根据设计稿调整)
742
772
  - type: style
743
773
  selector: '.primary-btn'
744
- style: border-radius
745
- value: 4px
774
+ style: border-radius # CSS 属性: 圆角
775
+ value: 4px # 预期 4px 圆角
746
776
 
747
777
  # ── 场景36: 视觉对比测试 ──
778
+ # 说明: 截图后与基线图片对比,检测 UI 回归
779
+ # 前置条件: 先执行一次生成基线图片,后续对比以此为准
748
780
  - name: 通用-视觉对比测试
749
781
  description: 模块:ui 页面:/ 视觉回归
750
782
  actions:
751
783
  - type: navigate
752
784
  value: /
753
- - type: screenshot
785
+ - type: screenshot # 页面截图
754
786
  assertions:
755
787
  - type: visual
756
- selector: 'body'
757
- threshold: normal
788
+ selector: 'body' # 对比整个页面
789
+ threshold: normal # 阈值: strict/normal/loose
758
790
 
759
791
  # ── 场景37: 键盘操作 ──
792
+ # 说明: 聚焦搜索框 → 输入关键词 → 按回车触发搜索
760
793
  - name: 通用-键盘操作
761
794
  description: 模块:common 页面:/products 键盘导航
762
795
  actions:
763
796
  - type: navigate
764
797
  value: /products
765
798
  - type: focus
766
- selector: 'input[name="keyword"]'
799
+ selector: 'input[name="keyword"]' # 聚焦搜索框
767
800
  - type: fill
768
801
  selector: 'input[name="keyword"]'
769
802
  value: MacBook
770
803
  - type: press
771
- key: Enter
804
+ key: Enter # 按回车
772
805
  - type: wait
773
806
  delay: 1500
774
807
  assertions:
@@ -776,37 +809,40 @@ scenarios:
776
809
  selector: '.search-result-list'
777
810
  - type: count
778
811
  selector: '.product-item'
779
- count: 2
812
+ count: 2 # 预期 2 个结果
780
813
 
781
814
  # ── 场景38: hover 效果 ──
815
+ # 说明: 鼠标悬停在商品卡片上,验证阴影/边框等 hover 样式
782
816
  - name: 通用-hover效果
783
817
  description: 模块:ui 页面:/products hover交互
784
818
  actions:
785
819
  - type: navigate
786
820
  value: /products
787
821
  - type: hover
788
- selector: '.product-item:first-child'
822
+ selector: '.product-item:first-child' # 悬停在第一个商品
789
823
  - type: wait
790
- delay: 500
824
+ delay: 500 # 等待 hover 动画
791
825
  assertions:
792
826
  - type: style
793
827
  selector: '.product-item:first-child'
794
- style: box-shadow
795
- contains: rgba
828
+ style: box-shadow # CSS 属性: 阴影
829
+ contains: rgba # 包含 rgba(有阴影)
796
830
 
797
831
  # ── 场景39: 元素隐藏检查 ──
832
+ # 说明: 验证未登录状态下,用户菜单和退出按钮不显示
798
833
  - name: 通用-元素隐藏
799
834
  description: 模块:ui 页面:/login 未登录状态
800
835
  actions:
801
836
  - type: navigate
802
- value: /login
837
+ value: /login # 未登录页面
803
838
  assertions:
804
839
  - type: hidden
805
- selector: '.user-menu'
840
+ selector: '.user-menu' # 用户菜单应隐藏
806
841
  - type: hidden
807
- selector: '.logout-btn'
842
+ selector: '.logout-btn' # 退出按钮应隐藏
808
843
 
809
844
  # ── 场景40: 表单值断言 ──
845
+ # 说明: 验证表单字段的默认值是否正确
810
846
  - name: 通用-表单值检查
811
847
  description: 模块:user 页面:/profile/edit 表单默认值
812
848
  actions:
@@ -814,30 +850,33 @@ scenarios:
814
850
  value: /profile/edit
815
851
  assertions:
816
852
  - type: value
817
- selector: 'input[name="username"]'
818
- equals: test_user
853
+ selector: 'input[name="username"]' # 断言表单值
854
+ equals: test_user # 精确匹配
819
855
  - type: value
820
856
  selector: 'input[name="email"]'
821
- contains: '@'
857
+ contains: '@' # 包含 @ 符号
822
858
 
823
859
  # ── 场景41: JavaScript 注入执行 ──
860
+ # 说明: 执行自定义 JS,如修改全局变量、调用前端方法
824
861
  - name: 通用-JS脚本注入
825
862
  description: 模块:common 页面:/ JS注入测试
826
863
  actions:
827
864
  - type: navigate
828
865
  value: /
829
866
  - type: script
830
- value: 'window.testFlag = "injected";'
867
+ value: 'window.testFlag = "injected";' # 设置全局变量
831
868
  - type: wait
832
869
  delay: 500
833
870
  - type: script
834
- value: 'return window.testFlag;'
871
+ value: 'return window.testFlag;' # 读取全局变量(返回给引擎)
835
872
  assertions:
836
873
  - type: text
837
874
  selector: 'body'
838
- contains: injected
875
+ contains: injected # 断言页面包含 injected 文本
839
876
 
840
- # ── 场景42: 响应式断点测试 ──
877
+ # ── 场景42: 响应式布局测试 ──
878
+ # 说明: 验证移动端下显示移动端导航,隐藏桌面端侧边栏
879
+ # 注意: Playwright 可通过 viewport 配置模拟不同设备尺寸
841
880
  - name: 通用-响应式布局
842
881
  description: 模块:ui 页面:/ 移动端适配
843
882
  actions:
@@ -847,6 +886,6 @@ scenarios:
847
886
  delay: 800
848
887
  assertions:
849
888
  - type: visible
850
- selector: '.mobile-nav'
889
+ selector: '.mobile-nav' # 移动端导航应可见
851
890
  - type: hidden
852
- selector: '.desktop-sidebar'
891
+ selector: '.desktop-sidebar' # 桌面端侧边栏应隐藏