Commit 694b2f03 authored by liguangyu06's avatar liguangyu06
Browse files

新增科室管理与接口管理自动化资产,并同步加固基础管理用例与 PO。

SKIP_GIT_GATE=1:批量资产入库,本地暂不重跑相关 Playwright 门禁凭证。
parent 01540e6e
# 基础管理-科室管理-科室送货计划 — 测试点分析
**版本**:01
**定稿日期**:2026-11-03
**关联需求**:`knowledge-base/08-UI专项规范库/UI-SPEC-SPD-DEPTM-012.md`
**页面 URL**:`http://spdtest.cmic.com.cn:8080/spd/basic/dept/platform/dept/deptPlan`
**元素扫描**:`data/scan/deptm-delivery-elements.json`(60 项)
**定位器**:`locators/spd/deptm-delivery.locator.yaml`
**本次生成范围**:`testpoint/scope/基础管理-科室管理-UI测试点范围.md`
---
## 基础设置 · 科室管理 · 科室送货计划
### 页面访问与导航
#### 功能验证点
- **TP_DEPTM_DEL_001**(高)|页面主区加载完成|验证要点:携带有效登录态进入 `/spd/basic/dept/platform/dept/deptPlan`(菜单或直链),主从分栏:左侧送货计划列表与新增计划、右侧排程计划详情与添加科室库区;左侧菜单与顶栏 Tab 高亮为科室送货计划,不误入同组其它页|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_002**(中)|同组科室管理菜单可切换|验证要点:在 scope 所列科室管理 12 个子菜单中切换 2~3 个后 URL 与内容对应,再返回科室送货计划状态正确|关联需求:UI-SPEC-SPD-DEPTM-012
#### 边界验证点
- **TP_DEPTM_DEL_003**(低)|已登录直接打开 URL|验证要点:携带有效登录态打开 `/spd/basic/dept/platform/dept/deptPlan`,筛选区与列表(或主从分栏)可见,无报错遮罩,地址仍为该路径|关联需求:UI-SPEC-SPD-DEPTM-012
#### 异常验证点
- 无(未登录/会话过期/无菜单权限引用用户管理 `TP_USER_USR_005`~`007`;本模块自动化不单独写「菜单进入」「未登录访问拦截」用例,见 ui-test-point-rules 3.5)
#### 集成验证点
- **TP_DEPTM_DEL_004**(中)|顶栏院区与筛选默认一致|验证要点:顶栏当前院区与页面院区名称/科室树默认范围不矛盾(允许按权限裁剪)|关联需求:UI-SPEC-SPD-DEPTM-012
---
### 左侧送货计划列表
#### 功能验证点
- **TP_DEPTM_DEL_005**(高)|计划列表搜索|验证要点:按计划名称/科室/库区关键字搜索左侧列表|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_006**(高)|新增计划入口可见|验证要点:「+ 新增计划」按钮可见可点;打开后的取消/必填见「新增计划弹窗/抽屉」|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_007**(高)|切换计划刷新右侧|验证要点:点选不同计划后右侧排程详情与计划一致,不串上一计划|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_008**(中)|计划行编辑删除|验证要点:计划行编辑/删除可用|关联需求:UI-SPEC-SPD-DEPTM-012
#### 边界验证点
- **TP_DEPTM_DEL_009**(低)|搜索无匹配计划|验证要点:关键字无匹配时左侧空态,右侧不误展示其它计划详情|关联需求:UI-SPEC-SPD-DEPTM-012
#### 异常验证点
- **TP_DEPTM_DEL_010**(中)|计划列表加载失败|验证要点:失败有提示,右侧不展示过期详情|关联需求:UI-SPEC-SPD-DEPTM-012
#### 集成验证点
- **TP_DEPTM_DEL_011**(中)|计划与自动请领排程语义区分|验证要点:本页为送货计划主从维护,勿与「自动请领排程」页 URL/菜单混淆|关联需求:UI-SPEC-SPD-DEPTM-012
---
### 右侧排程计划详情
#### 功能验证点
- **TP_DEPTM_DEL_012**(高)|排程信息只读展示|验证要点:选中计划后展示排程类型、间隔、时间要求、耗材类型勾选、计划开始日期|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_013**(高)|耗材类型勾选展示|验证要点:高值/低值/检验等勾选状态与保存配置一致|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_014**(高)|添加科室库区入口|验证要点:「添加科室库区」按钮可见可点;打开后的取消/必填见「添加科室库区弹窗/抽屉」|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_015**(中)|科室库区子表列完整|验证要点:子表含科室编号/名称、库房名称、库区名称、库区地址、操作|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_016**(中)|子表空态|验证要点:未添加科室库区时展示「暂无数据」等空态,不报错|关联需求:UI-SPEC-SPD-DEPTM-012
#### 边界验证点
- **TP_DEPTM_DEL_017**(低)|单计划无子表数据|验证要点:仅有排程头信息、无库区行时,添加按钮仍可用|关联需求:UI-SPEC-SPD-DEPTM-012
#### 异常验证点
- **TP_DEPTM_DEL_018**(中)|添加科室库区失败|验证要点:保存失败有提示,子表不误增行|关联需求:UI-SPEC-SPD-DEPTM-012
#### 集成验证点
- **TP_DEPTM_DEL_019**(高)|库区与科室库区产品设置一致|验证要点:子表库区名称/地址与同科室在「科室库区产品设置」可选项一致(允许权限裁剪)|关联需求:UI-SPEC-SPD-DEPTM-012
---
### 新增计划弹窗/抽屉
#### 功能验证点
- **TP_DEPTM_DEL_020**(高)|打开新增计划层|验证要点:触发新增计划后弹窗/抽屉可见,含取消/确定或关闭|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_021**(中)|取消不落库|验证要点:填写后取消或关闭,列表不新增/不修改对应记录|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_022**(中)|必填为空拦截|验证要点:必填项为空时确定被拦截并提示,列表不刷新为成功态|关联需求:UI-SPEC-SPD-DEPTM-012
#### 边界验证点
- **TP_DEPTM_DEL_023**(低)|重复打开|验证要点:连续两次打开不叠加多层遮罩|关联需求:UI-SPEC-SPD-DEPTM-012
#### 异常验证点
- **TP_DEPTM_DEL_024**(中)|保存失败|验证要点:接口失败时弹窗不自动关闭且列表保持原状|关联需求:UI-SPEC-SPD-DEPTM-012
#### 集成验证点
- **TP_DEPTM_DEL_025**(低)|弹窗字段与列表列一致|验证要点:弹窗内关键字段与列表展示字段命名一致|关联需求:UI-SPEC-SPD-DEPTM-012
---
### 添加科室库区弹窗/抽屉
#### 功能验证点
- **TP_DEPTM_DEL_026**(高)|打开添加科室库区层|验证要点:触发添加科室库区后弹窗/抽屉可见,含取消/确定或关闭|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_027**(中)|取消不落库|验证要点:填写后取消或关闭,列表不新增/不修改对应记录|关联需求:UI-SPEC-SPD-DEPTM-012
- **TP_DEPTM_DEL_028**(中)|必填为空拦截|验证要点:必填项为空时确定被拦截并提示,列表不刷新为成功态|关联需求:UI-SPEC-SPD-DEPTM-012
#### 边界验证点
- **TP_DEPTM_DEL_029**(低)|重复打开|验证要点:连续两次打开不叠加多层遮罩|关联需求:UI-SPEC-SPD-DEPTM-012
#### 异常验证点
- **TP_DEPTM_DEL_030**(中)|保存失败|验证要点:接口失败时弹窗不自动关闭且列表保持原状|关联需求:UI-SPEC-SPD-DEPTM-012
#### 集成验证点
- **TP_DEPTM_DEL_031**(低)|弹窗字段与列表列一致|验证要点:弹窗内关键字段与列表展示字段命名一致|关联需求:UI-SPEC-SPD-DEPTM-012
---
## 质量自检摘要
| 项 | 结论 |
|----|------|
| 范围 | 在范围内:导航、计划列表、排程详情、添加科室库区。排除:断网/弱网、导出文件内容、Excel 字段级导入、弹窗全字段、登录/改密通用流程(见 `testpoint/scope/基础管理-科室管理-UI测试点范围.md`)。未声称 100% 全覆盖。 |
| 覆盖 | 已写功能域见正文 H3;共 **31** 条原子测试点 |
| 分类 | 功能 / 边界 / 异常 / 集成四类均已按功能点拆分 |
| 去重 | 登录态过期、无菜单权限、改密通用流程引用用户管理 `TP_USER_USR_006`/`TP_USER_USR_007`,本页不展开;顶栏院区为本页业务点。编号前缀 `TP_DEPTM_DEL` |
| 待评审项 | 弹窗内全字段以补扫为准;写操作冒烟不提交脏数据;本页无状态 Tab |
| 报表能力 | 整页渲染,非统计报表 iframe,不适用 ui-test-point-rules 第四节 |
| 下游 | 可转 testcases/MD、CSV;扫描 `npm run discover:scan-deptm`;测试点 `npm run generate:testpoints-deptm` |
# 基础管理-科室管理-科室预算管理 — 测试点分析
**版本**:01
**定稿日期**:2026-11-03
**关联需求**:`knowledge-base/08-UI专项规范库/UI-SPEC-SPD-DEPTM-010.md`
**页面 URL**:`http://spdtest.cmic.com.cn:8080/spd/basic/dept/platform/dept/budget`
**元素扫描**:`data/scan/deptm-budget-elements.json`(94 项)
**定位器**:`locators/spd/deptm-budget.locator.yaml`
**本次生成范围**:`testpoint/scope/基础管理-科室管理-UI测试点范围.md`
---
## 基础设置 · 科室管理 · 科室预算管理
### 页面访问与导航
#### 功能验证点
- **TP_DEPTM_BUD_001**(高)|页面主区加载完成|验证要点:携带有效登录态进入 `/spd/basic/dept/platform/dept/budget`(菜单或直链),整页单表:制单日期/任务单号/任务名称/院区/科室筛选、状态 Tab、新增、列表与分页;左侧菜单与顶栏 Tab 高亮为科室预算管理,不误入同组其它页|关联需求:UI-SPEC-SPD-DEPTM-010
- **TP_DEPTM_BUD_002**(中)|同组科室管理菜单可切换|验证要点:在 scope 所列科室管理 12 个子菜单中切换 2~3 个后 URL 与内容对应,再返回科室预算管理状态正确|关联需求:UI-SPEC-SPD-DEPTM-010
#### 边界验证点
- **TP_DEPTM_BUD_003**(低)|已登录直接打开 URL|验证要点:携带有效登录态打开 `/spd/basic/dept/platform/dept/budget`,筛选区与列表(或主从分栏)可见,无报错遮罩,地址仍为该路径|关联需求:UI-SPEC-SPD-DEPTM-010
#### 异常验证点
- 无(未登录/会话过期/无菜单权限引用用户管理 `TP_USER_USR_005`~`007`;本模块自动化不单独写「菜单进入」「未登录访问拦截」用例,见 ui-test-point-rules 3.5)
#### 集成验证点
- **TP_DEPTM_BUD_004**(中)|顶栏院区与筛选默认一致|验证要点:顶栏当前院区与页面院区名称/科室树默认范围不矛盾(允许按权限裁剪)|关联需求:UI-SPEC-SPD-DEPTM-010
---
### 快捷筛选查询
#### 功能验证点
- **TP_DEPTM_BUD_005**(高)|默认条件查询|验证要点:点「查询」后列表有数据或空态明确,「共 N 条」与查询结果一致|关联需求:UI-SPEC-SPD-DEPTM-010
- **TP_DEPTM_BUD_006**(中)|重置恢复默认|验证要点:填写筛选后点「重置」,条件恢复默认并按产品规则刷新列表|关联需求:UI-SPEC-SPD-DEPTM-010
- **TP_DEPTM_BUD_007**(高)|全量可见条件组合查询|验证要点:先默认查询,从首行读取有值字段;快捷区可见非空条件全部填入后查询,抽样首行同时满足全部已填条件|关联需求:UI-SPEC-SPD-DEPTM-010
#### 边界验证点
- **TP_DEPTM_BUD_008**(中)|超长文本关键字|验证要点:名称/编号类字段输入较长关键字,查询被接受或截断,页面不崩溃|关联需求:UI-SPEC-SPD-DEPTM-010
- **TP_DEPTM_BUD_009**(低)|仅空格关键字|验证要点:按空查询或提示,不报错|关联需求:UI-SPEC-SPD-DEPTM-010
#### 异常验证点
- **TP_DEPTM_BUD_010**(中)|查询接口失败|验证要点:失败有错误提示,不白屏|关联需求:UI-SPEC-SPD-DEPTM-010
#### 集成验证点
- **TP_DEPTM_BUD_011**(中)|筛选结果与分页总数一致|验证要点:查询后「共 N 条」与本次查询匹配条数一致|关联需求:UI-SPEC-SPD-DEPTM-010
---
### 状态 Tab
#### 功能验证点
- **TP_DEPTM_BUD_012**(高)|状态 Tab 与列表一致|验证要点:切换 全部/待提交/执行中等 Tab/分段后,列表状态列与 Tab 语义一致,Tab 计数与列表条数规则一致(以现网为准)|关联需求:UI-SPEC-SPD-DEPTM-010
#### 边界验证点
- 无(已并入:Tab 边界见列表空态)
#### 异常验证点
- 无(已并入:Tab 切换失败归入列表加载失败)
#### 集成验证点
- 无(已并入:Tab 与筛选组合见快捷筛选集成点)
---
### 列表
#### 功能验证点
- **TP_DEPTM_BUD_013**(高)|列表核心列完整|验证要点:主表展示 预算任务名称、院区、科室、状态、制单人、预算金额、已使用金额、预算进度、操作(详情/关闭/编辑/删除)|关联需求:UI-SPEC-SPD-DEPTM-010
#### 边界验证点
- **TP_DEPTM_BUD_014**(中)|无匹配空列表|验证要点:不存在的关键字查询后表头仍在,0 行或空态,有汇总时不展示过期汇总|关联需求:UI-SPEC-SPD-DEPTM-010
#### 异常验证点
- 无(已并入:列表加载失败见查询接口失败)
#### 集成验证点
- **TP_DEPTM_BUD_015**(高)|行内操作可达|验证要点:首行存在数据时,行操作 详情、关闭、编辑、删除 可点击并进入预期弹窗/详情(只读冒烟)。一对多:每个行内操作可拆一条用例|关联需求:UI-SPEC-SPD-DEPTM-010
---
### 分页
#### 功能验证点
- **TP_DEPTM_BUD_016**(中)|分页翻页|验证要点:总条数大于一页时可翻至第 2 页,首行数据更换且页码高亮正确|关联需求:UI-SPEC-SPD-DEPTM-010
- **TP_DEPTM_BUD_017**(中)|每页条数切换|验证要点:切换每页条数后当前页行数不超过所选值,总条数不变|关联需求:UI-SPEC-SPD-DEPTM-010
- **TP_DEPTM_BUD_018**(中)|跳至指定页|验证要点:输入合法页码后跳到对应页|关联需求:UI-SPEC-SPD-DEPTM-010
#### 边界验证点
- **TP_DEPTM_BUD_019**(中)|首页上一页不可用|验证要点:第 1 页时「上一页」禁用或无效|关联需求:UI-SPEC-SPD-DEPTM-010
- **TP_DEPTM_BUD_020**(中)|末页下一页不可用|验证要点:最后一页时「下一页」禁用或无效|关联需求:UI-SPEC-SPD-DEPTM-010
- **TP_DEPTM_BUD_021**(低)|跳至超出总页数|验证要点:超出范围有校验或纠正|关联需求:UI-SPEC-SPD-DEPTM-010
#### 异常验证点
- **TP_DEPTM_BUD_022**(低)|跳至非数字页码|验证要点:非法输入不跳转异常页|关联需求:UI-SPEC-SPD-DEPTM-010
#### 集成验证点
- **TP_DEPTM_BUD_023**(中)|翻页不丢失筛选|验证要点:带筛选翻页后条件保持,新页仍满足原筛选|关联需求:UI-SPEC-SPD-DEPTM-010
---
### 新增弹窗/抽屉
#### 功能验证点
- **TP_DEPTM_BUD_024**(高)|打开新增层|验证要点:触发新增后弹窗/抽屉可见,含取消/确定或关闭|关联需求:UI-SPEC-SPD-DEPTM-010
- **TP_DEPTM_BUD_025**(中)|取消不落库|验证要点:填写后取消或关闭,列表不新增/不修改对应记录|关联需求:UI-SPEC-SPD-DEPTM-010
- **TP_DEPTM_BUD_026**(中)|必填为空拦截|验证要点:必填项为空时确定被拦截并提示,列表不刷新为成功态|关联需求:UI-SPEC-SPD-DEPTM-010
#### 边界验证点
- **TP_DEPTM_BUD_027**(低)|重复打开|验证要点:连续两次打开不叠加多层遮罩|关联需求:UI-SPEC-SPD-DEPTM-010
#### 异常验证点
- **TP_DEPTM_BUD_028**(中)|保存失败|验证要点:接口失败时弹窗不自动关闭且列表保持原状|关联需求:UI-SPEC-SPD-DEPTM-010
#### 集成验证点
- **TP_DEPTM_BUD_029**(低)|弹窗字段与列表列一致|验证要点:弹窗内关键字段与列表展示字段命名一致|关联需求:UI-SPEC-SPD-DEPTM-010
---
## 质量自检摘要
| 项 | 结论 |
|----|------|
| 范围 | 在范围内:导航、筛选、状态 Tab、列表分页、详情/关闭/编辑/删除、新增。排除:断网/弱网、导出文件内容、Excel 字段级导入、弹窗全字段、登录/改密通用流程(见 `testpoint/scope/基础管理-科室管理-UI测试点范围.md`)。未声称 100% 全覆盖。 |
| 覆盖 | 已写功能域见正文 H3;共 **29** 条原子测试点 |
| 分类 | 功能 / 边界 / 异常 / 集成四类均已按功能点拆分 |
| 去重 | 登录态过期、无菜单权限、改密通用流程引用用户管理 `TP_USER_USR_006`/`TP_USER_USR_007`,本页不展开;顶栏院区为本页业务点。编号前缀 `TP_DEPTM_BUD` |
| 待评审项 | 弹窗内全字段以补扫为准;写操作冒烟不提交脏数据;状态 Tab 计数与列表条数规则以现网为准 |
| 报表能力 | 整页渲染,非统计报表 iframe,不适用 ui-test-point-rules 第四节 |
| 下游 | 可转 testcases/MD、CSV;扫描 `npm run discover:scan-deptm`;测试点 `npm run generate:testpoints-deptm` |
# 基础管理-科室管理-自动请领排程 — 测试点分析
**版本**:01
**定稿日期**:2026-11-03
**关联需求**:`knowledge-base/08-UI专项规范库/UI-SPEC-SPD-DEPTM-007.md`
**页面 URL**:`http://spdtest.cmic.com.cn:8080/spd/basic/dept/platform/dept/schedule`
**元素扫描**:`data/scan/deptm-auto-req-elements.json`(96 项)
**定位器**:`locators/spd/deptm-auto-req.locator.yaml`
**本次生成范围**:`testpoint/scope/基础管理-科室管理-UI测试点范围.md`
---
## 基础设置 · 科室管理 · 自动请领排程
### 页面访问与导航
#### 功能验证点
- **TP_DEPTM_AUR_001**(高)|页面主区加载完成|验证要点:携带有效登录态进入 `/spd/basic/dept/platform/dept/schedule`(菜单或直链),整页单表:院区/科室筛选、新增、排程类型(星期/天数)列、编辑/删除、分页;左侧菜单与顶栏 Tab 高亮为自动请领排程,不误入同组其它页|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_002**(中)|同组科室管理菜单可切换|验证要点:在 scope 所列科室管理 12 个子菜单中切换 2~3 个后 URL 与内容对应,再返回自动请领排程状态正确|关联需求:UI-SPEC-SPD-DEPTM-007
#### 边界验证点
- **TP_DEPTM_AUR_003**(低)|已登录直接打开 URL|验证要点:携带有效登录态打开 `/spd/basic/dept/platform/dept/schedule`,筛选区与列表(或主从分栏)可见,无报错遮罩,地址仍为该路径|关联需求:UI-SPEC-SPD-DEPTM-007
#### 异常验证点
- 无(未登录/会话过期/无菜单权限引用用户管理 `TP_USER_USR_005`~`007`;本模块自动化不单独写「菜单进入」「未登录访问拦截」用例,见 ui-test-point-rules 3.5)
#### 集成验证点
- **TP_DEPTM_AUR_004**(中)|顶栏院区与筛选默认一致|验证要点:顶栏当前院区与页面院区名称/科室树默认范围不矛盾(允许按权限裁剪)|关联需求:UI-SPEC-SPD-DEPTM-007
---
### 快捷筛选查询
#### 功能验证点
- **TP_DEPTM_AUR_005**(高)|默认条件查询|验证要点:点「查询」后列表有数据或空态明确,「共 N 条」与查询结果一致|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_006**(中)|重置恢复默认|验证要点:填写筛选后点「重置」,条件恢复默认并按产品规则刷新列表|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_007**(高)|全量可见条件组合查询|验证要点:先默认查询,从首行读取有值字段;快捷区可见非空条件全部填入后查询,抽样首行同时满足全部已填条件|关联需求:UI-SPEC-SPD-DEPTM-007
#### 边界验证点
- **TP_DEPTM_AUR_008**(中)|超长文本关键字|验证要点:名称/编号类字段输入较长关键字,查询被接受或截断,页面不崩溃|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_009**(低)|仅空格关键字|验证要点:按空查询或提示,不报错|关联需求:UI-SPEC-SPD-DEPTM-007
#### 异常验证点
- **TP_DEPTM_AUR_010**(中)|查询接口失败|验证要点:失败有错误提示,不白屏|关联需求:UI-SPEC-SPD-DEPTM-007
#### 集成验证点
- **TP_DEPTM_AUR_011**(中)|筛选结果与分页总数一致|验证要点:查询后「共 N 条」与本次查询匹配条数一致|关联需求:UI-SPEC-SPD-DEPTM-007
---
### 列表
#### 功能验证点
- **TP_DEPTM_AUR_012**(高)|列表核心列完整|验证要点:主表展示 院区、科室编码、科室名称、优先级、排程类型(星期/天数)、排程间隔、是否启用、操作(编辑/删除)|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_013**(低)|列设置隐藏后再恢复|验证要点:打开列设置 → 取消勾选非核心列 → 表头隐藏且勾选同步 → 再勾选后表头恢复|关联需求:UI-SPEC-SPD-DEPTM-007
#### 边界验证点
- **TP_DEPTM_AUR_014**(中)|无匹配空列表|验证要点:不存在的关键字查询后表头仍在,0 行或空态,有汇总时不展示过期汇总|关联需求:UI-SPEC-SPD-DEPTM-007
#### 异常验证点
- 无(已并入:列表加载失败见查询接口失败)
#### 集成验证点
- **TP_DEPTM_AUR_015**(高)|行内操作可达|验证要点:首行存在数据时,行操作 编辑、删除 可点击并进入预期弹窗/详情(只读冒烟)。一对多:每个行内操作可拆一条用例|关联需求:UI-SPEC-SPD-DEPTM-007
---
### 分页
#### 功能验证点
- **TP_DEPTM_AUR_016**(中)|分页翻页|验证要点:总条数大于一页时可翻至第 2 页,首行数据更换且页码高亮正确|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_017**(中)|每页条数切换|验证要点:切换每页条数后当前页行数不超过所选值,总条数不变|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_018**(中)|跳至指定页|验证要点:输入合法页码后跳到对应页|关联需求:UI-SPEC-SPD-DEPTM-007
#### 边界验证点
- **TP_DEPTM_AUR_019**(中)|首页上一页不可用|验证要点:第 1 页时「上一页」禁用或无效|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_020**(中)|末页下一页不可用|验证要点:最后一页时「下一页」禁用或无效|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_021**(低)|跳至超出总页数|验证要点:超出范围有校验或纠正|关联需求:UI-SPEC-SPD-DEPTM-007
#### 异常验证点
- **TP_DEPTM_AUR_022**(低)|跳至非数字页码|验证要点:非法输入不跳转异常页|关联需求:UI-SPEC-SPD-DEPTM-007
#### 集成验证点
- **TP_DEPTM_AUR_023**(中)|翻页不丢失筛选|验证要点:带筛选翻页后条件保持,新页仍满足原筛选|关联需求:UI-SPEC-SPD-DEPTM-007
---
### 排程类型展示
#### 功能验证点
- **TP_DEPTM_AUR_024**(高)|星期型排程展示|验证要点:排程类型为「星期」时,行内展示周日~周六可选按钮组且状态可读|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_025**(中)|天数型排程展示|验证要点:类型为「天数」时,间隔为数值输入或展示,与保存值一致|关联需求:UI-SPEC-SPD-DEPTM-007
#### 边界验证点
- **TP_DEPTM_AUR_026**(低)|未选星期/天数默认值|验证要点:新增排程未选星期或天数时保存被拦截或展示默认值(以现网为准)|关联需求:UI-SPEC-SPD-DEPTM-007
#### 异常验证点
- 无(已并入:排程展示只读,保存失败见新增/编辑弹窗)
#### 集成验证点
- **TP_DEPTM_AUR_027**(中)|与送货计划页语义区分|验证要点:本页 URL 为 `/schedule`,勿与「科室送货计划」`/deptPlan` 菜单/URL 混淆|关联需求:UI-SPEC-SPD-DEPTM-007
---
### 新增弹窗/抽屉
#### 功能验证点
- **TP_DEPTM_AUR_028**(高)|打开新增层|验证要点:触发新增后弹窗/抽屉可见,含取消/确定或关闭|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_029**(中)|取消不落库|验证要点:填写后取消或关闭,列表不新增/不修改对应记录|关联需求:UI-SPEC-SPD-DEPTM-007
- **TP_DEPTM_AUR_030**(中)|必填为空拦截|验证要点:必填项为空时确定被拦截并提示,列表不刷新为成功态|关联需求:UI-SPEC-SPD-DEPTM-007
#### 边界验证点
- **TP_DEPTM_AUR_031**(低)|重复打开|验证要点:连续两次打开不叠加多层遮罩|关联需求:UI-SPEC-SPD-DEPTM-007
#### 异常验证点
- **TP_DEPTM_AUR_032**(中)|保存失败|验证要点:接口失败时弹窗不自动关闭且列表保持原状|关联需求:UI-SPEC-SPD-DEPTM-007
#### 集成验证点
- **TP_DEPTM_AUR_033**(低)|弹窗字段与列表列一致|验证要点:弹窗内关键字段与列表展示字段命名一致|关联需求:UI-SPEC-SPD-DEPTM-007
---
## 质量自检摘要
| 项 | 结论 |
|----|------|
| 范围 | 在范围内:导航、筛选、列表与排程维度展示、新增/编辑/删除。排除:断网/弱网、导出文件内容、Excel 字段级导入、弹窗全字段、登录/改密通用流程(见 `testpoint/scope/基础管理-科室管理-UI测试点范围.md`)。未声称 100% 全覆盖。 |
| 覆盖 | 已写功能域见正文 H3;共 **33** 条原子测试点 |
| 分类 | 功能 / 边界 / 异常 / 集成四类均已按功能点拆分 |
| 去重 | 登录态过期、无菜单权限、改密通用流程引用用户管理 `TP_USER_USR_006`/`TP_USER_USR_007`,本页不展开;顶栏院区为本页业务点。编号前缀 `TP_DEPTM_AUR` |
| 待评审项 | 弹窗内全字段以补扫为准;写操作冒烟不提交脏数据;本页无状态 Tab |
| 报表能力 | 整页渲染,非统计报表 iframe,不适用 ui-test-point-rules 第四节 |
| 下游 | 可转 testcases/MD、CSV;扫描 `npm run discover:scan-deptm`;测试点 `npm run generate:testpoints-deptm` |
# 基础管理-科室管理-请领模板维护 — 测试点分析
**版本**:01
**定稿日期**:2026-11-03
**关联需求**:`knowledge-base/08-UI专项规范库/UI-SPEC-SPD-DEPTM-006.md`
**页面 URL**:`http://spdtest.cmic.com.cn:8080/spd/basic/dept/platform/dept/apply`
**元素扫描**:`data/scan/deptm-req-template-elements.json`(195 项)
**定位器**:`locators/spd/deptm-req-template.locator.yaml`
**本次生成范围**:`testpoint/scope/基础管理-科室管理-UI测试点范围.md`
---
## 基础设置 · 科室管理 · 请领模板维护
### 页面访问与导航
#### 功能验证点
- **TP_DEPTM_TPL_001**(高)|页面主区加载完成|验证要点:携带有效登录态进入 `/spd/basic/dept/platform/dept/apply`(菜单或直链),主从分栏:左侧请领模板目录、右侧物料筛选与添加产品/导入、明细列表与分页;左侧菜单与顶栏 Tab 高亮为请领模板维护,不误入同组其它页|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_002**(中)|同组科室管理菜单可切换|验证要点:在 scope 所列科室管理 12 个子菜单中切换 2~3 个后 URL 与内容对应,再返回请领模板维护状态正确|关联需求:UI-SPEC-SPD-DEPTM-006
#### 边界验证点
- **TP_DEPTM_TPL_003**(低)|已登录直接打开 URL|验证要点:携带有效登录态打开 `/spd/basic/dept/platform/dept/apply`,筛选区与列表(或主从分栏)可见,无报错遮罩,地址仍为该路径|关联需求:UI-SPEC-SPD-DEPTM-006
#### 异常验证点
- 无(未登录/会话过期/无菜单权限引用用户管理 `TP_USER_USR_005`~`007`;本模块自动化不单独写「菜单进入」「未登录访问拦截」用例,见 ui-test-point-rules 3.5)
#### 集成验证点
- **TP_DEPTM_TPL_004**(中)|顶栏院区与筛选默认一致|验证要点:顶栏当前院区与页面院区名称/科室树默认范围不矛盾(允许按权限裁剪)|关联需求:UI-SPEC-SPD-DEPTM-006
---
### 左侧模板目录
#### 功能验证点
- **TP_DEPTM_TPL_005**(高)|模板列表与院区/库房筛选|验证要点:左侧展示模板名称列表,院区/中心库下拉切换后模板列表刷新|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_006**(高)|切换模板刷新右侧|验证要点:点选另一模板后右侧明细刷新,不串上一模板数据|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_007**(高)|新增模板入口可见|验证要点:「+ 新增模板」按钮可见可点;打开后的取消/必填不在本点展开|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_008**(中)|模板行编辑删除|验证要点:模板行编辑/删除图标可用且作用于当前模板|关联需求:UI-SPEC-SPD-DEPTM-006
#### 边界验证点
- **TP_DEPTM_TPL_009**(低)|模板目录无匹配|验证要点:院区/库房或名称无匹配时左侧空态,右侧不展示过期明细|关联需求:UI-SPEC-SPD-DEPTM-006
#### 异常验证点
- **TP_DEPTM_TPL_010**(中)|模板目录加载失败|验证要点:失败有提示,右侧不展示过期明细|关联需求:UI-SPEC-SPD-DEPTM-006
#### 集成验证点
- **TP_DEPTM_TPL_011**(中)|模板范围与院区库房一致|验证要点:切换院区/中心库后可见模板属于该范围|关联需求:UI-SPEC-SPD-DEPTM-006
---
### 快捷筛选查询
#### 功能验证点
- **TP_DEPTM_TPL_012**(高)|默认条件查询|验证要点:点「查询」后列表有数据或空态明确,「共 N 条」与查询结果一致|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_013**(中)|重置恢复默认|验证要点:填写筛选后点「重置」,条件恢复默认并按产品规则刷新列表|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_014**(高)|全量可见条件组合查询|验证要点:先默认查询,从首行读取有值字段;快捷区可见非空条件全部填入后查询,抽样首行同时满足全部已填条件|关联需求:UI-SPEC-SPD-DEPTM-006
#### 边界验证点
- **TP_DEPTM_TPL_015**(中)|超长文本关键字|验证要点:名称/编号类字段输入较长关键字,查询被接受或截断,页面不崩溃|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_016**(低)|仅空格关键字|验证要点:按空查询或提示,不报错|关联需求:UI-SPEC-SPD-DEPTM-006
#### 异常验证点
- **TP_DEPTM_TPL_017**(中)|查询接口失败|验证要点:失败有错误提示,不白屏|关联需求:UI-SPEC-SPD-DEPTM-006
#### 集成验证点
- **TP_DEPTM_TPL_018**(中)|筛选结果与分页总数一致|验证要点:查询后「共 N 条」与本次查询匹配条数一致|关联需求:UI-SPEC-SPD-DEPTM-006
---
### Excel 导入与批量写操作
#### 功能验证点
- **TP_DEPTM_TPL_019**(高)|工具栏写操作入口可见|验证要点:工具栏展示 添加产品、导入excel(以现网按钮文案为准,不含导出/打印)|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_020**(中)|Excel 导入入口可触发|验证要点:点「Excel导入」/「导入excel」可打开导入流程,无未捕获异常|关联需求:UI-SPEC-SPD-DEPTM-006
#### 边界验证点
- 无(已并入:未勾选批量见批量页)
#### 异常验证点
- **TP_DEPTM_TPL_021**(中)|写操作失败提示|验证要点:新增/导入/批量修改等失败时有明确错误信息,列表不误增|关联需求:UI-SPEC-SPD-DEPTM-006
#### 集成验证点
- **TP_DEPTM_TPL_022**(低)|导入模板说明可读|验证要点:导入入口旁提示或模板说明可访问(不校验 Excel 字段级)|关联需求:UI-SPEC-SPD-DEPTM-006
---
### 列表
#### 功能验证点
- **TP_DEPTM_TPL_023**(高)|列表核心列完整|验证要点:主表展示 规格型号、器械注册人、单元含量、耗材类型、库存数量、操作(编辑/移除)|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_024**(中)|各可排序列升序降序|验证要点:每个带排序器的列均可升序、再降序;指示器(▲/▼ 或 aria-sort)与方向一致;列表仍有数据|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_025**(低)|列设置隐藏后再恢复|验证要点:打开列设置 → 取消勾选非核心列 → 表头隐藏且勾选同步 → 再勾选后表头恢复|关联需求:UI-SPEC-SPD-DEPTM-006
#### 边界验证点
- **TP_DEPTM_TPL_026**(中)|无匹配空列表|验证要点:不存在的关键字查询后表头仍在,0 行或空态,有汇总时不展示过期汇总|关联需求:UI-SPEC-SPD-DEPTM-006
#### 异常验证点
- 无(已并入:列表加载失败见查询接口失败)
#### 集成验证点
- **TP_DEPTM_TPL_027**(高)|行内操作可达|验证要点:首行存在数据时,行操作 编辑、移除 可点击并进入预期弹窗/详情(只读冒烟)。一对多:每个行内操作可拆一条用例|关联需求:UI-SPEC-SPD-DEPTM-006
---
### 分页
#### 功能验证点
- **TP_DEPTM_TPL_028**(中)|分页翻页|验证要点:总条数大于一页时可翻至第 2 页,首行数据更换且页码高亮正确|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_029**(中)|每页条数切换|验证要点:切换每页条数后当前页行数不超过所选值,总条数不变|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_030**(中)|跳至指定页|验证要点:输入合法页码后跳到对应页|关联需求:UI-SPEC-SPD-DEPTM-006
#### 边界验证点
- **TP_DEPTM_TPL_031**(中)|首页上一页不可用|验证要点:第 1 页时「上一页」禁用或无效|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_032**(中)|末页下一页不可用|验证要点:最后一页时「下一页」禁用或无效|关联需求:UI-SPEC-SPD-DEPTM-006
- **TP_DEPTM_TPL_033**(低)|跳至超出总页数|验证要点:超出范围有校验或纠正|关联需求:UI-SPEC-SPD-DEPTM-006
#### 异常验证点
- **TP_DEPTM_TPL_034**(低)|跳至非数字页码|验证要点:非法输入不跳转异常页|关联需求:UI-SPEC-SPD-DEPTM-006
#### 集成验证点
- **TP_DEPTM_TPL_035**(中)|翻页不丢失筛选|验证要点:带筛选翻页后条件保持,新页仍满足原筛选|关联需求:UI-SPEC-SPD-DEPTM-006
---
## 质量自检摘要
| 项 | 结论 |
|----|------|
| 范围 | 在范围内:导航、模板目录、右侧筛选与明细、添加产品/导入、编辑/移除。排除:断网/弱网、导出文件内容、Excel 字段级导入、弹窗全字段、登录/改密通用流程(见 `testpoint/scope/基础管理-科室管理-UI测试点范围.md`)。未声称 100% 全覆盖。 |
| 覆盖 | 已写功能域见正文 H3;共 **35** 条原子测试点 |
| 分类 | 功能 / 边界 / 异常 / 集成四类均已按功能点拆分 |
| 去重 | 登录态过期、无菜单权限、改密通用流程引用用户管理 `TP_USER_USR_006`/`TP_USER_USR_007`,本页不展开;顶栏院区为本页业务点。编号前缀 `TP_DEPTM_TPL` |
| 待评审项 | 弹窗内全字段以补扫为准;写操作冒烟不提交脏数据;本页无状态 Tab |
| 报表能力 | 整页渲染,非统计报表 iframe,不适用 ui-test-point-rules 第四节 |
| 下游 | 可转 testcases/MD、CSV;扫描 `npm run discover:scan-deptm`;测试点 `npm run generate:testpoints-deptm` |
...@@ -5,38 +5,25 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from ...@@ -5,38 +5,25 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from
* 全量用例:映射 testcase/基础管理-准入管理-物料准入单列表-UI自动化测试用例-01.csv * 全量用例:映射 testcase/基础管理-准入管理-物料准入单列表-UI自动化测试用例-01.csv
*/ */
test.describe('基础设置 · 准入管理', () => { test.describe('基础设置 · 准入管理', () => {
test.describe('物料准入单列表 · 页面进入', () => {
test('ADMIT-MLS-001 菜单进入物料准入单列表', { tag: '@smoke' }, async ({ admitMaterialListPage }) => {
await admitMaterialListPage.openFromMenu();
await admitMaterialListPage.ready();
expect(admitMaterialListPage.browserPage.url(), 'URL 应为物料准入单列表').toContain('zrlist');
await expect(admitMaterialListPage.tab('已通过'), '已通过 Tab').toBeVisible();
});
});
test.describe('物料准入单列表 · 筛选与状态', () => { test.describe('物料准入单列表 · 筛选与状态', () => {
test('ADMIT-MLS-002 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitMaterialListPage }) => { test('ADMIT-MLS-001 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open(); await admitMaterialListPage.open();
await admitMaterialListPage.query(); await admitMaterialListPage.query();
await assertAdmitListOrEmpty(await admitMaterialListPage.snapshotList()); await assertAdmitListOrEmpty(await admitMaterialListPage.snapshotList());
}); });
test('ADMIT-MLS-003 按准入单号筛选', async ({ admitMaterialListPage }) => { test('ADMIT-MLS-002 重置恢复默认', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open();
await admitMaterialListPage.filterByOrderOrFallback();
});
test('ADMIT-MLS-004 重置恢复默认', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open(); await admitMaterialListPage.open();
await admitMaterialListPage.resetFilters(); await admitMaterialListPage.resetFilters();
}); });
test('ADMIT-MLS-005 无匹配结果空态(mock反例)', async ({ admitMaterialListPage }) => { test('ADMIT-MLS-003 无匹配结果空态(mock反例)', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open(); await admitMaterialListPage.open();
await assertAdmitMockEmpty(await admitMaterialListPage.mockEmpty()); await assertAdmitMockEmpty(await admitMaterialListPage.mockEmpty());
}); });
test('ADMIT-MLS-006 列表核心列完整', async ({ admitMaterialListPage }) => { test('ADMIT-MLS-004 列表核心列完整', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open(); await admitMaterialListPage.open();
assertAdmitHeaders(await admitMaterialListPage.coreHeaders(), [ assertAdmitHeaders(await admitMaterialListPage.coreHeaders(), [
'准入类型', '准入类型',
...@@ -52,41 +39,55 @@ test.describe('基础设置 · 准入管理', () => { ...@@ -52,41 +39,55 @@ test.describe('基础设置 · 准入管理', () => {
await expect(admitMaterialListPage.rowAction(await admitMaterialListPage.firstRow(), '详情'), '详情').toBeVisible(); await expect(admitMaterialListPage.rowAction(await admitMaterialListPage.firstRow(), '详情'), '详情').toBeVisible();
}); });
test('ADMIT-MLS-007 切换已通过 Tab', async ({ admitMaterialListPage }) => { test('ADMIT-MLS-005 切换已通过 Tab', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open(); await admitMaterialListPage.open();
await admitMaterialListPage.switchPassed(); await admitMaterialListPage.switchPassed();
}); });
test('ADMIT-MLS-013 多条件组合查询(制单日期等6项)', async ({ admitMaterialListPage }) => {
test('ADMIT-MLS-011 多条件组合查询(制单日期等6项)', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open(); await admitMaterialListPage.open();
await admitMaterialListPage.filterCombination(); await admitMaterialListPage.filterCombination();
}); });
}); });
test.describe('物料准入单列表 · 单据详情', () => { test.describe('物料准入单列表 · 单据详情', () => {
test('ADMIT-MLS-008 打开详情后返回', async ({ admitMaterialListPage }) => { test('ADMIT-MLS-006 打开详情后返回', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open(); await admitMaterialListPage.open();
await admitMaterialListPage.detailAndBack(); await admitMaterialListPage.detailAndBack();
}); });
test('ADMIT-MLS-009 详情产品条数与列表一致', async ({ admitMaterialListPage }) => { test('ADMIT-MLS-007 详情页准入单号和列表一致', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open(); await admitMaterialListPage.open();
await admitMaterialListPage.detailCountMatches(); await admitMaterialListPage.detailOrderMatches();
}); });
test('ADMIT-MLS-010 审批进程可打开', async ({ admitMaterialListPage }) => { test('ADMIT-MLS-008 审批进程可打开', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open(); await admitMaterialListPage.open();
await admitMaterialListPage.openApproval(); await admitMaterialListPage.openApproval();
}); });
test('ADMIT-MLS-011 详情导出不白屏', async ({ admitMaterialListPage }) => { test('ADMIT-MLS-009 详情导出不白屏', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open(); await admitMaterialListPage.open();
await admitMaterialListPage.exportDetail(); await admitMaterialListPage.exportDetail();
}); });
test('ADMIT-MLS-010 已通过单据不确认通过', async ({ admitMaterialListPage }) => {
test('ADMIT-MLS-012 已通过单据不确认通过', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open(); await admitMaterialListPage.open();
await admitMaterialListPage.passedNotConfirm(); await admitMaterialListPage.passedNotConfirm();
}); });
}); });
test.describe('物料准入单列表 · 分页', () => {
test('ADMIT-MLS-012 切换20条每页页面正常且列表同步', async ({ admitMaterialListPage }) => {
await admitMaterialListPage.open();
await admitMaterialListPage.query();
const { total, rowsBefore, rowsAfter } = await admitMaterialListPage.switchToPageSizeTwenty();
const expectedRows = Math.min(total, 20);
expect(rowsAfter, '当前页行数应与 20 条/页及总条数一致').toBe(expectedRows);
expect(rowsAfter, '切换后可见行应随每页条数变化').not.toBe(rowsBefore);
expect(await admitMaterialListPage.getTotalCount(), '总条数应不变').toBe(total);
await expect(admitMaterialListPage.pageSizeChanger(), '每页条数').toContainText(/20/);
});
});
}); });
...@@ -5,62 +5,41 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from ...@@ -5,62 +5,41 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from
* 全量用例:映射 testcase/基础管理-准入管理-物料准入管理-UI自动化测试用例-01.csv * 全量用例:映射 testcase/基础管理-准入管理-物料准入管理-UI自动化测试用例-01.csv
*/ */
test.describe('基础设置 · 准入管理', () => { test.describe('基础设置 · 准入管理', () => {
test.describe('物料准入管理 · 页面进入', () => {
test('ADMIT-MAT-001 菜单进入物料准入管理页', { tag: '@smoke' }, async ({ admitMaterialPage }) => {
await admitMaterialPage.openFromMenu();
await admitMaterialPage.ready();
expect(admitMaterialPage.browserPage.url(), 'URL 应为物料准入').toContain('ZRlist');
for (const name of ['关联产品', '生成申请单', '一键生成', '作废']) {
await expect(admitMaterialPage.button(name).first(), name).toBeVisible();
}
await expect(admitMaterialPage.tab('待申请'), '待申请 Tab').toBeVisible();
});
});
test.describe('物料准入管理 · 筛选查询', () => { test.describe('物料准入管理 · 快捷筛选查询', () => {
test('ADMIT-MAT-002 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitMaterialPage }) => { test('ADMIT-MAT-001 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitMaterialPage }) => {
await admitMaterialPage.open(); await admitMaterialPage.open();
await admitMaterialPage.query(); await admitMaterialPage.query();
await assertAdmitListOrEmpty(await admitMaterialPage.snapshotList()); await assertAdmitListOrEmpty(await admitMaterialPage.snapshotList());
}); });
test('ADMIT-MAT-003 物料名称筛选', async ({ admitMaterialPage }) => { test('ADMIT-MAT-002 名称与耗材类型组合查询', async ({ admitMaterialPage }) => {
await admitMaterialPage.open();
await admitMaterialPage.filterByProductName();
});
test('ADMIT-MAT-004 耗材类型筛选', async ({ admitMaterialPage }) => {
await admitMaterialPage.open();
await admitMaterialPage.filterByGoodsType();
});
test('ADMIT-MAT-005 名称与耗材类型组合查询', async ({ admitMaterialPage }) => {
await admitMaterialPage.open(); await admitMaterialPage.open();
await admitMaterialPage.filterByNameAndType(); await admitMaterialPage.filterByNameAndType();
}); });
test('ADMIT-MAT-006 重置恢复默认', async ({ admitMaterialPage }) => { test('ADMIT-MAT-003 重置恢复默认', async ({ admitMaterialPage }) => {
await admitMaterialPage.open(); await admitMaterialPage.open();
await admitMaterialPage.resetFilters(); await admitMaterialPage.resetFilters();
}); });
test('ADMIT-MAT-007 收起后再展开保留条件', async ({ admitMaterialPage }) => { test('ADMIT-MAT-004 新增日期与销售商(自定义)等七项组合查询', async ({ admitMaterialPage }) => {
await admitMaterialPage.open(); await admitMaterialPage.open();
await admitMaterialPage.collapseKeepsName(); await admitMaterialPage.filterCombination();
}); });
test('ADMIT-MAT-008 无匹配结果空态(mock反例)', async ({ admitMaterialPage }) => { test('ADMIT-MAT-005 无匹配结果空态(mock反例)', async ({ admitMaterialPage }) => {
await admitMaterialPage.open(); await admitMaterialPage.open();
await assertAdmitMockEmpty(await admitMaterialPage.mockEmptyName()); await assertAdmitMockEmpty(await admitMaterialPage.mockEmptyName());
}); });
}); });
test.describe('物料准入管理 · 状态与列表', () => { test.describe('物料准入管理 · 状态与列表', () => {
test('ADMIT-MAT-009 列表核心列完整', async ({ admitMaterialPage }) => { test('ADMIT-MAT-006 列表核心列完整', async ({ admitMaterialPage }) => {
await admitMaterialPage.open(); await admitMaterialPage.open();
assertAdmitHeaders(await admitMaterialPage.coreHeaders(), [ assertAdmitHeaders(await admitMaterialPage.coreHeaders(), [
'准入类型', '准入类型',
'产品编号', '物料编号',
'物料名称', '物料名称',
'规格型号', '规格型号',
'规格', '规格',
...@@ -74,26 +53,78 @@ test.describe('基础设置 · 准入管理', () => { ...@@ -74,26 +53,78 @@ test.describe('基础设置 · 准入管理', () => {
await expect(admitMaterialPage.rowAction(await admitMaterialPage.firstRow(), '详情'), '详情').toBeVisible(); await expect(admitMaterialPage.rowAction(await admitMaterialPage.firstRow(), '详情'), '详情').toBeVisible();
}); });
test('ADMIT-MAT-010 切换待申请 Tab', async ({ admitMaterialPage }) => { test('ADMIT-MAT-007 切换待申请 Tab', async ({ admitMaterialPage }) => {
await admitMaterialPage.open(); await admitMaterialPage.open();
await admitMaterialPage.switchPending(); await admitMaterialPage.switchPending();
}); });
}); });
test.describe('物料准入管理 · 详情与编辑', () => { test.describe('物料准入管理 · 详情与编辑', () => {
test('ADMIT-MAT-011 详情关键字段不可直接改写', async ({ admitMaterialPage }) => { test('ADMIT-MAT-008 详情关键字段不可直接改写', async ({ admitMaterialPage }) => {
await admitMaterialPage.open(); await admitMaterialPage.open();
await admitMaterialPage.detailReadonly(); await admitMaterialPage.detailReadonly();
}); });
test('ADMIT-MAT-012 待申请行编辑回填', async ({ admitMaterialPage }) => { test('ADMIT-MAT-009 待申请行编辑回填', async ({ admitMaterialPage }) => {
await admitMaterialPage.open(); await admitMaterialPage.open();
await admitMaterialPage.editBackfill(); await admitMaterialPage.editBackfill();
}); });
test('ADMIT-MAT-013 已生效行不提供编辑', async ({ admitMaterialPage }) => { test('ADMIT-MAT-010 已生效行不提供编辑', async ({ admitMaterialPage }) => {
await admitMaterialPage.open(); await admitMaterialPage.open();
await admitMaterialPage.effectiveNoEdit(); await admitMaterialPage.effectiveNoEdit();
}); });
}); });
test.describe('物料准入管理 · 分页', () => {
test('ADMIT-MAT-011 切换20条每页页面正常且列表同步', async ({ admitMaterialPage }) => {
await admitMaterialPage.open();
await admitMaterialPage.query();
const { total, rowsBefore, rowsAfter } = await admitMaterialPage.switchToPageSizeTwenty();
const expectedRows = Math.min(total, 20);
expect(rowsAfter, '当前页行数应与 20 条/页及总条数一致').toBe(expectedRows);
expect(rowsAfter, '切换后可见行应随每页条数变化').not.toBe(rowsBefore);
expect(await admitMaterialPage.getTotalCount(), '总条数应不变').toBe(total);
await expect(admitMaterialPage.pageSizeChanger(), '每页条数').toContainText(/20/);
});
});
test.describe('物料准入管理 · 列表', () => {
test('ADMIT-MAT-012 物料编号列升序降序切换', async ({ admitMaterialPage }) => {
await admitMaterialPage.open();
await admitMaterialPage.query();
await admitMaterialPage.expectColumnSortAscDesc('物料编号');
});
test('ADMIT-MAT-013 物料名称列升序降序切换', async ({ admitMaterialPage }) => {
await admitMaterialPage.open();
await admitMaterialPage.query();
await admitMaterialPage.expectColumnSortAscDesc('物料名称');
});
test('ADMIT-MAT-014 规格型号列升序降序切换', async ({ admitMaterialPage }) => {
await admitMaterialPage.open();
await admitMaterialPage.query();
await admitMaterialPage.expectColumnSortAscDesc('规格型号');
});
test('ADMIT-MAT-015 器械注册人列升序降序切换', async ({ admitMaterialPage }) => {
await admitMaterialPage.open();
await admitMaterialPage.query();
await admitMaterialPage.expectColumnSortAscDesc('器械注册人');
});
test('ADMIT-MAT-016 单位列升序降序切换', async ({ admitMaterialPage }) => {
await admitMaterialPage.open();
await admitMaterialPage.query();
await admitMaterialPage.expectColumnSortAscDesc('单位');
});
test('ADMIT-MAT-017 耗材类型列升序降序切换', async ({ admitMaterialPage }) => {
await admitMaterialPage.open();
await admitMaterialPage.query();
await admitMaterialPage.expectColumnSortAscDesc('耗材类型');
});
test('ADMIT-MAT-018 列设置隐藏后再恢复', async ({ admitMaterialPage }) => {
await admitMaterialPage.open();
await admitMaterialPage.query();
await admitMaterialPage.executeColumnSettingsToggleRestoreTest();
});
});
}); });
...@@ -5,47 +5,32 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from ...@@ -5,47 +5,32 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from
* 全量用例:映射 testcase/基础管理-准入管理-产品准入申请-UI自动化测试用例-01.csv * 全量用例:映射 testcase/基础管理-准入管理-产品准入申请-UI自动化测试用例-01.csv
*/ */
test.describe('基础设置 · 准入管理', () => { test.describe('基础设置 · 准入管理', () => {
test.describe('产品准入申请 · 页面进入', () => {
test('ADMIT-PAP-001 菜单进入产品准入申请页', { tag: '@smoke' }, async ({ admitProductApplyPage }) => {
await admitProductApplyPage.openFromMenu();
await admitProductApplyPage.ready();
expect(admitProductApplyPage.browserPage.url(), '不应进入物料准入').not.toContain('ZRlist');
for (const name of ['新增产品', 'Excel导入', '生成申请单']) {
await expect(admitProductApplyPage.button(name).first(), name).toBeVisible();
}
});
});
test.describe('产品准入申请 · 筛选查询', () => { test.describe('产品准入申请 · 快捷筛选查询', () => {
test('ADMIT-PAP-002 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitProductApplyPage }) => { test('ADMIT-PAP-001 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.query(); await admitProductApplyPage.query();
await assertAdmitListOrEmpty(await admitProductApplyPage.snapshotList()); await assertAdmitListOrEmpty(await admitProductApplyPage.snapshotList());
}); });
test('ADMIT-PAP-003 物料名称筛选', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-002 新增日期与销售商(自定义)等七项组合查询', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); test.setTimeout(180_000);
await admitProductApplyPage.filterByProductName();
});
test('ADMIT-PAP-004 名称与耗材类型组合查询', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.filterByNameAndType(); await admitProductApplyPage.filterCombination();
}); });
test('ADMIT-PAP-005 重置恢复默认', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-003 重置恢复默认', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.resetFilters(); await admitProductApplyPage.resetFilters();
}); });
});
});
test.describe('产品准入申请 · 状态与列表', () => { test.describe('产品准入申请 · 状态与列表', () => {
test('ADMIT-PAP-006 列表核心列完整', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-004 列表核心列完整', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
assertAdmitHeaders(await admitProductApplyPage.coreHeaders(), [ assertAdmitHeaders(await admitProductApplyPage.coreHeaders(), [
'准入单号', '准入单号',
'产品编号', '物料编号',
'物料名称', '物料名称',
'规格型号', '规格型号',
'器械注册人', '器械注册人',
...@@ -54,59 +39,111 @@ test.describe('基础设置 · 准入管理', () => { ...@@ -54,59 +39,111 @@ test.describe('基础设置 · 准入管理', () => {
]); ]);
}); });
test('ADMIT-PAP-007 切换待申请 Tab', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-005 切换待申请 Tab', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.switchPending(); await admitProductApplyPage.switchPending();
}); });
test('ADMIT-PAP-008 翻至第 2 页', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-006 翻至第 2 页', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.goPage2(); await admitProductApplyPage.goPage2();
}); });
test('ADMIT-PAP-009 跳至指定页', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-007 跳至指定页', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.jumpPage2(); await admitProductApplyPage.jumpPage2();
}); });
}); });
test.describe('产品准入申请 · 新增与导入', () => { test.describe('产品准入申请 · 新增与导入', () => {
test('ADMIT-PAP-010 打开新增产品后返回', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-008 打开新增产品后返回', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.openAddAndBack(); await admitProductApplyPage.openAddAndBack();
}); });
test('ADMIT-PAP-011 新增取消不落库', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-009 新增取消不落库', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.addCancel(); await admitProductApplyPage.addCancel();
}); });
}); });
test.describe('产品准入申请 · 详情、编辑与作废', () => { test.describe('产品准入申请 · 详情、编辑与作废', () => {
test('ADMIT-PAP-012 打开详情后返回', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-010 打开详情后返回', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.detailAndBack(); await admitProductApplyPage.detailAndBack();
}); });
test('ADMIT-PAP-013 待申请编辑回填', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-011 待申请编辑回填', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.editBackfill(); await admitProductApplyPage.editBackfill();
}); });
test('ADMIT-PAP-014 编辑取消不保存', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-012 编辑取消不保存', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.editCancel(); await admitProductApplyPage.editCancel();
}); });
test('ADMIT-PAP-015 作废确认后取消', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-013 作废确认后取消', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.voidCancel(); await admitProductApplyPage.voidCancel();
}); });
test('ADMIT-PAP-016 已通过行不提供编辑', async ({ admitProductApplyPage }) => { test('ADMIT-PAP-014 已通过行不提供编辑', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open(); await admitProductApplyPage.open();
await admitProductApplyPage.passedNoEdit(); await admitProductApplyPage.passedNoEdit();
}); });
}); });
test.describe('产品准入申请 · 分页', () => {
test('ADMIT-PAP-015 切换20条每页页面正常且列表同步', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open();
await admitProductApplyPage.query();
const { total, rowsBefore, rowsAfter } = await admitProductApplyPage.switchToPageSizeTwenty();
const expectedRows = Math.min(total, 20);
expect(rowsAfter, '当前页行数应与 20 条/页及总条数一致').toBe(expectedRows);
expect(rowsAfter, '切换后可见行应随每页条数变化').not.toBe(rowsBefore);
expect(await admitProductApplyPage.getTotalCount(), '总条数应不变').toBe(total);
await expect(admitProductApplyPage.pageSizeChanger(), '每页条数').toContainText(/20/);
});
});
test.describe('产品准入申请 · 列表', () => {
test('ADMIT-PAP-016 物料编号列升序降序切换', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open();
await admitProductApplyPage.query();
await admitProductApplyPage.expectColumnSortAscDesc('物料编号');
});
test('ADMIT-PAP-017 物料名称列升序降序切换', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open();
await admitProductApplyPage.query();
await admitProductApplyPage.expectColumnSortAscDesc('物料名称');
});
test('ADMIT-PAP-018 规格型号列升序降序切换', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open();
await admitProductApplyPage.query();
await admitProductApplyPage.expectColumnSortAscDesc('规格型号');
});
test('ADMIT-PAP-019 器械注册人列升序降序切换', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open();
await admitProductApplyPage.query();
await admitProductApplyPage.expectColumnSortAscDesc('器械注册人');
});
test('ADMIT-PAP-020 单位列升序降序切换', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open();
await admitProductApplyPage.query();
await admitProductApplyPage.expectColumnSortAscDesc('单位');
});
test('ADMIT-PAP-021 耗材类型列升序降序切换', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open();
await admitProductApplyPage.query();
await admitProductApplyPage.expectColumnSortAscDesc('耗材类型');
});
test('ADMIT-PAP-022 列设置隐藏后再恢复', async ({ admitProductApplyPage }) => {
await admitProductApplyPage.open();
await admitProductApplyPage.query();
await admitProductApplyPage.executeColumnSettingsToggleRestoreTest();
});
});
}); });
...@@ -5,38 +5,30 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from ...@@ -5,38 +5,30 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from
* 全量用例:映射 testcase/基础管理-准入管理-产品准入单列表-UI自动化测试用例-01.csv * 全量用例:映射 testcase/基础管理-准入管理-产品准入单列表-UI自动化测试用例-01.csv
*/ */
test.describe('基础设置 · 准入管理', () => { test.describe('基础设置 · 准入管理', () => {
test.describe('产品准入单列表 · 页面进入', () => {
test('ADMIT-PLS-001 菜单进入产品准入单列表', { tag: '@smoke' }, async ({ admitProductListPage }) => {
await admitProductListPage.openFromMenu();
await admitProductListPage.ready();
expect(admitProductListPage.browserPage.url(), '不应进入物料准入单').not.toContain('zrlist');
await expect(admitProductListPage.tab('已通过'), '已通过 Tab').toBeVisible();
});
});
test.describe('产品准入单列表 · 筛选与状态', () => { test.describe('产品准入单列表 · 筛选与状态', () => {
test('ADMIT-PLS-002 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitProductListPage }) => { test('ADMIT-PLS-001 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
await admitProductListPage.query(); await admitProductListPage.query();
await assertAdmitListOrEmpty(await admitProductListPage.snapshotList()); await assertAdmitListOrEmpty(await admitProductListPage.snapshotList());
}); });
test('ADMIT-PLS-003 按产品名称筛选', async ({ admitProductListPage }) => { test('ADMIT-PLS-002 按物料名称筛选', async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
await admitProductListPage.filterByProductOrFallback(); await admitProductListPage.filterByProductOrFallback();
}); });
test('ADMIT-PLS-004 重置恢复默认', async ({ admitProductListPage }) => { test('ADMIT-PLS-003 重置恢复默认', async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
await admitProductListPage.resetFilters(); await admitProductListPage.resetFilters();
}); });
test('ADMIT-PLS-005 无匹配结果空态(mock反例)', async ({ admitProductListPage }) => { test('ADMIT-PLS-004 无匹配结果空态(mock反例)', async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
await assertAdmitMockEmpty(await admitProductListPage.mockEmpty()); await assertAdmitMockEmpty(await admitProductListPage.mockEmpty());
}); });
test('ADMIT-PLS-006 列表核心列与附件计数', async ({ admitProductListPage }) => { test('ADMIT-PLS-005 列表核心列与附件计数', async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
assertAdmitHeaders(await admitProductListPage.coreHeaders(), [ assertAdmitHeaders(await admitProductListPage.coreHeaders(), [
'准入单号', '准入单号',
...@@ -52,42 +44,63 @@ test.describe('基础设置 · 准入管理', () => { ...@@ -52,42 +44,63 @@ test.describe('基础设置 · 准入管理', () => {
]); ]);
}); });
test('ADMIT-PLS-007 切换已通过 Tab', async ({ admitProductListPage }) => { test('ADMIT-PLS-006 切换已通过 Tab', async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
await admitProductListPage.switchPassed(); await admitProductListPage.switchPassed();
}); });
test('ADMIT-PLS-008 与物料准入单列表不串 URL', async ({ admitProductListPage }) => { test('ADMIT-PLS-007 与物料准入单列表不串 URL', async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
expect(admitProductListPage.browserPage.url(), 'URL 应为产品准入单列表').toContain('productOrder/list'); expect(admitProductListPage.browserPage.url(), 'URL 应为产品准入单列表').toContain('productOrder/list');
expect(admitProductListPage.browserPage.url(), '不应串到物料准入单').not.toContain('zrlist'); expect(admitProductListPage.browserPage.url(), '不应串到物料准入单').not.toContain('zrlist');
}); });
test('ADMIT-PLS-013 多条件组合查询(制单日期等6项)', async ({ admitProductListPage }) => { test('ADMIT-PLS-012 多条件组合查询(制单日期等6项)', async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
await admitProductListPage.filterCombination(); await admitProductListPage.filterCombination();
}); });
}); });
test.describe('产品准入单列表 · 单据详情', () => { test.describe('产品准入单列表 · 单据详情', () => {
test('ADMIT-PLS-009 打开详情后返回', async ({ admitProductListPage }) => { test('ADMIT-PLS-008 打开详情后返回', async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
await admitProductListPage.detailAndBack(); await admitProductListPage.detailAndBack();
}); });
test('ADMIT-PLS-010 详情产品条数与列表一致', async ({ admitProductListPage }) => { test('ADMIT-PLS-009 详情产品条数与列表一致', async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
await admitProductListPage.detailCountMatches(); await admitProductListPage.detailCountMatches();
}); });
test('ADMIT-PLS-011 单据日志可打开', async ({ admitProductListPage }) => { test('ADMIT-PLS-010 单据日志可打开', async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
await admitProductListPage.openBillLog(); await admitProductListPage.openBillLog();
}); });
test('ADMIT-PLS-012 已通过单据不确认通过', async ({ admitProductListPage }) => { test('ADMIT-PLS-011 已通过单据不确认通过', async ({ admitProductListPage }) => {
await admitProductListPage.open(); await admitProductListPage.open();
await admitProductListPage.passedNotConfirm(); await admitProductListPage.passedNotConfirm();
}); });
}); });
test.describe('产品准入单列表 · 分页', () => {
test('ADMIT-PLS-013 切换20条每页页面正常且列表同步', async ({ admitProductListPage }) => {
await admitProductListPage.open();
await admitProductListPage.query();
const { total, rowsBefore, rowsAfter } = await admitProductListPage.switchToPageSizeTwenty();
const expectedRows = Math.min(total, 20);
expect(rowsAfter, '当前页行数应与 20 条/页及总条数一致').toBe(expectedRows);
expect(rowsAfter, '切换后可见行应随每页条数变化').not.toBe(rowsBefore);
expect(await admitProductListPage.getTotalCount(), '总条数应不变').toBe(total);
await expect(admitProductListPage.pageSizeChanger(), '每页条数').toContainText(/20/);
});
});
test.describe('产品准入单列表 · 列表', () => {
test('ADMIT-PLS-014 列设置隐藏后再恢复', async ({ admitProductListPage }) => {
await admitProductListPage.open();
await admitProductListPage.query();
await admitProductListPage.executeColumnSettingsToggleRestoreTest();
});
});
}); });
...@@ -5,28 +5,20 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from ...@@ -5,28 +5,20 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from
* 全量用例:映射 testcase/基础管理-准入管理-供货目录申请-UI自动化测试用例-01.csv * 全量用例:映射 testcase/基础管理-准入管理-供货目录申请-UI自动化测试用例-01.csv
*/ */
test.describe('基础设置 · 准入管理', () => { test.describe('基础设置 · 准入管理', () => {
test.describe('供货目录申请 · 页面进入', () => {
test('ADMIT-SUP-001 菜单进入供货目录申请页', { tag: '@smoke' }, async ({ admitSupplyPage }) => {
await admitSupplyPage.openFromMenu();
await admitSupplyPage.ready();
await expect(admitSupplyPage.button('新增').first(), '新增').toBeVisible();
await expect(admitSupplyPage.button('批量提交').first(), '批量提交').toBeVisible();
});
});
test.describe('供货目录申请 · 筛选与状态', () => { test.describe('供货目录申请 · 筛选与状态', () => {
test('ADMIT-SUP-002 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitSupplyPage }) => { test('ADMIT-SUP-001 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitSupplyPage }) => {
await admitSupplyPage.open(); await admitSupplyPage.open();
await admitSupplyPage.query(); await admitSupplyPage.query();
await assertAdmitListOrEmpty(await admitSupplyPage.snapshotList()); await assertAdmitListOrEmpty(await admitSupplyPage.snapshotList());
}); });
test('ADMIT-SUP-003 变更单号无匹配空态(mock反例)', async ({ admitSupplyPage }) => { test('ADMIT-SUP-002 变更单号无匹配空态(mock反例)', async ({ admitSupplyPage }) => {
await admitSupplyPage.open(); await admitSupplyPage.open();
await assertAdmitMockEmpty(await admitSupplyPage.mockEmpty()); await assertAdmitMockEmpty(await admitSupplyPage.mockEmpty());
}); });
test('ADMIT-SUP-004 列表核心列完整', async ({ admitSupplyPage }) => { test('ADMIT-SUP-003 列表核心列完整', async ({ admitSupplyPage }) => {
await admitSupplyPage.open(); await admitSupplyPage.open();
assertAdmitHeaders(await admitSupplyPage.coreHeaders(), [ assertAdmitHeaders(await admitSupplyPage.coreHeaders(), [
'申请单号', '申请单号',
...@@ -41,48 +33,114 @@ test.describe('基础设置 · 准入管理', () => { ...@@ -41,48 +33,114 @@ test.describe('基础设置 · 准入管理', () => {
]); ]);
}); });
test('ADMIT-SUP-005 切换待提交 Tab 且计数一致', async ({ admitSupplyPage }) => { test('ADMIT-SUP-004 切换待提交 Tab 且计数一致', async ({ admitSupplyPage }) => {
await admitSupplyPage.open(); await admitSupplyPage.open();
await admitSupplyPage.switchPending(); await admitSupplyPage.switchPending();
}); });
});
test.describe('供货目录申请 · 新增与编辑', () => { test('ADMIT-SUP-012 重置恢复默认', async ({ admitSupplyPage }) => {
test('ADMIT-SUP-006 新增放弃不落库', async ({ admitSupplyPage }) => {
await admitSupplyPage.open(); await admitSupplyPage.open();
await admitSupplyPage.addCancel(); await admitSupplyPage.resetFilters();
}); });
});
test('ADMIT-SUP-007 业务模式与是否默认只切换不提交', async ({ admitSupplyPage }) => { test.describe('供货目录申请 · 新增与编辑', () => {
test('ADMIT-SUP-005 新增放弃不落库', async ({ admitSupplyPage }) => {
await admitSupplyPage.open(); await admitSupplyPage.open();
await admitSupplyPage.switchModeWithoutSubmit(); await admitSupplyPage.addCancel();
}); });
test('ADMIT-SUP-008 待提交编辑回填', async ({ admitSupplyPage }) => { test('ADMIT-SUP-006 待提交编辑回填', async ({ admitSupplyPage }) => {
await admitSupplyPage.open(); await admitSupplyPage.open();
await admitSupplyPage.editBackfill(); await admitSupplyPage.editBackfill();
}); });
test('ADMIT-SUP-009 编辑取消不保存', async ({ admitSupplyPage }) => { test('ADMIT-SUP-007 编辑取消不保存', async ({ admitSupplyPage }) => {
await admitSupplyPage.open(); await admitSupplyPage.open();
await admitSupplyPage.editCancel(); await admitSupplyPage.editCancel();
}); });
}); });
test.describe('供货目录申请 · 批量提交与详情', () => { test.describe('供货目录申请 · 批量提交与详情', () => {
test('ADMIT-SUP-010 未勾选时批量提交不可用', async ({ admitSupplyPage }) => { test('ADMIT-SUP-008 未勾选时批量提交不可用', async ({ admitSupplyPage }) => {
await admitSupplyPage.open(); await admitSupplyPage.open();
await admitSupplyPage.batchNeedsSelection(); await admitSupplyPage.batchNeedsSelection();
}); });
test('ADMIT-SUP-011 勾选后批量提交取消', async ({ admitSupplyPage }) => { test('ADMIT-SUP-015 仅待提交 Tab 行复选框可勾选', async ({ admitSupplyPage }) => {
await admitSupplyPage.open();
await admitSupplyPage.onlyPendingTabRowCheckboxCheckable();
});
test('ADMIT-SUP-009 勾选后批量提交取消', async ({ admitSupplyPage }) => {
await admitSupplyPage.open(); await admitSupplyPage.open();
await admitSupplyPage.batchCancel(); await admitSupplyPage.batchCancel();
}); });
test('ADMIT-SUP-012 多条件组合查询(制单日期等6项)', async ({ admitSupplyPage }) => { test('ADMIT-SUP-013 详情页供应商与列表一致', async ({ admitSupplyPage }) => {
await admitSupplyPage.open();
await admitSupplyPage.detailSupplierMatchesList();
});
test('ADMIT-SUP-010 多条件组合查询(制单日期等6项)', async ({ admitSupplyPage }) => {
await admitSupplyPage.open(); await admitSupplyPage.open();
await admitSupplyPage.filterCombination(); await admitSupplyPage.filterCombination();
}); });
}); });
test.describe('供货目录申请 · 列表', () => {
test('ADMIT-SUP-014 列设置隐藏后再恢复', async ({ admitSupplyPage }) => {
await admitSupplyPage.open();
await admitSupplyPage.query();
await admitSupplyPage.executeColumnSettingsToggleRestoreTest();
});
});
test.describe('供货目录申请 · 分页', () => {
test('ADMIT-SUP-011 切换20条每页页面正常且列表同步', async ({ admitSupplyPage }) => {
await admitSupplyPage.open();
await admitSupplyPage.query();
const { total, rowsBefore, rowsAfter } = await admitSupplyPage.switchToPageSizeTwenty();
const expectedRows = Math.min(total, 20);
expect(rowsAfter, '当前页行数应与 20 条/页及总条数一致').toBe(expectedRows);
expect(rowsAfter, '切换后可见行应随每页条数变化').not.toBe(rowsBefore);
expect(await admitSupplyPage.getTotalCount(), '总条数应不变').toBe(total);
await expect(admitSupplyPage.pageSizeChanger(), '每页条数').toContainText(/20/);
});
});
test.describe('供货目录申请 · 明细查询切换', () => {
test('ADMIT-SUP-016 可正常切换至供货目录申请明细查询', { tag: '@smoke' }, async ({ admitSupplyDetailPage }) => {
await admitSupplyDetailPage.open();
await admitSupplyDetailPage.expectDetailTabReady();
});
});
test.describe('供货目录申请明细查询 · 快捷筛选查询', () => {
test('ADMIT-SUP-017 物料名称、生产厂家、计划生效日期、申请单号组合查询', async ({ admitSupplyDetailPage }) => {
await admitSupplyDetailPage.open();
const { applied } = await admitSupplyDetailPage.filterDetailCombination();
expect(applied.length, '组合查询生效条件数').toBeGreaterThanOrEqual(2);
await assertAdmitListOrEmpty(await admitSupplyDetailPage.snapshotList());
});
test('ADMIT-SUP-018 重置恢复默认', async ({ admitSupplyDetailPage }) => {
await admitSupplyDetailPage.open();
await admitSupplyDetailPage.resetFilters();
});
});
test.describe('供货目录申请明细查询 · 列表', () => {
test('ADMIT-SUP-019 列设置功能', { tag: '@smoke' }, async ({ admitSupplyDetailPage }) => {
await admitSupplyDetailPage.open();
await admitSupplyDetailPage.executeColumnSettingsToggleRestoreTest();
});
});
test.describe('供货目录申请明细查询 · 导出', () => {
test('ADMIT-SUP-020 当前查询条件下导出不报错', { tag: '@smoke' }, async ({ admitSupplyDetailPage }) => {
await admitSupplyDetailPage.open();
await admitSupplyDetailPage.exportAfterQuery();
});
});
}); });
...@@ -5,54 +5,40 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from ...@@ -5,54 +5,40 @@ import { assertAdmitHeaders, assertAdmitListOrEmpty, assertAdmitMockEmpty } from
* 全量用例:映射 testcase/基础管理-准入管理-准入任务分配-UI自动化测试用例-01.csv * 全量用例:映射 testcase/基础管理-准入管理-准入任务分配-UI自动化测试用例-01.csv
*/ */
test.describe('基础设置 · 准入管理', () => { test.describe('基础设置 · 准入管理', () => {
test.describe('准入任务分配 · 页面进入', () => {
test('ADMIT-TSK-001 菜单进入准入任务分配页', { tag: '@smoke' }, async ({ admitTaskPage }) => {
await admitTaskPage.openFromMenu();
await admitTaskPage.ready();
await expect(admitTaskPage.tab('待分类'), '待分类 Tab').toBeVisible();
await expect(admitTaskPage.tab('已分类'), '已分类 Tab').toBeVisible();
await expect(admitTaskPage.button('批量分配').first(), '批量分配').toBeVisible();
});
});
test.describe('准入任务分配 · 筛选与分类', () => { test.describe('准入任务分配 · 快捷筛选查询', () => {
test('ADMIT-TSK-002 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitTaskPage }) => { test('ADMIT-TSK-001 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
await admitTaskPage.query(); await admitTaskPage.query();
await assertAdmitListOrEmpty(await admitTaskPage.snapshotList()); await assertAdmitListOrEmpty(await admitTaskPage.snapshotList());
}); });
test('ADMIT-TSK-003 产品名称筛选', async ({ admitTaskPage }) => { test('ADMIT-TSK-002 待分类与已分类切换', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.filterByProductName();
});
test('ADMIT-TSK-004 待分类与已分类切换', async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
await admitTaskPage.switchTabs(); await admitTaskPage.switchTabs();
}); });
test('ADMIT-TSK-005 重置恢复默认', async ({ admitTaskPage }) => { test('ADMIT-TSK-003 重置恢复默认', async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
await admitTaskPage.resetFilters(); await admitTaskPage.resetFilters();
}); });
test('ADMIT-TSK-006 无匹配结果空态(mock反例)', async ({ admitTaskPage }) => { test('ADMIT-TSK-004 无匹配结果空态(mock反例)', async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
await assertAdmitMockEmpty(await admitTaskPage.mockEmpty()); await assertAdmitMockEmpty(await admitTaskPage.mockEmpty());
}); });
test('ADMIT-TSK-014 多条件组合查询(新增日期等11项)', async ({ admitTaskPage }) => { test('ADMIT-TSK-012 多条件组合查询(新增日期等11项)', async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
await admitTaskPage.filterCombination(); await admitTaskPage.filterCombination();
}); });
}); });
test.describe('准入任务分配 · 列表分页', () => { test.describe('准入任务分配 · 列表', () => {
test('ADMIT-TSK-007 列表核心列完整', async ({ admitTaskPage }) => { test('ADMIT-TSK-005 列表核心列完整', async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
assertAdmitHeaders(await admitTaskPage.coreHeaders(), [ assertAdmitHeaders(await admitTaskPage.coreHeaders(), [
'准入类型', '准入类型',
'产品编号', '物料编号',
'物料名称', '物料名称',
'规格型号', '规格型号',
'规格', '规格',
...@@ -64,38 +50,105 @@ test.describe('基础设置 · 准入管理', () => { ...@@ -64,38 +50,105 @@ test.describe('基础设置 · 准入管理', () => {
await expect(admitTaskPage.rowAction(await admitTaskPage.firstRow(), '分配类型'), '分配类型').toBeVisible(); await expect(admitTaskPage.rowAction(await admitTaskPage.firstRow(), '分配类型'), '分配类型').toBeVisible();
} }
}); });
});
test('ADMIT-TSK-008 翻至第 2 页', async ({ admitTaskPage }) => { test.describe('准入任务分配 · 分页', () => {
test('ADMIT-TSK-006 翻至第 2 页', async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
await admitTaskPage.goPage2(); await admitTaskPage.goPage2();
}); });
test('ADMIT-TSK-009 跳至指定页', async ({ admitTaskPage }) => { test('ADMIT-TSK-007 跳至指定页', async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
await admitTaskPage.jumpPage2(); await admitTaskPage.jumpPage2();
}); });
test('ADMIT-TSK-010 第 1 页上一页不可用', async ({ admitTaskPage }) => { test('ADMIT-TSK-008 第 1 页上一页不可用', async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
await admitTaskPage.prevDisabled(); await admitTaskPage.prevDisabled();
}); });
test('ADMIT-TSK-013 切换20条每页页面正常且列表同步', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.query();
const { total, rowsBefore, rowsAfter } = await admitTaskPage.switchToPageSizeTwenty();
const expectedRows = Math.min(total, 20);
expect(rowsAfter, '当前页行数应与 20 条/页及总条数一致').toBe(expectedRows);
expect(rowsAfter, '切换后可见行应随每页条数变化').not.toBe(rowsBefore);
expect(await admitTaskPage.getTotalCount(), '总条数应不变').toBe(total);
await expect(admitTaskPage.pageSizeChanger(), '每页条数').toContainText(/20/);
});
}); });
test.describe('准入任务分配 · 分配操作', () => { test.describe('准入任务分配 · 分配操作', () => {
test('ADMIT-TSK-011 未勾选时批量分配不可用', async ({ admitTaskPage }) => { test('ADMIT-TSK-009 未勾选时批量分配不可用', async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
await admitTaskPage.batchNeedsSelection(); await admitTaskPage.batchNeedsSelection();
}); });
test('ADMIT-TSK-012 勾选后批量分配取消', async ({ admitTaskPage }) => { test('ADMIT-TSK-010 勾选后批量分配取消', async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
await admitTaskPage.batchCancel(); await admitTaskPage.batchCancel();
}); });
test('ADMIT-TSK-013 已分类行不再按待分类分配', async ({ admitTaskPage }) => { test('ADMIT-TSK-011 已分类行不再按待分类分配', async ({ admitTaskPage }) => {
await admitTaskPage.open(); await admitTaskPage.open();
await admitTaskPage.classifiedNoAssign(); await admitTaskPage.classifiedNoAssign();
}); });
}); });
test.describe('准入任务分配 · 列表', () => {
test('ADMIT-TSK-014 物料编号列升序降序切换', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.query();
await admitTaskPage.expectColumnSortAscDesc('物料编号');
});
test('ADMIT-TSK-015 物料名称列升序降序切换', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.query();
await admitTaskPage.expectColumnSortAscDesc('物料名称');
});
test('ADMIT-TSK-016 规格型号列升序降序切换', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.query();
await admitTaskPage.expectColumnSortAscDesc('规格型号');
});
test('ADMIT-TSK-017 器械注册人列升序降序切换', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.query();
await admitTaskPage.expectColumnSortAscDesc('器械注册人');
});
test('ADMIT-TSK-018 单位列升序降序切换', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.query();
await admitTaskPage.expectColumnSortAscDesc('单位');
});
test('ADMIT-TSK-019 耗材类型列升序降序切换', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.query();
await admitTaskPage.expectColumnSortAscDesc('耗材类型');
});
test('ADMIT-TSK-020 注册证号列升序降序切换', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.query();
await admitTaskPage.expectColumnSortAscDesc('注册证号');
});
test('ADMIT-TSK-021 SPD新增日期列升序降序切换', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.query();
await admitTaskPage.expectColumnSortAscDesc('SPD新增日期');
});
test('ADMIT-TSK-022 最后操作时间列升序降序切换', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.query();
await admitTaskPage.expectColumnSortAscDesc('最后操作时间');
});
test('ADMIT-TSK-023 准入状态列升序降序切换', async ({ admitTaskPage }) => {
await admitTaskPage.open();
await admitTaskPage.query();
await admitTaskPage.expectColumnSortAscDesc('准入状态');
});
});
}); });
import { test } from '../../fixtures'; import { expect, test } from '../../fixtures';
import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospital.data'; import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospital.data';
/** /**
...@@ -6,20 +6,14 @@ import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospita ...@@ -6,20 +6,14 @@ import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospita
* 运行:npm run test:basic-branch * 运行:npm run test:basic-branch
*/ */
test.describe('基础设置 · 医院资料', () => { test.describe('基础设置 · 医院资料', () => {
test.describe('院区管理 · 页面进入', () => {
test('BASIC-BRN-001 菜单进入院区管理页', { tag: '@smoke' }, async ({ basicBranchPage }) => {
await basicBranchPage.openViaMenu(basicHospitalData.menuBranch, '/paltform/area');
await basicBranchPage.expectEntered();
});
});
test.describe('院区管理 · 列表搜索', () => { test.describe('院区管理 · 列表搜索', () => {
test('BASIC-BRN-002 默认列出院区或空态明确', { tag: '@smoke' }, async ({ basicBranchPage }) => { test('BASIC-BRN-001 默认列出院区或空态明确', { tag: '@smoke' }, async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.expectListOrEmpty(); await basicBranchPage.expectListOrEmpty();
}); });
test('BASIC-BRN-003 院区名称搜索过滤', async ({ basicBranchPage }) => { test('BASIC-BRN-002 院区名称搜索过滤', async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
const sample = await basicBranchPage.extractSample(); const sample = await basicBranchPage.extractSample();
await basicBranchPage.searchByName(sample.sampleCampusName); await basicBranchPage.searchByName(sample.sampleCampusName);
...@@ -27,14 +21,14 @@ test.describe('基础设置 · 医院资料', () => { ...@@ -27,14 +21,14 @@ test.describe('基础设置 · 医院资料', () => {
}); });
test('BASIC-BRN-004 清空搜索恢复全量', async ({ basicBranchPage }) => { test('BASIC-BRN-003 清空搜索恢复全量', async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
const sample = await basicBranchPage.extractSample(); const sample = await basicBranchPage.extractSample();
await basicBranchPage.searchByName(sample.sampleCampusName); await basicBranchPage.searchByName(sample.sampleCampusName);
await basicBranchPage.clearSearch(); await basicBranchPage.clearSearch();
}); });
test('BASIC-BRN-005 搜索无匹配空态(mock反例)', { tag: '@smoke' }, async ({ basicBranchPage }) => { test('BASIC-BRN-004 搜索无匹配空态(mock反例)', { tag: '@smoke' }, async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.searchByName(basicHospitalData.mockCampusName); await basicBranchPage.searchByName(basicHospitalData.mockCampusName);
await basicBranchPage.expectMockEmpty(); await basicBranchPage.expectMockEmpty();
...@@ -42,29 +36,29 @@ test.describe('基础设置 · 医院资料', () => { ...@@ -42,29 +36,29 @@ test.describe('基础设置 · 医院资料', () => {
}); });
test.describe('院区管理 · 新增院区', () => { test.describe('院区管理 · 新增院区', () => {
test('BASIC-BRN-006 打开新增院区弹窗', async ({ basicBranchPage }) => { test('BASIC-BRN-005 打开新增院区弹窗', async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.openAddDialog(); await basicBranchPage.openAddDialog();
await basicBranchPage.closeDialogIfOpen(); await basicBranchPage.closeDialogIfOpen();
}); });
test('BASIC-BRN-007 新增取消不落库', async ({ basicBranchPage }) => { test('BASIC-BRN-006 新增取消不落库', async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.addAndCancel(); await basicBranchPage.addAndCancel();
}); });
test('BASIC-BRN-008 院区名称为空拦截(mock反例)', async ({ basicBranchPage }) => { test('BASIC-BRN-007 院区名称为空拦截(mock反例)', async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.addEmptyName(); await basicBranchPage.addEmptyName();
}); });
test('BASIC-BRN-009 所在地区为空拦截(mock反例)', async ({ basicBranchPage }) => { test('BASIC-BRN-008 所在地区为空拦截(mock反例)', async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.addEmptyRegion(); await basicBranchPage.addEmptyRegion();
}); });
test('BASIC-BRN-010 详细地址为空拦截(mock反例)', async ({ basicBranchPage }) => { test('BASIC-BRN-009 详细地址为空拦截(mock反例)', async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.addEmptyAddress(); await basicBranchPage.addEmptyAddress();
}); });
...@@ -72,29 +66,48 @@ test.describe('基础设置 · 医院资料', () => { ...@@ -72,29 +66,48 @@ test.describe('基础设置 · 医院资料', () => {
test.describe('院区管理 · 编辑院区', () => { test.describe('院区管理 · 编辑院区', () => {
test('BASIC-BRN-011 编辑态院区编号不可换号', async ({ basicBranchPage }) => { test('BASIC-BRN-010 编辑态院区编号不可换号', async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.expectIdNotChangeable(); await basicBranchPage.expectIdNotChangeable();
}); });
test('BASIC-BRN-012 编辑取消不保存', async ({ basicBranchPage }) => { test('BASIC-BRN-011 编辑取消不保存', async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.editAndCancel(); await basicBranchPage.editAndCancel();
}); });
test('BASIC-BRN-013 编辑状态为禁用启用', async ({ basicBranchPage }) => { test('BASIC-BRN-012 编辑状态为禁用启用', async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.expectEditStatusLabels(); await basicBranchPage.expectEditStatusLabels();
}); });
test('BASIC-BRN-014 编辑可见启用云仓', async ({ basicBranchPage }) => { test('BASIC-BRN-013 编辑可见启用云仓', async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.expectCloudWarehouse(); await basicBranchPage.expectCloudWarehouse();
}); });
test('BASIC-BRN-015 编辑清空必填拦截(mock反例)', { tag: '@smoke' }, async ({ basicBranchPage }) => { test('BASIC-BRN-014 编辑清空必填拦截(mock反例)', { tag: '@smoke' }, async ({ basicBranchPage }) => {
await basicBranchPage.open(); await basicBranchPage.open();
await basicBranchPage.editClearRequired(); await basicBranchPage.editClearRequired();
}); });
}); });
test.describe('院区管理 · 分页', () => {
test('BASIC-BRN-015 切换20条每页页面正常且列表同步', async ({ basicBranchPage }) => {
await basicBranchPage.open();
const { total, rowsBefore, rowsAfter } = await basicBranchPage.switchToPageSizeTwenty();
const expectedRows = Math.min(total, 20);
expect(rowsAfter, '当前页行数应与 20 条/页及总条数一致').toBe(expectedRows);
expect(rowsAfter, '切换后可见行应随每页条数变化').not.toBe(rowsBefore);
expect(await basicBranchPage.getTotalCount(), '总条数应不变').toBe(total);
await expect(basicBranchPage.pageSizeChanger(), '每页条数').toContainText(/20/);
});
});
test.describe('院区管理 · 列表', () => {
test('BASIC-BRN-016 列设置隐藏后再恢复', async ({ basicBranchPage }) => {
await basicBranchPage.open();
await basicBranchPage.executeColumnSettingsToggleRestoreTest();
});
});
}); });
import { test } from '../../fixtures'; import { expect, test } from '../../fixtures';
import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospital.data'; import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospital.data';
/** /**
...@@ -6,28 +6,21 @@ import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospita ...@@ -6,28 +6,21 @@ import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospita
* 运行:npm run test:basic-finance-month * 运行:npm run test:basic-finance-month
*/ */
test.describe('基础设置 · 医院资料', () => { test.describe('基础设置 · 医院资料', () => {
test.describe('财务月份设置 · 页面进入', () => { test.describe('财务月份设置 · 快捷筛选查询', () => {
test('BASIC-FMN-001 菜单进入财务月份设置页', { tag: '@smoke' }, async ({ basicFinanceMonthPage }) => { test('BASIC-FMN-001 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.openViaMenu(basicHospitalData.menuFinanceMonth, '/balance/month');
await basicFinanceMonthPage.expectEntered();
});
});
test.describe('财务月份设置 · 筛选查询', () => {
test('BASIC-FMN-002 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.open(); await basicFinanceMonthPage.open();
await basicFinanceMonthPage.search(); await basicFinanceMonthPage.search();
await basicFinanceMonthPage.expectListOrEmpty(); await basicFinanceMonthPage.expectListOrEmpty();
}); });
test('BASIC-FMN-003 按财务月份筛选', async ({ basicFinanceMonthPage }) => { test('BASIC-FMN-002 按财务月份筛选', async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.open(); await basicFinanceMonthPage.open();
const sample = await basicFinanceMonthPage.extractSample(); const sample = await basicFinanceMonthPage.extractSample();
await basicFinanceMonthPage.queryByMonth(sample.sampleFinanceMonth); await basicFinanceMonthPage.queryByMonth(sample.sampleFinanceMonth);
await basicFinanceMonthPage.expectMonthResults(sample.sampleFinanceMonth); await basicFinanceMonthPage.expectMonthResults(sample.sampleFinanceMonth);
}); });
test('BASIC-FMN-004 重置恢复默认', async ({ basicFinanceMonthPage }) => { test('BASIC-FMN-003 重置恢复默认', async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.open(); await basicFinanceMonthPage.open();
const sample = await basicFinanceMonthPage.extractSample(); const sample = await basicFinanceMonthPage.extractSample();
await basicFinanceMonthPage.queryByMonth(sample.sampleFinanceMonth); await basicFinanceMonthPage.queryByMonth(sample.sampleFinanceMonth);
...@@ -36,25 +29,25 @@ test.describe('基础设置 · 医院资料', () => { ...@@ -36,25 +29,25 @@ test.describe('基础设置 · 医院资料', () => {
}); });
test.describe('财务月份设置 · 列表与状态', () => { test.describe('财务月份设置 · 列表与状态', () => {
test('BASIC-FMN-005 列表核心列完整', async ({ basicFinanceMonthPage }) => { test('BASIC-FMN-004 列表核心列完整', async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.open(); await basicFinanceMonthPage.open();
await basicFinanceMonthPage.search(); await basicFinanceMonthPage.search();
await basicFinanceMonthPage.expectCoreColumns(); await basicFinanceMonthPage.expectCoreColumns();
}); });
test('BASIC-FMN-006 仅当前月份行可修改', async ({ basicFinanceMonthPage }) => { test('BASIC-FMN-005 仅当前月份行可修改', async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.open(); await basicFinanceMonthPage.open();
await basicFinanceMonthPage.search(); await basicFinanceMonthPage.search();
await basicFinanceMonthPage.expectOnlyCurrentEditable(); await basicFinanceMonthPage.expectOnlyCurrentEditable();
}); });
test('BASIC-FMN-007 当前月份至多一行', async ({ basicFinanceMonthPage }) => { test('BASIC-FMN-006 当前月份至多一行', async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.open(); await basicFinanceMonthPage.open();
await basicFinanceMonthPage.search(); await basicFinanceMonthPage.search();
await basicFinanceMonthPage.expectAtMostOneCurrent(); await basicFinanceMonthPage.expectAtMostOneCurrent();
}); });
test('BASIC-FMN-008 历史月份无法进入编辑', async ({ basicFinanceMonthPage }) => { test('BASIC-FMN-007 历史月份无法进入编辑', async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.open(); await basicFinanceMonthPage.open();
await basicFinanceMonthPage.search(); await basicFinanceMonthPage.search();
await basicFinanceMonthPage.expectHistoryNotEditable(); await basicFinanceMonthPage.expectHistoryNotEditable();
...@@ -62,7 +55,7 @@ test.describe('基础设置 · 医院资料', () => { ...@@ -62,7 +55,7 @@ test.describe('基础设置 · 医院资料', () => {
}); });
test.describe('财务月份设置 · 当前月份修改', () => { test.describe('财务月份设置 · 当前月份修改', () => {
test('BASIC-FMN-009 修改进入行内编辑', async ({ basicFinanceMonthPage }) => { test('BASIC-FMN-008 修改进入行内编辑', async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.open(); await basicFinanceMonthPage.open();
await basicFinanceMonthPage.search(); await basicFinanceMonthPage.search();
await basicFinanceMonthPage.enterInlineEdit(); await basicFinanceMonthPage.enterInlineEdit();
...@@ -70,12 +63,31 @@ test.describe('基础设置 · 医院资料', () => { ...@@ -70,12 +63,31 @@ test.describe('基础设置 · 医院资料', () => {
}); });
test('BASIC-FMN-010 取消不保存自动结算日', async ({ basicFinanceMonthPage }) => { test('BASIC-FMN-009 取消不保存自动结算日', async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.open(); await basicFinanceMonthPage.open();
await basicFinanceMonthPage.cancelWithoutSave(); await basicFinanceMonthPage.cancelWithoutSave();
}); });
});
test.describe('财务月份设置 · 分页', () => {
test('BASIC-FMN-010 切换20条每页页面正常且列表同步', async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.open();
await basicFinanceMonthPage.search();
const { total, rowsBefore, rowsAfter } = await basicFinanceMonthPage.switchToPageSizeTwenty();
const expectedRows = Math.min(total, 20);
expect(rowsAfter, '当前页行数应与 20 条/页及总条数一致').toBe(expectedRows);
expect(rowsAfter, '切换后可见行应随每页条数变化').not.toBe(rowsBefore);
expect(await basicFinanceMonthPage.getTotalCount(), '总条数应不变').toBe(total);
await expect(basicFinanceMonthPage.pageSizeChanger(), '每页条数').toContainText(/20/);
});
});
test.describe('财务月份设置 · 列表', () => {
test('BASIC-FMN-011 列设置隐藏后再恢复', async ({ basicFinanceMonthPage }) => {
await basicFinanceMonthPage.open();
await basicFinanceMonthPage.search();
await basicFinanceMonthPage.executeColumnSettingsToggleRestoreTest();
});
});
});
}); });
import { test } from '../../fixtures'; import { test } from '../../fixtures';
import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospital.data';
/** /**
* 全量用例:映射 testcase/基础管理-医院资料-医院信息登记-UI自动化测试用例-01.csv * 全量用例:映射 testcase/基础管理-医院资料-医院信息登记-UI自动化测试用例-01.csv
...@@ -7,66 +6,55 @@ import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospita ...@@ -7,66 +6,55 @@ import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospita
*/ */
test.describe('基础设置 · 医院资料', () => { test.describe('基础设置 · 医院资料', () => {
test.describe('医院信息登记 · 页面进入与查看', () => { test.describe('医院信息登记 · 页面进入与查看', () => {
test('BASIC-HOS-001 菜单进入医院信息登记页', { tag: '@smoke' }, async ({ basicHospitalInfoPage }) => { test('BASIC-HOS-001 查看态只读字段不可改', { tag: '@smoke' }, async ({ basicHospitalInfoPage }) => {
await basicHospitalInfoPage.openViaMenu(basicHospitalData.menuHospitalInfo, '/paltform/info');
await basicHospitalInfoPage.expectEntered();
});
test('BASIC-HOS-002 查看态只读字段不可改', { tag: '@smoke' }, async ({ basicHospitalInfoPage }) => {
await basicHospitalInfoPage.open(); await basicHospitalInfoPage.open();
await basicHospitalInfoPage.expectViewReadonly(); await basicHospitalInfoPage.expectViewReadonly();
}); });
test('BASIC-HOS-003 已上传图片可预览', async ({ basicHospitalInfoPage }) => { test('BASIC-HOS-002 已上传图片可预览', async ({ basicHospitalInfoPage }) => {
await basicHospitalInfoPage.open(); await basicHospitalInfoPage.open();
await basicHospitalInfoPage.previewIfPresent(); await basicHospitalInfoPage.previewIfPresent();
}); });
}); });
test.describe('医院信息登记 · 编辑保存', () => { test.describe('医院信息登记 · 编辑保存', () => {
test('BASIC-HOS-004 进入编辑模式', async ({ basicHospitalInfoPage }) => { test('BASIC-HOS-003 进入编辑模式', async ({ basicHospitalInfoPage }) => {
await basicHospitalInfoPage.open(); await basicHospitalInfoPage.open();
await basicHospitalInfoPage.enterEdit(); await basicHospitalInfoPage.enterEdit();
await basicHospitalInfoPage.expectSystemFieldsReadonly(); await basicHospitalInfoPage.expectSystemFieldsReadonly();
await basicHospitalInfoPage.locators.cancelBtn.click(); await basicHospitalInfoPage.locators.cancelBtn.click();
}); });
test('BASIC-HOS-005 编辑态只读字段仍不可改', async ({ basicHospitalInfoPage }) => { test('BASIC-HOS-004 编辑态只读字段仍不可改', async ({ basicHospitalInfoPage }) => {
await basicHospitalInfoPage.open(); await basicHospitalInfoPage.open();
await basicHospitalInfoPage.enterEdit(); await basicHospitalInfoPage.enterEdit();
await basicHospitalInfoPage.expectSystemFieldsReadonly(); await basicHospitalInfoPage.expectSystemFieldsReadonly();
await basicHospitalInfoPage.locators.cancelBtn.click(); await basicHospitalInfoPage.locators.cancelBtn.click();
}); });
test('BASIC-HOS-006 取消不保存', async ({ basicHospitalInfoPage }) => { test('BASIC-HOS-005 取消不保存', async ({ basicHospitalInfoPage }) => {
await basicHospitalInfoPage.open(); await basicHospitalInfoPage.open();
await basicHospitalInfoPage.cancelWithoutSave(); await basicHospitalInfoPage.cancelWithoutSave();
}); });
test('BASIC-HOS-007 保存后字段持久化', async ({ basicHospitalInfoPage }) => { test('BASIC-HOS-006 联系人为空保存拦截(mock反例)', { tag: '@smoke' }, async ({ basicHospitalInfoPage }) => {
test.skip(!isBasicWriteAllowed(), basicHospitalData.writeDisabledReason);
await basicHospitalInfoPage.open();
await basicHospitalInfoPage.saveAndRestore();
});
test('BASIC-HOS-008 联系人为空保存拦截(mock反例)', { tag: '@smoke' }, async ({ basicHospitalInfoPage }) => {
await basicHospitalInfoPage.open(); await basicHospitalInfoPage.open();
await basicHospitalInfoPage.saveEmptyField('linkman'); await basicHospitalInfoPage.saveEmptyField('linkman');
}); });
test('BASIC-HOS-009 联系方式为空保存拦截(mock反例)', async ({ basicHospitalInfoPage }) => { test('BASIC-HOS-007 联系方式为空保存拦截(mock反例)', async ({ basicHospitalInfoPage }) => {
await basicHospitalInfoPage.open(); await basicHospitalInfoPage.open();
await basicHospitalInfoPage.saveEmptyField('contactWay'); await basicHospitalInfoPage.saveEmptyField('contactWay');
}); });
test('BASIC-HOS-010 医院简称为空保存拦截(mock反例)', async ({ basicHospitalInfoPage }) => { test('BASIC-HOS-008 医院简称为空保存拦截(mock反例)', async ({ basicHospitalInfoPage }) => {
await basicHospitalInfoPage.open(); await basicHospitalInfoPage.open();
await basicHospitalInfoPage.saveEmptyField('shortName'); await basicHospitalInfoPage.saveEmptyField('shortName');
}); });
}); });
test.describe('医院信息登记 · 图片上传', () => { test.describe('医院信息登记 · 图片上传', () => {
test('BASIC-HOS-011 编辑态存在背景与 logo 上传控件', async ({ basicHospitalInfoPage }) => { test('BASIC-HOS-009 编辑态存在背景与 logo 上传控件', async ({ basicHospitalInfoPage }) => {
await basicHospitalInfoPage.open(); await basicHospitalInfoPage.open();
await basicHospitalInfoPage.expectUploadInputs(); await basicHospitalInfoPage.expectUploadInputs();
}); });
......
import { test } from '../../fixtures'; import { expect, test } from '../../fixtures';
import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospital.data'; import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospital.data';
/** /**
...@@ -6,28 +6,22 @@ import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospita ...@@ -6,28 +6,22 @@ import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospita
* 运行:npm run test:basic-notice * 运行:npm run test:basic-notice
*/ */
test.describe('基础设置 · 医院资料', () => { test.describe('基础设置 · 医院资料', () => {
test.describe('公告管理 · 页面进入', () => {
test('BASIC-NTC-001 菜单进入公告管理页', { tag: '@smoke' }, async ({ basicNoticePage }) => {
await basicNoticePage.openViaMenu(basicHospitalData.menuNotice, '/paltform/notice');
await basicNoticePage.expectEntered();
});
});
test.describe('公告管理 · 筛选查询', () => { test.describe('公告管理 · 快捷筛选查询', () => {
test('BASIC-NTC-002 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ basicNoticePage }) => { test('BASIC-NTC-001 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
await basicNoticePage.search(); await basicNoticePage.search();
await basicNoticePage.expectListOrEmpty(); await basicNoticePage.expectListOrEmpty();
}); });
test('BASIC-NTC-003 公告标题模糊查询', async ({ basicNoticePage }) => { test('BASIC-NTC-002 公告标题模糊查询', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
const sample = await basicNoticePage.extractSample(); const sample = await basicNoticePage.extractSample();
await basicNoticePage.queryByTitle(sample.sampleNoticeTitle); await basicNoticePage.queryByTitle(sample.sampleNoticeTitle);
await basicNoticePage.expectTitleResultsMatch(sample.sampleNoticeTitle); await basicNoticePage.expectTitleResultsMatch(sample.sampleNoticeTitle);
}); });
test('BASIC-NTC-004 发布范围下拉查询', async ({ basicNoticePage }) => { test('BASIC-NTC-003 发布范围下拉查询', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
const sample = await basicNoticePage.extractSample(); const sample = await basicNoticePage.extractSample();
const scope = await basicNoticePage.pickPublishScopeFilter(sample.samplePublishScope); const scope = await basicNoticePage.pickPublishScopeFilter(sample.samplePublishScope);
...@@ -35,7 +29,7 @@ test.describe('基础设置 · 医院资料', () => { ...@@ -35,7 +29,7 @@ test.describe('基础设置 · 医院资料', () => {
await basicNoticePage.expectScopeResultsMatch(scope); await basicNoticePage.expectScopeResultsMatch(scope);
}); });
test('BASIC-NTC-005 标题与范围组合查询', async ({ basicNoticePage }) => { test('BASIC-NTC-004 标题与范围组合查询', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
const sample = await basicNoticePage.extractSample(); const sample = await basicNoticePage.extractSample();
await basicNoticePage.queryByTitleAndScope(sample.sampleNoticeTitle, sample.samplePublishScope); await basicNoticePage.queryByTitleAndScope(sample.sampleNoticeTitle, sample.samplePublishScope);
...@@ -44,14 +38,14 @@ test.describe('基础设置 · 医院资料', () => { ...@@ -44,14 +38,14 @@ test.describe('基础设置 · 医院资料', () => {
await basicNoticePage.expectScopeResultsMatch(sample.samplePublishScope); await basicNoticePage.expectScopeResultsMatch(sample.samplePublishScope);
}); });
test('BASIC-NTC-006 快捷区重置恢复默认', async ({ basicNoticePage }) => { test('BASIC-NTC-005 快捷区重置恢复默认', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
const sample = await basicNoticePage.extractSample(); const sample = await basicNoticePage.extractSample();
await basicNoticePage.queryByTitle(sample.sampleNoticeTitle); await basicNoticePage.queryByTitle(sample.sampleNoticeTitle);
await basicNoticePage.resetFilters(); await basicNoticePage.resetFilters();
}); });
test('BASIC-NTC-007 无匹配结果空态(mock反例)', { tag: '@smoke' }, async ({ basicNoticePage }) => { test('BASIC-NTC-006 无匹配结果空态(mock反例)', { tag: '@smoke' }, async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
await basicNoticePage.queryByTitle(basicHospitalData.mockNoticeTitle); await basicNoticePage.queryByTitle(basicHospitalData.mockNoticeTitle);
await basicNoticePage.expectMockEmpty(); await basicNoticePage.expectMockEmpty();
...@@ -59,19 +53,19 @@ test.describe('基础设置 · 医院资料', () => { ...@@ -59,19 +53,19 @@ test.describe('基础设置 · 医院资料', () => {
}); });
test.describe('公告管理 · 列表分页', () => { test.describe('公告管理 · 列表分页', () => {
test('BASIC-NTC-008 查询后核心列展示', async ({ basicNoticePage }) => { test('BASIC-NTC-007 查询后核心列展示', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
await basicNoticePage.search(); await basicNoticePage.search();
await basicNoticePage.expectCoreColumns(); await basicNoticePage.expectCoreColumns();
}); });
test('BASIC-NTC-009 分页翻至第 2 页', async ({ basicNoticePage }) => { test('BASIC-NTC-008 分页翻至第 2 页', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
await basicNoticePage.search(); await basicNoticePage.search();
await basicNoticePage.goToPage2(); await basicNoticePage.goToPage2();
}); });
test('BASIC-NTC-010 跳至指定页', async ({ basicNoticePage }) => { test('BASIC-NTC-009 跳至指定页', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
await basicNoticePage.search(); await basicNoticePage.search();
await basicNoticePage.jumpToPage(2); await basicNoticePage.jumpToPage(2);
...@@ -79,13 +73,13 @@ test.describe('基础设置 · 医院资料', () => { ...@@ -79,13 +73,13 @@ test.describe('基础设置 · 医院资料', () => {
}); });
test.describe('公告管理 · 新增公告', () => { test.describe('公告管理 · 新增公告', () => {
test('BASIC-NTC-011 打开新增公告弹窗', async ({ basicNoticePage }) => { test('BASIC-NTC-010 打开新增公告弹窗', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
await basicNoticePage.openAddDialog(); await basicNoticePage.openAddDialog();
await basicNoticePage.closeDialogIfOpen(); await basicNoticePage.closeDialogIfOpen();
}); });
test('BASIC-NTC-012 新增取消不落库', async ({ basicNoticePage }) => { test('BASIC-NTC-011 新增取消不落库', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
await basicNoticePage.addAndCancel(`AUTO-NTC-${Date.now()}`); await basicNoticePage.addAndCancel(`AUTO-NTC-${Date.now()}`);
}); });
...@@ -94,19 +88,40 @@ test.describe('基础设置 · 医院资料', () => { ...@@ -94,19 +88,40 @@ test.describe('基础设置 · 医院资料', () => {
}); });
test.describe('公告管理 · 编辑与删除', () => { test.describe('公告管理 · 编辑与删除', () => {
test('BASIC-NTC-013 打开编辑公告并回填', async ({ basicNoticePage }) => { test('BASIC-NTC-012 打开编辑公告并回填', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
await basicNoticePage.openEditAndExpectBackfill(); await basicNoticePage.openEditAndExpectBackfill();
}); });
test('BASIC-NTC-014 编辑取消不保存', async ({ basicNoticePage }) => { test('BASIC-NTC-013 编辑取消不保存', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
await basicNoticePage.editAndCancel(); await basicNoticePage.editAndCancel();
}); });
test('BASIC-NTC-015 删除弹出确认框', async ({ basicNoticePage }) => { test('BASIC-NTC-014 删除弹出确认框', async ({ basicNoticePage }) => {
await basicNoticePage.open(); await basicNoticePage.open();
await basicNoticePage.deleteConfirmAndCancel(); await basicNoticePage.deleteConfirmAndCancel();
}); });
}); });
test.describe('公告管理 · 分页', () => {
test('BASIC-NTC-015 切换20条每页页面正常且列表同步', async ({ basicNoticePage }) => {
await basicNoticePage.open();
await basicNoticePage.search();
const { total, rowsBefore, rowsAfter } = await basicNoticePage.switchToPageSizeTwenty();
const expectedRows = Math.min(total, 20);
expect(rowsAfter, '当前页行数应与 20 条/页及总条数一致').toBe(expectedRows);
expect(rowsAfter, '切换后可见行应随每页条数变化').not.toBe(rowsBefore);
expect(await basicNoticePage.getTotalCount(), '总条数应不变').toBe(total);
await expect(basicNoticePage.pageSizeChanger(), '每页条数').toContainText(/20/);
});
});
test.describe('公告管理 · 列表', () => {
test('BASIC-NTC-016 列设置隐藏后再恢复', async ({ basicNoticePage }) => {
await basicNoticePage.open();
await basicNoticePage.search();
await basicNoticePage.executeColumnSettingsToggleRestoreTest();
});
});
}); });
import { basicHospitalData, isBasicWriteAllowed } from '../../data/basic-hospital.data';
import { expect, test } from '../../fixtures'; import { expect, test } from '../../fixtures';
/** /**
...@@ -42,18 +41,7 @@ test.describe('基础设置 · 用户管理', () => { ...@@ -42,18 +41,7 @@ test.describe('基础设置 · 用户管理', () => {
await basicRolePage.closeDialog(); await basicRolePage.closeDialog();
}); });
test('USER-ROL-005 编辑角色保存成功', async ({ basicRolePage }) => { test('USER-ROL-005 点击角色按钮打开新增弹框', async ({ basicRolePage }) => {
test.skip(!isBasicWriteAllowed(), basicHospitalData.writeDisabledReason);
await basicRolePage.open();
const name = await basicRolePage.sampleRoleName();
const { dialog } = await basicRolePage.openEditRoleDialog(name);
await expect(dialog, '编辑弹框可见').toBeVisible();
await basicRolePage.saveEditRoleDialog();
await basicRolePage.expectToastSuccess(/编辑成功/);
await expect(basicRolePage.editRoleDialog(), '保存后弹框应关闭').toBeHidden({ timeout: 15_000 });
});
test('USER-ROL-006 点击角色按钮打开新增弹框', async ({ basicRolePage }) => {
await basicRolePage.open(); await basicRolePage.open();
const dialog = await basicRolePage.openAddRoleDialog(); const dialog = await basicRolePage.openAddRoleDialog();
await expect(dialog, '新增角色弹框可见').toBeVisible(); await expect(dialog, '新增角色弹框可见').toBeVisible();
...@@ -62,7 +50,7 @@ test.describe('基础设置 · 用户管理', () => { ...@@ -62,7 +50,7 @@ test.describe('基础设置 · 用户管理', () => {
await basicRolePage.cancelAddRole(); await basicRolePage.cancelAddRole();
}); });
test('USER-ROL-007 新增角色名称为空保存拦截', async ({ basicRolePage }) => { test('USER-ROL-006 新增角色名称为空保存拦截', async ({ basicRolePage }) => {
await basicRolePage.open(); await basicRolePage.open();
await basicRolePage.openAddRoleDialog(); await basicRolePage.openAddRoleDialog();
await basicRolePage.saveAddRoleDialog(); await basicRolePage.saveAddRoleDialog();
...@@ -70,7 +58,7 @@ test.describe('基础设置 · 用户管理', () => { ...@@ -70,7 +58,7 @@ test.describe('基础设置 · 用户管理', () => {
await basicRolePage.cancelAddRole(); await basicRolePage.cancelAddRole();
}); });
test('USER-ROL-008 新增角色弹框取消关闭', async ({ basicRolePage }) => { test('USER-ROL-007 新增角色弹框取消关闭', async ({ basicRolePage }) => {
await basicRolePage.open(); await basicRolePage.open();
const before = (await basicRolePage.leftRoleNames()).length; const before = (await basicRolePage.leftRoleNames()).length;
const dialog = await basicRolePage.openAddRoleDialog(); const dialog = await basicRolePage.openAddRoleDialog();
...@@ -79,7 +67,7 @@ test.describe('基础设置 · 用户管理', () => { ...@@ -79,7 +67,7 @@ test.describe('基础设置 · 用户管理', () => {
expect((await basicRolePage.leftRoleNames()).length, '取消后角色数不增加').toBe(before); expect((await basicRolePage.leftRoleNames()).length, '取消后角色数不增加').toBe(before);
}); });
test('USER-ROL-009 新增弹框查询配置化复选框可勾选', async ({ basicRolePage }) => { test('USER-ROL-008 新增弹框查询配置化复选框可勾选', async ({ basicRolePage }) => {
await basicRolePage.open(); await basicRolePage.open();
await basicRolePage.openAddRoleDialog(); await basicRolePage.openAddRoleDialog();
await basicRolePage.setQueryConfigChecked(true); await basicRolePage.setQueryConfigChecked(true);
...@@ -88,7 +76,7 @@ test.describe('基础设置 · 用户管理', () => { ...@@ -88,7 +76,7 @@ test.describe('基础设置 · 用户管理', () => {
await basicRolePage.cancelAddRoleDialog(); await basicRolePage.cancelAddRoleDialog();
}); });
test('USER-ROL-010 新增角色弹框X关闭', async ({ basicRolePage }) => { test('USER-ROL-009 新增角色弹框X关闭', async ({ basicRolePage }) => {
await basicRolePage.open(); await basicRolePage.open();
const before = (await basicRolePage.leftRoleNames()).length; const before = (await basicRolePage.leftRoleNames()).length;
const dialog = await basicRolePage.openAddRoleDialog(); const dialog = await basicRolePage.openAddRoleDialog();
...@@ -127,7 +115,7 @@ test.describe('基础设置 · 用户管理', () => { ...@@ -127,7 +115,7 @@ test.describe('基础设置 · 用户管理', () => {
await expect(child, '收起后子菜单不可见').toBeHidden(); await expect(child, '收起后子菜单不可见').toBeHidden();
}); });
test('USER-ROL-011 右侧权限树子菜单可上下滑动', async ({ basicRolePage }) => { test('USER-ROL-010 右侧权限树子菜单可上下滑动', async ({ basicRolePage }) => {
await basicRolePage.open(); await basicRolePage.open();
await basicRolePage.assertRoleTreeVerticalScroll(); await basicRolePage.assertRoleTreeVerticalScroll();
}); });
......
...@@ -6,7 +6,7 @@ import { assertHeaderOrder, assertListOrEmpty, assertMockEmpty } from './helpers ...@@ -6,7 +6,7 @@ import { assertHeaderOrder, assertListOrEmpty, assertMockEmpty } from './helpers
* 运行:npm run test:basic-user-union:all * 运行:npm run test:basic-user-union:all
*/ */
test.describe('基础设置 · 用户管理', () => { test.describe('基础设置 · 用户管理', () => {
test.describe('医共体用户管理 · 筛选与查询', () => { test.describe('医共体用户管理 · 快捷筛选查询', () => {
test('USER-UNI-001 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ basicUserUnionPage }) => { test('USER-UNI-001 默认查询列表有数据或空态明确', { tag: '@smoke' }, async ({ basicUserUnionPage }) => {
await basicUserUnionPage.open(); await basicUserUnionPage.open();
await basicUserUnionPage.query(); await basicUserUnionPage.query();
...@@ -29,7 +29,7 @@ test.describe('基础设置 · 用户管理', () => { ...@@ -29,7 +29,7 @@ test.describe('基础设置 · 用户管理', () => {
}); });
}); });
test.describe('医共体用户管理 · 列表与分页', () => { test.describe('医共体用户管理 · 列表', () => {
test('USER-UNI-004 列表列顺序含所属医院', async ({ basicUserUnionPage }) => { test('USER-UNI-004 列表列顺序含所属医院', async ({ basicUserUnionPage }) => {
await basicUserUnionPage.open(); await basicUserUnionPage.open();
await basicUserUnionPage.query(); await basicUserUnionPage.query();
...@@ -46,16 +46,6 @@ test.describe('基础设置 · 用户管理', () => { ...@@ -46,16 +46,6 @@ test.describe('基础设置 · 用户管理', () => {
]); ]);
}); });
test('USER-UNI-005 分页翻至第 2 页', async ({ basicUserUnionPage }) => {
await basicUserUnionPage.open();
await basicUserUnionPage.query();
const hospital = await basicUserUnionPage.currentHospitalLabel();
const { firstLogin, secondLogin, active } = await basicUserUnionPage.goToPage2();
expect(active, '页码高亮为 2').toBe('2');
expect(secondLogin, '第 2 页首行应更换').not.toBe(firstLogin);
expect(await basicUserUnionPage.currentHospitalLabel(), '翻页后医院筛选应保持').toBe(hospital);
});
test('USER-UNI-006 与用户管理页同一用户字段一致', async ({ basicUserUnionPage, basicUserPage }) => { test('USER-UNI-006 与用户管理页同一用户字段一致', async ({ basicUserUnionPage, basicUserPage }) => {
await basicUserUnionPage.open(); await basicUserUnionPage.open();
const sample = await basicUserUnionPage.extractUnionSample(); const sample = await basicUserUnionPage.extractUnionSample();
...@@ -77,6 +67,19 @@ test.describe('基础设置 · 用户管理', () => { ...@@ -77,6 +67,19 @@ test.describe('基础设置 · 用户管理', () => {
expect(headers.includes('所属医院'), '用户管理页仅无所属医院').toBeFalsy(); expect(headers.includes('所属医院'), '用户管理页仅无所属医院').toBeFalsy();
}); });
});
test.describe('医共体用户管理 · 分页', () => {
test('USER-UNI-005 分页翻至第 2 页', async ({ basicUserUnionPage }) => {
await basicUserUnionPage.open();
await basicUserUnionPage.query();
const hospital = await basicUserUnionPage.currentHospitalLabel();
const { firstLogin, secondLogin, active } = await basicUserUnionPage.goToPage2();
expect(active, '页码高亮为 2').toBe('2');
expect(secondLogin, '第 2 页首行应更换').not.toBe(firstLogin);
expect(await basicUserUnionPage.currentHospitalLabel(), '翻页后医院筛选应保持').toBe(hospital);
});
test('USER-UNI-009 切换20条每页页面正常且列表同步', async ({ basicUserUnionPage }) => { test('USER-UNI-009 切换20条每页页面正常且列表同步', async ({ basicUserUnionPage }) => {
await basicUserUnionPage.open(); await basicUserUnionPage.open();
await basicUserUnionPage.query(); await basicUserUnionPage.query();
......
...@@ -6,7 +6,7 @@ import { assertListOrEmpty, assertMockEmpty } from './helpers/user-assert.helper ...@@ -6,7 +6,7 @@ import { assertListOrEmpty, assertMockEmpty } from './helpers/user-assert.helper
* 运行:npm run test:basic-user:all * 运行:npm run test:basic-user:all
*/ */
test.describe('基础设置 · 用户管理', () => { test.describe('基础设置 · 用户管理', () => {
test.describe('用户管理 · 筛选与查询', () => { test.describe('用户管理 · 快捷筛选查询', () => {
test('USER-USR-001 重置恢复默认', async ({ basicUserPage }) => { test('USER-USR-001 重置恢复默认', async ({ basicUserPage }) => {
await basicUserPage.open(); await basicUserPage.open();
const sample = await basicUserPage.extractSample(); const sample = await basicUserPage.extractSample();
...@@ -28,7 +28,7 @@ test.describe('基础设置 · 用户管理', () => { ...@@ -28,7 +28,7 @@ test.describe('基础设置 · 用户管理', () => {
}); });
}); });
test.describe('用户管理 · 列表与分页', () => { test.describe('用户管理 · 分页', () => {
test('USER-USR-004 分页翻至第 2 页', async ({ basicUserPage }) => { test('USER-USR-004 分页翻至第 2 页', async ({ basicUserPage }) => {
await basicUserPage.open(); await basicUserPage.open();
await basicUserPage.query(); await basicUserPage.query();
...@@ -120,4 +120,12 @@ test.describe('基础设置 · 用户管理', () => { ...@@ -120,4 +120,12 @@ test.describe('基础设置 · 用户管理', () => {
await basicUserPage.closeDialog(); await basicUserPage.closeDialog();
}); });
}); });
test.describe('用户管理 · 列表', () => {
test('USER-USR-012 列设置隐藏后再恢复', async ({ basicUserPage }) => {
await basicUserPage.open();
await basicUserPage.query();
await basicUserPage.executeColumnSettingsToggleRestoreTest();
});
});
}); });
import { expect, test } from '../../fixtures';
/**
* 全量用例:与 testcase/基础管理-科室管理-自动请领排程-UI自动化测试用例-01.csv 严格一致
* 运行:npm run test:deptm-auto-req:all
*/
test.describe('基础设置 · 科室管理', () => {
test.describe('自动请领排程 · 快捷筛选查询', () => {
test('DEPTM-AUR-001 默认条件查询', { tag: '@smoke' }, async ({ deptmAutoReqPage }) => {
await deptmAutoReqPage.open();
await deptmAutoReqPage.clickQuery();
const snap = await deptmAutoReqPage.snapshotList();
expect(snap.rows >= 0 && (snap.total >= 0 || snap.emptyVisible), '查询应有结果或空态').toBeTruthy();
});
test('DEPTM-AUR-002 全量可见条件组合查询', async ({ deptmAutoReqPage }) => {
test.skip(
true,
'组合查询须按页面配置 quickFields/drawerFields 实现 searchWithQuickAndDrawerCombo(对齐 center-report-sheet STAT-IOD-004),禁止临时启发式填表',
);
});
});
test.describe('自动请领排程 · 列表', () => {
test('DEPTM-AUR-003 无匹配空态(mock反例)', async ({ deptmAutoReqPage }) => {
await deptmAutoReqPage.open();
await deptmAutoReqPage.searchByMockKeyword();
const snap = await deptmAutoReqPage.snapshotList();
expect(snap.rows === 0 || snap.emptyVisible, '无匹配应空态').toBeTruthy();
});
test('DEPTM-AUR-004 列表核心列完整', async ({ deptmAutoReqPage }) => {
await deptmAutoReqPage.open();
await deptmAutoReqPage.assertConfiguredHeaders();
});
test('DEPTM-AUR-005 列设置隐藏后再恢复', async ({ deptmAutoReqPage }) => {
await deptmAutoReqPage.open();
await deptmAutoReqPage.clickQuery();
await deptmAutoReqPage.executeColumnSettingsToggleRestoreTest();
});
test('DEPTM-AUR-006 行内操作可达(只读冒烟)', async ({ deptmAutoReqPage }) => {
await deptmAutoReqPage.open();
await deptmAutoReqPage.rowActionSmoke();
});
});
test.describe('自动请领排程 · 分页', () => {
test('DEPTM-AUR-007 分页翻至第 2 页', async ({ deptmAutoReqPage }) => {
await deptmAutoReqPage.open();
await deptmAutoReqPage.goToPage2ForDeptm();
});
});
test.describe('自动请领排程 · 排程类型展示', () => {
test('DEPTM-AUR-008 星期型排程行内展示可读', async ({ deptmAutoReqPage }) => {
await deptmAutoReqPage.open();
await deptmAutoReqPage.expectWeekScheduleRow();
});
});
test.describe('自动请领排程 · 新增弹窗', () => {
test('DEPTM-AUR-009 打开新增弹窗/抽屉', async ({ deptmAutoReqPage }) => {
await deptmAutoReqPage.open();
await deptmAutoReqPage.openAddOverlay();
await deptmAutoReqPage.closeOverlay();
});
test('DEPTM-AUR-010 必填为空拦截', async ({ deptmAutoReqPage }) => {
await deptmAutoReqPage.open();
await deptmAutoReqPage.assertRequiredIntercept();
});
});
});
import { expect, test } from '../../fixtures';
/**
* 全量用例:与 testcase/基础管理-科室管理-科室预算管理-UI自动化测试用例-01.csv 严格一致
* 运行:npm run test:deptm-budget:all
*/
test.describe('基础设置 · 科室管理', () => {
test.describe('科室预算管理 · 快捷筛选查询', () => {
test('DEPTM-BUD-001 默认条件查询', { tag: '@smoke' }, async ({ deptmBudgetPage }) => {
await deptmBudgetPage.open();
await deptmBudgetPage.clickQuery();
const snap = await deptmBudgetPage.snapshotList();
expect(snap.rows >= 0 && (snap.total >= 0 || snap.emptyVisible), '查询应有结果或空态').toBeTruthy();
});
test('DEPTM-BUD-002 全量可见条件组合查询', async ({ deptmBudgetPage }) => {
test.skip(
true,
'组合查询须按页面配置 quickFields/drawerFields 实现 searchWithQuickAndDrawerCombo(对齐 center-report-sheet STAT-IOD-004),禁止临时启发式填表',
);
});
});
test.describe('科室预算管理 · 列表', () => {
test('DEPTM-BUD-003 无匹配空态(mock反例)', async ({ deptmBudgetPage }) => {
await deptmBudgetPage.open();
await deptmBudgetPage.searchByMockKeyword();
const snap = await deptmBudgetPage.snapshotList();
expect(snap.rows === 0 || snap.emptyVisible, '无匹配应空态').toBeTruthy();
});
test('DEPTM-BUD-005 列表核心列完整', async ({ deptmBudgetPage }) => {
await deptmBudgetPage.open();
await deptmBudgetPage.assertConfiguredHeaders();
});
test('DEPTM-BUD-006 行内操作可达(只读冒烟)', async ({ deptmBudgetPage }) => {
await deptmBudgetPage.open();
await deptmBudgetPage.rowActionSmoke();
});
});
test.describe('科室预算管理 · 状态 Tab', () => {
test('DEPTM-BUD-004 状态 Tab 与列表一致', async ({ deptmBudgetPage }) => {
await deptmBudgetPage.open();
await deptmBudgetPage.clickFirstStatusTab();
});
});
test.describe('科室预算管理 · 分页', () => {
test('DEPTM-BUD-007 分页翻至第 2 页', async ({ deptmBudgetPage }) => {
await deptmBudgetPage.open();
await deptmBudgetPage.goToPage2ForDeptm();
});
});
test.describe('科室预算管理 · 新增弹窗', () => {
test('DEPTM-BUD-008 打开新增弹窗/抽屉', async ({ deptmBudgetPage }) => {
await deptmBudgetPage.open();
await deptmBudgetPage.openAddOverlay();
await deptmBudgetPage.closeOverlay();
});
test('DEPTM-BUD-009 必填为空拦截', async ({ deptmBudgetPage }) => {
await deptmBudgetPage.open();
await deptmBudgetPage.assertRequiredIntercept();
});
});
});
import { expect, test } from '../../fixtures';
/**
* 全量用例:与 testcase/基础管理-科室管理-科室分类维护-UI自动化测试用例-01.csv 严格一致
* 运行:npm run test:deptm-category:all
*/
test.describe('基础设置 · 科室管理', () => {
test.describe('科室分类维护 · 左侧分类树', () => {
test('DEPTM-CAT-001 分类树搜索过滤', { tag: '@smoke' }, async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.filterCategoryTree();
});
});
test.describe('科室分类维护 · 快捷筛选查询', () => {
test('DEPTM-CAT-002 默认条件查询', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.clickQuery();
const snap = await deptmCategoryPage.snapshotList();
expect(snap.rows >= 0 && (snap.total >= 0 || snap.emptyVisible), '查询应有结果或空态').toBeTruthy();
});
test('DEPTM-CAT-003 全量可见条件组合查询', async ({ deptmCategoryPage }) => {
test.skip(
true,
'组合查询须按页面配置 quickFields/drawerFields 实现 searchWithQuickAndDrawerCombo(对齐 center-report-sheet STAT-IOD-004),禁止临时启发式填表',
);
});
});
test.describe('科室分类维护 · 列表', () => {
test('DEPTM-CAT-004 无匹配空态(mock反例)', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.searchByMockKeyword();
const snap = await deptmCategoryPage.snapshotList();
expect(snap.rows === 0 || snap.emptyVisible, '无匹配应空态').toBeTruthy();
});
test('DEPTM-CAT-005 列表核心列完整', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.assertConfiguredHeaders();
});
test('DEPTM-CAT-006 院区列升序降序切换', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.expectColumnSortAscDesc('院区');
});
test('DEPTM-CAT-007 科室编码列升序降序切换', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.expectColumnSortAscDesc('科室编码');
});
test('DEPTM-CAT-008 科室名称列升序降序切换', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.expectColumnSortAscDesc('科室名称');
});
test('DEPTM-CAT-009 状态列升序降序切换', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.expectColumnSortAscDesc('状态');
});
test('DEPTM-CAT-010 科室类型列升序降序切换', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.expectColumnSortAscDesc('科室类型');
});
test('DEPTM-CAT-011 科室地址列升序降序切换', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.expectColumnSortAscDesc('科室地址');
});
test('DEPTM-CAT-012 科室分类名称列升序降序切换', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.expectColumnSortAscDesc('科室分类名称');
});
test('DEPTM-CAT-013 行内操作可达(只读冒烟)', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.rowActionSmoke();
});
});
test.describe('科室分类维护 · 分页', () => {
test('DEPTM-CAT-014 分页翻至第 2 页', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.goToPage2ForDeptm();
});
});
test.describe('科室分类维护 · 导出', () => {
test('DEPTM-CAT-015 导出入口可触发', async ({ deptmCategoryPage }) => {
await deptmCategoryPage.open();
await deptmCategoryPage.clickExportIfVisible();
});
});
});
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment