feat(P2): 实现质量保障类5项功能(无障碍/视觉回归/通知渠道/漏洞扫描/灾备)
## 新增功能 ### 1. 屏幕阅读器兼容性增强(a11y) - 无障碍工具库:src/shared/lib/a11y.ts - aria-live Hook:src/shared/hooks/use-aria-live.ts - a11y 组件:skip-link/visually-hidden/focus-trap/aria-status - 增强 UI:table.tsx 系统性 ARIA role,dialog.tsx aria-modal - 审计文档:docs/accessibility/a11y-audit.md(WCAG 2.1 AA 清单) ### 2. 视觉回归测试 - 测试套件:tests/visual/(homepage + 3 个 dashboard) - 3 视口(desktop/tablet/mobile)× 2 主题(light/dark) - 动态元素遮罩,避免误报 - playwright.config.ts 新增 visual-chromium 项目 - 文档:docs/testing/visual-regression.md ### 3. 短信/微信推送渠道集成 - 新模块:src/modules/notifications/ - 4 个渠道:SMS(阿里云/腾讯云)、WeChat(公众号)、Email(SMTP)、In-App - 分发器按用户偏好并行多渠道发送 - 外部 SDK 动态 import,Mock 模式开发可用 - 文档:docs/notifications/channels.md ### 4. 漏洞扫描 CI 集成 - CI security-scan job:npm audit + Snyk + Trivy FS + OWASP ZAP - 独立工作流 security.yml:每周一深度扫描 + 容器镜像扫描 - 配置:suppressions.json + .trivyignore - 本地脚本:security-scan.sh/ps1 - 文档:docs/security/scanning.md(SLA 分级) ### 5. 灾备方案 - 脚本:backup-verify/backup-offsite-sync/dr-drill/failover/health-check - CI 增强:备份后校验+异地同步,每周灾备演练 - 独立工作流 dr-drill.yml:每周一凌晨 4 点自动演练 - 文档:docs/dr/dr-plan.md(RTO 4h/RPO 24h)+ dr-runbook.md(6 故障场景) ## 验证 - npx tsc --noEmit:0 错误 - npm run lint:0 错误 0 警告
This commit is contained in:
185
docs/testing/visual-regression.md
Normal file
185
docs/testing/visual-regression.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# 视觉回归测试 (Visual Regression Testing)
|
||||
|
||||
本项目使用 [Playwright](https://playwright.dev/) 的 `toHaveScreenshot()` API 实现视觉回归测试,对关键页面在多种视口与主题下进行像素级快照对比,以捕获 UI 的意外变化。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
tests/visual/
|
||||
├── visual.config.ts # 视觉测试配置(页面、视口、主题、快照路径)
|
||||
├── homepage.spec.ts # 登录页视觉测试
|
||||
├── admin-dashboard.spec.ts # 管理员仪表盘视觉测试
|
||||
├── teacher-dashboard.spec.ts # 教师仪表盘视觉测试
|
||||
├── student-dashboard.spec.ts # 学生仪表盘视觉测试
|
||||
├── helpers/
|
||||
│ ├── auth.ts # 认证辅助(登录、setupAuthState)
|
||||
│ └── visual-helpers.ts # 视觉通用辅助(视口、主题、遮罩)
|
||||
└── __screenshots__/ # 快照基线存储目录(自动生成)
|
||||
```
|
||||
|
||||
## 覆盖范围
|
||||
|
||||
| 页面 | 路径 | 视口 | 主题 | 是否需要登录 |
|
||||
|------|------|------|------|--------------|
|
||||
| 登录页 | `/login` | desktop / tablet / mobile | light / dark | 否 |
|
||||
| 管理员仪表盘 | `/admin/dashboard` | desktop / tablet / mobile | light / dark | 是 (admin) |
|
||||
| 教师仪表盘 | `/teacher/dashboard` | desktop / tablet / mobile | light / dark | 是 (teacher) |
|
||||
| 学生仪表盘 | `/student/dashboard` | desktop / tablet / mobile | light / dark | 是 (student) |
|
||||
|
||||
视口尺寸:
|
||||
- desktop: 1920 × 1080
|
||||
- tablet: 768 × 1024
|
||||
- mobile: 375 × 812
|
||||
|
||||
## 运行测试
|
||||
|
||||
### 前置条件
|
||||
|
||||
- 需要启动开发服务器(Playwright 会通过 `webServer` 配置自动启动)
|
||||
- 需要登录的视觉测试需要 `DATABASE_URL` 环境变量,否则会自动跳过
|
||||
- 测试账号默认为 `admin@xiaoxue.edu.cn / 123456`,可通过环境变量覆盖
|
||||
|
||||
### 运行命令
|
||||
|
||||
```bash
|
||||
# 运行所有视觉回归测试
|
||||
npm run test:visual
|
||||
|
||||
# 运行单个测试文件
|
||||
npx playwright test --project=visual-chromium tests/visual/homepage.spec.ts
|
||||
|
||||
# 以 UI 模式运行(便于调试)
|
||||
npx playwright test --project=visual-chromium --ui
|
||||
```
|
||||
|
||||
### 环境变量
|
||||
|
||||
| 变量 | 默认值 | 说明 |
|
||||
|------|--------|------|
|
||||
| `DATABASE_URL` | - | 数据库连接串,未设置时需要登录的测试会跳过 |
|
||||
| `VISUAL_ADMIN_EMAIL` | `admin@xiaoxue.edu.cn` | 管理员测试账号 |
|
||||
| `VISUAL_ADMIN_PASSWORD` | `123456` | 管理员测试密码 |
|
||||
| `VISUAL_TEACHER_EMAIL` | `admin@xiaoxue.edu.cn` | 教师测试账号 |
|
||||
| `VISUAL_TEACHER_PASSWORD` | `123456` | 教师测试密码 |
|
||||
| `VISUAL_STUDENT_EMAIL` | `admin@xiaoxue.edu.cn` | 学生测试账号 |
|
||||
| `VISUAL_STUDENT_PASSWORD` | `123456` | 学生测试密码 |
|
||||
|
||||
## 更新基线
|
||||
|
||||
当 UI 发生**预期内**的变化时,需要更新快照基线:
|
||||
|
||||
```bash
|
||||
# 更新所有视觉快照基线
|
||||
npm run test:visual:update
|
||||
|
||||
# 更新单个测试文件的基线
|
||||
npx playwright test --project=visual-chromium tests/visual/homepage.spec.ts --update-snapshots
|
||||
```
|
||||
|
||||
更新后的快照应作为 PR 的一部分提交到版本库,以便团队评审 UI 变更。
|
||||
|
||||
## 处理误报
|
||||
|
||||
视觉测试可能因为动态内容(时间戳、用户名、实时数据等)产生误报。本项目通过以下方式消除误报:
|
||||
|
||||
### 1. 动态元素遮罩
|
||||
|
||||
`maskDynamicElements()` 辅助函数会自动遮罩以下选择器:
|
||||
|
||||
- `[data-testid='timestamp']`
|
||||
- `[data-testid='current-time']`
|
||||
- `[data-testid='user-avatar']`
|
||||
- `[data-testid='user-name']`
|
||||
- `time`
|
||||
- `[data-visual-dynamic]`
|
||||
|
||||
可在测试中追加额外需要遮罩的选择器:
|
||||
|
||||
```ts
|
||||
const masks = await maskDynamicElements(page, ["[data-testid='stat-card-value']"])
|
||||
```
|
||||
|
||||
### 2. 标记动态元素
|
||||
|
||||
在组件代码中为动态元素添加 `data-visual-dynamic` 属性,即可自动被遮罩:
|
||||
|
||||
```tsx
|
||||
<div data-visual-dynamic>{new Date().toLocaleString()}</div>
|
||||
```
|
||||
|
||||
### 3. 调整容差
|
||||
|
||||
`playwright.config.ts` 中配置了默认容差 `maxDiffPixelRatio: 0.01`(允许 1% 像素差异)。若特定页面需要更宽松的容差,可在断言时覆盖:
|
||||
|
||||
```ts
|
||||
await expect(page).toHaveScreenshot("name.png", {
|
||||
maxDiffPixelRatio: 0.05,
|
||||
})
|
||||
```
|
||||
|
||||
### 4. 禁用动画
|
||||
|
||||
默认配置 `animations: "disabled"`,避免动画过渡态导致快照不稳定。
|
||||
|
||||
## CI 集成
|
||||
|
||||
### GitHub Actions 示例
|
||||
|
||||
```yaml
|
||||
name: Visual Regression
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "src/**"
|
||||
- "tests/visual/**"
|
||||
- "playwright.config.ts"
|
||||
|
||||
jobs:
|
||||
visual:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npx playwright install --with-deps chromium
|
||||
|
||||
# 启动数据库(按需)
|
||||
- run: npm run db:setup
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
|
||||
|
||||
- name: Run visual tests
|
||||
run: npm run test:visual
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
|
||||
CI: "true"
|
||||
|
||||
- name: Upload snapshot diff
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: snapshot-diff
|
||||
path: test-results/
|
||||
retention-days: 7
|
||||
```
|
||||
|
||||
### CI 注意事项
|
||||
|
||||
1. **快照基线需提交到版本库**: `tests/visual/__screenshots__/` 目录应纳入 Git 跟踪
|
||||
2. **跨平台一致性**: 不同操作系统的字体渲染存在差异,建议 CI 与本地使用相同的 Linux 容器环境。若本地为 Windows/macOS,可能出现少量误报,以 CI 结果为准
|
||||
3. **storageState 缓存**: `tests/visual/.auth/` 目录应加入 `.gitignore`,不要提交登录态文件
|
||||
|
||||
## 与 E2E 测试的关系
|
||||
|
||||
| 维度 | E2E 测试 | 视觉测试 |
|
||||
|------|----------|----------|
|
||||
| 目录 | `tests/e2e/` | `tests/visual/` |
|
||||
| Playwright 项目 | `chromium` | `visual-chromium` |
|
||||
| 运行命令 | `npm run test:e2e` | `npm run test:visual` |
|
||||
| 关注点 | 功能正确性 | UI 视觉一致性 |
|
||||
| 断言方式 | DOM/行为断言 | 像素快照对比 |
|
||||
|
||||
两个测试套件相互独立,可分别运行,互不影响。
|
||||
Reference in New Issue
Block a user