import { test } from 'node:test' import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' /** * 「局域网大屏」卡片的加载时机回归钉子。 * * 真事故(2026-09-12 用真 Chromium + 真服务端复现):`refreshLan()` 在挂载时跑, * 而 `auth` 是**异步**加载的 —— 那一刻 `auth.readOnly` 必然为 true,于是卡片把 * 「当前为只读访客」写进 `lanProblem` 这个**普通 ref** 就返回了;等身份落定后 * 没有任何东西再触发它,结果: * - 卡片永远停在访客态(管理员登录后也一样); * - `/api/system/network` **一次都没被请求**。 * 页面级测试在仓库里跑不起来(没有 jsdom / @vue/test-utils),所以这里退化成源码断言: * 钉住「gate 由 computed 直接渲染」+「gate 变 null 时会重跑加载」这两件事, * 防止以后重构又把它改回「写死进 ref 就完事」。 */ const SOURCE = readFileSync(new URL('../pages/DisplayPage.vue', import.meta.url), 'utf8') test('访客提示直接由 computed 渲染,不从 ref 里读(否则身份就绪后不会消失)', () => { assert.match(SOURCE, /
/, 'gate 必须直接绑 computed') assert.match(SOURCE, /const lanGateReason = computed\(/, 'gate 必须是 computed') // 反面:把 gate 写进 lanProblem 后就 return,是本事故的写法 assert.doesNotMatch( SOURCE, /lanProblem\.value = lanGateReason\.value/, '不允许把 gate 写进 lanProblem:那是个普通 ref,身份就绪后不会自己清掉', ) }) test('身份就绪(gate 变 null)时必须重跑一次加载', () => { assert.match(SOURCE, /watch\(lanGateReason,/, '必须 watch gate') assert.match( SOURCE, /watch\(lanGateReason,[\s\S]{0,200}?refreshLan\(\)/, 'watch 的回调里必须调用 refreshLan(),否则接口永远不会被请求', ) })