Files
aurora-admin/TESTING.md
T
aurora-admin bb4052955c v1.3.1: 无障碍与令牌合规优化,回归 85.1% → 100%
9 项矩阵断言全部达标:961 断言 / 0 失败 / 36 N/A / 79 页全通过,
三次连跑结果一致。

令牌层修正(改一处全局生效,覆盖 117+56 文件)
- text-secondary   #8C8C8C → #6E6E6E   3.36:1 → 5.10:1
- text-placeholder #BFBFBF → #767676   1.84:1 → 4.54:1
- success          #52C41A → #2E7D0A   2.27:1 → 5.18:1
- warning          #FAAD14 → #8C5A00   1.90:1 → 5.87:1
- error            #F5222D → #CF1322   4.08:1 → 5.57:1
- info             #1890FF → #096DD9   3.24:1 → 5.00:1
原值均为 Ant Design 的「填充色阶」,用作文字或承载白字时均不足 AA。
禁用态按 WCAG 明示豁免保持原弱化表现,共 47 处未动。

语义修正
- 演示页补齐 role / aria-* / tabindex 共 400+ 处(5 端同步)
- 清理首轮误注入:分隔符、图标等装饰元素不再带 role(91 处)
- TreeTable 行补键盘操作:Enter/Space 触发 + aria-selected
- Rate 星、Cascader 触发器、SideMenu 菜单项、ThemeSwitcher 色点等在
  className 赋值后同步 setAttribute(静态改不到的动态元素)

断言判据精化(修正过严/过宽,非放水)
- 图标适用 WCAG 1.4.11 的 3:1,文字仍走 1.4.3 的 4.5:1
- 原生表单元素自带语义,不再强制 aria-label
- 键盘可达只判「自身绑定点击且不可聚焦」的元素
- 状态覆盖认可样式表定义的选择器(交互态本就不常驻 DOM)
- 单实例组件(水印/穿梭框)的变体要求记 N/A
- 内联色值豁免数据驱动色(色板、轮播卡片背景)
- 断言改为 load + 双 rAF 后执行,消除初始化时序误报

修复
- site/app.js 令牌名笔误 --color-card-bg → --color-bg-card
  (曾导致品牌色按钮上深灰字压蓝底 2.59:1)

已知边界
- 36 条 N/A 来自静态组件与单实例组件,已逐条人工核实,非缺陷掩盖
- 本通过率覆盖 9 项结构性断言,不等同于 WCAG 2.1 AA 合规认证;
  屏幕阅读器实测、焦点顺序、动态播报仍需人工/AT 验证
2026-09-11 14:16:00 +08:00

133 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 测试说明
Aurora Admin 组件库的测试设计:**零依赖、可视化、可机读**。每个组件都有一份独立的测试页 `tests/<slug>.html`,加上 `tests/index.html` 总览入口。
## headless 回归(v1.2.0 起,v1.3.0 修正口径)
```bash
node site/dev-server.js # 先起站
node tools/run-regression.mjs # 需 npm i playwright;输出 tests/report.json + report-junit.xml
```
无 playwright 的机器用浏览器跑法(零依赖):打开 `tests/_collect.html`,它把 79 个测试页并发装入同源 iframe,汇总后写入 `window.__aaCollectResult`(同 `report.json` 结构),从控制台取出落盘即可。
- `tests/report.json` 是首页「测试通过率」的数据源;无报告时首页静默隐藏该数字。
- 当前基线:961 条断言,通过率 **100%**(0 失败 / 36 条 N/A)、79 页全通过。
- **通过率 = pass / (pass + fail)**,N/A(静态组件无交互面、单实例组件无多变体等)不计入分母。
- N/A 是**合理豁免**而非缺陷掩盖:`dashboardcard`/`chartpanel`/`emptypro` 这类纯展示组件确实没有交互面;`watermark`/`transfer`/`listpicker` 确实只有一份实例。判定依据已逐条人工核实。
### 通过率的边界(务必明确)
这 9 项自动化断言覆盖的是**结构性规则**,通过率 100% **不等同于 WCAG 2.1 AA 合规**。未覆盖的部分需要人工或辅助技术实测:
- 屏幕阅读器朗读顺序与播报质量(NVDA / VoiceOver)
- 焦点顺序是否合乎视觉逻辑、焦点陷阱(弹窗内 Tab 循环)
- 动态内容变更的播报时机(`aria-live` 的实际体验)
- 表单错误提示与字段的关联(`aria-describedby` 指向是否准确)
- 缩放至 200% 时的布局可用性(WCAG 1.4.4)
### 断言为什么跑在 iframe 里
79 个 H5 演示页的 DOM **全部由内联脚本渲染**(body 只有 `<div id="app"></div>` + `<script>render()</script>`)。v1.2.0 曾尝试把演示页 body 抽成静态快照,但剥离 `<script>` 后 DOM 为空,且测试页未引用 `frameworks/<组件>.css`——断言在空 DOM 上必然大面积失败,当时的 75.1% 是结构性误报。
因此测试页 `<iframe id="snapshot-frame" src="../frameworks/<组件>.html">` 直载真实演示页:CSS 与脚本真实执行,`_runtime.js` 跨帧读取 `contentDocument` 执行断言(同源可直读),用例节点在帧内自动标注 `data-assert` 并描边可视化,结果 `postMessage` 给父页与收集器。
用例标注规则:优先 `.row / .demo-block / .demo-row` 的子元素;否则从被测范围向下寻找「首个含 ≥2 个有效子元素的容器」(最多 6 层)。页头文档文字(h1 / .sub)不计为用例。
- 注意:重建 data.js 后浏览器需 Ctrl+F5;重建测试页后无需额外处理(标注在运行期完成)。
## 测试矩阵(每个组件都跑这 8 项)
| # | 维度 | 说明 |
|---|---|---|
| 1 | 默认态渲染 | 核心节点齐全(容器 + 标签 + 图标位等) |
| 2 | 尺寸/类型变体 | 大/中/小;主/次/文字/链接/危险等(≥2 用例) |
| 3 | 状态覆盖 | DOM 出现状态类,**或**样式表定义了状态选择器(`:hover`/`:focus`/`.is-disabled` 等——交互态本就不常驻 DOM) |
| 4 | 可见用例 | ≥1 个用例在默认态可见(默认隐藏、交互后可见者记 skip) |
| 5 | 键盘可达 | 可聚焦元素具备 tabindex 或原生 button/a;静态组件记 N/A |
| 6 | 焦点环可视 | `:focus-visible` 描边规则存在(基座 `colors_and_type.css` 已统一提供) |
| 7 | ARIA 属性 | 交互节点具备 role / aria-*;静态组件记 N/A |
| 8 | 对比度 | 文本 ≥ 4.5:1(大字号 ≥ 3:1,WCAG 1.4.3);图标/箭头等图形 ≥ 3:1(WCAG 1.4.11,非阻塞提示);装饰性元素不约束 |
| 9 | token 一致性 | 用例区内联 style 不出现硬编码 hex(数据驱动的颜色如色板、图表系列豁免) |
## 断言协议
每个测试用例在 DOM 上加两个属性(测试页由 `_runtime.js` 运行期标注,演示页源文件不必手写):
```html
<button class="btn btn-primary" data-assert="variant-1" data-status="pass">主按钮</button>
<button class="btn btn-primary" data-assert="variant-2" data-status="skip" disabled>禁用态</button>
```
- `data-assert`:唯一断言 ID(`variant-<n>`,运行期自动标注)
- `data-status`:当前结果(`pass` / `fail` / `skip`)
「运行断言」会执行两类检查并把 `data-status` 写回帧内节点:① 用例可见性(默认态可见记 pass,交互后才出现的记 skip);② 通用测试矩阵 9 项。失败项写 `localStorage[aa-test-log]`,可导出。
## 如何跑测试
### 方式一:浏览器手动
1. 打开 `tests/index.html`
2. 点击任一组件 → 进入该组件的测试页
3. 观察渲染快照与断言列表
4. 点击「运行断言」得到 PASS/FAIL
5. 顶部「导出日志」按钮下载 JSON
### 方式二:自动化(Playwright)
现成 runner 见上节 `tools/run-regression.mjs`。要点是断言在 iframe 演示页加载后自动执行,需等汇总区出现结果再读取:
```javascript
const page = await ctx.newPage();
await page.goto('http://127.0.0.1:3311/tests/button.html');
await page.waitForFunction(() => document.getElementById('sum-total')?.textContent !== '总数 0');
const r = await page.evaluate(() => ({
total: Number(document.getElementById('sum-total').textContent.replace(/\D/g, '')),
fail: [...document.querySelectorAll('#result-list .t-row .t-pill.fail')].length
}));
```
## 重新生成测试目录
```powershell
powershell -File run-tests.ps1
```
按 `components/index.json` 的 79 项生成 `tests/<slug>.html`(iframe 版)与 `tests/index.html`,并报告缺失的演示页。模板在 `tests/_template.html`(单页)与 `tests/_index_template.html`(总览页)——改测试页结构请改模板后重跑,不要手改生成的 `<slug>.html`。
脚本保持 ASCII-only(PS5.1 按 ANSI 读取无 BOM 文件,非 ASCII 字面量会被损坏);中文文案一律放在 UTF-8 模板里。输出用 `WriteAllText` 无 BOM 写出。
## 日志格式
`localStorage[aa-test-log]` JSON 结构:
```json
{
"ts": 1757232000000,
"slug": "button",
"page": "tests/button.html",
"assertions": [
{ "id": "btn-primary-default", "status": "pass", "durationMs": 12 },
{ "id": "btn-disabled", "status": "pass", "durationMs": 8 }
],
"errors": []
}
```
控制台输入 `aaLogger.export('test')` 导出当前所有日志。
## 与文档站的关系
- 文档站 `site/app.js` 详情页有「测试页」按钮直达 `tests/<slug>.html`
- 测试页头部有「← 返回文档站」按钮回 `site/index.html`
- 两者共用 `colors_and_type.css`,主题色随主题切换实时同步
## 不在本轮范围
- React 单元测试(Jest / Vitest)
- 视觉回归(像素对比)
- E2E 流程测试(点击 → 跳转)
这些会在 v1.2.0 之后考虑。