130 lines
4.3 KiB
JavaScript
130 lines
4.3 KiB
JavaScript
"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);
|
|
});
|