"use strict"; const assert = require("assert"); const fs = require("fs"); const path = require("path"); const run = async () => { const source = fs.readFileSync( path.join(__dirname, "../data/mock.js"), "utf8", ); const contractSource = fs.readFileSync( path.join(__dirname, "../utils/genealogy-contracts.js"), "utf8", ); const contractUrl = `data:text/javascript;base64,${Buffer.from(contractSource).toString("base64")}`; const { GENEALOGY_ACCESS_PRESET, isGenealogyAccessPreset, toApiGenealogyAccess, fromApiGenealogyAccess, } = await import(contractUrl); assert.strictEqual(isGenealogyAccessPreset(GENEALOGY_ACCESS_PRESET.MEMBER_ONLY), true); assert.strictEqual(isGenealogyAccessPreset(GENEALOGY_ACCESS_PRESET.PUBLIC_APPLY), true); assert.strictEqual(isGenealogyAccessPreset("UNKNOWN"), false); assert.strictEqual(isGenealogyAccessPreset(null), false); assert.deepStrictEqual(toApiGenealogyAccess(GENEALOGY_ACCESS_PRESET.MEMBER_ONLY), { visibility: "2", joinMode: "0", }); assert.deepStrictEqual(toApiGenealogyAccess(GENEALOGY_ACCESS_PRESET.PUBLIC_APPLY), { visibility: "1", joinMode: "1", }); assert.strictEqual(fromApiGenealogyAccess({ visibility: "2", joinMode: "0" }), "MEMBER_ONLY"); assert.strictEqual(fromApiGenealogyAccess({ visibility: "1", joinMode: "1" }), "PUBLIC_APPLY"); assert.strictEqual(fromApiGenealogyAccess({ visibility: "1", joinMode: "2" }), null); const moduleUrl = `data:text/javascript;base64,${Buffer.from(source.replace("../utils/genealogy-contracts.js", contractUrl)).toString("base64")}`; const { genealogies, publicGenealogies, createLocalGenealogyPreview, updateLocalGenealogyPreview, updateLocalGenealogyPreviewAncestor, removeLocalGenealogyPreview, findGenealogyFixture, getGenealogyFixtureAccess, isGenealogySearchVisible, } = await import(moduleUrl); assert(genealogies.every((item) => typeof item.id === "string")); assert(publicGenealogies.every((item) => typeof item.id === "string")); assert( publicGenealogies.every((item) => !Object.hasOwn(item, "membership")), "公开搜索投影不得携带成员权限字段", ); for (const publicItem of publicGenealogies.filter((item) => ["joined", "owned"].includes(item.relation), )) { const memberItem = genealogies.find((item) => item.id === publicItem.id); assert(memberItem, `${publicItem.relation} 搜索结果必须对应真实成员家谱`); assert.strictEqual(publicItem.name, memberItem.name, "同一 ID 的家谱名称必须一致"); assert.strictEqual( getGenealogyFixtureAccess(publicItem.id).accessRole, publicItem.relation === "owned" ? "owner" : "member", ); } assert.strictEqual(findGenealogyFixture("2003")?.name, "汤氏济宁宗谱"); assert.strictEqual(findGenealogyFixture("2001")?.accessPreset, "PUBLIC_APPLY"); for (const id of ["2003", "2004", "2005"]) { assert.strictEqual( findGenealogyFixture(id)?.accessPreset, "PUBLIC_APPLY", `${id} 只有公开可申请家谱才能暴露关系动作`, ); } for (const [id, relation, canApply] of [ ["1001", "owned", false], ["1002", "joined", false], ["2001", "available", true], ["2003", "pending", false], ["2004", "rejected", true], ["2005", "removed", true], ["local-created-genealogy", "preview", false], ["unknown", "unknown", false], ]) { const access = getGenealogyFixtureAccess(id); assert.strictEqual(access.relation, relation, `${id} 关系必须来自共享夹具 owner`); assert.strictEqual(access.canApply, canApply, `${id} 申请资格必须失败关闭`); } assert.strictEqual(getGenealogyFixtureAccess("local-created-genealogy").viewMode, "preview"); assert.strictEqual(getGenealogyFixtureAccess("unknown").accessRole, "guest"); const publicFixture = findGenealogyFixture("2001"); const originalAccessPreset = publicFixture.accessPreset; publicFixture.accessPreset = "MEMBER_ONLY"; assert.strictEqual( getGenealogyFixtureAccess("2001").canView, false, "陌生账号不得直接打开仅成员可见家谱的总览", ); assert.strictEqual( getGenealogyFixtureAccess("2001").canApply, false, "仅成员可见家谱即使关系标签陈旧也必须失败关闭", ); assert.strictEqual( isGenealogySearchVisible("2001"), false, "陌生账号不得搜索到仅成员可见的家谱", ); publicFixture.accessPreset = originalAccessPreset; assert.strictEqual(getGenealogyFixtureAccess("2001").canView, true); assert.strictEqual(isGenealogySearchVisible("2001"), true); assert.strictEqual(getGenealogyFixtureAccess("1001").canView, true, "所有者可查看自己的私密家谱"); assert.strictEqual(getGenealogyFixtureAccess("local-created-genealogy").canView, true, "本轮本地预览必须可回看"); assert.strictEqual(getGenealogyFixtureAccess("unknown").canView, false); assert.strictEqual(isGenealogySearchVisible("1001"), true, "所有者仍可定位自己的私密家谱"); const firstPreviewId = createLocalGenealogyPreview({ surname: "欧阳", name: "欧阳氏测试谱", hall: "敦本堂", location: "江西·吉安", accessPreset: "PUBLIC_APPLY", }); const secondPreviewId = createLocalGenealogyPreview({ surname: "汤", name: "第二部测试谱", hall: "", location: "河南·洛阳", accessPreset: "MEMBER_ONLY", }); assert.notStrictEqual(firstPreviewId, secondPreviewId, "重复创建不得复用本地预览 ID"); assert.strictEqual(typeof firstPreviewId, "string"); assert.deepStrictEqual( { surname: findGenealogyFixture(firstPreviewId)?.surname, name: findGenealogyFixture(firstPreviewId)?.name, hall: findGenealogyFixture(firstPreviewId)?.hall, location: findGenealogyFixture(firstPreviewId)?.location, accessPreset: findGenealogyFixture(firstPreviewId)?.accessPreset, }, { surname: "欧阳", name: "欧阳氏测试谱", hall: "敦本堂", location: "江西·吉安", accessPreset: "PUBLIC_APPLY", }, ); updateLocalGenealogyPreviewAncestor(firstPreviewId, { personName: "欧阳修" }); assert.strictEqual(findGenealogyFixture(firstPreviewId)?.ancestorName, "欧阳修"); assert.strictEqual( updateLocalGenealogyPreview(firstPreviewId, { surname: "欧阳", name: "欧阳氏修订谱", hall: "敦本堂", location: "江西·庐陵", accessPreset: "MEMBER_ONLY", }), firstPreviewId, ); assert.strictEqual(findGenealogyFixture(firstPreviewId)?.name, "欧阳氏修订谱"); assert.strictEqual(findGenealogyFixture(firstPreviewId)?.ancestorName, "欧阳修"); assert.deepStrictEqual( { viewMode: getGenealogyFixtureAccess(firstPreviewId).viewMode, accessRole: getGenealogyFixtureAccess(firstPreviewId).accessRole, relation: getGenealogyFixtureAccess(firstPreviewId).relation, canView: getGenealogyFixtureAccess(firstPreviewId).canView, canApply: getGenealogyFixtureAccess(firstPreviewId).canApply, }, { viewMode: "preview", accessRole: "guest", relation: "preview", canView: true, canApply: false }, ); assert.strictEqual(removeLocalGenealogyPreview(secondPreviewId), true); assert.strictEqual(findGenealogyFixture(secondPreviewId), null); process.stdout.write("GENEALOGY-FIXTURE-RUNTIME-SMOKE PASS\n"); }; run().catch((error) => { process.stderr.write(`${error.stack || error.message}\n`); process.exit(1); });