25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 

626 satır
20 KiB

  1. {
  2. "title": "接口错误 Message 回归报告",
  3. "status": "PASS_WITH_LEGACY_BLOCKERS",
  4. "generatedAt": "2026-09-05T17:36:20.720Z",
  5. "startedAt": "2026-09-05T17:32:19.650Z",
  6. "durationMs": 84090.698,
  7. "passed": 9,
  8. "total": 9,
  9. "screenshotCount": 17,
  10. "requestCount": 58,
  11. "pageErrorCount": 0,
  12. "validation": {
  13. "commands": [
  14. {
  15. "command": "pnpm run build",
  16. "scope": "unreal_tran_web",
  17. "status": "PASS",
  18. "details": "最终 vue-tsc、Vite 与 legacy iframe public/dist 哈希校验通过;仍有既有 chunk 体积提示。",
  19. "log": "validation/build.log"
  20. },
  21. {
  22. "command": "node --test tools/scene-cover-api.test.mjs tools/guide-error-message.test.mjs",
  23. "scope": "ute2e",
  24. "status": "PASS",
  25. "details": "20/20 通过,包含保存失败只提示一次、阻断发布与离开,以及指导书/场景错误提示回归。",
  26. "log": "validation/runtime-tests.log"
  27. },
  28. {
  29. "command": "pnpm exec tsc --noEmit --target ES2022 --module ESNext --moduleResolution Bundler --strict --types 'node,@playwright/test' tests/api-error-messages.spec.ts api-error-messages.config.ts",
  30. "scope": "ute2e",
  31. "status": "PASS",
  32. "details": "本轮新增浏览器测试与配置类型检查通过。"
  33. },
  34. {
  35. "command": "git diff --check",
  36. "scope": "unreal_tran_web、ute2e",
  37. "status": "PASS",
  38. "details": "主任务检查通过;报告生成后再次核验本轮文件。"
  39. }
  40. ]
  41. },
  42. "authentication": {
  43. "title": "认证提示附加回归",
  44. "status": "PASS_WITH_LEGACY_BLOCKERS",
  45. "result": "共实际运行 5 项:3 项通过;2 项旧强制改密用例受当前路由契约阻断,未验证到原断言。主报告 9 项结果单独统计。",
  46. "screenshotPathBase": "api-error-messages-20260906",
  47. "environment": "Edge headless,http://127.0.0.1:6180,认证 API 全部由 Playwright 拦截模拟;trace/video 关闭。",
  48. "counts": {
  49. "executed": 5,
  50. "passed": 3,
  51. "legacyBlocked": 2,
  52. "skipped": 0
  53. },
  54. "runs": [
  55. {
  56. "command": "pnpm exec playwright test --config E:\\work\\edit_3d\\.codex-tmp\\auth-message-regression.config.ts",
  57. "result": "首轮运行当时文件中的 4 项旧回归,2 passed / 2 failed(均为输入定位超时),用时 45.4 秒;原始结果保留。",
  58. "json": "authentication/results.json",
  59. "html": "authentication/html/index.html",
  60. "log": "authentication/run.log"
  61. },
  62. {
  63. "command": "pnpm exec playwright test --config E:\\work\\edit_3d\\.codex-tmp\\auth-login-message.config.ts",
  64. "result": "新增当前登录 API 错误回归独立执行,1 passed,用时 10.8 秒。",
  65. "json": "authentication/login-message/results.json",
  66. "html": "authentication/login-message/html/index.html",
  67. "log": "authentication/login-message/run.log"
  68. }
  69. ],
  70. "checks": [
  71. {
  72. "title": "859:无可登录教员时账号选择器禁用",
  73. "status": "PASS",
  74. "result": "保留业务空态,选择器不可展开。",
  75. "screenshots": [
  76. {
  77. "title": "无教员业务空态",
  78. "path": "authentication/screenshots/859-passed.png"
  79. }
  80. ]
  81. },
  82. {
  83. "title": "861:旧强制改密不一致校验",
  84. "status": "BLOCKED",
  85. "rawStatus": "failed",
  86. "result": "当前 /change-password 对已认证用户重定向 /dashboard;旧 fixture 只有强制改密标记而无工作台权限,后续导航取消,停留在启动页,未进入改密表单。该旧用例不适用于当前路由契约,本次未改路由、未跳过或记为通过。",
  87. "screenshots": [
  88. {
  89. "title": "旧改密入口阻断",
  90. "path": "authentication/screenshots/861-failed.png"
  91. }
  92. ]
  93. },
  94. {
  95. "title": "864:旧强制改密停用账号提示",
  96. "status": "BLOCKED",
  97. "rawStatus": "failed",
  98. "result": "与 861 相同的既有路由契约阻断,未能提交初始改密接口,也未验证一次性登录提示。原始失败证据保留。",
  99. "screenshots": [
  100. {
  101. "title": "旧停用账号流程阻断",
  102. "path": "authentication/screenshots/864-failed.png"
  103. }
  104. ]
  105. },
  106. {
  107. "title": "普通会话过期不泄露后端内部详情",
  108. "status": "PASS",
  109. "result": "跳转登录页,登录错误栏为空,不显示内部会话或刷新令牌详情,仅发起一次刷新请求。",
  110. "screenshots": []
  111. },
  112. {
  113. "title": "当前管理员登录 API 401 错误使用自动消失的 Message",
  114. "status": "PASS",
  115. "result": "实际点击登录;mock POST /auth/login 返回 401。只出现一条 .el-message--error,#login-error 始终为空;未点击关闭,Message 自动消失。登录请求 1 次,刷新请求 0 次。",
  116. "screenshots": [
  117. {
  118. "title": "登录失败 Message",
  119. "path": "authentication/login-message/screenshots/login-api-error-message.png"
  120. },
  121. {
  122. "title": "Message 自动消失后",
  123. "path": "authentication/login-message/screenshots/login-api-error-message-dismissed.png"
  124. }
  125. ]
  126. }
  127. ],
  128. "limitations": [
  129. "仅模拟认证接口与浏览器交互,不使用真实账号,不验证后端认证规则或真实密码修改。",
  130. "未运行依赖真实账号的 auth.spec.ts 全量;仅更新其中接口错误提示的断言选择器。",
  131. "两条旧强制改密用例没有通过,不能作为当前改密功能验证证据;既有路由策略不在本轮提示展示调整范围。"
  132. ]
  133. },
  134. "stages": [
  135. {
  136. "title": "资料",
  137. "text": "按本轮“接口错误使用 Message,不保留常驻错误横条”的要求检查。沿用已确认的教学业务边界:离线识别回放、观察模式、步骤反馈和表单校验仍需可见。"
  138. },
  139. {
  140. "title": "原型",
  141. "text": "错误发生时顶部短暂提示;可以手动关闭,约 4.5 秒自动消失。同一错误合并展示;失败后仍可重新加载,已成功取得的数据不因后续刷新失败消失。"
  142. },
  143. {
  144. "title": "设计",
  145. "text": "共享 Message 处理负责统一展示与缓存页面生命周期;请求层保留业务错误码、HTTP 状态和 requestId,静默请求不会自行弹窗。未取得数据与空结果保持区分。"
  146. },
  147. {
  148. "title": "开发",
  149. "text": "代表性覆盖内容制作、系统用户与教学实施,包括训练编辑器加载失败的重试入口。接口异常详情仅在 Message 中展示;表单必填错误、项目编码说明和离线运行模式继续保留。"
  150. },
  151. {
  152. "title": "测试",
  153. "text": "使用真实 Vue / Element Plus 页面、Edge 无头浏览器和浏览器级 API mock。覆盖本机与局域网入口。身份及接口数据均为合成测试数据;不登录真实账号、不写业务库,不将本轮测试称为真实服务端或设备联调。"
  154. }
  155. ],
  156. "checks": [
  157. {
  158. "title": "内容列表:错误自动消失、重试恢复、再次失败保留旧数据",
  159. "status": "PASS",
  160. "durationMs": 12754,
  161. "screenshots": [
  162. {
  163. "title": "01-content-error-message",
  164. "path": "screenshots/01-content-error-message.png"
  165. },
  166. {
  167. "title": "02-content-old-data-retained",
  168. "path": "screenshots/02-content-old-data-retained.png"
  169. }
  170. ],
  171. "isolation": {
  172. "requests": [
  173. {
  174. "method": "GET",
  175. "path": "/api/auth/v1/system-config/public"
  176. },
  177. {
  178. "method": "GET",
  179. "path": "/api/auth/v1/auth/me"
  180. },
  181. {
  182. "method": "GET",
  183. "path": "/api/auth/v1/menus/navigation"
  184. },
  185. {
  186. "method": "GET",
  187. "path": "/api/tran/v1/content/projects/summary"
  188. },
  189. {
  190. "method": "GET",
  191. "path": "/api/tran/v1/content/projects"
  192. },
  193. {
  194. "method": "GET",
  195. "path": "/api/tran/v1/content/projects"
  196. },
  197. {
  198. "method": "GET",
  199. "path": "/api/tran/v1/content/projects/summary"
  200. },
  201. {
  202. "method": "GET",
  203. "path": "/api/tran/v1/content/projects"
  204. }
  205. ],
  206. "unexpected": [],
  207. "writes": [],
  208. "pageErrors": []
  209. }
  210. },
  211. {
  212. "title": "系统用户:并行同错合并一条,重复搜索可再次提示",
  213. "status": "PASS",
  214. "durationMs": 12705,
  215. "screenshots": [
  216. {
  217. "title": "03-users-grouped-message",
  218. "path": "screenshots/03-users-grouped-message.png"
  219. },
  220. {
  221. "title": "04-users-retry-without-banner",
  222. "path": "screenshots/04-users-retry-without-banner.png"
  223. }
  224. ],
  225. "isolation": {
  226. "requests": [
  227. {
  228. "method": "GET",
  229. "path": "/api/auth/v1/system-config/public"
  230. },
  231. {
  232. "method": "GET",
  233. "path": "/api/auth/v1/auth/me"
  234. },
  235. {
  236. "method": "GET",
  237. "path": "/api/auth/v1/menus/navigation"
  238. },
  239. {
  240. "method": "GET",
  241. "path": "/api/auth/v1/roles/all"
  242. },
  243. {
  244. "method": "GET",
  245. "path": "/api/auth/v1/departments/tree"
  246. },
  247. {
  248. "method": "GET",
  249. "path": "/api/auth/v1/users"
  250. },
  251. {
  252. "method": "GET",
  253. "path": "/api/auth/v1/users/stats"
  254. },
  255. {
  256. "method": "GET",
  257. "path": "/api/auth/v1/users"
  258. },
  259. {
  260. "method": "GET",
  261. "path": "/api/auth/v1/users/stats"
  262. }
  263. ],
  264. "unexpected": [],
  265. "writes": [],
  266. "pageErrors": []
  267. }
  268. },
  269. {
  270. "title": "训练编辑器:加载失败提示消失后保留重新加载按钮",
  271. "status": "PASS",
  272. "durationMs": 6385,
  273. "screenshots": [
  274. {
  275. "title": "05-legacy-training-message",
  276. "path": "screenshots/05-legacy-training-message.png"
  277. },
  278. {
  279. "title": "06-legacy-training-retry",
  280. "path": "screenshots/06-legacy-training-retry.png"
  281. }
  282. ],
  283. "isolation": {
  284. "requests": [
  285. {
  286. "method": "GET",
  287. "path": "/api/auth/v1/system-config/public"
  288. },
  289. {
  290. "method": "GET",
  291. "path": "/api/auth/v1/auth/me"
  292. },
  293. {
  294. "method": "GET",
  295. "path": "/api/auth/v1/menus/navigation"
  296. },
  297. {
  298. "method": "GET",
  299. "path": "/api/tran/v1/content/projects/message-training-901"
  300. }
  301. ],
  302. "unexpected": [],
  303. "writes": [],
  304. "pageErrors": []
  305. }
  306. },
  307. {
  308. "title": "实装预览:任务上下文错误用 Message,离线与教员模式持续可见",
  309. "status": "PASS",
  310. "durationMs": 6450,
  311. "screenshots": [
  312. {
  313. "title": "07-physical-context-message",
  314. "path": "screenshots/07-physical-context-message.png"
  315. },
  316. {
  317. "title": "08-physical-mode-preserved",
  318. "path": "screenshots/08-physical-mode-preserved.png"
  319. }
  320. ],
  321. "isolation": {
  322. "requests": [
  323. {
  324. "method": "GET",
  325. "path": "/api/auth/v1/system-config/public"
  326. },
  327. {
  328. "method": "GET",
  329. "path": "/api/auth/v1/auth/me"
  330. },
  331. {
  332. "method": "GET",
  333. "path": "/api/auth/v1/menus/navigation"
  334. },
  335. {
  336. "method": "GET",
  337. "path": "/api/tran/v1/teaching/assignments/mock-physical"
  338. }
  339. ],
  340. "unexpected": [],
  341. "writes": [],
  342. "pageErrors": []
  343. }
  344. },
  345. {
  346. "title": "新建训练:业务说明与必填校验保留,不发起创建请求",
  347. "status": "PASS",
  348. "durationMs": 2485,
  349. "screenshots": [
  350. {
  351. "title": "09-create-validation-preserved",
  352. "path": "screenshots/09-create-validation-preserved.png"
  353. }
  354. ],
  355. "isolation": {
  356. "requests": [
  357. {
  358. "method": "GET",
  359. "path": "/api/auth/v1/system-config/public"
  360. },
  361. {
  362. "method": "GET",
  363. "path": "/api/auth/v1/auth/me"
  364. },
  365. {
  366. "method": "GET",
  367. "path": "/api/auth/v1/menus/navigation"
  368. },
  369. {
  370. "method": "GET",
  371. "path": "/api/tran/v1/content/projects/summary"
  372. },
  373. {
  374. "method": "GET",
  375. "path": "/api/tran/v1/content/projects"
  376. }
  377. ],
  378. "unexpected": [],
  379. "writes": [],
  380. "pageErrors": []
  381. }
  382. },
  383. {
  384. "title": "缓存列表:失活时晚到错误不弹出,返回不重放旧错误",
  385. "status": "PASS",
  386. "durationMs": 1947,
  387. "screenshots": [
  388. {
  389. "title": "10-inactive-page-no-message",
  390. "path": "screenshots/10-inactive-page-no-message.png"
  391. },
  392. {
  393. "title": "11-reactivated-no-stale-message",
  394. "path": "screenshots/11-reactivated-no-stale-message.png"
  395. }
  396. ],
  397. "isolation": {
  398. "requests": [
  399. {
  400. "method": "GET",
  401. "path": "/api/auth/v1/system-config/public"
  402. },
  403. {
  404. "method": "GET",
  405. "path": "/api/auth/v1/auth/me"
  406. },
  407. {
  408. "method": "GET",
  409. "path": "/api/auth/v1/menus/navigation"
  410. },
  411. {
  412. "method": "GET",
  413. "path": "/api/tran/v1/content/projects/summary"
  414. },
  415. {
  416. "method": "GET",
  417. "path": "/api/tran/v1/content/projects"
  418. },
  419. {
  420. "method": "GET",
  421. "path": "/api/tran/v1/content/projects/summary"
  422. },
  423. {
  424. "method": "GET",
  425. "path": "/api/tran/v1/content/projects"
  426. },
  427. {
  428. "method": "GET",
  429. "path": "/api/auth/v1/roles/all"
  430. },
  431. {
  432. "method": "GET",
  433. "path": "/api/auth/v1/departments/tree"
  434. },
  435. {
  436. "method": "GET",
  437. "path": "/api/auth/v1/users"
  438. },
  439. {
  440. "method": "GET",
  441. "path": "/api/auth/v1/users/stats"
  442. },
  443. {
  444. "method": "GET",
  445. "path": "/api/tran/v1/content/projects/summary"
  446. },
  447. {
  448. "method": "GET",
  449. "path": "/api/tran/v1/content/projects"
  450. }
  451. ],
  452. "unexpected": [],
  453. "writes": [],
  454. "pageErrors": []
  455. }
  456. },
  457. {
  458. "title": "HTTP 合同:真实 Axios 超时中文化,403/409 元数据保留,静默请求不自动弹窗",
  459. "status": "PASS",
  460. "durationMs": 1942,
  461. "screenshots": [
  462. {
  463. "title": "12-http-silent-errors",
  464. "path": "screenshots/12-http-silent-errors.png"
  465. },
  466. {
  467. "title": "15-business-message-keeps-original-text",
  468. "path": "screenshots/15-business-message-keeps-original-text.png"
  469. }
  470. ],
  471. "isolation": {
  472. "requests": [
  473. {
  474. "method": "GET",
  475. "path": "/api/auth/v1/system-config/public"
  476. },
  477. {
  478. "method": "GET",
  479. "path": "/api/auth/v1/auth/me"
  480. },
  481. {
  482. "method": "GET",
  483. "path": "/api/auth/v1/menus/navigation"
  484. },
  485. {
  486. "method": "GET",
  487. "path": "/api/tran/v1/content/projects/summary"
  488. },
  489. {
  490. "method": "GET",
  491. "path": "/api/tran/v1/content/projects"
  492. },
  493. {
  494. "method": "GET",
  495. "path": "/api/auth/v1/__message_e2e/timeout"
  496. },
  497. {
  498. "method": "GET",
  499. "path": "/api/auth/v1/__message_e2e/forbidden"
  500. },
  501. {
  502. "method": "GET",
  503. "path": "/api/auth/v1/__message_e2e/conflict"
  504. },
  505. {
  506. "method": "GET",
  507. "path": "/api/auth/v1/__message_e2e/timeout"
  508. },
  509. {
  510. "method": "GET",
  511. "path": "/api/auth/v1/__message_e2e/business-text"
  512. }
  513. ],
  514. "unexpected": [],
  515. "writes": [],
  516. "pageErrors": []
  517. },
  518. "http": [
  519. {
  520. "endpoint": "timeout",
  521. "message": "请求超时,请稍后重试",
  522. "code": "NETWORK_ERROR",
  523. "status": null,
  524. "requestId": ""
  525. },
  526. {
  527. "endpoint": "forbidden",
  528. "message": "无权访问测试数据",
  529. "code": "ACCESS_DENIED",
  530. "status": 403,
  531. "requestId": "mock-403"
  532. },
  533. {
  534. "endpoint": "conflict",
  535. "message": "版本已变化,请重新加载",
  536. "code": "VERSION_CONFLICT",
  537. "status": 409,
  538. "requestId": "mock-409"
  539. }
  540. ],
  541. "httpBoundaries": {
  542. "cancellation": {
  543. "name": "CanceledError",
  544. "code": "ERR_CANCELED"
  545. },
  546. "businessError": {
  547. "message": "Network Error",
  548. "code": "ASSET_VALIDATION",
  549. "requestId": "mock-business",
  550. "status": 400
  551. }
  552. }
  553. },
  554. {
  555. "title": "局域网教学列表:既有 ElMessage.error 使用全局关闭和自动消失配置",
  556. "status": "PASS",
  557. "durationMs": 6935,
  558. "screenshots": [
  559. {
  560. "title": "13-lan-teaching-message",
  561. "path": "screenshots/13-lan-teaching-message.png"
  562. },
  563. {
  564. "title": "14-lan-teaching-after-dismiss",
  565. "path": "screenshots/14-lan-teaching-after-dismiss.png"
  566. }
  567. ],
  568. "isolation": {
  569. "requests": [
  570. {
  571. "method": "GET",
  572. "path": "/api/auth/v1/system-config/public"
  573. },
  574. {
  575. "method": "GET",
  576. "path": "/api/auth/v1/auth/me"
  577. },
  578. {
  579. "method": "GET",
  580. "path": "/api/auth/v1/menus/navigation"
  581. },
  582. {
  583. "method": "GET",
  584. "path": "/api/tran/v1/teaching/assignments"
  585. },
  586. {
  587. "method": "GET",
  588. "path": "/api/tran/v1/teaching/assignments/summary"
  589. }
  590. ],
  591. "unexpected": [],
  592. "writes": [],
  593. "pageErrors": []
  594. }
  595. },
  596. {
  597. "title": "模型桥接 DOM 合同:初次错误与晚写详情转为重试说明,ready 恢复交互",
  598. "status": "PASS",
  599. "durationMs": 791,
  600. "screenshots": [
  601. {
  602. "title": "16-model-bridge-neutral-retry",
  603. "path": "screenshots/16-model-bridge-neutral-retry.png"
  604. },
  605. {
  606. "title": "17-model-bridge-ready",
  607. "path": "screenshots/17-model-bridge-ready.png"
  608. }
  609. ],
  610. "isolation": {
  611. "requests": [],
  612. "unexpected": [],
  613. "writes": [],
  614. "pageErrors": []
  615. }
  616. }
  617. ],
  618. "limitations": [
  619. "这是接口失败展示的聚焦浏览器回归,未逐一遍历所有业务页面。",
  620. "页面渲染、Element Plus Message、缓存路由和 Axios 超时均运行于真实浏览器;服务端响应由测试模拟。",
  621. "模型 iframe 项为真实宿主桥接的 DOM 合同测试,使用空画布夹具,不代表完整 GLB 模型加载测试。",
  622. "保留训练业务状态、表单校验与重试入口。未扩大教学流程、权限或接口合同。"
  623. ],
  624. "reproduction": "pnpm exec playwright test -c api-error-messages.config.ts"
  625. }