# 用户迁移 E2E ## 范围 当前已落地两层 E2E: - API 黑盒 E2E:真实双节点、真实 HTTP、真实 SQLite、真实 `region_sync` - UI Smoke E2E:Playwright 驱动真实浏览器访问 `/console/user` 的迁移中心 对应代码位置: - `test/e2e/user_migration_test.go` - `test/e2e/helpers/` - `test/e2e/cmd/user_migration_ui_server/main.go` - `web/playwright.config.ts` - `web/e2e/` - `scripts/run-user-migration-e2e.ps1` ## 已覆盖用例 ### API E2E - `TestUserMigrationE2E_FullFlow_GrayScenarios` - `TestUserMigrationE2E_IdempotentRetry` - `TestUserMigrationE2E_ExecutionTimeDriftFails` - `TestUserMigrationE2E_RescanPreservesHumanDecision` - `TestUserMigrationE2E_ScanPagination` - `TestUserMigrationE2E_RootPermission` - `TestUserMigrationE2E_ResolveInvalidPayload` - `TestUserMigrationE2E_ScanConflict_WhenAlreadyScanning` - `TestUserMigrationE2E_ExecuteConflict_WhenAlreadyRunning` - `TestUserMigrationE2E_VerifyQuotaMismatchDetected` - `TestUserMigrationE2E_SkipNeverConvertsRemote` ### UI Smoke E2E - 非 root 管理员看不到“用户迁移”页签 - root 可以进入迁移中心并创建批次 - 扫描状态能通过页面轮询从 `scanning` 进入 `scanned` - 冲突项可以在页面中执行人工决策 - 执行前会出现冻结窗口确认 - 执行完成后可以触发 verify 并看到结果表 - 页面刷新后,批次列表和详情仍可重新加载 ## 固定约定 - CN 端口:`3100` - OV 端口:`3101` - CN session:`cn_session` - OV session:`ov_session` - Sync API Key:`e2e-sync-key` - API E2E 运行目录:`test-artifacts/user-migration-e2e/runs//` - UI E2E 运行目录:`test-artifacts/user-migration-e2e/runs/playwright-ui/` ## 运行方式 只跑 API E2E: ```powershell go test -v ./test/e2e -count=1 ``` 只跑 UI E2E: ```powershell cd web bunx playwright test ``` 通过统一脚本执行: ```powershell ./scripts/run-user-migration-e2e.ps1 -ApiOnly ./scripts/run-user-migration-e2e.ps1 -UiOnly ./scripts/run-user-migration-e2e.ps1 -All ``` ## UI E2E 依赖 Playwright 当前使用系统 Edge: - `web/playwright.config.ts` 中固定 `channel: 'msedge'` - 不需要额外下载 Chromium 浏览器 首次在新机器上跑 UI E2E,需要安装 Playwright 的 `ffmpeg`,否则失败视频无法生成: ```powershell cd web bunx playwright install ffmpeg ``` ## UI E2E 启动流程 `bunx playwright test` 会自动执行以下流程: 1. `global-setup.ts` 先清理 `3100/3101` 残留监听进程 2. 构建前端 `web/dist` 3. 构建 `test/e2e/cmd/user_migration_ui_server` 4. 启动 UI helper,helper 内部调用 `helpers.PrepareEnvironment(...)` 5. helper 完成双节点准备后写入 `test-artifacts/user-migration-e2e/playwright/server-ready.json` 6. `global-setup.ts` 读取 ready 标记,再登录 root,并生成两套 storage state - `root-storage.json` - `user-storage.json`(当前实际保存的是“非 root 管理员”会话,因为 `/console/user` 受 `AdminRoute` 保护) 7. 测试结束后由 `global-teardown.ts` 回收 UI helper 进程树 ## 产物位置 ### API 产物 每个 API 用例的产物都在: ```text test-artifacts/user-migration-e2e/runs// ``` 常见文件: - `cn.db` - `ov.db` - `cn.log` - `ov.log` - `system-logs/cn/*` - `system-logs/ov/*` ### UI 产物 Playwright 相关产物在: ```text test-artifacts/user-migration-e2e/playwright/ ``` 常见文件: - `metadata.json` - `server-ready.json` - `ui-server.log` - `auth/root-storage.json` - `auth/user-storage.json` - `html-report/` - `test-output//trace.zip` - `test-output//video.webm` - `test-output//test-failed-1.png` ## 排查建议 如果 API E2E 失败,优先看: - `test-artifacts/user-migration-e2e/runs//cn.log` - `test-artifacts/user-migration-e2e/runs//ov.log` - `cn.db` 中的 `user_migration_batches` - `cn.db` 中的 `user_migration_items` - `ov.db` 中的 `users` 如果 UI E2E 失败,优先看: - `test-artifacts/user-migration-e2e/playwright/ui-server.log` - `test-artifacts/user-migration-e2e/playwright/test-output//error-context.md` - `trace.zip` - 失败截图和视频 ## 如何新增迁移场景 新增 API 迁移场景时,优先按下面顺序扩展: 1. 在 `test/e2e/helpers/seed.go` 里补固定 seed 或新的冲突样本 2. 在 `test/e2e/helpers/assert.go` 里补通用断言或轮询逻辑 3. 在 `test/e2e/user_migration_test.go` 里新增独立测试,尽量复用 `prepareGrayScenarioBatch` 一类的局部 helper 4. 如果是跨节点准备逻辑变化,优先改 `test/e2e/helpers/cluster.go` 或 `options.go` 新增 UI smoke 场景时,优先按下面顺序扩展: 1. 先判断是否需要新的稳定选择器;需要时只在迁移中心组件上补 `data-testid` 2. 在 `web/e2e/user-migration.spec.ts` 中新增页面行为断言,不做 DB 最终值断言 3. 如果需要新的登录态或前置环境,改 `web/e2e/global-setup.ts` 4. 若新增场景改变运行产物或依赖,再同步更新本文档