# 角色管理 — 测试用例

> **依据：** 《角色管理功能需求.md》v1.1、《角色管理技术方案.md》v1.1  
> **关联：** 《员工管理测试用例.md》（roleOptions 协作）、《管理员列表测试用例.md》（平台角色边界）  
> **范围：** 商家端 `/agri/seller/role`；`MerchantRoleSupport` / `MerchantRoleService` / `MerchantRoleController`  
> **排除：** 平台 RuoYi `/system/role`、员工 CRUD 本身、C 端会员  
> **环境：** RuoYi v3.9.2-springboot2；MySQL 5.7.39；请求头 **`X-Shop-Id`** 标识当前店铺

---

## 用例编号说明

| 前缀 | 类型 | 工具 |
|------|------|------|
| RM-UT-xxx | 单元测试 | JUnit 5 + Mockito |
| RM-API-xxx | 接口测试 | MockMvc / Apifox |
| RM-UI-xxx | 界面测试 | Playwright（Chromium） |

---

## 测试数据约定

| 实体 | 说明 |
|------|------|
| 商户 A | 店铺 101（另有 102）；角色 `401=店员`（101，正常，已绑 1 员工）、`402=库管`（101，停用）、`403=待删`（101，无绑定） |
| 店铺 102 | 角色 `501`（用于跨店越权） |
| 商家端菜单 | `menuId=6001` 商品分类、`6002` 商品管理（`agri:seller:*`） |
| 平台菜单 | `menuId=1001` 系统用户（**不可分配**） |
| 经营账号 Token | 商户 A 经营账号；`X-Shop-Id=101`；含 `agri:seller:role:*` |
| 员工 Token | 商户 A 员工；默认 **无** 角色管理权限 |
| 已绑员工 | userId=1001 绑定 roleId=401 |

---

## 一、单元测试

### RM-UT-001 列表范围为当前店铺 biz_shop_role

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-001 |
| **测试模块** | 角色管理 |
| **测试项** | selectList 数据范围 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 + Mockito |
| **测试目的** | 验证 RM1：仅当前店铺（`X-Shop-Id`）有效员工角色 |
| **前置条件** | 店铺 101 有角色 401、402、403；店铺 102 有角色 501 |
| **测试步骤** | `X-Shop-Id=101` 上下文调用 `MerchantRoleServiceImpl.selectRoleList` |
| **预期结果** | 返回 3 条；**不含** 501 及 admin/merchant 平台角色 |

### RM-UT-002 列表默认按创建时间倒序

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-002 |
| **测试模块** | 角色管理 |
| **测试项** | 列表排序 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 §5.1 排序 |
| **前置条件** | 角色创建时间 403 > 401 > 402 |
| **测试步骤** | 调用 selectList 无检索条件 |
| **预期结果** | 首行 roleId=403；末行 roleId=402 |

### RM-UT-003 检索仅 roleName 模糊匹配

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-003 |
| **测试模块** | 角色管理 |
| **测试项** | roleName 检索 |
| **测试类型** | 单元测试 / SQL |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM3 |
| **前置条件** | 角色名「店员」「店长」 |
| **测试步骤** | `roleName=店`；再 `roleName=401`（按 ID 搜） |
| **预期结果** | 前者命中名称含「店」的角色；后者 **不** 按 roleId 命中 |

### RM-UT-004 列表 bindCount 统计员工绑定

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-004 |
| **测试模块** | 角色管理 |
| **测试项** | bind_count 聚合 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 §2.4、§5.2 可选扩展 |
| **前置条件** | 401 绑 1 员工；403 无绑定 |
| **测试步骤** | selectList 检查 bindCount |
| **预期结果** | 401 的 bindCount=1；403 的 bindCount=0；**不计** 经营账号 |

### RM-UT-005 非经营账号 requireMerchantAdmin 失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-005 |
| **测试模块** | 角色管理 |
| **测试项** | requireMerchantAdmin |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM2 |
| **前置条件** | 当前用户为员工（shop_id 非空） |
| **测试步骤** | 任意写操作入口 |
| **预期结果** | 抛 `ServiceException`；msg 含「仅商户经营账号」 |

### RM-UT-006 创建角色名店铺内唯一-成功

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-006 |
| **测试模块** | 角色管理 |
| **测试项** | assertRoleNameUnique |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM6 正常路径 |
| **前置条件** | 店铺 101 无同名「财务」 |
| **测试步骤** | 创建 roleName=财务 |
| **预期结果** | 校验通过 |

### RM-UT-007 创建角色名重复失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-007 |
| **测试模块** | 角色管理 |
| **测试项** | assertRoleNameUnique |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM6 |
| **前置条件** | 已有角色名「店员」 |
| **测试步骤** | 再创建 roleName=店员 |
| **预期结果** | 失败；msg 含「该角色名称已存在」 |

### RM-UT-008 编辑角色名排除自身可保留

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-008 |
| **测试模块** | 角色管理 |
| **测试项** | 编辑名称唯一 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 §8.1 排除自身 |
| **前置条件** | 编辑 roleId=401，名称仍为「店员」 |
| **测试步骤** | updateRole 不改 roleName |
| **预期结果** | 校验通过 |

### RM-UT-009 menuIds 为空失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-009 |
| **测试模块** | 角色管理 |
| **测试项** | validateMenuIds |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM4 |
| **前置条件** | CreateDTO menuIds=[] |
| **测试步骤** | createRole |
| **预期结果** | 失败；msg 含「请至少选择一项功能权限」 |

### RM-UT-010 含平台 menuId 失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-010 |
| **测试模块** | 角色管理 |
| **测试项** | listAssignableMenuIds |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM5 |
| **前置条件** | menuIds 含 1001（system:user） |
| **测试步骤** | createRole / updateRole |
| **预期结果** | 失败；msg 含「只能选择商家端功能权限」 |

### RM-UT-011 创建写三表事务

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-011 |
| **测试模块** | 角色管理 |
| **测试项** | createRole 事务 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 + Mockito |
| **测试目的** | 验证 §4.1 主流程 |
| **前置条件** | 合法 CreateDTO；menuIds=[6001] |
| **测试步骤** | 调用 createRole |
| **预期结果** | insert sys_role（role_key=`seller_s{shopId}_*`）；insert biz_shop_role；batch insert sys_role_menu |

### RM-UT-012 role_key 禁止 admin/merchant

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-012 |
| **测试模块** | 角色管理 |
| **测试项** | role_key 生成 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM10、§2.2 |
| **前置条件** | 创建成功 |
| **测试步骤** | 读取新角色 role_key |
| **预期结果** | 以 `seller_s101_` 开头；**不为** admin/merchant/member |

### RM-UT-013 编辑替换 sys_role_menu

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-013 |
| **测试模块** | 角色管理 |
| **测试项** | updateRole |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 + Mockito |
| **测试目的** | 验证 §4.2 |
| **前置条件** | 401 原 menuIds=[6001] |
| **测试步骤** | 改 menuIds=[6001,6002]、status=1 |
| **预期结果** | sys_role 更新；旧 sys_role_menu 删除后重插；**不改** role_key |

### RM-UT-014 跨店铺 roleId 不可编辑

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-014 |
| **测试模块** | 角色管理 |
| **测试项** | requireRoleRow 跨店 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证跨店铺隔离 |
| **前置条件** | `X-Shop-Id=101`；roleId=501 属店铺 102 |
| **测试步骤** | updateRole(501) |
| **预期结果** | 失败；msg 含「角色不存在」或无权 |

### RM-UT-015 删除无绑定成功

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-015 |
| **测试模块** | 角色管理 |
| **测试项** | deleteRole |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 + Mockito |
| **测试目的** | 验证 §4.3 正常路径 |
| **前置条件** | roleId=403，bind_count=0 |
| **测试步骤** | deleteRole(403) |
| **预期结果** | 删 sys_role_menu、biz_shop_role；sys_role.del_flag=2 |

### RM-UT-016 删除已绑定员工失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-016 |
| **测试模块** | 角色管理 |
| **测试项** | countRoleBindings |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM9 |
| **前置条件** | roleId=401，bind_count=1 |
| **测试步骤** | deleteRole(401) |
| **预期结果** | 失败；msg 含「已分配给员工」；三表 **不变** |

### RM-UT-017 停用角色 status=1 入库

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-017 |
| **测试模块** | 角色管理 |
| **测试项** | 停用 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM8、§12 |
| **前置条件** | 401 status=0 |
| **测试步骤** | updateRole status=1 |
| **预期结果** | sys_role.status=1；列表仍展示 |

### RM-UT-018 可分配菜单树仅 seller 范围

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-018 |
| **测试模块** | 角色管理 |
| **测试项** | selectMenuTree |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM5、§2.5 |
| **前置条件** | sys_menu 含 seller 与 platform 菜单 |
| **测试步骤** | 调用 selectMenuTree |
| **预期结果** | 节点 perms 均为 `agri:seller:*` 或其目录父级；**不含** system:* |

### RM-UT-019 角色个数不受员工配额限制

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-019 |
| **测试模块** | 角色管理 |
| **测试项** | 创建数量 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM11 |
| **前置条件** | 员工已达 max_sub_admin=5；已有 3 角色 |
| **测试步骤** | 连续 createRole 第 4、5 个角色 |
| **预期结果** | **均成功**；不调用配额校验 |

### RM-UT-020 详情含 menuIds 与 bindCount

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-020 |
| **测试模块** | 角色管理 |
| **测试项** | selectDetail |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 §3.2 |
| **前置条件** | roleId=401 绑 menu 6001、6002 |
| **测试步骤** | getDetail(401) |
| **预期结果** | menuIds 含 6001、6002；bindCount=1；roleDesc 映射 remark |

### RM-UT-021 编辑权限后员工菜单并集变化（协作）

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-021 |
| **测试模块** | 角色管理 |
| **测试项** | RM7 权限即时生效 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 + Mockito |
| **测试目的** | 验证 RM7 |
| **前置条件** | 员工 1001 仅绑 401；401 原仅 6001 |
| **测试步骤** | updateRole 401 增加 6002 → 模拟员工加载菜单 |
| **预期结果** | 员工可见菜单含 6001+6002；**无需** 重登 Token |

### RM-UT-022 停用后 roleOptions 过滤（协作）

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UT-022 |
| **测试模块** | 角色管理（员工协作） |
| **测试项** | selectRoleOptions |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 RM8、§2.6 |
| **前置条件** | 402 status=1（停用） |
| **测试步骤** | 调用 MerchantEmployeeMapper.selectRoleOptions |
| **预期结果** | **不含** roleId=402；含 401、403 |

---

## 二、接口测试

### RM-API-001 列表分页成功

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-001 |
| **测试模块** | 角色管理 |
| **测试项** | GET /list |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc / Apifox |
| **测试目的** | 验证 RM1、RM12 主流程 |
| **前置条件** | 经营账号 Token；`agri:seller:role:list` |
| **测试步骤** | `GET /agri/seller/role/list?pageNum=1&pageSize=10` |
| **预期结果** | `code=200`；rows 含 roleName、roleDesc、status、createTime；**不含** 平台 admin/merchant 角色 |

### RM-API-002 列表 roleName 检索

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-002 |
| **测试模块** | 角色管理 |
| **测试项** | GET /list 检索 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 RM3 |
| **前置条件** | 角色「店员」「库管」 |
| **测试步骤** | `GET .../list?roleName=店` |
| **预期结果** | 仅命中「店员」；清空 roleName 恢复全量 |

### RM-API-003 菜单树仅商家端

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-003 |
| **测试模块** | 角色管理 |
| **测试项** | GET /menuTree |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证 RM5 |
| **前置条件** | `agri:seller:role:list` |
| **测试步骤** | `GET /agri/seller/role/menuTree` |
| **预期结果** | `code=200`；树节点 **不含** 平台 system 菜单；含商品分类/商品管理等 seller 项 |

### RM-API-004 详情含 menuIds

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-004 |
| **测试模块** | 角色管理 |
| **测试项** | GET /{roleId} |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证详情回显 |
| **前置条件** | `agri:seller:role:query`；401 已配权限 |
| **测试步骤** | `GET /agri/seller/role/401` |
| **预期结果** | `code=200`；`menuIds` 非空；`bindCount≥0` |

### RM-API-005 创建角色成功

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-005 |
| **测试模块** | 角色管理 |
| **测试项** | POST / |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc / Apifox |
| **测试目的** | 验证 §7 主流程 |
| **前置条件** | `agri:seller:role:add`；body 合法 |
| **测试步骤** | `POST /agri/seller/role` body：roleName=财务、roleDesc、status=0、menuIds=[6001] |
| **预期结果** | `code=200`；列表新增；员工 roleOptions **可选** 该角色 |

### RM-API-006 创建角色名重复失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-006 |
| **测试模块** | 角色管理 |
| **测试项** | POST / 名称 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 RM6 |
| **前置条件** | 已有「店员」 |
| **测试步骤** | POST roleName=店员 |
| **预期结果** | 失败；msg 含「该角色名称已存在」 |

### RM-API-007 创建未选权限失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-007 |
| **测试模块** | 角色管理 |
| **测试项** | POST / menuIds |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 RM4 |
| **前置条件** | menuIds=[] |
| **测试步骤** | POST 创建 |
| **预期结果** | 失败；msg 含「请至少选择一项功能权限」 |

### RM-API-008 创建含平台 menuId 失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-008 |
| **测试模块** | 角色管理 |
| **测试项** | POST / 菜单范围 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 RM5 |
| **前置条件** | menuIds 含 1001 |
| **测试步骤** | POST 创建 |
| **预期结果** | 失败；msg 含「只能选择商家端功能权限」 |

### RM-API-009 编辑角色成功

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-009 |
| **测试模块** | 角色管理 |
| **测试项** | PUT / |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证 §8 主流程 |
| **前置条件** | `agri:seller:role:edit` |
| **测试步骤** | `PUT /agri/seller/role` 改 roleName、roleDesc、menuIds、status |
| **预期结果** | `code=200`；详情与列表同步；已绑员工权限 **即时** 变化（RM7） |

### RM-API-010 编辑清空权限失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-010 |
| **测试模块** | 角色管理 |
| **测试项** | PUT / menuIds |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 §8.1 至少一项 |
| **前置条件** | 编辑 401 |
| **测试步骤** | PUT menuIds=[] |
| **预期结果** | 失败；msg 含「请至少选择一项功能权限」 |

### RM-API-011 停用角色成功

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-011 |
| **测试模块** | 角色管理 |
| **测试项** | PUT / status |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 RM8、§12 |
| **前置条件** | 401 status=0 |
| **测试步骤** | PUT status=1 |
| **预期结果** | 成功；列表 status=停用；`GET /agri/seller/employee/roleOptions` **不含** 401 |

### RM-API-012 删除无绑定角色成功

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-012 |
| **测试模块** | 角色管理 |
| **测试项** | DELETE /{roleIds} |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证 §11 正常删除 |
| **前置条件** | `agri:seller:role:remove`；403 无绑定 |
| **测试步骤** | `DELETE /agri/seller/role/403` |
| **预期结果** | `code=200`；列表不再展示；roleOptions 不含 403 |

### RM-API-013 删除已绑定角色失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-013 |
| **测试模块** | 角色管理 |
| **测试项** | DELETE 绑定校验 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 RM9 |
| **前置条件** | 401 bind_count=1 |
| **测试步骤** | DELETE /401 |
| **预期结果** | 失败；msg 含「已分配给员工」；角色仍在列表 |

### RM-API-014 跨店铺编辑失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-014 |
| **测试模块** | 角色管理 |
| **测试项** | 数据隔离 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证跨店铺 |
| **前置条件** | `X-Shop-Id=101`；roleId=501 属店铺 102 |
| **测试步骤** | PUT 编辑 501 |
| **预期结果** | 失败；无跨店写库 |

### RM-API-015 员工账号访问被拒绝

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-015 |
| **测试模块** | 角色管理 |
| **测试项** | 访问控制 |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证 RM2、§1.4 |
| **前置条件** | Token 为员工账号 |
| **测试步骤** | GET /list |
| **预期结果** | 403 或业务失败；msg 含「仅商户经营账号」 |

### RM-API-016 无 list 权限拒绝

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-016 |
| **测试模块** | 角色管理 |
| **测试项** | @PreAuthorize |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证权限注解 |
| **前置条件** | Token **不含** `agri:seller:role:list` |
| **测试步骤** | GET /list |
| **预期结果** | HTTP 403 |

### RM-API-017 创建超员工配额仍可成功

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-017 |
| **测试模块** | 角色管理 |
| **测试项** | RM11 协作 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证角色数不受子管理员上限约束 |
| **前置条件** | 员工 5/5；已有 6 个角色 |
| **测试步骤** | POST 创建第 7 个角色 |
| **预期结果** | `code=200`；**不** 返回配额相关错误 |

### RM-API-018 停用后已绑员工失去该角色权限

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-018 |
| **测试模块** | 角色管理（协作） |
| **测试项** | RM8 登录鉴权 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证停用即时失效 |
| **前置条件** | 员工 1001 仅绑 401；401 含商品分类权限 |
| **测试步骤** | 1. 员工 Token 访问商品分类 API 2. PUT 401 status=1 3. 同 Token 再访问 |
| **预期结果** | 步骤 1 成功；步骤 3 **403** 或无菜单权限 |

### RM-API-019 编辑权限后员工可见新菜单

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-019 |
| **测试模块** | 角色管理（协作） |
| **测试项** | RM7 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证权限变更即时生效 |
| **前置条件** | 401 原仅 6001；员工已登录 |
| **测试步骤** | PUT 401 增加 6002 → 员工 GET 路由/菜单 |
| **预期结果** | 员工侧栏 **出现** 商品管理；**无需** 重新登录 |

### RM-API-020 批量删除含已绑定失败

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-020 |
| **测试模块** | 角色管理 |
| **测试项** | DELETE 批量 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 RM9 批量场景 |
| **前置条件** | roleIds=403,401（401 有绑定） |
| **测试步骤** | `DELETE /agri/seller/role/403,401` |
| **预期结果** | 整体失败或部分回滚；401、403 **均未被删** |

### RM-API-021 列表不含平台 admin 角色

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-021 |
| **测试模块** | 角色管理 |
| **测试项** | 平台边界 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 RM10、§2.3 |
| **前置条件** | sys_role 存在 admin、merchant |
| **测试步骤** | GET /list |
| **预期结果** | rows **不含** admin/merchant；仅 biz_shop_role 当前店铺归属角色 |

### RM-API-022 创建后员工管理可选用

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-API-022 |
| **测试模块** | 角色管理（协作） |
| **测试项** | roleOptions |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 §7.3 闭环 |
| **前置条件** | 刚 POST 创建「巡店员」 |
| **测试步骤** | `GET /agri/seller/employee/roleOptions` |
| **预期结果** | 下拉含「巡店员」；POST 创建员工可选该 roleId |

---

## 三、界面测试（Playwright）

> **通用前置：** Chromium；商家端 URL 以环境为准；经营账号 `13800001001` 登录；菜单「账号管理 → 角色管理」（路由 `/agri/seller/role`）。

### RM-UI-001 进入列表展示商户上下文

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-001 |
| **测试模块** | 角色管理 |
| **测试项** | 列表页 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright (Chrome) |
| **测试目的** | 验证 §5.1、RM1 |
| **前置条件** | 经营账号已登录；商户 A 有 3 角色 |
| **测试步骤** | 1. 登录商家端 2. 进入「角色管理」 |
| **预期结果** | 展示当前商户名称（只读）；表格含角色名称、角色描述、状态、操作；**不含** 平台角色 |

### RM-UI-002 按角色名称检索

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-002 |
| **测试模块** | 角色管理 |
| **测试项** | 高级检索 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 RM3、§6 |
| **前置条件** | 角色「店员」「库管」 |
| **测试步骤** | 检索框输入「店员」→ 查询 → 清空 |
| **预期结果** | 仅展示「店员」；清空后恢复全量 |

### RM-UI-003 创建角色成功

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-003 |
| **测试模块** | 角色管理 |
| **测试项** | 创建 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 §7 主流程 |
| **前置条件** | 有 add 权限；菜单树已加载 |
| **测试步骤** | 1. 点「创建角色」2. 填名称/描述/选正常 3. 权限树勾选「商品分类」4. 提交 |
| **预期结果** | 成功提示；列表新增；状态为正常 |

### RM-UI-004 权限树仅商家端菜单

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-004 |
| **测试模块** | 角色管理 |
| **测试项** | 功能权限树 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 RM5、§7.2 |
| **前置条件** | 打开创建/编辑弹窗 |
| **测试步骤** | 展开权限树查看节点 |
| **预期结果** | 含商品分类、商品管理、员工管理等 seller 项；**不含** 平台「系统管理」类菜单 |

### RM-UI-005 创建未选权限拦截

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-005 |
| **测试模块** | 角色管理 |
| **测试项** | 创建校验 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 RM4 |
| **前置条件** | 打开创建表单 |
| **测试步骤** | 填名称不勾选权限 → 提交 |
| **预期结果** | 前端校验或后端提示「请至少选择一项功能权限」 |

### RM-UI-006 创建角色名重复提示

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-006 |
| **测试模块** | 角色管理 |
| **测试项** | 名称唯一 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 RM6 |
| **前置条件** | 已有「店员」 |
| **测试步骤** | 创建 roleName=店员 并提交 |
| **预期结果** | 错误提示「该角色名称已存在」 |

### RM-UI-007 编辑角色含权限与停用

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-007 |
| **测试模块** | 角色管理 |
| **测试项** | 修改角色 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 §8、§9 |
| **前置条件** | 角色「店员」行 |
| **测试步骤** | 点「修改角色」→ 改描述、增勾商品管理、切换停用 → 保存 |
| **预期结果** | 成功刷新；状态列变为停用；权限树回显新勾选 |

### RM-UI-008 删除无绑定角色二次确认

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-008 |
| **测试模块** | 角色管理 |
| **测试项** | 删除 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 §11 二次确认 |
| **前置条件** | 角色「待删」无员工绑定 |
| **测试步骤** | 点「删除」→ 确认框确定 |
| **预期结果** | 确认文案提示不可恢复；确认后行消失 |

### RM-UI-009 删除已绑定角色失败提示

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-009 |
| **测试模块** | 角色管理 |
| **测试项** | 删除阻断 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 RM9 |
| **前置条件** | 「店员」已绑员工 |
| **测试步骤** | 点「删除」→ 确认 |
| **预期结果** | 提示「该角色已分配给员工，请先解除绑定」；行仍在 |

### RM-UI-010 停用角色后员工管理不可选

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-010 |
| **测试模块** | 角色管理（协作） |
| **测试项** | 停用协作 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 RM8 |
| **前置条件** | 已将「库管」停用 |
| **测试步骤** | 进入「员工管理」→ 创建/编辑 → 展开角色下拉 |
| **预期结果** | 下拉 **不含**「库管」；仍含正常角色 |

### RM-UI-011 员工账号不可见角色管理菜单

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-011 |
| **测试模块** | 角色管理 |
| **测试项** | 菜单权限 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 §1.4 默认员工无入口 |
| **前置条件** | 员工账号登录（无角色管理权限） |
| **测试步骤** | 查看侧栏；直接访问 `/agri/seller/role` |
| **预期结果** | **无**「角色管理」菜单；直链被拒绝或跳转无权限 |

### RM-UI-012 权限父子联动

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-012 |
| **测试模块** | 角色管理 |
| **测试项** | 权限树交互 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 §7.2 父子联动 |
| **前置条件** | 创建表单权限树 |
| **测试步骤** | 1. 勾选子菜单「商品列表」2. 取消父级「商品管理」 |
| **预期结果** | 勾选子时父级自动选中；取消父级时子级 **同步取消** |

### RM-UI-013 编辑权限后员工菜单即时变化

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-013 |
| **测试模块** | 角色管理（协作） |
| **测试项** | RM7 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证权限变更即时生效 |
| **前置条件** | 员工浏览器已登录；角色原仅商品分类 |
| **测试步骤** | 经营账号编辑该角色增加「商品管理」→ 员工页刷新侧栏 |
| **预期结果** | 员工侧栏 **出现** 商品管理；无需员工重新登录 |

### RM-UI-014 角色描述为空展示占位

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-014 |
| **测试模块** | 角色管理 |
| **测试项** | 列表展示 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 §5.2 |
| **前置条件** | 某角色无 roleDesc |
| **测试步骤** | 查看列表描述列 |
| **预期结果** | 展示「—」或空占位 |

### RM-UI-015 创建多个角色不受员工配额限制

| 要素 | 内容 |
|------|------|
| **用例编号** | RM-UI-015 |
| **测试模块** | 角色管理 |
| **测试项** | RM11 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证角色数与员工配额解耦 |
| **前置条件** | 员工管理显示 5/5 已满 |
| **测试步骤** | 连续创建 2 个新角色 |
| **预期结果** | **均可成功**；不出现「员工已达上限」类提示 |

---

## 四、业务规则覆盖矩阵

| 规则 | 单元 | 接口 | UI |
|------|:----:|:----:|:--:|
| RM1 列表范围 | UT-001 | API-001,021 | UI-001 |
| RM2 仅经营账号 | UT-005 | API-015 | UI-011 |
| RM3 名称检索 | UT-003 | API-002 | UI-002 |
| RM4 至少一项权限 | UT-009 | API-007,010 | UI-005 |
| RM5 仅商家端菜单 | UT-010,018 | API-003,008 | UI-004 |
| RM6 名称唯一 | UT-006,007,008 | API-006 | UI-006 |
| RM7 权限即时生效 | UT-021 | API-009,019 | UI-013 |
| RM8 停用协作 | UT-017,022 | API-011,018 | UI-007,010 |
| RM9 有绑定不可删 | UT-016 | API-013,020 | UI-009 |
| RM10 平台角色隔离 | UT-012 | API-021 | UI-001 |
| RM11 不受员工配额 | UT-019 | API-017 | UI-015 |
| RM12 店铺上下文 | — | API-023 | UI-016 |
| RM13 响应格式 | — | API-001 等 | — |
| 员工管理协作 | UT-022 | API-022 | UI-010 |
| 跨店隔离 | UT-014 | API-014 | — |
| 删除确认 | UT-015 | API-012 | UI-008 |

---

## 五、修订记录

| 版本 | 说明 |
|------|------|
| **v1.1** | 对齐需求 v1.1：当前店铺列表、`biz_shop_role`、`X-Shop-Id`、`seller_s{shopId}_*` |
| **v1.0** | 首版：22 单元 + 22 接口 + 15 UI；覆盖 RM1～RM12 及员工管理协作 |

---

*文档版本：v1.1 · 关联《角色管理功能需求.md》v1.1、《角色管理技术方案.md》v1.1*
