# Nexus 全站测试用例矩阵(SSOT) > 编号规则:`<层>-<域>-<序号>` > 层:`UT` 单元 · `IT` 集成 · `CH` 链条 · `E2E` Playwright · `MCP` Agent 浏览器 > 状态:`✅` 已有 · `🔲` 待写 · `🟡` 部分覆盖 · `⏭` 不验收(已确认豁免) 最后更新:2026-06-09 --- ## 0. 横切能力 | ID | 层 | 用例 | 前置 | 步骤 | 期望 | 状态 | 实现位置 | |----|-----|------|------|------|------|------|----------| | UT-AUTH-001 | UT | JWT access 过期边界 | 固定 clock | 签发 exp-1s token | 401 + 中文提示 | ✅ | test_login_access.py | | UT-AUTH-002 | UT | refresh 复用检测 | 双 refresh 同 jti | 第二次 refresh | 401 revoke 全家 | ✅ | test_auth_refresh_reuse.py | | UT-VAL-001 | UT | 422 loc 中文化 | — | per_page=999 | detail 含 `每页条数` | ✅ | test_validation_errors_zh.py | | UT-TIME-001 | UT | 北京时间格式化 | UTC 输入 | format_display_time | `Asia/Shanghai` 字符串 | ✅ | test_display_time.py | | UT-SEC-001 | UT | 路径穿越拒绝 | — | `../etc/passwd` | ValidationError | ✅ | test_remote_path_validation.py | | IT-AUTH-001 | IT | 登录换 token | API 活 | POST /api/auth/login | access+refresh | ✅ | test_api.py | | IT-AUTH-002 | IT | 无 token 403 | — | GET /api/servers | 401/403 | ✅ | test_api.py | | CH-AUTH-001 | CH | 登录→刷新→访问 | 活 API | login→refresh→GET servers | 200 | ✅ | tests/chain/test_auth_flow.py | | E2E-AUTH-001 | E2E | 错误密码 | 浏览器 | 填错密码登录 | 页内错误提示 | ✅ | e2e/pages/auth.spec.mjs | | MCP-AUTH-001 | MCP | 登录页渲染 | base URL | snapshot #/login | 表单+品牌可见 | ✅ | e2e/pages/login.spec.mjs | --- ## 1. 安装向导 `/app/install.html` | ID | 层 | 用例 | 期望 | 状态 | 备注 | |----|-----|------|------|------|------| | UT-INST-001 | UT | 已安装锁 404 | /api/install/* 404 | ✅ | test_install_locked_404.py | | IT-INST-001 | IT | 无 .env 仅 install 路由 | /health 与 /api/servers 行为 | ✅ | tests/integration/test_install_mode.py | | E2E-INST-001 | E2E | 安装页可打开 | install.html 200 | ✅ | e2e/pages/install.spec.mjs | | MCP-INST-001 | MCP | 安装步骤 UI | 各 step 控件可见 | ⏭ | **不验收**:生产已锁安装向导;E2E-INST-001 可达性已够 | --- ## 2. 仪表盘 Dashboard `#/` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | IT-DASH-001 | IT | GET /api/dashboard/stats | 200 + 数字字段 | ✅ | tests/integration/test_servers_dashboard.py | | E2E-DASH-001 | E2E | 仪表盘加载 | 卡片/图表区域可见 | ✅ | full-acceptance #2 + dashboard-stats.spec.mjs | | MCP-DASH-001 | MCP | 统计数字非空 | 在线/告警计数 | ✅ | 沉淀 E2E-DASH-001 | --- ## 3. 服务器 Servers `#/servers` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-SRV-001 | UT | 列表排序键合法 | sort 白名单 | ✅ | test_server_list_sort.py | | UT-SRV-002 | UT | status 字段枚举 | online/offline/… | ✅ | test_server_status_field.py | | UT-SRV-003 | UT | target_path 过滤 | 非法路径拒绝 | ✅ | test_server_target_path_filter.py | | IT-SRV-001 | IT | GET /api/servers 分页 | total+items | ✅ | test_api.py | | IT-SRV-002 | IT | per_page>200 → 422 中文 | loc_zh | ✅ | 422 改造后 | | IT-SRV-003 | IT | notify 开关 settings API | 审计+CUD | ✅ | tests/integration/test_notify_settings.py | | CH-SRV-001 | CH | 列表→详情抽屉→保存 | DB 与响应一致 | ✅ | tests/chain/test_server_update_flow.py | | E2E-SRV-001 | E2E | 表格+筛选 | 表头+搜索框 | ✅ | full-acceptance #3 | | E2E-SRV-002 | E2E | **无 CSV 导出按钮** | 按钮不存在 | ✅ | e2e/pages/servers.spec.mjs | | E2E-SRV-003 | E2E | 分类筛选可见 | chip/文案 | ✅ | e2e/pages/servers-filter.spec.mjs | | MCP-SRV-001 | MCP | 打开筛选抽屉 | 分类/状态 chip | ✅ | 沉淀 E2E-SRV-003 | --- ## 4. 终端 Terminal `#/terminal` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-TERM-001 | UT | WebSSH payload 校验 | 非法 host 拒绝 | ✅ | test_webssh_terminal_payload.py | | IT-TERM-001 | IT | WS /ws/webssh 握手 | 401 无 token | ✅ | tests/integration/test_webssh_auth.py | | E2E-TERM-001 | E2E | 页加载 idle 提示 | 未选服务器文案 | ✅ | e2e/pages/terminal.spec.mjs | | MCP-TERM-001 | MCP | 选子机不连真 SSH | UI 状态 idle | ✅ | 沉淀 e2e/pages/terminal.spec.mjs | --- ## 5. 文件 Files `#/files` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-FILE-001 | UT | ls 解析 | unix ls 输出 | ✅ | test_unix_ls.py | | UT-FILE-002 | UT | browse etag | 304 条件 | ✅ | test_files_browse_etag.py | | UT-FILE-003 | UT | 提权路径策略 | sudo 边界 | ✅ | test_files_elevation.py | | IT-FILE-001 | IT | GET browse | 列表 JSON | ✅ | tests/integration/test_files_browse.py | | CH-FILE-001 | CH | 浏览→上传 staging→确认 | staging 清理 | ✅ | tests/chain/test_file_staging_flow.py | | E2E-FILE-001 | E2E | 文件页表格 | 路径栏可见 | ✅ | e2e/pages/files.spec.mjs | | MCP-FILE-001 | MCP | 目录树展开一级 | 无 500 toast | ✅ | 沉淀 e2e/pages/files.spec.mjs | --- ## 6. 推送 Push `#/push` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-PUSH-001 | UT | batch_id 生成唯一 | UUID 格式 | ✅ | test_sync_batch_id.py | | UT-PUSH-002 | UT | rsync 权限位 | 映射正确 | ✅ | test_rsync_push_permissions.py | | UT-PUSH-003 | UT | upload form 字段 | schema | ✅ | test_sync_upload_form.py | | IT-PUSH-001 | IT | POST sync 立即 accepted | `accepted:true` 非阻塞 | ✅ | tests/integration/test_push_sync.py | | IT-PUSH-002 | IT | GET /api/sync/logs | 分页 | ✅ | tests/integration/test_servers_dashboard.py | | CH-PUSH-001 | CH | accepted→WS progress→log 行 | batch 状态终态 | ✅ | tests/chain/test_push_async_flow.py | | E2E-PUSH-001 | E2E | 推送页控件 | 目标路径+提交 | ✅ | full-acceptance #6 | | E2E-PUSH-002 | E2E | 提交后短暂 loading 非一直转圈 | submitting 结束 | ✅ | e2e/pages/push.spec.mjs | | MCP-PUSH-001 | MCP | 选测试子机 dry-run 提交 | toast + 进度表 | ✅ | e2e/pages/push.spec.mjs(mock 子机+API) | --- ## 7. 脚本 Scripts `#/scripts` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-SCR-001 | UT | dispatch 路由 | server_ids 校验 | ✅ | test_script_dispatch.py | | IT-SCR-001 | IT | CRUD /api/scripts | 201/200/404 | ✅ | tests/integration/test_scripts_executions.py | | E2E-SCR-001 | E2E | 脚本列表+新建按钮 | 无 JS 错误 | ✅ | e2e/pages/scripts.spec.mjs | | MCP-SCR-001 | MCP | Monaco 编辑器加载 | 无 JS 错误 | ✅ | 沉淀 e2e/pages/scripts.spec.mjs | --- ## 8. 执行看板 Executions `#/executions` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-EXEC-001 | UT | 进度分组 | 按 server 聚合 | ✅ | test_exec_detail_grouping.py | | UT-EXEC-002 | UT | MySQL 持久化字段 | 状态机 | ✅ | test_script_execution_mysql_persist.py | | IT-EXEC-001 | IT | GET /api/script-executions | 分页+filter | ✅ | tests/integration/test_scripts_executions.py | | CH-EXEC-001 | CH | 创建执行→轮询→完成 | status=completed | ✅ | tests/chain/test_script_exec_flow.py | | E2E-EXEC-001 | E2E | 看板页加载 | 表+筛选 | ✅ | e2e/pages/executions.spec.mjs | | E2E-EXEC-002 | E2E | 展开执行详情行 | stdout/面板 | ✅ | e2e/pages/executions-detail.spec.mjs | | MCP-EXEC-001 | MCP | 展开执行详情行 | stdout 片段 | ✅ | 沉淀 e2e/pages/executions-detail.spec.mjs | --- ## 9. 凭据 Credentials `#/credentials` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-CRED-001 | UT | poller 周期 | mock clock | ✅ | test_credential_poller.py | | IT-CRED-001 | IT | 列表不返回明文 secret | 脱敏 | ✅ | tests/integration/test_presets.py | | E2E-CRED-001 | E2E | 凭据对话框表单校验 | 必填红框 | ✅ | e2e/pages/credentials.spec.mjs | | MCP-CRED-001 | MCP | 新建凭据表单校验 | 必填红框 | ✅ | 沉淀 e2e/pages/credentials.spec.mjs | --- ## 10. 调度 Schedules `#/schedules` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-SCH-001 | UT | next_run 计算 | cron/周期 | ✅ | test_schedule_next_run.py | | UT-SCH-002 | UT | cycle 标签 | 仅开始周期 | ✅ | test_schedule_cycle.py | | UT-SCH-003 | UT | runner once | 不重复触发 | ✅ | test_schedule_runner_once.py | | IT-SCH-001 | IT | CRUD schedules | 审计 | ✅ | tests/integration/test_schedules.py | | E2E-SCH-001 | E2E | 新建调度对话框 | ✅ | full-acceptance #9 | | E2E-SCH-002 | E2E | 新建调度周期中文 | 开始执行周期 | ✅ | e2e/pages/schedules-cycle.spec.mjs | | MCP-SCH-001 | MCP | 周期字段中文标签 | 与后端一致 | ✅ | 沉淀 E2E-SCH-002 | --- ## 11. 重试 Retries `#/retries` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-RET-001 | UT | runner outcome | 成功/失败计数 | ✅ | test_retry_runner_outcome.py | | IT-RET-001 | IT | GET /api/retries | 队列列表 | ✅ | tests/integration/test_retries_commands.py | | E2E-RET-001 | E2E | 重试页无行级重试按钮(空表) | 表+筛选 | ✅ | e2e/pages/retries.spec.mjs | | MCP-RET-001 | MCP | 手动重试按钮 disabled 态 | 无选中时 | ✅ | 沉淀 e2e/pages/retries.spec.mjs | --- ## 12. 命令日志 Commands `#/commands` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | IT-CMD-001 | IT | 命令/推送/会话三视图 API | 200 | ✅ | tests/integration/test_retries_commands.py | | E2E-CMD-001 | E2E | 切换三视图 | ✅ | full-acceptance #11 | | E2E-CMD-002 | E2E | 推送日志时间格式 | 无裸 ISO UTC | ✅ | e2e/pages/commands-time.spec.mjs | | MCP-CMD-001 | MCP | 推送日志表北京时间 | 列格式 | ✅ | 沉淀 E2E-CMD-002 | --- ## 13. 告警 Alerts `#/alerts` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-ALT-001 | UT | Agent 恢复去重 | 同 metric 1 条 | ✅ | test_agent_recovery_dedup.py | | UT-ALT-002 | UT | Telegram 时间格式 | 北京时间 | ✅ | test_telegram_time_format.py | | IT-ALT-001 | IT | GET /api/alerts + WS | 推送事件 | ✅ | tests/integration/test_alerts_audit.py | | CH-ALT-001 | CH | 心跳告警→恢复→TG 一条 | Redis+mock TG | ✅ | tests/chain/test_alert_recovery_flow.py | | E2E-ALT-001 | E2E | 告警筛选 UI | ✅ | full-acceptance #12 | | E2E-ALT-002 | E2E | 告警表时间格式 | 无裸 ISO UTC | ✅ | e2e/pages/alerts-time.spec.mjs | | MCP-ALT-001 | MCP | 告警表时间列 | 无 UTC 裸字符串 | ✅ | 沉淀 E2E-ALT-002 | --- ## 14. 审计 Audit `#/audit` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | IT-AUD-001 | IT | GET /api/audit 分页 | CUD 记录 | ✅ | tests/integration/test_alerts_audit.py | | E2E-AUD-001 | E2E | 审计页+分页 | ✅ | full-acceptance #13 | | E2E-AUD-002 | E2E | 审计表时间格式 | 无裸 ISO UTC | ✅ | e2e/pages/audit-time.spec.mjs | | MCP-AUD-001 | MCP | 时间列北京时间 | 与设置无关 | ✅ | 沉淀 E2E-AUD-002 | --- ## 15. 设置 Settings `#/settings` | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-SET-001 | UT | Telegram 设置校验 | token 格式 | ✅ | test_settings_telegram.py | | IT-SET-001 | IT | PATCH settings 禁止覆盖密钥 | 403 | ✅ | tests/integration/test_settings_security.py | | E2E-SET-001 | E2E | 各 section 可见 | ✅ | e2e/pages/settings.spec.mjs + full-acceptance #14 | | MCP-SET-001 | MCP | 保存设置 toast | 成功中文 | ✅ | e2e/pages/settings.spec.mjs E2E-SET-002 | --- ## 16. Agent 子机(无 SPA 页) | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-AGT-001 | UT | heartbeat TTL | Redis 过期 | ✅ | test_agent_heartbeat_ttl.py | | UT-AGT-002 | UT | per-server API key | 隔离 | ✅ | test_agent_per_server_key.py | | UT-AGT-003 | UT | version 上报 | 语义化版本 | ✅ | test_agent_version.py | | IT-AGT-001 | IT | POST /api/agent/heartbeat | 200 | ✅ | tests/integration/test_agent_heartbeat.py | | CH-AGT-001 | CH | 心跳→Redis→仪表盘计数 | 一致 | ✅ | tests/chain/test_agent_dashboard_flow.py | --- ## 17. 批量 / 后台任务 | ID | 层 | 用例 | 期望 | 状态 | 实现 | |----|-----|------|------|------|------| | UT-BAT-001 | UT | batch job 持久化 | ✅ | test_server_batch_job_persist.py | | UT-BAT-002 | UT | reconcile 状态机 | ✅ | test_server_batch_reconcile.py | | UT-SYNC-001 | UT | sync_log purge | ✅ | test_sync_log_purge.py | | CH-BAT-001 | CH | 批量操作→job 表→完成 | ✅ | tests/chain/test_batch_job_flow.py | --- ## 覆盖率汇总(2026-06-08 估算) | 层 | 已有 | 待写 | 合计 | |----|------|------|------| | UT | ~45 | ~15 | ~60 | | IT | ~26 | ~11 | ~37 | | CH | ~9 | ~5 | ~14 | | E2E | ~35 | ~2 | ~37 | | MCP | ~18(沉淀 E2E) | ~3(manual/安装) | ~21 | | **合计** | **~133** | **~36** | **~169** | --- ## PR 检查清单 - [ ] 改动域在表中至少更新 1 行状态 - [ ] 新 API 必有 `IT-*`;新纯函数必有 `UT-*` - [ ] UI 行为变更必有 `E2E-*` 或 `MCP-*` 计划 - [ ] 破坏性 E2E 仅对测试子机