# 产业政策宣传 — 测试用例

> 依据：`产业政策宣传功能需求.md`、`产业政策宣传功能管理技术方案.md`  
> **接口 Base Path（示例）**：`/policy/publicity`；若含 `context-path` 或网关前缀须补齐。鉴权与若依一致（Cookie / Token）。

**通用前置（无特殊说明）**：具备本模块菜单与按钮权限的账号已登录；可先调 `POST /common/upload` 取得政策文件/封面的 `url`、`fileName`（存储路径）、`originalFilename`（政策文件展示名）。政策文件白名单：`pdf`/`md`/`doc`/`docx`/`xls`/`xlsx`/`ppt`/`pptx`（≤30MB）；封面：`jpg`/`jpeg`/`png`（≤10MB）。**政策名称**：**1～20** 字符（必填）。**政策层级**：`1` 国家级、`2` 省级、`3` 市级、`4` 县级。**政策文件、封面**：选填。

**界面（UI）测试**：借助 **Playwright** 启动 **Chromium**（与 **Google Chrome 同源内核**）；可配置 `channel: 'chrome'` 调用本机已安装的谷歌浏览器，模拟点击、输入、文件选择与断言。

---

## 一、单元测试用例

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-XC-UT-001 | 状态机 | 编辑守卫 | 单元测试 | JUnit5 | 仅未发布可改 | 无 | 调用 `canEdit(publishStatus)`：`0`→true，`1`→false | 与需求 §6 矩阵一致 |
| ZCZX-XC-UT-002 | 状态机 | 删除守卫 | 单元测试 | JUnit5 | 仅未发布可删 | 无 | 调用 `canDelete`：`0`→true，`1`→false | 与 §5.4 一致 |
| ZCZX-XC-UT-003 | 状态机 | 发布守卫 | 单元测试 | JUnit5 | 仅未发布可发布 | 无 | 调用 `canPublish`：`0`→true，`1`→false | 与 §5.6 一致 |
| ZCZX-XC-UT-004 | 状态机 | 下架守卫 | 单元测试 | JUnit5 | 仅已发布可下架 | 无 | 调用 `canOffline`：`1`→true，`0`→false | 与 §5.6 一致 |
| ZCZX-XC-UT-005 | 参数校验 | 政策名称长度 | 单元测试 | JUnit5 | 1～20 字 | 无 | 空串、1 字、20 字、21 字 | 空/21 失败；1～20 通过 |
| ZCZX-XC-UT-006 | 参数校验 | 政策层级 | 单元测试 | JUnit5 | 仅 1～4 | 无 | `policyLevel` 为 1/4 通过；0、5、null 失败 | 与技术方案 §2.2 一致 |
| ZCZX-XC-UT-007 | 参数校验 | 简介/描述字数 | 单元测试 | JUnit5 | 简介选填≤50；描述必填≤50 | 无 | 简介 null/空通过、51 字失败；描述空/51 字失败、50 字通过 | 符合 §5.1 |
| ZCZX-XC-UT-008 | 参数校验 | 出台日期 | 单元测试 | JUnit5 | 合法且非未来 | 无 | 非法格式、明天日期、今天/过去日期 | 非法/未来失败；合法日期通过 |
| ZCZX-XC-UT-009 | 附件校验 | 政策文件后缀 | 单元测试 | JUnit5 | 白名单 | 无 | `.pdf` 通过；`.exe` 拒绝 | 与 §5.1 一致 |
| ZCZX-XC-UT-010 | 附件校验 | 封面后缀 | 单元测试 | JUnit5 | 白名单 | 无 | `.jpg` 通过；`.bmp` 拒绝 | 与 §5.1 一致 |
| ZCZX-XC-UT-011 | 附件校验 | 文件三件套一致性 | 单元测试 | JUnit5 | url/path/name 同有或同无 | 无 | 仅传 url 无 path；三者齐全 | 前者失败；后者通过 |
| ZCZX-XC-UT-012 | Service | 新增初始状态 | 单元测试 | JUnit5+Mockito | 草稿 | 合法 Body | `insert(...)` | `publish_status=0`；`publish_time` 为空 |
| ZCZX-XC-UT-013 | Service | 更新已发布拒绝 | 单元测试 | JUnit5+Mockito | 状态约束 | Mock `publish=1` | `update(...)` | 业务异常；不写库 |
| ZCZX-XC-UT-014 | Service | 发布成功 | 单元测试 | JUnit5+Mockito | 上架 | Mock `publish=0` 且必填齐全 | `publish(id)` | `publish=1`；`publish_time` 非空 |
| ZCZX-XC-UT-015 | Service | 下架成功回流 | 单元测试 | JUnit5+Mockito | 下架回流 | Mock `publish=1` | `offline(id)` | `publish=0`；`offline_time` 非空；附件字段保留 |
| ZCZX-XC-UT-016 | Service | 未发布禁止下架 | 单元测试 | JUnit5+Mockito | 异常 | Mock `publish=0` | `offline(id)` | 业务失败；状态不变 |
| ZCZX-XC-UT-017 | Service | 删除联动清文件 | 单元测试 | JUnit5+Mockito | §5.4 | `publish=0`；记录含 policy/cover path | `remove(ids)` | 删库记录；Mock 验证 `deleteFile` 对两 path 各调用 |
| ZCZX-XC-UT-018 | Service | 替换附件删旧文件 | 单元测试 | JUnit5+Mockito | §5.3 | `publish=0`；旧 path 已知 | `update` 换新 path 成功 | Mock 验证删除旧 `policy_file_path`/`cover_file_path` |

---

## 二、接口测试用例

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-XC-API-001 | 列表 | 默认分页排序 | 接口测试 | Postman/curl | §5.2 | 已登录；有数据 | `GET /industryPolicy/publicity/list` | `rows`≤20；`create_time` 倒序 |
| ZCZX-XC-API-002 | 列表 | 关键字-名称 | 接口测试 | Postman | 名称模糊 | 已登录 | `keyword=` 仅命中名称的词 | 返回含该名称记录 |
| ZCZX-XC-API-003 | 列表 | 关键字-简介 | 接口测试 | Postman | OR 关系 | 简介含词、名称不含 | 同上 keyword | 仍命中 |
| ZCZX-XC-API-004 | 列表 | 政策层级筛选 | 接口测试 | Postman | 精确 | 已登录 | `policyLevel=2` | 均为省级 |
| ZCZX-XC-API-005 | 列表 | 发布状态筛选 | 接口测试 | Postman | §5.2 | 已登录 | `publishStatus=0` / `1` | 与筛选一致 |
| ZCZX-XC-API-006 | 列表 | 组合查询 | 接口测试 | Postman | 多条件 | 已登录 | keyword+policyLevel+publishStatus | 同时满足 |
| ZCZX-XC-API-007 | 新增 | 最小必填无附件 | 接口测试 | Postman | 正常新增 | 已登录 | `POST /industryPolicy/publicity` 仅必填、不传文件 | `code` 成功；`publishStatus=0` |
| ZCZX-XC-API-008 | 新增 | 含政策文件与封面 | 接口测试 | Postman | 选填附件 | 已上传合法文件 | `POST` Body 含 file 三件套与 cover | 成功；字段落库 |
| ZCZX-XC-API-009 | 新增 | 名称非法 | 接口测试 | Postman | 1～20 | 已登录 | 名称空/21 字/缺 policyName | 失败；无新记录 |
| ZCZX-XC-API-010 | 新增 | 层级非法 | 接口测试 | Postman | 枚举 | 已登录 | `policyLevel=0` 或 `99` | 失败 |
| ZCZX-XC-API-011 | 新增 | 简介/描述超长 | 接口测试 | Postman | ≤50 | 已登录 | introduction 或 policyDesc 51 字 | 失败 |
| ZCZX-XC-API-012 | 新增 | 未来出台日期 | 接口测试 | Postman | 日期约束 | 已登录 | `issueDate` 为明天 | 失败 |
| ZCZX-XC-API-013 | 新增 | 缺必填 policyDesc | 接口测试 | Postman | 必填 | 已登录 | 缺 policyDesc | 失败 |
| ZCZX-XC-API-014 | 详情 | 有效 id | 接口测试 | Postman | §5.5 | 已登录 | `GET /industryPolicy/publicity/{id}` | 含 policyFileName、publishStatus 等 |
| ZCZX-XC-API-015 | 详情 | 无效 id | 接口测试 | Postman | 异常 | 已登录 | 不存在 id | 404 或业务失败 |
| ZCZX-XC-API-016 | 修改 | 未发布成功 | 接口测试 | Postman | §5.3 | 已登录；publish=0 | `PUT /industryPolicy/publicity` | 成功 |
| ZCZX-XC-API-017 | 修改 | 已发布拒绝 | 接口测试 | Postman | 矩阵 | 已登录；publish=1 | `PUT` | 失败；`msg` 含须下架类提示；数据不变 |
| ZCZX-XC-API-018 | 修改 | 替换政策文件 | 接口测试 | Postman | 删旧文件 | publish=0；原 path 已知 | `PUT` 换新 file 三件套 | 成功；旧文件不可访问（抽查存储） |
| ZCZX-XC-API-019 | 删除 | 未发布成功 | 接口测试 | Postman | §5.4 | 已登录；publish=0 | `DELETE /industryPolicy/publicity/{ids}` | 成功；详情 404 |
| ZCZX-XC-API-020 | 删除 | 已发布拒绝 | 接口测试 | Postman | 矩阵 | 已登录；publish=1 | `DELETE` | 失败 |
| ZCZX-XC-API-021 | 发布 | 未发布成功 | 接口测试 | Postman | §5.6 | 已登录；publish=0；必填齐全 | `POST .../publish/{id}` | publish=1；publishTime 有值 |
| ZCZX-XC-API-022 | 发布 | 已发布重复 | 接口测试 | Postman | 异常 | 已登录；publish=1 | `POST .../publish/{id}` | 失败 |
| ZCZX-XC-API-023 | 下架 | 已发布成功 | 接口测试 | Postman | §5.6 | 已登录；publish=1 | `POST .../offline/{id}` | publish=0；offlineTime 有值；附件仍在 |
| ZCZX-XC-API-024 | 下架 | 未发布拒绝 | 接口测试 | Postman | 约束 | 已登录；publish=0 | `POST .../offline/{id}` | 失败 |
| ZCZX-XC-API-025 | 端到端 | 全生命周期 | 接口测试 | Postman | §4 流程 | 已登录 | 新增→发布→下架→修改→再发布→下架→删除 | 每步状态与矩阵一致；同 id 贯穿 |
| ZCZX-XC-API-026 | 鉴权 | 未登录 | 接口测试 | curl | 安全 | 无 Token | `GET .../list` | 401 或统一未登录响应 |
| ZCZX-XC-API-027 | 权限 | 无写权限 | 接口测试 | Postman | 越权 | 仅 list 权限账号 | `POST .../publicity` | 无权限失败 |
| ZCZX-XC-API-028 | 响应 | 失败可读 | 接口测试 | Postman | §7 | 已登录 | 触发名称空串等校验 | Body 含 `code`、`msg`；`msg` 可区分错误类型 |
| ZCZX-XC-API-029 | 上传 | 政策文件超限（可选） | 接口测试 | Postman | §5.1 | 环境允许略超 30MB | `POST /common/upload` 或提交触发校验 | 明确大小/格式提示；业务表无脏数据 |

---

## 三、界面测试用例（UI）

**测试工具**：**Playwright** + **Chromium**（`channel: 'chrome'` 时使用本机 **Google Chrome**）。步骤映射：`page.goto`、`locator.fill`、`locator.click`、`setInputFiles`、`expect`；确认框：`page.on('dialog')` 或 `getByRole('button', { name: /确定|确认/ })`。

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-XC-UI-001 | 列表 | 默认分页排序 | UI 测试 | Playwright+Chrome | §5.2 | 已登录；数据>20 | 进入「产业政策宣传」菜单 | 默认每页 20；创建时间新在前 |
| ZCZX-XC-UI-002 | 列表 | 关键字-名称 | UI 测试 | Playwright+Chrome | 名称模糊 | 存在名称含关键词记录 | 输入关键字→查询 | 表格含该行 |
| ZCZX-XC-UI-003 | 列表 | 关键字-简介 | UI 测试 | Playwright+Chrome | OR | 简介含词、名称不含 | 输入该词→查询 | 命中 |
| ZCZX-XC-UI-004 | 列表 | 政策层级筛选 | UI 测试 | Playwright+Chrome | 精确 | 多层级均有数据 | 选「省级」→查询 | 层级列均为省级 |
| ZCZX-XC-UI-005 | 列表 | 发布状态筛选 | UI 测试 | Playwright+Chrome | §5.2 | 有已发布/未发布数据 | 分别筛「未发布」「已发布」 | 状态列与筛选一致 |
| ZCZX-XC-UI-006 | 列表 | 组合与重置 | UI 测试 | Playwright+Chrome | 恢复条件 | 已多条件筛选 | 查询→重置 | 条件清空；恢复默认列表 |
| ZCZX-XC-UI-007 | 列表 | 操作按钮矩阵 | UI 测试 | Playwright+Chrome | §6 | 准备未发布、已发布各一条 | 逐行查看操作列 | 未发布：编辑/发布/删除可见；已发布：下架可见；已发布无编辑/删除/发布 |
| ZCZX-XC-UI-008 | 新增 | 最小必填主流程 | UI 测试 | Playwright+Chrome | §5.1 | 已登录 | 新增→填名称、层级、出台日期、描述→提交 | 成功；列表状态「未发布」 |
| ZCZX-XC-UI-009 | 新增 | 含简介与附件 | UI 测试 | Playwright+Chrome | 选填 | 已登录 | 填简介；上传 pdf 与 jpg 封面→提交 | 成功；详情可见文件名与封面 |
| ZCZX-XC-UI-010 | 新增 | 名称空或超长 | UI 测试 | Playwright+Chrome | 异常 | 已登录 | 名称留空或 21 字→提交 | 前端或提交后校验失败 |
| ZCZX-XC-UI-011 | 新增 | 名称 20 字边界 | UI 测试 | Playwright+Chrome | 上限 | 已登录 | 名称恰好 20 字+其余合法→提交 | 成功 |
| ZCZX-XC-UI-012 | 新增 | 层级必选 | UI 测试 | Playwright+Chrome | 约束 | 可清空层级时 | 不选层级→提交 | 必选提示 |
| ZCZX-XC-UI-013 | 新增 | 未来出台日期 | UI 测试 | Playwright+Chrome | 异常 | 已登录 | 出台日期选明天→提交 | 校验失败 |
| ZCZX-XC-UI-014 | 新增 | 简介/描述超长 | UI 测试 | Playwright+Chrome | ≤50 | 已登录 | 简介或描述>50 字→提交 | 失败 |
| ZCZX-XC-UI-015 | 新增 | 政策文件无附件可提交 | UI 测试 | Playwright+Chrome | 选填 | 已登录 | 仅必填、不上传政策文件→提交 | 成功（与标准类「正文必填」区分） |
| ZCZX-XC-UI-016 | 新增 | 政策文件/封面非法 | UI 测试 | Playwright+Chrome | §5.1 | 准备 .exe、.bmp 或超限文件 | `setInputFiles` 上传→提交 | 拒绝或明确错误提示 |
| ZCZX-XC-UI-017 | 详情 | 字段完整 | UI 测试 | Playwright+Chrome | §5.5 | 任意记录 | 点「详情」 | 名称、层级、简介、日期、描述、文件名、封面、发布状态齐全 |
| ZCZX-XC-UI-018 | 详情 | 已发布只读 | UI 测试 | Playwright+Chrome | §5.5 | 已发布记录 | 开详情 | 无「保存」类按钮；可有「下架」 |
| ZCZX-XC-UI-019 | 修改 | 未发布编辑成功 | UI 测试 | Playwright+Chrome | §5.3 | 未发布记录 | 编辑→改名称→保存 | 列表/详情已更新 |
| ZCZX-XC-UI-020 | 修改 | 已发布禁止编辑 | UI 测试 | Playwright+Chrome | 矩阵 | 已发布 | 尝试进编辑或改字段保存 | 无编辑入口或提示须先下架 |
| ZCZX-XC-UI-021 | 修改 | 保存清空必填失败 | UI 测试 | Playwright+Chrome | 异常 | 未发布 | 清空名称或描述→保存 | 校验失败 |
| ZCZX-XC-UI-022 | 修改 | 替换政策文件与封面 | UI 测试 | Playwright+Chrome | §5.3 | 未发布；原有附件 | 编辑→换 pdf 与 png→保存 | 详情为新文件名；旧 URL 不可访问 |
| ZCZX-XC-UI-023 | 发布 | 未发布发布成功 | UI 测试 | Playwright+Chrome | §5.6 | 未发布、必填齐全 | 点「发布」→确认 | 状态变「已发布」 |
| ZCZX-XC-UI-024 | 发布 | 已发布无发布钮 | UI 测试 | Playwright+Chrome | 矩阵 | 已发布行 | 查看操作列 | 「发布」隐藏或禁用 |
| ZCZX-XC-UI-025 | 下架 | 已发布下架成功 | UI 测试 | Playwright+Chrome | §5.6 | 已发布 | 点「下架」→确认 | 状态变「未发布」；记录仍在 |
| ZCZX-XC-UI-026 | 下架 | 未发布无下架钮 | UI 测试 | Playwright+Chrome | 约束 | 未发布行 | 查看操作列 | 无「下架」 |
| ZCZX-XC-UI-027 | 发布下架 | 下架后再发布闭环 | UI 集成 | Playwright+Chrome | §4 步骤 6 | 完成 UI-025 | 编辑（可选）→再发布 | 再次「已发布」；同一行 id |
| ZCZX-XC-UI-028 | 删除 | 未发布删除成功 | UI 测试 | Playwright+Chrome | §5.4 | 未发布 | 删除→确认 | 列表无该行 |
| ZCZX-XC-UI-029 | 删除 | 已发布禁删 | UI 测试 | Playwright+Chrome | 矩阵 | 已发布 | 尝试删除 | 按钮不可用或提示先下架 |
| ZCZX-XC-UI-030 | 删除 | 删后附件失效 | UI 测试 | Playwright+Chrome | 存储清理 | 删除前复制政策文件 URL | 删除后新标签打开 URL | 不可访问或 404 |
| ZCZX-XC-UI-031 | 端到端 | 全生命周期串联 | UI 集成 | Playwright+Chrome | §4 | 可新建 | 新增→发布→下架→改→再发布→下架→删除 | 每步状态与按钮矩阵一致 |
| ZCZX-XC-UI-032 | 权限 | 只读账号 | UI 测试 | Playwright+Chrome | §8 权限 | 无 add/edit/remove 权限 | 登录进模块 | 无新增/编辑/删除或操作拒绝 |
| ZCZX-XC-UI-033 | 层级 | 四级均可发布 | UI 测试 | Playwright+Chrome | §2.1 | 已登录 | 各建国家级/省级/市级/县级一条并筛选 | 展示与筛选正确；均可走发布流 |
| ZCZX-XC-UI-034 | 错误提示 | 业务失败可读 | UI 测试 | Playwright+Chrome | §7 | 已登录 | 对已发布记录若强行调编辑 API 或绕过 UI 保存 | 页面 Message 含明确 `msg`（若 UI 暴露） |

---

## Playwright 与谷歌浏览器（实施提示）

- 安装：`npm i -D @playwright/test`；`npx playwright install chromium`；本机 Chrome：`npx playwright install chrome`，配置 `channel: 'chrome'`。  
- `playwright.config.ts` 示例：`use: { channel: 'chrome', headless: false, locale: 'zh-CN', baseURL: 'http://localhost:80' }`。  
- 登录复用：`test.beforeAll` 登录一次，`storageState: 'auth.json'` 写入配置。  
- 菜单：侧栏 `getByText('产业政策宣传')` 或路由 `goto('/industryPolicy/publicity')`（以实际为准）。  
- 文件上传：`page.locator('input[type=file]').setInputFiles('fixtures/policy.pdf')`。  
- 按钮示例：`getByRole('button', { name: /新增|发布|下架|删除/ })`。

---

## 覆盖对照

| 类别 | 单元 UT | 接口 API | 界面 UI |
| --- | --- | --- | --- |
| 正常流程 | UT-012～015、017～018 | API-001～008、014、016、018～019、021、023、025 | UI-001～009、011、015、017、019、022～023、025、027～028、031、033 |
| 异常流程 | UT-005～011、013、016 | API-009～013、015、017、020、022、024、026～029 | UI-010、012～014、016、020～021、024、026、029～030、034 |
| 业务约束/矩阵 | UT-001～004、013 | API-017、020、022、024、027 | UI-007、018、020、024、026、029、032 |

---

## 功能需求追溯（自查）

| 需求章节 | 要点 | 主要对应用例 |
| --- | --- | --- |
| §5.1 新增 | 名称 1～20、层级 1～4、简介/文件/封面选填、描述与日期必填、初始未发布 | UT-005～012；API-007～013；UI-008～016 |
| §5.2 列表 | 关键字 OR、层级、发布状态、分页排序 | API-001～006；UI-001～006 |
| §5.3 修改 | 仅未发布；替换删旧文件 | UT-001、013、018；API-016～018；UI-019～022 |
| §5.4 删除 | 仅未发布；删存储文件 | UT-002、017；API-019～020；UI-028～030 |
| §5.5 详情 | 字段完整、已发布只读 | API-014～015；UI-017～018 |
| §5.6 发布/下架 | 发布前置；下架保留附件 | UT-003～004、014～016；API-021～024；UI-023～027 |
| §6 矩阵 | 五类操作权限 | UT-001～004；UI-007、018、020、024、026、029、031 |
| §7 错误约定 | code/msg 可读 | API-028；UI-034 |

---

## 修订记录

| 版本 | 说明 |
| --- | --- |
| 1.0 | 初版：单元 18、接口 29、UI 34；无知识库用例；Playwright+Chrome；Base Path `/industryPolicy/publicity` |
