2026-06-01-FE-04-verify-r1.md 8.17 KB

FE-04 用户信息单据 — 证据验证报告(round=1,第 1 轮 fix 后复验)

阶段:前端(frontend)。验证对象:FE-04(关联 REQ-USR-001 增加用户 + REQ-USR-002 修改用户,scope=usr)。 上游 spec:docs/superpowers/specs/2026-06-01-FE-04.md(产物文件名日期前缀 2026-06-01 取自 spec 文件名首段)。 上游 TDD 摘要:第 1 轮 fix 后复验,上轮 review(2026-06-01-FE-04.md)裁决 request-changes,must-fix 1 项(B1:edit 态预填把用户主键当「用户号」查询,正常导航流必然取不到记录 → 40401)。 验证时间:2026-06-02。本报告由 fe-feature-verify 渲染;主会话不自由编写测试,仅按测试命令的结构化结果落盘。 测试以分离进程执行(非主会话交互式跑),仅运行 frontend/ 下套件。


一、验证结论

全部通过(PASS)。单测与 E2E 两个门禁目标 exit_code 均为 0,failed=0,可进入 review。

目标 命令 exit_code passed failed 结论
单元测试(jsdom / Vitest) npx vitest run <FE-04 8 文件> 0 55(8 文件) 0 PASS
端到端(Playwright) npx playwright test tests/e2e/userdetail.spec.ts 0 5 0 PASS

命令来源:docs/04-技术规范.md § 零 命令清单(前端 unit=npm run test:unit=vitest run、e2e=npm run test:e2e=playwright testconfig-vars.yaml 未覆盖测试命令,故按 docs/04 锁定值,未触发 flow 默认兜底 pnpm test:ci/pnpm e2e:ci)。本验证按 flow 取 FE-04 计划中 测试先行类型=jsdom 的 8 个单测文件拼 vitest 过滤模式、取 测试先行类型=e2euserdetail.spec.ts 拼 Playwright 过滤模式,scope 收敛到 FE-04 新增/改动的测试。 上轮 must-fix(B1)针对 edit 预填数据流,本轮 fix 改动落在 frontend/src/pages/usr/UserDetail/ 与对应单测(useUserDetail.test.tsxUserDetailPage.test.tsx),复验后涉及 edit 预填的用例(单测 useUserDetail/UserDetailPage 的 edit 分支、E2E edit user prefill then save)全部通过。


二、单元测试(jsdom / Vitest)

  • 命令: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
  • exit_code:0
  • 结果:Test Files 8 passed (8) / Tests 55 passed (55)
  • failed_list:(空)
  • FE-04 的 8 个单测文件逐个通过:
    • tests/unit/usrApi.userdetail.test.ts(6 用例:createUser/updateUser/getUserDetail/listEmployees/listPermissions 端点透传与 Result 拆包)
    • tests/unit/userDetailMappers.test.ts(4 用例:EmployeeOption/PermissionItem/UserVO→表单值映射)
    • tests/unit/useUserDetail.test.tsx(10 用例:状态机 initialLoading/editing/submitting/submitError/submitSuccess/loadError + create/edit 分支,含 edit 预填)
    • tests/unit/UserBasicForm.test.tsx(9 用例:BR1-BR8 字段渲染/只读/默认值/必填校验/员工联动)
    • tests/unit/PermissionGroupList.test.tsx(8 用例:BR10/BR11 权限项渲染/全选 indeterminate/勾选集合/edit 回勾)
    • tests/unit/PermissionTabs.test.tsx(3 用例:权限组 active + 5 个占位页签 D9)
    • tests/unit/UserDetailToolbar.test.tsx(5 用例:保存/取消/新增 + 占位按钮 D8)
    • tests/unit/UserDetailPage.test.tsx(10 用例:create 默认值/edit 预填/提交成功回流/用户名冲突就近高亮/dirty 取消二次确认/loadError 重试)

stdout 摘录(≤30 行)

 ✓ tests/unit/userDetailMappers.test.ts (4 tests) 3ms
 ✓ tests/unit/usrApi.userdetail.test.ts (6 tests) 3ms
 ✓ tests/unit/PermissionTabs.test.tsx (3 tests) 137ms
 ✓ tests/unit/PermissionGroupList.test.tsx (8 tests) 154ms
 ✓ tests/unit/UserDetailToolbar.test.tsx (5 tests) 163ms
 ✓ tests/unit/useUserDetail.test.tsx (10 tests) 603ms
 ✓ tests/unit/UserBasicForm.test.tsx (9 tests) 751ms
 ✓ tests/unit/UserDetailPage.test.tsx (10 tests) 1651ms

 Test Files  8 passed (8)
      Tests  55 passed (55)
   Duration  3.26s

说明:日志中 window.getComputedStyle(elt, pseudoElt) Not implemented(来自 rc-util measureScrollbarSize / AntD Modal 滚动锁)、act(...) 包裹建议(rc-field-form 异步校验态)、React Router v7 future flag 等均为 jsdom/依赖侧非致命 stderr 警告,不影响断言,全部用例仍判定通过(exit_code=055 passed)。


三、端到端测试(Playwright)

  • 命令:cd frontend && npx playwright test tests/e2e/userdetail.spec.ts
  • exit_code:0
  • 结果:5 passed (5.4s)
  • failed_list:(空)
  • FE-04 tests/e2e/userdetail.spec.ts 5 用例全过:
    • create user and return to list(新增提交成功回流列表 BR12/BR16)
    • edit user prefill then save(edit 预填原值 + 保存 BR17/BR11;对应上轮 B1 数据流修复点)
    • username conflict shows inline error(40901 用户名冲突就近报错)
    • placeholder tabs/buttons are inert(占位页签/按钮惰性 D8/D9)
    • load error shows retry(loadError 取数失败重试入口)

stdout 摘录(≤30 行)

Running 5 tests using 5 workers
  ✓  1 [chromium] › tests/e2e/userdetail.spec.ts:170:3 › 用户单据关键旅程 › placeholder tabs/buttons are inert (904ms)
  ✓  5 [chromium] › tests/e2e/userdetail.spec.ts:126:3 › 用户单据关键旅程 › username conflict shows inline error (1.2s)
  ✓  3 [chromium] › tests/e2e/userdetail.spec.ts:97:3 › 用户单据关键旅程 › edit user prefill then save (1.3s)
  ✓  4 [chromium] › tests/e2e/userdetail.spec.ts:69:3 › 用户单据关键旅程 › create user and return to list (1.3s)
  ✓  2 [chromium] › tests/e2e/userdetail.spec.ts:146:3 › 用户单据关键旅程 › load error shows retry (4.3s)

  5 passed (5.4s)

说明:WebServer 日志中 [vite] http proxy error ... ECONNREFUSED /api/usr/users 为预期噪声——E2E 在路由层 mock API 响应,开发后端(config-vars.yaml backend.http_port=5172)未启动,Vite proxy 透传请求被拒;用例不依赖真实后端,5 个用例全部判定通过(exit_code=05 passed),与 FE-01/FE-02/FE-03 验证及本 FE round=0 验证同型非致命基建告警。


四、作用域校验

  • 验证仅运行 frontend/ 下的测试套件(frontend/tests/unit/*(FE-04 8 文件)+ frontend/tests/e2e/userdetail.spec.ts);未触碰 backend/ / sql/ / scripts/,作用域校验通过。
  • 本报告落盘于 docs/superpowers/reviews/(与 review 报告同目录),round=1 → 文件名后缀 -verify-r1.md,与 round=0 的 -verify.md 各自独立、不覆盖前轮,符合命名约定。

五、自主决策记录(decisions)

# 问题 选择 依据 置信度
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 testfrontend/package.json scripts 实测存在;config-vars.yaml 未覆盖测试命令) flow 明确「命令从 docs/04 § 零取,缺失才用默认」;本仓 docs/04 § 零已锁定前端命令,默认值仅缺失兜底,此处不缺失 high
V2 单测/E2E 跑全量套件还是 FE-04 过滤模式 按 flow 取 FE-04 计划中 测试先行类型=jsdom 的 8 个单测文件拼 vitest 过滤、取 =e2euserdetail.spec.ts 拼 Playwright 过滤,scope 收敛到本 FE flow 明确「从 plan 取 测试先行类型=jsdom 的 test_file 拼 vitest 过滤、=e2e 的拼 Playwright spec 过滤」 high
V3 E2E 运行中 ECONNREFUSED /api/usr/users proxy 报错是否判失败 判通过(非致命基建噪声) E2E 在路由层 mock 响应,不依赖真实后端;Playwright 汇总 5 passed 且进程 exit_code=0,proxy 噪声来自 Vite dev server 透传未启动的后端端口,与用例断言无关,与历次验证同型处理 high