> For the complete documentation index, see [llms.txt](https://cc-code.rongyeliu.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cc-code.rongyeliu.com/skills/whole-qa/references/assertions.md).

# 标准断言库

> 被 `whole-qa` 的 ❷ 阶段引用。每类元素/接口的**最小必测集**。 这些是**通用底线**；`prd.md` §1.5 的业务断言优先级更高，两者都要过。

## 一、页面级：五态矩阵

每个页面都必须覆盖，缺一态即该页未完成验收。

| 态              | 怎么造             | 期望                                              |
| -------------- | --------------- | ----------------------------------------------- |
| **正常 Idle**    | 正常数据进入          | 按 `ux.md` 布局渲染，无 console 错误                     |
| **加载 Loading** | 网络限速 / 拦截延迟响应   | 有加载指示（按 `ux.md` 约定），不出现空白闪烁                     |
| **完成 Success** | 完成一次主操作         | 有成功反馈，数据刷新，不重复提交                                |
| **错误 Error**   | 拦截接口返回 500 / 断网 | 有错误提示（不是白屏、不是静默），可重试                            |
| **空 Empty**    | 清空数据 / 用空账号     | 有空状态（按 `ux.md` 约定），不显示 `undefined`/`null`/`NaN` |

> 造态优先用浏览器的网络拦截能力；无法拦截时用 seed 数据构造。

## 二、元素级：9 类

### 1. button

| #  | 断言                                     |
| -- | -------------------------------------- |
| B1 | 可见且可点击（非 `pointer-events:none`、非被遮挡）   |
| B2 | 点击后有可观测反馈（导航 / 状态变化 / toast / loading） |
| B3 | 提交类按钮在请求期间禁用或防抖 —— **连点 3 次只产生 1 次提交** |
| B4 | 条件禁用的按钮：条件不满足时确实 `disabled`，满足后可用      |
| B5 | 危险操作（删除/清空/支付）弹二次确认，取消后**无副作用**        |
| B6 | 点击不产生 console 错误、不产生失败网络请求             |

### 2. link

| #  | 断言                                             |
| -- | ---------------------------------------------- |
| L1 | `href` 非空、非 `#`、非 `javascript:void(0)`（除非是纯锚点） |
| L2 | 目标页可达（非 404 / 非白屏）                             |
| L3 | 外链 `target="_blank"` 且带 `rel="noopener"`       |
| L4 | 站内跳转不整页刷新（SPA 场景）                              |
| L5 | 无权限时不可见或点击后正确拦截，**不泄露受保护内容**                   |

### 3. input

| #  | 断言                                                                 |
| -- | ------------------------------------------------------------------ |
| I1 | 必填留空 → 拦截 + 明确提示，**不静默失败**                                         |
| I2 | 长度边界：min-1 / min / max / max+1 四点                                  |
| I3 | 类型校验：email/number/date/url 等按 `api.md` 校验规则                        |
| I4 | 特殊字符不崩：`<script>alert(1)</script>` / `'` / `"` / emoji / 中日韩 / RTL |
| I5 | 前后空格按契约处理（trim 或保留，二者都要与 `api.md` 一致）                              |
| I6 | 清空后校验状态复位                                                          |
| I7 | 密码类：不明文回显、不出现在 DOM value 明文（按 `ux.md` 约定）                          |
| I8 | checkbox/radio：选中/取消/互斥组只能单选                                       |

### 4. select

| #  | 断言                               |
| -- | -------------------------------- |
| S1 | 默认值符合 `prd.md` 规则                |
| S2 | 每个选项都可选中且触发正确联动                  |
| S3 | 选项为空时有空提示，不是空白下拉                 |
| S4 | 联动 select：上游变化后下游正确重置（**不残留旧值**） |

### 5. textarea

继承 input 全部断言，额外：

| #  | 断言                         |
| -- | -------------------------- |
| T1 | 换行符按契约保存与回显                |
| T2 | 超长文本不破坏布局（按 `ux.md` 的溢出规则） |

### 6. form

| #  | 断言                     |
| -- | ---------------------- |
| F1 | 正常提交成功且有反馈             |
| F2 | 多字段错误时**全部**列出，不是只报第一个 |
| F3 | 提交失败后已填内容不丢失           |
| F4 | 重复提交防护（连点 / 回车连按）      |
| F5 | 取消/重置回到初始态             |
| F6 | 键盘可完成：Tab 顺序合理、回车提交    |

### 7. upload

| #  | 断言                          |
| -- | --------------------------- |
| U1 | 允许类型可上传，禁止类型被拦截且有提示         |
| U2 | 超大文件被拦截（边界：limit / limit+1） |
| U3 | 0 字节文件、无扩展名文件处理正确           |
| U4 | 多文件：数量上限、部分失败的处理            |
| U5 | 上传中可取消，取消后无残留               |

### 8. drag

| #  | 断言                |
| -- | ----------------- |
| D1 | 拖到合法目标生效并持久化      |
| D2 | 拖到非法目标被拒绝且回弹      |
| D3 | 拖出视口 / 中途松手不产生脏状态 |

### 9. modal

| #  | 断言                      |
| -- | ----------------------- |
| M1 | 打开后焦点进入弹窗（可访问性）         |
| M2 | ESC 关闭（除非 `ux.md` 明确禁止） |
| M3 | 点遮罩关闭行为与 `ux.md` 一致     |
| M4 | 关闭后表单状态按约定保留或清空         |
| M5 | 嵌套弹窗层级正确，关闭顺序正确         |
| M6 | 打开时背景不可滚动、不可 Tab 到背景元素  |

## 三、接口级：5 类

对 `api.md` 中每个接口逐条执行。

| 类       | 断言                                                                 |
| ------- | ------------------------------------------------------------------ |
| **正常**  | 合法入参 → 状态码、响应 schema、字段类型与 `api.md` 完全一致                           |
| **缺参**  | 逐个必填参数缺失 → 400 + 契约规定的错误码（不是 500、不是 200）                           |
| **越权**  | ① 未登录访问 → 401；② 登录但无权限 → 403；③ 访问他人资源 → 403/404（按契约），**绝不返回他人数据**  |
| **边界**  | 分页 `page=0/-1/超大`、`size=0/超大`；排序非法字段；ID 不存在 / 格式非法；并发重复提交（幂等接口须幂等） |
| **错误码** | 错误响应结构与 `api.md` 一致；**不泄露堆栈、SQL、内部路径、原始异常 message**                |

> ⚠️ 副作用接口（写库/扣费/发信）只在隔离环境测。无法隔离 → `SKIPPED(需隔离环境)`。

## 四、全局：每次操作都要盯的

| #  | 断言                                                        |
| -- | --------------------------------------------------------- |
| G1 | console 无 error / 无未捕获 Promise rejection                  |
| G2 | 无失败网络请求（4xx/5xx），除非该请求本身就是被测的错误路径                         |
| G3 | 页面无 `undefined` / `null` / `NaN` / `[object Object]` 字面输出 |
| G4 | 无中文乱码、无未翻译的 i18n key（如 `common.button.save` 直接显示）         |
| G5 | 无布局破裂（元素溢出容器、遮挡关键操作）                                      |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cc-code.rongyeliu.com/skills/whole-qa/references/assertions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
