import assert from 'node:assert/strict'; import test from 'node:test'; import { createSilenceGuard, isSilenceGuardAllowed, pagePathOf, silenceExtensionUrl } from '../utils/silence-guard.js'; const expiredItems = [{ package_usage_id: 45016, package_name: '套餐', silence: { silence_status: 'expired', extendable: true } }]; const okItems = [{ package_usage_id: 1, silence: { silence_status: 'ended' } }]; const setup = (items) => { let clock = 0; const calls = []; const state = { items, session: { token: 't', identifier: 'A' } }; const guard = createSilenceGuard({ getSession: () => state.session, loadPackageHistory: async (identifier) => { calls.push(identifier); return { items: state.items }; }, now: () => clock }); return { guard, calls, state, advance: (ms) => { clock += ms; } }; }; test('只有绑定手机号、首页、登录授权与延期支付相关页面不拦截', () => { for (const url of ['/pages/bind/bind?fromLogin=true', 'pages/index/index', '/pages/login/login', '/pages/silence-extension/silence-extension?package_usage_id=1', '/pages/silence-payment/silence-payment', '/pages/silence-orders/detail?id=3', '/pages/alipay-payment/alipay-payment']) { assert.equal(isSilenceGuardAllowed(url), true, url); } for (const url of ['/pages/change-phone/change-phone', '/pages/package-order/package-order', '/pages/switch/switch', '/pages/order-list/order-list', '/pages/my-wallet/my-wallet', '/pages/device-exchange/device-exchange', '/pages/asset-package-history/asset-package-history', '/pages/notifications/notifications']) { assert.equal(isSilenceGuardAllowed(url), false, url); } assert.equal(pagePathOf('/pages/a/b?x=1'), 'pages/a/b'); assert.equal(silenceExtensionUrl({ packageUsageId: 45016 }), '/pages/silence-extension/silence-extension?package_usage_id=45016'); }); test('沉默期已过期待延期时拦截,且每次都重新查询,延期完成后立即放行', async () => { const { guard, calls, state } = setup(expiredItems); assert.equal(guard.isKnownPass(), false); assert.equal((await guard.resolveBlock()).packageUsageId, 45016); assert.equal((await guard.resolveBlock()).packageUsageId, 45016); assert.equal(calls.length, 2); state.items = okItems; assert.equal(await guard.resolveBlock(), null); assert.equal(guard.isKnownPass(), true); }); test('不需要延期时缓存放行结果 5 分钟,换资产或换登录重新检查', async () => { const { guard, calls, state, advance } = setup(okItems); assert.equal(await guard.resolveBlock(), null); assert.equal(guard.isKnownPass(), true); await guard.resolveBlock(); assert.equal(calls.length, 1); advance(5 * 60 * 1000); assert.equal(guard.isKnownPass(), false); state.session = { token: 't', identifier: 'B' }; assert.equal(guard.isKnownPass(), false); state.items = expiredItems; assert.equal((await guard.resolveBlock()).packageUsageId, 45016); }); test('未登录不拦截;查询失败放行但不缓存', async () => { const anon = createSilenceGuard({ getSession: () => ({ token: '', identifier: '' }), loadPackageHistory: async () => { throw new Error('x'); } }); assert.equal(anon.isKnownPass(), true); assert.equal(await anon.resolveBlock(), null); const origError = console.error; console.error = () => {}; const failing = createSilenceGuard({ getSession: () => ({ token: 't', identifier: 'A' }), loadPackageHistory: async () => { throw new Error('x'); } }); assert.equal(await failing.resolveBlock(), null); assert.equal(failing.isKnownPass(), false); console.error = origError; }); test('不可延期的过期套餐不拦截(无法办理延期)', async () => { const { guard } = setup([{ package_usage_id: 2, silence: { silence_status: 'expired', extendable: false } }]); assert.equal(await guard.resolveBlock(), null); });