t16-freshness.log 5.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. PASS A1-shows-last-success-clock — 最近一次成功更新 10:00:00(5 秒前)
  2. PASS A2-missing-time-is-placeholder — 没有成功过时显示「—」(不编一个 00:00:00)
  3. PASS A3-accepts-iso-and-epoch — 毫秒时间戳与 ISO 串(后端 updatedAt 的形状)都认,解析不出回 null
  4. PASS A4-age-text-scales — 「多久之前」随量级换单位(秒/分钟/小时)
  5. PASS B1-four-states-distinct — 四态:current / stale / unavailable / empty(新鲜 / 过期 / 不可用 / 尚未取数)
  6. PASS B2-four-texts-distinct — 四句文案互不相同,且过期与不可用**说得不一样**:数据新鲜 | 数据已过期(显示最后一次成功数据) | 数据不可用(尚未取到过数据) | 尚未取数
  7. PASS B3-partial-is-its-own-state — 部分失败是独立状态:「部分数据过期或不可用」(一对一全坏才算整体不可用)
  8. PASS B4-maps-to-section-vocabulary — 四态映射到票 05 的分区状态词汇(不新造第二套状态词)
  9. PASS B5-bridges-backend-conclusion — 后端给了结论时能桥接过来(认不出的回空串,不猜)
  10. PASS C1-two-cycles-is-the-bar — 判定阈值 = 2(与票 05 的 EXPIRED_MISSED_CYCLES 一致)
  11. PASS C2-one-failure-not-yet-stale — 第 1 个周期失败:连续失败 1,仍是「数据新鲜」
  12. PASS C3-two-consecutive-failures-stale — 第 2 个周期失败:连续失败 2 → 「数据已过期(显示最后一次成功数据)」
  13. PASS C4-success-resets-streak — 失败→成功→失败:连续失败回到 1(不是累计 2),仍是「数据新鲜」
  14. PASS C5-never-succeeded-is-unavailable — 从未取到值又连续失败 2 次 → 「数据不可用(尚未取到过数据)」(与"过期"分开:没有旧值可留)
  15. PASS D1-stale-keeps-last-success — 过期后 lastSuccessAt 仍是第一次成功那一刻(10:00:00)—— 保留最后已知值,界面上带过期标识
  16. PASS D2-failure-does-not-erase-success-time — 失败**不覆盖**"最后一次成功是什么时候"(否则值班人员就查不到旧值有多旧)
  17. PASS D3-retained-only-for-stale — 只有「过期」带保留标识;新鲜与尚未取数都不带
  18. PASS D4-view-carries-retained-flag — 视图对象把 retained / failures 一并交给界面(组件不自己算)
  19. PASS E1-age-missing-is-placeholder — 年龄缺失显示「—」,**不是**「0 秒前」(那会被读成刚更新过)
  20. PASS E2-real-zero-is-valid — 后端真给 0 是有效数据:0 秒前(照实显示,不当缺失)
  21. PASS E3-missed-cycles-drives-expiry — 后端只给 missedCycles 时按 >= 2 兜底;给了 freshness 结论则以它为准(前端不推翻后端)
  22. PASS E4-no-zero-fabrication-on-empty — 从未成功时不编一个时间戳出来(字段保持 null,界面显示占位符)
  23. PASS E5-since-success-missing-is-placeholder — 两个年龄入口在缺失时都给「—」(不编「0 秒前」),而真的 0 秒照实显示
  24. PASS F1-first-cycle-runs-immediately — 启动即跑一轮(否则首屏要空等一个周期),并排好下一次
  25. PASS F2-not-polling-before-start — 默认周期 30 秒(配置 runtime.refreshSeconds 可覆盖)
  26. PASS F3-successful-cycles-stay-current — 3 个周期都成功 → 仍是「数据新鲜」
  27. PASS F4-push-down-counts-as-failure — WS 断线两个周期(REST 仍取数成功)→ 第 1 个周期仍是新鲜、第 2 个转「数据已过期(显示最后一次成功数据)」,原因是「状态推送未连接」
  28. PASS F5-recovery-clears-failures — 链路恢复后回到「数据新鲜」(连续失败清零)
  29. PASS F6-tick-failure-counts — `tick` 返回 false 也算失败周期(取数失败与 WS 断线两条路都进同一本账)
  30. PASS F7-stop-clears-timer — stopPolling 后定时器剩 0 个、isPolling=false
  31. PASS F8-tick-throw-is-failure — `tick` 抛错也收成失败周期(不把异常冒成页面级报错)
  32. PASS F9-push-arrival-counts-as-live — WS 未连时启动那轮先记失败(1 次);推送到达后连续失败清零、成功数 0 → 1
  33. PASS F10-store-exposes-view-for-ui — store 给出视图对象(view=current、text=「数据新鲜」)供组件直接消费
  34. PASS G1-shell-shows-freshness — 外壳把新鲜度画出来(data-freshness / data-freshness-at 是走查断言面)
  35. PASS G2-shell-does-not-own-wording — 外壳不自己拼状态文案(文案只在 domain/freshnessModel.js 一份)
  36. PASS G3-shell-stops-polling-on-unmount — 离开外壳必须停轮询(定时器不跟着页面跑下去)
  37. PASS G4-domain-pure-and-no-timer — domain/freshnessModel.js 是纯函数(不发请求、不 import service、不自己起定时器)
  38. PASS G5-service-timers-are-injectable — 轮询服务的定时器可注入(单测与走查用假定时器演示两个周期)
  39. PASS G6-period-comes-from-config — 周期来自配置 runtime.refreshSeconds;0/负数被拒并退回默认(否则"两个周期"永远不成立)
  40. PASS G7-no-credential-in-freshness-modules — 新鲜度两层都不碰凭据
  41. PASS G8-store-owns-the-accounting — WS 可用性取自 store 的连接状态(方向不反:service 不认识 store)
  42. PASS G9-partial-state-is-consumed-by-ui — 「部分失败」被外壳真的画出来(data-freshness-partial),不是只写在 domain 里
  43. PASS G10-bridges-section-to-freshness — 分区状态与新鲜度四态之间有唯一一处显式翻译(界面不自己数数)
  44. T16 数据新鲜度检查:43/43 项通过。
  45. T16 数据新鲜度全部通过。