ykq-playwright-ci 0.1.0

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.
Files changed (47) hide show
  1. package/.env.example +25 -0
  2. package/.nvmrc +1 -0
  3. package/README.md +553 -0
  4. package/bin/playwright-ci.mjs +116 -0
  5. package/cases/doctor-pc/auth/doctor-auth.setup.ts +15 -0
  6. package/cases/doctor-pc/prescription/submit-failure-keeps-drugs.spec.ts +10 -0
  7. package/cases/doctor-pc/smoke/authenticated-home.spec.ts +28 -0
  8. package/cases/doctor-pc/smoke/login-page.spec.ts +21 -0
  9. package/cases/doctor-pc/smoke/prescription-tab.spec.ts +30 -0
  10. package/cases/doctor-pc/test-env/doctor-master-basic.spec.ts +89 -0
  11. package/ci/github-actions/playwright.yml +61 -0
  12. package/docs/auth-runbook.md +44 -0
  13. package/docs/case-map.md +10 -0
  14. package/docs/ci.md +36 -0
  15. package/docs/runbook.md +39 -0
  16. package/docs/selector-convention.md +24 -0
  17. package/docs/test-data.md +23 -0
  18. package/eslint.config.mjs +28 -0
  19. package/package.json +64 -0
  20. package/playwright.config.ts +44 -0
  21. package/projects.config.json +33 -0
  22. package/scripts/configure-project.mjs +280 -0
  23. package/scripts/run-doctor-test.mjs +19 -0
  24. package/scripts/run-project.mjs +252 -0
  25. package/src/api/doctor.api.ts +25 -0
  26. package/src/api/test-data.api.ts +33 -0
  27. package/src/fixtures/auth.fixture.ts +26 -0
  28. package/src/fixtures/base.fixture.ts +14 -0
  29. package/src/fixtures/doctor.fixture.ts +39 -0
  30. package/src/flows/doctor-pc/chat.flow.ts +10 -0
  31. package/src/flows/doctor-pc/login.flow.ts +28 -0
  32. package/src/flows/doctor-pc/medicine.flow.ts +11 -0
  33. package/src/flows/doctor-pc/prescription.flow.ts +19 -0
  34. package/src/mocks/routes/prescription.routes.ts +25 -0
  35. package/src/mocks/websocket/.gitkeep +1 -0
  36. package/src/pages/doctor-pc/chat.page.ts +26 -0
  37. package/src/pages/doctor-pc/drug-dialog.page.ts +28 -0
  38. package/src/pages/doctor-pc/home.page.ts +30 -0
  39. package/src/pages/doctor-pc/login.page.ts +35 -0
  40. package/src/pages/doctor-pc/prescription.page.ts +29 -0
  41. package/src/pages/doctor-pc/worklist.page.ts +21 -0
  42. package/src/pages/shared/.gitkeep +1 -0
  43. package/src/utils/env.ts +78 -0
  44. package/src/utils/evidence.ts +34 -0
  45. package/src/utils/selectors.ts +9 -0
  46. package/src/utils/waiters.ts +11 -0
  47. package/tsconfig.json +14 -0
package/.env.example ADDED
@@ -0,0 +1,25 @@
1
+ # Target environment name used in reports.
2
+ TEST_ENV=test
3
+
4
+ # Deployed doctor PC base URL, for example:
5
+ # DOCTOR_BASE_URL=https://doctor-test.example.com
6
+ DOCTOR_BASE_URL=
7
+
8
+ # App paths under DOCTOR_BASE_URL.
9
+ DOCTOR_PUBLIC_PATH=/
10
+ DOCTOR_LOGIN_PATH=/login
11
+
12
+ # Local auth state generated by `npm run auth:doctor` or manual codegen.
13
+ DOCTOR_STORAGE_STATE=playwright/.auth/doctor.json
14
+
15
+ # Optional UI login credentials. Leave empty if auth is still manual.
16
+ DOCTOR_USERNAME=
17
+ DOCTOR_PASSWORD=
18
+ DOCTOR_OTP=
19
+
20
+ # Optional service endpoints for future data seeding and API assertions.
21
+ API_BASE_URL=
22
+ TEST_DATA_API_URL=
23
+
24
+ # Build metadata shown in attachments and CI artifacts.
25
+ BUILD_SHA=local
package/.nvmrc ADDED
@@ -0,0 +1 @@
1
+ 22
package/README.md ADDED
@@ -0,0 +1,553 @@
1
+ # Playwright CI 使用说明
2
+
3
+ 独立 Playwright 自动化测试工程。当前工程用于承接医生端 PC 的 E2E 自动化测试,不把 Playwright 依赖直接放进医生端 Vue2 / Node 14 业务仓。
4
+
5
+ ## 适用范围
6
+
7
+ 当前优先覆盖医生端测试环境的基础链路:
8
+
9
+ - 登录页是否能正常渲染。
10
+ - 未登录访问首页是否按路由守卫跳回登录页。
11
+ - 用户协议页是否允许未登录访问。
12
+ - 登录表单的基础校验是否符合 `doctor-master` 逻辑。
13
+
14
+ 这些用例不需要真实医生账号,也不会真的登录、开方或提交处方。登录后业务链路需要先解决测试账号、验证码或登录态方案。
15
+
16
+ ## 环境要求
17
+
18
+ 本地使用这个 runner 前,需要准备这些环境:
19
+
20
+ | 环境 | 要求 | 说明 |
21
+ | --- | --- | --- |
22
+ | Node.js | 建议使用 `.nvmrc` 指定的 `22` | 本工具运行在 Node 侧,不受医生端业务仓 Node 14 限制 |
23
+ | npm | 随 Node 安装即可 | 推荐用 `npm ci` 或 `npm install` 安装依赖 |
24
+ | Git | 需要可执行 `git clone`、`git fetch`、`git pull` | 用于拉取各项目的用例库 |
25
+ | Git 权限 | 需要能访问 `git.int.ybm100.com` | 可用本机 Git 凭据,也可临时传 `GIT_USERNAME` / `GIT_PASSWORD` |
26
+ | 浏览器 | Playwright Chromium | 首次运行前执行 `npx playwright install chromium` |
27
+ | 网络 | 需要访问 Git 仓库和目标测试环境 | 医生端默认访问 `https://ys-test.heyejk.com` |
28
+
29
+ 当前基础用例不需要医生测试账号。后续如果跑登录后链路,还需要测试医生账号、验证码绕过方案,或 `playwright/.auth/doctor.json` 登录态文件。
30
+
31
+ 不要把账号、密码、token、登录态写进 Git:
32
+
33
+ ```text
34
+ .env
35
+ playwright/.auth/*.json
36
+ GIT_PASSWORD
37
+ ```
38
+
39
+ ## 环境准备
40
+
41
+ 进入工程目录:
42
+
43
+ ```bash
44
+ cd /Users/huangcongqiang/Desktop/products/playwright-ci
45
+ ```
46
+
47
+ 安装依赖:
48
+
49
+ ```bash
50
+ npm install
51
+ ```
52
+
53
+ 如果使用 `nvm`:
54
+
55
+ ```bash
56
+ nvm use
57
+ ```
58
+
59
+ 安装浏览器:
60
+
61
+ ```bash
62
+ npx playwright install chromium
63
+ ```
64
+
65
+ 如果机器已经装过对应版本,Playwright 会复用缓存。
66
+
67
+ ## 通过 npm 安装使用
68
+
69
+ npm 包名使用 `ykq-playwright-ci`。`playwright-ci` 这个包名已经被 npm 上其它作者占用,所以本工具发布时不能继续使用原仓库名。
70
+
71
+ 全局安装:
72
+
73
+ ```bash
74
+ npm install -g ykq-playwright-ci
75
+ ```
76
+
77
+ 首次在某个目录使用时,先初始化项目配置:
78
+
79
+ ```bash
80
+ mkdir playwright-runner
81
+ cd playwright-runner
82
+ playwright-ci init
83
+ ```
84
+
85
+ 初始化后会在当前目录生成:
86
+
87
+ ```text
88
+ projects.config.json
89
+ ```
90
+
91
+ 之后可以直接按项目运行:
92
+
93
+ ```bash
94
+ playwright-ci list
95
+ playwright-ci run doctor-pc
96
+ playwright-ci run doctor-pc --headed
97
+ playwright-ci run doctor-pc --debug
98
+ ```
99
+
100
+ 也可以使用项目配置命令:
101
+
102
+ ```bash
103
+ playwright-ci add
104
+ playwright-ci show doctor-pc
105
+ playwright-ci update doctor-pc
106
+ playwright-ci delete doctor-pc
107
+ ```
108
+
109
+ 如果不想全局安装,发布后也可以用 `npx`:
110
+
111
+ ```bash
112
+ npx ykq-playwright-ci init
113
+ npx ykq-playwright-ci run doctor-pc
114
+ ```
115
+
116
+ 从 npm 安装后,Git 用例库仍然拉到当前工作目录的 `.case-repos/`,`projects.config.json` 也保存在当前工作目录,不会写到全局 `node_modules` 目录。
117
+
118
+ ## 最常用命令
119
+
120
+ 查看已配置的项目:
121
+
122
+ ```bash
123
+ npm run project:list
124
+ ```
125
+
126
+ 交互式新增项目配置:
127
+
128
+ ```bash
129
+ npm run project:add
130
+ ```
131
+
132
+ 查看某个项目详情:
133
+
134
+ ```bash
135
+ npm run project:show -- doctor-pc
136
+ ```
137
+
138
+ 交互式更新项目配置:
139
+
140
+ ```bash
141
+ npm run project:update -- doctor-pc
142
+ ```
143
+
144
+ 删除项目配置:
145
+
146
+ ```bash
147
+ npm run project:delete -- doctor-pc
148
+ ```
149
+
150
+ 后台无头运行测试环境基础用例:
151
+
152
+ ```bash
153
+ npm run doctor:test
154
+ ```
155
+
156
+ 打开浏览器窗口,看 Playwright 实际操作:
157
+
158
+ ```bash
159
+ npm run doctor:test:headed
160
+ ```
161
+
162
+ 调试模式,适合逐步看定位、点击和断言:
163
+
164
+ ```bash
165
+ npm run doctor:test:debug
166
+ ```
167
+
168
+ 打开 Playwright UI,适合筛选、重跑、查看每一步:
169
+
170
+ ```bash
171
+ npm run doctor:test:ui
172
+ ```
173
+
174
+ 查看最近一次测试报告:
175
+
176
+ ```bash
177
+ npm run report
178
+ ```
179
+
180
+ ## 命令说明
181
+
182
+ | 命令 | 用途 | 是否打开浏览器窗口 |
183
+ | --- | --- | --- |
184
+ | `npm run project:list` | 查看当前 runner 已配置的项目 | 否 |
185
+ | `npm run project:show -- doctor-pc` | 查看单个项目完整配置 | 否 |
186
+ | `npm run project:add` | 交互式新增项目配置 | 否 |
187
+ | `npm run project:update -- doctor-pc` | 交互式更新项目配置 | 否 |
188
+ | `npm run project:delete -- doctor-pc` | 删除项目配置,需要输入 `delete` 确认 | 否 |
189
+ | `npm run project:test -- doctor-pc` | 按项目名运行用例 | 否 |
190
+ | `npm run doctor:test` | 跑医生端测试环境基础用例,适合日常验证和 CI | 否 |
191
+ | `npm run doctor:test:headed` | 跑同一批用例,同时显示浏览器窗口 | 是 |
192
+ | `npm run doctor:test:debug` | 调试用例,可暂停、逐步执行 | 是 |
193
+ | `npm run doctor:test:ui` | 打开 Playwright UI 选择和重跑用例 | 是 |
194
+ | `npm run doctor:test:local` | 不拉远程仓库,直接跑当前 runner 内置医生端用例 | 否 |
195
+ | `npm run patient:test` | 跑患者端用例库;需要先配置 repo | 否 |
196
+ | `npm run admin:test` | 跑后台用例库;需要先配置 repo | 否 |
197
+ | `npm run report` | 打开 HTML 测试报告 | 是 |
198
+ | `npm run typecheck` | TypeScript 类型检查 | 否 |
199
+ | `npm run lint` | ESLint 检查 | 否 |
200
+
201
+ ## 多项目用例库
202
+
203
+ 本工程现在是一个本地 Playwright Runner。Runner 负责:
204
+
205
+ - 管理 Playwright 版本、浏览器、报告和通用命令。
206
+ - 按项目名读取配置。
207
+ - 如果项目配置了 Git 用例库,运行前自动 clone 或 `git pull --ff-only`。
208
+ - 根据项目配置设置测试环境变量。
209
+ - 调用 Playwright 执行对应用例目录。
210
+
211
+ 医生端用例库:
212
+
213
+ ```text
214
+ https://git.int.ybm100.com/ykq/doctor-pc-web-test-store
215
+ ```
216
+
217
+ 项目配置文件:
218
+
219
+ ```text
220
+ projects.config.json
221
+ ```
222
+
223
+ 当前结构:
224
+
225
+ ```json
226
+ {
227
+ "caseCacheDir": ".case-repos",
228
+ "projects": {
229
+ "doctor-pc": {
230
+ "repo": "https://git.int.ybm100.com/ykq/doctor-pc-web-test-store",
231
+ "branch": "master",
232
+ "caseDir": ".case-repos/doctor-pc",
233
+ "env": {
234
+ "DOCTOR_BASE_URL": "https://ys-test.heyejk.com",
235
+ "DOCTOR_PUBLIC_PATH": "/physician-admin/",
236
+ "DOCTOR_LOGIN_PATH": "/physician-admin/login"
237
+ },
238
+ "playwrightArgs": ["--project=chromium", "--no-deps"]
239
+ }
240
+ }
241
+ }
242
+ ```
243
+
244
+ `doctor-pc` 已配置为远程用例库。首次运行会拉取到:
245
+
246
+ ```text
247
+ .case-repos/doctor-pc
248
+ ```
249
+
250
+ 如果 Git 需要登录,可以用本机 Git 凭据管理,也可以临时通过环境变量传入:
251
+
252
+ ```bash
253
+ GIT_USERNAME=你的用户名 GIT_PASSWORD='你的密码或访问令牌' npm run doctor:test
254
+ ```
255
+
256
+ 不要把账号密码写进 `projects.config.json`、README、脚本或 Git remote URL。
257
+
258
+ 远程用例库配置示例:
259
+
260
+ ```json
261
+ {
262
+ "repo": "https://git.int.ybm100.com/ykq/doctor-pc-web-test-store",
263
+ "branch": "master",
264
+ "caseDir": ".case-repos/doctor-pc",
265
+ "env": {
266
+ "DOCTOR_BASE_URL": "https://ys-test.heyejk.com",
267
+ "DOCTOR_PUBLIC_PATH": "/physician-admin/",
268
+ "DOCTOR_LOGIN_PATH": "/physician-admin/login"
269
+ },
270
+ "playwrightArgs": ["--project=chromium", "--no-deps"]
271
+ }
272
+ ```
273
+
274
+ 运行时逻辑:
275
+
276
+ ```text
277
+ npm run doctor:test
278
+ -> 读取 projects.config.json 的 doctor-pc
279
+ -> 如果 repo 不为空,clone / pull 到 .case-repos/doctor-pc
280
+ -> 设置 DOCTOR_BASE_URL 等环境变量
281
+ -> 执行 Playwright
282
+ ```
283
+
284
+ `.case-repos/` 是本地缓存目录,已加入 `.gitignore`,不要提交。
285
+
286
+ 如果本地用例库有未提交改动,runner 会停止自动拉取,避免覆盖你调试中的用例。确认不需要这些改动后,再自己处理对应用例库的 Git 状态。
287
+
288
+ 通用运行方式:
289
+
290
+ ```bash
291
+ npm run project:test -- doctor-pc
292
+ npm run project:test -- doctor-pc --headed
293
+ npm run project:test -- doctor-pc --debug
294
+ ```
295
+
296
+ 项目配置增删改查:
297
+
298
+ ```bash
299
+ npm run project:list
300
+ npm run project:show -- doctor-pc
301
+ npm run project:add
302
+ npm run project:update -- doctor-pc
303
+ npm run project:delete -- doctor-pc
304
+ ```
305
+
306
+ 新增和更新会依次询问:
307
+
308
+ - 项目名
309
+ - 用例库 Git 地址
310
+ - 分支
311
+ - 本地用例缓存目录
312
+ - 项目说明
313
+ - Playwright 参数
314
+ - 环境变量
315
+
316
+ 写入后会更新 `projects.config.json`。账号密码不要写进项目配置,运行时通过本机 Git 凭据或临时环境变量传入:
317
+
318
+ ```bash
319
+ GIT_USERNAME=你的用户名 GIT_PASSWORD='你的密码或访问令牌' npm run project:test -- 项目名
320
+ ```
321
+
322
+ 如果只想跑 runner 内置的临时本地用例,不拉远程用例库:
323
+
324
+ ```bash
325
+ npm run doctor:test:local
326
+ ```
327
+
328
+ ## 默认测试环境
329
+
330
+ 医生端测试环境命令默认使用:
331
+
332
+ ```text
333
+ DOCTOR_BASE_URL=https://ys-test.heyejk.com
334
+ DOCTOR_PUBLIC_PATH=/physician-admin/
335
+ DOCTOR_LOGIN_PATH=/physician-admin/login
336
+ ```
337
+
338
+ 也就是说,基础用例会访问:
339
+
340
+ ```text
341
+ https://ys-test.heyejk.com/physician-admin/login
342
+ https://ys-test.heyejk.com/physician-admin/home
343
+ https://ys-test.heyejk.com/physician-admin/serviceAgreement
344
+ ```
345
+
346
+ 如果要临时切换环境,可以在命令前覆盖变量:
347
+
348
+ ```bash
349
+ DOCTOR_BASE_URL=https://your-test-host npm run doctor:test
350
+ ```
351
+
352
+ 如果路径也不同,可以一起覆盖:
353
+
354
+ ```bash
355
+ DOCTOR_BASE_URL=https://your-test-host \
356
+ DOCTOR_PUBLIC_PATH=/physician-admin/ \
357
+ DOCTOR_LOGIN_PATH=/physician-admin/login \
358
+ npm run doctor:test
359
+ ```
360
+
361
+ ## 当前测试用例
362
+
363
+ 文件位置:
364
+
365
+ ```text
366
+ cases/doctor-pc/test-env/doctor-master-basic.spec.ts
367
+ ```
368
+
369
+ 当前包含 4 条用例:
370
+
371
+ | 用例 ID | 验证内容 | 方式 |
372
+ | --- | --- | --- |
373
+ | `PW-TEST-001` | 登录页控件渲染:手机号、图形验证码、短信验证码、协议、登录按钮 | 直接访问登录路由 |
374
+ | `PW-TEST-002` | 未登录访问 `/home` 会被路由守卫跳到 `/login` | 直接访问受保护路由 |
375
+ | `PW-TEST-003` | `/serviceAgreement` 在白名单内,未登录可访问 | 直接访问白名单路由 |
376
+ | `PW-TEST-004` | 登录表单校验:必填、手机号格式、未勾协议提示 | 真实输入和点击 |
377
+
378
+ 前 3 条主要验证路由和页面状态;第 4 条包含真实输入和点击。
379
+
380
+ ## 如何看结果
381
+
382
+ 命令行里看到类似结果表示通过:
383
+
384
+ ```text
385
+ 4 passed
386
+ ```
387
+
388
+ 失败时,Playwright 会在这些目录生成证据:
389
+
390
+ ```text
391
+ test-results/
392
+ playwright-report/
393
+ ```
394
+
395
+ 常用查看方式:
396
+
397
+ ```bash
398
+ npm run report
399
+ ```
400
+
401
+ 失败报告里通常包含:
402
+
403
+ - 失败截图
404
+ - 操作视频
405
+ - trace 回放
406
+ - 报错堆栈
407
+ - 失败前后的页面状态
408
+
409
+ trace 可以帮助判断到底是页面没出来、定位器没找到、跳转不符合预期,还是网络/环境问题。
410
+
411
+ ## 第一次运行常见问题
412
+
413
+ ### 缺少 Chromium
414
+
415
+ 报错类似:
416
+
417
+ ```text
418
+ Executable doesn't exist
419
+ Please run the following command to download new browsers:
420
+ npx playwright install
421
+ ```
422
+
423
+ 处理:
424
+
425
+ ```bash
426
+ npx playwright install chromium
427
+ ```
428
+
429
+ ### 测试环境访问慢
430
+
431
+ 如果测试偶发超时,先用可视化模式看页面是否真的打开:
432
+
433
+ ```bash
434
+ npm run doctor:test:headed
435
+ ```
436
+
437
+ 再打开报告看失败证据:
438
+
439
+ ```bash
440
+ npm run report
441
+ ```
442
+
443
+ ### 断言找到了多个元素
444
+
445
+ Playwright 默认严格模式下,一个定位器只能匹配一个元素。比如 `验证码` 可能同时匹配 `图形验证码` 和 `验证码`。这种情况需要把定位器写得更精确,例如:
446
+
447
+ ```ts
448
+ page.getByPlaceholder('验证码', { exact: true })
449
+ ```
450
+
451
+ ## 如何新增用例
452
+
453
+ 医生端测试环境基础用例优先放在:
454
+
455
+ ```text
456
+ cases/doctor-pc/test-env/
457
+ ```
458
+
459
+ 建议命名:
460
+
461
+ ```text
462
+ 模块-场景-预期.spec.ts
463
+ ```
464
+
465
+ 示例:
466
+
467
+ ```text
468
+ login-form-validation.spec.ts
469
+ home-route-guard.spec.ts
470
+ ```
471
+
472
+ 每条用例建议补充 `annotateCase`,方便报告里追踪用例 ID:
473
+
474
+ ```ts
475
+ annotateCase(testInfo, {
476
+ caseId: 'PW-TEST-005',
477
+ evidenceId: 'TEST-some-business-evidence',
478
+ priority: 'Smoke'
479
+ });
480
+ ```
481
+
482
+ 写用例时优先使用接近用户行为的定位方式:
483
+
484
+ ```ts
485
+ page.getByRole('button', { name: '登录' })
486
+ page.getByPlaceholder('手机号')
487
+ page.getByText('荷叶医生')
488
+ ```
489
+
490
+ 不要优先依赖样式类名、DOM 层级或 `nth-child`。如果页面没有稳定语义定位,再考虑让业务仓补 `data-testid`。
491
+
492
+ ## 登录后用例怎么做
493
+
494
+ 当前基础用例不需要登录。后续要测登录后页面,比如首页、问诊列表、处方 tab、开方、撤回处方,需要先满足至少一种方案:
495
+
496
+ - 后端提供测试登录接口。
497
+ - 测试环境提供固定验证码或验证码绕过能力。
498
+ - 手工生成 `playwright/.auth/doctor.json` 登录态。
499
+
500
+ 手工登录态方式参考:
501
+
502
+ ```bash
503
+ npx playwright codegen --save-storage=playwright/.auth/doctor.json https://ys-test.heyejk.com/physician-admin/login
504
+ ```
505
+
506
+ 在打开的浏览器里完成登录后关闭窗口,后续已登录用例可复用该 storageState。
507
+
508
+ 注意:`playwright/.auth/*.json` 包含登录态,已被 `.gitignore` 排除,不要提交。
509
+
510
+ ## CI 或服务器运行
511
+
512
+ 服务器不需要显示器,可以直接跑无头模式:
513
+
514
+ ```bash
515
+ npm ci
516
+ npx playwright install --with-deps chromium
517
+ npm run doctor:test
518
+ ```
519
+
520
+ CI 建议归档:
521
+
522
+ ```text
523
+ playwright-report/
524
+ test-results/
525
+ ```
526
+
527
+ 不要归档或提交:
528
+
529
+ ```text
530
+ playwright/.auth/*.json
531
+ .env
532
+ ```
533
+
534
+ ## 项目结构
535
+
536
+ ```text
537
+ cases/doctor-pc/ # 医生端业务用例
538
+ src/fixtures/ # Playwright fixtures 和登录态工具
539
+ src/pages/doctor-pc/ # Page Object
540
+ src/flows/doctor-pc/ # 跨页面业务流程
541
+ src/api/ # API 和测试数据客户端
542
+ src/mocks/ # route / websocket mock
543
+ docs/ # 运行、登录、测试数据、选择器和 CI 说明
544
+ scripts/ # 命令封装脚本
545
+ ```
546
+
547
+ ## 维护原则
548
+
549
+ - 先用少量稳定 Smoke 验证页面和路由,再扩展登录后 P0 链路。
550
+ - 用例失败必须能留下截图、视频或 trace。
551
+ - 不在测试工程里硬编码真实账号密码。
552
+ - 不把 Playwright 依赖塞回医生端业务仓。
553
+ - 涉及处方、问诊、药品、自动关诊等业务链路时,要先确认测试数据和登录态方案。
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ /* global console, process */
3
+
4
+ import { spawn } from 'node:child_process';
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+
9
+ const packageRootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
10
+ const defaultConfigPath = path.join(packageRootDir, 'projects.config.json');
11
+ const userConfigPath = process.env.PROJECTS_CONFIG_PATH
12
+ ? path.resolve(process.env.PROJECTS_CONFIG_PATH)
13
+ : path.resolve(process.cwd(), 'projects.config.json');
14
+
15
+ const configActions = new Set(['list', 'show', 'add', 'update', 'delete', 'remove']);
16
+
17
+ function printHelp() {
18
+ console.log(`Usage:
19
+ playwright-ci init
20
+ playwright-ci list
21
+ playwright-ci show <project>
22
+ playwright-ci add [project]
23
+ playwright-ci update <project>
24
+ playwright-ci delete <project>
25
+ playwright-ci run <project> [playwright args]
26
+ playwright-ci <project> [playwright args]
27
+
28
+ Examples:
29
+ playwright-ci init
30
+ playwright-ci run doctor-pc --headed
31
+ GIT_USERNAME=user GIT_PASSWORD=token playwright-ci run doctor-pc`);
32
+ }
33
+
34
+ function ensureConfigExists() {
35
+ if (fs.existsSync(userConfigPath)) {
36
+ return;
37
+ }
38
+
39
+ throw new Error(`当前目录缺少 projects.config.json,请先执行:playwright-ci init\n目标路径:${userConfigPath}`);
40
+ }
41
+
42
+ function initConfig() {
43
+ if (fs.existsSync(userConfigPath)) {
44
+ console.log(`配置文件已存在:${userConfigPath}`);
45
+ return;
46
+ }
47
+
48
+ fs.copyFileSync(defaultConfigPath, userConfigPath);
49
+ console.log(`已创建配置文件:${userConfigPath}`);
50
+ }
51
+
52
+ function runNodeScript(scriptName, args) {
53
+ const child = spawn(process.execPath, [path.join(packageRootDir, 'scripts', scriptName), ...args], {
54
+ cwd: process.cwd(),
55
+ env: {
56
+ ...process.env,
57
+ PROJECTS_CONFIG_PATH: userConfigPath
58
+ },
59
+ stdio: 'inherit'
60
+ });
61
+
62
+ child.on('exit', (code, signal) => {
63
+ if (signal) {
64
+ process.kill(process.pid, signal);
65
+ return;
66
+ }
67
+
68
+ process.exit(code ?? 1);
69
+ });
70
+ }
71
+
72
+ function main() {
73
+ const [command = 'help', ...args] = process.argv.slice(2);
74
+
75
+ if (command === 'help' || command === '--help' || command === '-h') {
76
+ printHelp();
77
+ return;
78
+ }
79
+
80
+ if (command === 'init') {
81
+ initConfig();
82
+ return;
83
+ }
84
+
85
+ if (command === 'run' || command === 'project:test') {
86
+ ensureConfigExists();
87
+ runNodeScript('run-project.mjs', args);
88
+ return;
89
+ }
90
+
91
+ if (command.startsWith('project:')) {
92
+ const action = command.slice('project:'.length);
93
+ if (!configActions.has(action)) {
94
+ throw new Error(`未知命令:${command}`);
95
+ }
96
+ ensureConfigExists();
97
+ runNodeScript('configure-project.mjs', [action, ...args]);
98
+ return;
99
+ }
100
+
101
+ if (configActions.has(command)) {
102
+ ensureConfigExists();
103
+ runNodeScript('configure-project.mjs', [command, ...args]);
104
+ return;
105
+ }
106
+
107
+ ensureConfigExists();
108
+ runNodeScript('run-project.mjs', [command, ...args]);
109
+ }
110
+
111
+ try {
112
+ main();
113
+ } catch (error) {
114
+ console.error(error instanceof Error ? error.message : error);
115
+ process.exit(1);
116
+ }
@@ -0,0 +1,15 @@
1
+ import { test } from '../../../src/fixtures/base.fixture';
2
+ import { saveDoctorAuthState } from '../../../src/fixtures/auth.fixture';
3
+ import { LoginFlow } from '../../../src/flows/doctor-pc/login.flow';
4
+ import { hasDoctorBaseURL, hasDoctorCredentials } from '../../../src/utils/env';
5
+
6
+ test.skip(!hasDoctorBaseURL(), 'DOCTOR_BASE_URL is required to generate doctor auth state.');
7
+ test.skip(
8
+ !hasDoctorCredentials(),
9
+ 'DOCTOR_USERNAME and DOCTOR_PASSWORD are required unless auth is generated manually.'
10
+ );
11
+
12
+ test('PW-AUTH-SETUP generate doctor storageState @auth', async ({ page }) => {
13
+ await new LoginFlow(page).loginWithConfiguredCredentials();
14
+ await saveDoctorAuthState(page);
15
+ });