"use strict"; const assert = require("assert"); const fs = require("fs"); const path = require("path"); const toDataModuleUrl = (source) => `data:text/javascript;base64,${Buffer.from(source).toString("base64")}`; const run = async () => { const source = fs.readFileSync( path.join(__dirname, "../utils/genealogy-context.js"), "utf8", ); const storage = new Map(); const removals = []; globalThis.uni = { getStorageSync: (key) => storage.get(key), setStorageSync: (key, value) => storage.set(key, value), removeStorageSync: (key) => { removals.push(key); storage.delete(key); }, }; const { genealogyContext } = await import(toDataModuleUrl(source)); assert.throws( () => genealogyContext.setCurrentGenealogyId(1001), /字符串/, "当前家谱 ID 不得从可能已经失真的 JavaScript number 转换", ); for (const invalidId of ["", " 1001", "1001 "]) { assert.throws( () => genealogyContext.setCurrentGenealogyId(invalidId), /家谱 ID/, "空值或带边界空白的 ID 必须失败关闭", ); } genealogyContext.setCurrentGenealogyId("9223372036854775807"); assert.strictEqual( storage.get("jiapu_current_genealogy_id"), "9223372036854775807", "词法 ID 必须原样保存,不能转成 Number", ); storage.set("jiapu_current_genealogy_id", { id: "1001" }); assert.strictEqual( genealogyContext.getCurrentGenealogyId(), "", "旧对象或损坏值不得泄漏给页面", ); assert.strictEqual(storage.has("jiapu_current_genealogy_id"), false); assert.strictEqual( genealogyContext.reconcileCurrentGenealogyId(["1001", "1002"], "1002"), "1002", "显式且仍可用的路由目标优先", ); assert.strictEqual( genealogyContext.reconcileCurrentGenealogyId(["1001", "1002"]), "1002", "没有显式目标时保留仍可用的已存选择", ); assert.strictEqual( genealogyContext.reconcileCurrentGenealogyId(["1001"]), "", "权限或列表变化移除旧选择后必须清空,不能静默切换家谱", ); assert.strictEqual(storage.has("jiapu_current_genealogy_id"), false); assert.strictEqual( genealogyContext.reconcileCurrentGenealogyId(["1001", "1002"]), "", "撤权标记必须跨页面重载继续失败关闭", ); assert.strictEqual(storage.get("jiapu_current_genealogy_invalidated"), "1"); genealogyContext.setCurrentGenealogyId("1001"); assert.strictEqual(storage.has("jiapu_current_genealogy_invalidated"), false); genealogyContext.invalidateCurrentGenealogyId(); assert.strictEqual(genealogyContext.getCurrentGenealogyId(), ""); assert.strictEqual(genealogyContext.isCurrentGenealogyInvalidated(), true); assert.strictEqual( genealogyContext.reconcileCurrentGenealogyId(["1001"]), "", "领域列表异常写入的失效标记也必须阻止重载自动切谱", ); genealogyContext.clearCurrentGenealogyId(); assert.strictEqual( genealogyContext.reconcileCurrentGenealogyId(["1001", "1002"]), "1001", "只有没有历史撤权标记的首次进入才允许建立首个上下文", ); assert.strictEqual( genealogyContext.reconcileCurrentGenealogyId(["1001", "1002"], "missing"), "", "显式但不可用的目标必须失败关闭,不能回退到其他家谱", ); assert.strictEqual( genealogyContext.reconcileCurrentGenealogyId(["1001", "1002"]), "", "显式无权目标产生的撤权标记也必须跨重载保留", ); assert.strictEqual( genealogyContext.reconcileCurrentGenealogyId([], "missing"), "", "没有可用家谱时必须清空旧上下文", ); assert.strictEqual(storage.has("jiapu_current_genealogy_id"), false); assert.throws( () => genealogyContext.reconcileCurrentGenealogyId(["1001", "1001"]), /重复/, "重复实体必须在领域边界被拒绝,不能静默去重", ); assert.throws( () => genealogyContext.reconcileCurrentGenealogyId([1001]), /字符串/, "可用列表也必须保持词法 ID", ); assert.ok(removals.length >= 4, "损坏值、撤权与空列表都应清理持久上下文"); process.stdout.write("GENEALOGY-CONTEXT-RUNTIME-SMOKE PASS\n"); }; run().catch((error) => { process.stderr.write(`${error.stack || error.message}\n`); process.exit(1); });