Commit 8943945a7f35847c101e1642833132039865c69d
1 parent
96e88d38
docs(verify:FE-04:r1): 证据验证
Showing
1 changed file
with
105 additions
and
0 deletions
docs/superpowers/reviews/2026-06-01-FE-04-verify-r1.md
0 → 100644
| 1 | +# FE-04 用户信息单据 — 证据验证报告(round=1,第 1 轮 fix 后复验) | |
| 2 | + | |
| 3 | +> 阶段:前端(frontend)。验证对象:`FE-04`(关联 `REQ-USR-001` 增加用户 + `REQ-USR-002` 修改用户,scope=usr)。 | |
| 4 | +> 上游 spec:`docs/superpowers/specs/2026-06-01-FE-04.md`(产物文件名日期前缀 `2026-06-01` 取自 spec 文件名首段)。 | |
| 5 | +> 上游 TDD 摘要:第 1 轮 fix 后复验,上轮 review(`2026-06-01-FE-04.md`)裁决 request-changes,must-fix 1 项(B1:edit 态预填把用户主键当「用户号」查询,正常导航流必然取不到记录 → 40401)。 | |
| 6 | +> 验证时间:2026-06-02。本报告由 fe-feature-verify 渲染;主会话不自由编写测试,仅按测试命令的结构化结果落盘。 | |
| 7 | +> 测试以分离进程执行(非主会话交互式跑),仅运行 `frontend/` 下套件。 | |
| 8 | + | |
| 9 | +--- | |
| 10 | + | |
| 11 | +## 一、验证结论 | |
| 12 | + | |
| 13 | +**全部通过(PASS)**。单测与 E2E 两个门禁目标 `exit_code` 均为 0,`failed=0`,可进入 review。 | |
| 14 | + | |
| 15 | +| 目标 | 命令 | exit_code | passed | failed | 结论 | | |
| 16 | +|---|---|---|---|---|---| | |
| 17 | +| 单元测试(jsdom / Vitest) | `npx vitest run <FE-04 8 文件>` | 0 | 55(8 文件) | 0 | PASS | | |
| 18 | +| 端到端(Playwright) | `npx playwright test tests/e2e/userdetail.spec.ts` | 0 | 5 | 0 | PASS | | |
| 19 | + | |
| 20 | +> 命令来源:`docs/04-技术规范.md § 零 命令清单`(前端 unit=`npm run test:unit`=`vitest run`、e2e=`npm run test:e2e`=`playwright test`;`config-vars.yaml` 未覆盖测试命令,故按 docs/04 锁定值,未触发 flow 默认兜底 `pnpm test:ci`/`pnpm e2e:ci`)。本验证按 flow 取 FE-04 计划中 `测试先行类型=jsdom` 的 8 个单测文件拼 vitest 过滤模式、取 `测试先行类型=e2e` 的 `userdetail.spec.ts` 拼 Playwright 过滤模式,scope 收敛到 FE-04 新增/改动的测试。 | |
| 21 | +> 上轮 must-fix(B1)针对 edit 预填数据流,本轮 fix 改动落在 `frontend/src/pages/usr/UserDetail/` 与对应单测(`useUserDetail.test.tsx`、`UserDetailPage.test.tsx`),复验后涉及 edit 预填的用例(单测 `useUserDetail`/`UserDetailPage` 的 edit 分支、E2E `edit user prefill then save`)全部通过。 | |
| 22 | + | |
| 23 | +--- | |
| 24 | + | |
| 25 | +## 二、单元测试(jsdom / Vitest) | |
| 26 | + | |
| 27 | +- 命令:`cd frontend && npx vitest run tests/unit/usrApi.userdetail.test.ts tests/unit/userDetailMappers.test.ts tests/unit/useUserDetail.test.tsx tests/unit/UserBasicForm.test.tsx tests/unit/PermissionGroupList.test.tsx tests/unit/PermissionTabs.test.tsx tests/unit/UserDetailToolbar.test.tsx tests/unit/UserDetailPage.test.tsx` | |
| 28 | +- exit_code:`0` | |
| 29 | +- 结果:`Test Files 8 passed (8)` / `Tests 55 passed (55)` | |
| 30 | +- failed_list:(空) | |
| 31 | +- FE-04 的 8 个单测文件逐个通过: | |
| 32 | + - `tests/unit/usrApi.userdetail.test.ts`(6 用例:createUser/updateUser/getUserDetail/listEmployees/listPermissions 端点透传与 Result 拆包) | |
| 33 | + - `tests/unit/userDetailMappers.test.ts`(4 用例:EmployeeOption/PermissionItem/UserVO→表单值映射) | |
| 34 | + - `tests/unit/useUserDetail.test.tsx`(10 用例:状态机 initialLoading/editing/submitting/submitError/submitSuccess/loadError + create/edit 分支,含 edit 预填) | |
| 35 | + - `tests/unit/UserBasicForm.test.tsx`(9 用例:BR1-BR8 字段渲染/只读/默认值/必填校验/员工联动) | |
| 36 | + - `tests/unit/PermissionGroupList.test.tsx`(8 用例:BR10/BR11 权限项渲染/全选 indeterminate/勾选集合/edit 回勾) | |
| 37 | + - `tests/unit/PermissionTabs.test.tsx`(3 用例:权限组 active + 5 个占位页签 D9) | |
| 38 | + - `tests/unit/UserDetailToolbar.test.tsx`(5 用例:保存/取消/新增 + 占位按钮 D8) | |
| 39 | + - `tests/unit/UserDetailPage.test.tsx`(10 用例:create 默认值/edit 预填/提交成功回流/用户名冲突就近高亮/dirty 取消二次确认/loadError 重试) | |
| 40 | + | |
| 41 | +### stdout 摘录(≤30 行) | |
| 42 | + | |
| 43 | +``` | |
| 44 | + ✓ tests/unit/userDetailMappers.test.ts (4 tests) 3ms | |
| 45 | + ✓ tests/unit/usrApi.userdetail.test.ts (6 tests) 3ms | |
| 46 | + ✓ tests/unit/PermissionTabs.test.tsx (3 tests) 137ms | |
| 47 | + ✓ tests/unit/PermissionGroupList.test.tsx (8 tests) 154ms | |
| 48 | + ✓ tests/unit/UserDetailToolbar.test.tsx (5 tests) 163ms | |
| 49 | + ✓ tests/unit/useUserDetail.test.tsx (10 tests) 603ms | |
| 50 | + ✓ tests/unit/UserBasicForm.test.tsx (9 tests) 751ms | |
| 51 | + ✓ tests/unit/UserDetailPage.test.tsx (10 tests) 1651ms | |
| 52 | + | |
| 53 | + Test Files 8 passed (8) | |
| 54 | + Tests 55 passed (55) | |
| 55 | + Duration 3.26s | |
| 56 | +``` | |
| 57 | + | |
| 58 | +> 说明:日志中 `window.getComputedStyle(elt, pseudoElt) Not implemented`(来自 rc-util measureScrollbarSize / AntD Modal 滚动锁)、`act(...)` 包裹建议(rc-field-form 异步校验态)、React Router v7 future flag 等均为 jsdom/依赖侧非致命 stderr 警告,不影响断言,全部用例仍判定通过(`exit_code=0`,`55 passed`)。 | |
| 59 | + | |
| 60 | +--- | |
| 61 | + | |
| 62 | +## 三、端到端测试(Playwright) | |
| 63 | + | |
| 64 | +- 命令:`cd frontend && npx playwright test tests/e2e/userdetail.spec.ts` | |
| 65 | +- exit_code:`0` | |
| 66 | +- 结果:`5 passed (5.4s)` | |
| 67 | +- failed_list:(空) | |
| 68 | +- FE-04 `tests/e2e/userdetail.spec.ts` 5 用例全过: | |
| 69 | + - `create user and return to list`(新增提交成功回流列表 BR12/BR16) | |
| 70 | + - `edit user prefill then save`(edit 预填原值 + 保存 BR17/BR11;对应上轮 B1 数据流修复点) | |
| 71 | + - `username conflict shows inline error`(40901 用户名冲突就近报错) | |
| 72 | + - `placeholder tabs/buttons are inert`(占位页签/按钮惰性 D8/D9) | |
| 73 | + - `load error shows retry`(loadError 取数失败重试入口) | |
| 74 | + | |
| 75 | +### stdout 摘录(≤30 行) | |
| 76 | + | |
| 77 | +``` | |
| 78 | +Running 5 tests using 5 workers | |
| 79 | + ✓ 1 [chromium] › tests/e2e/userdetail.spec.ts:170:3 › 用户单据关键旅程 › placeholder tabs/buttons are inert (904ms) | |
| 80 | + ✓ 5 [chromium] › tests/e2e/userdetail.spec.ts:126:3 › 用户单据关键旅程 › username conflict shows inline error (1.2s) | |
| 81 | + ✓ 3 [chromium] › tests/e2e/userdetail.spec.ts:97:3 › 用户单据关键旅程 › edit user prefill then save (1.3s) | |
| 82 | + ✓ 4 [chromium] › tests/e2e/userdetail.spec.ts:69:3 › 用户单据关键旅程 › create user and return to list (1.3s) | |
| 83 | + ✓ 2 [chromium] › tests/e2e/userdetail.spec.ts:146:3 › 用户单据关键旅程 › load error shows retry (4.3s) | |
| 84 | + | |
| 85 | + 5 passed (5.4s) | |
| 86 | +``` | |
| 87 | + | |
| 88 | +> 说明:WebServer 日志中 `[vite] http proxy error ... ECONNREFUSED /api/usr/users` 为预期噪声——E2E 在路由层 mock API 响应,开发后端(`config-vars.yaml backend.http_port=5172`)未启动,Vite proxy 透传请求被拒;用例不依赖真实后端,5 个用例全部判定通过(`exit_code=0`,`5 passed`),与 FE-01/FE-02/FE-03 验证及本 FE round=0 验证同型非致命基建告警。 | |
| 89 | + | |
| 90 | +--- | |
| 91 | + | |
| 92 | +## 四、作用域校验 | |
| 93 | + | |
| 94 | +- 验证仅运行 `frontend/` 下的测试套件(`frontend/tests/unit/*`(FE-04 8 文件)+ `frontend/tests/e2e/userdetail.spec.ts`);未触碰 `backend/` / `sql/` / `scripts/`,作用域校验通过。 | |
| 95 | +- 本报告落盘于 `docs/superpowers/reviews/`(与 review 报告同目录),round=1 → 文件名后缀 `-verify-r1.md`,与 round=0 的 `-verify.md` 各自独立、不覆盖前轮,符合命名约定。 | |
| 96 | + | |
| 97 | +--- | |
| 98 | + | |
| 99 | +## 五、自主决策记录(decisions) | |
| 100 | + | |
| 101 | +| # | 问题 | 选择 | 依据 | 置信度 | | |
| 102 | +|---|---|---|---|---| | |
| 103 | +| V1 | 测试命令默认值取 `pnpm test:ci`/`pnpm e2e:ci` 还是 docs/04 锁定值 | 取 `docs/04-技术规范.md § 零` 锁定的前端命令(unit=`npm run test:unit`=`vitest run`、e2e=`npm run test:e2e`=`playwright test`,`frontend/package.json` scripts 实测存在;`config-vars.yaml` 未覆盖测试命令) | flow 明确「命令从 docs/04 § 零取,缺失才用默认」;本仓 docs/04 § 零已锁定前端命令,默认值仅缺失兜底,此处不缺失 | high | | |
| 104 | +| V2 | 单测/E2E 跑全量套件还是 FE-04 过滤模式 | 按 flow 取 FE-04 计划中 `测试先行类型=jsdom` 的 8 个单测文件拼 vitest 过滤、取 `=e2e` 的 `userdetail.spec.ts` 拼 Playwright 过滤,scope 收敛到本 FE | flow 明确「从 plan 取 `测试先行类型=jsdom` 的 test_file 拼 vitest 过滤、`=e2e` 的拼 Playwright spec 过滤」 | high | | |
| 105 | +| V3 | E2E 运行中 `ECONNREFUSED /api/usr/users` proxy 报错是否判失败 | 判通过(非致命基建噪声) | E2E 在路由层 mock 响应,不依赖真实后端;Playwright 汇总 `5 passed` 且进程 `exit_code=0`,proxy 噪声来自 Vite dev server 透传未启动的后端端口,与用例断言无关,与历次验证同型处理 | high | | ... | ... |