147 lines
5.9 KiB
JavaScript
147 lines
5.9 KiB
JavaScript
"use strict";
|
|
|
|
const assert = require("assert");
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
|
|
const loadMockModule = 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 moduleUrl = `data:text/javascript;base64,${Buffer.from(source.replace("../utils/genealogy-contracts.js", contractUrl)).toString("base64")}`;
|
|
return import(moduleUrl);
|
|
};
|
|
|
|
const assertScopedOwner = ({ list, find, ids, nestedField }) => {
|
|
assert.deepStrictEqual(list("1001").map((item) => item.id), ids);
|
|
assert.deepStrictEqual(list("1002"), [], "另一家谱不得读取 1001 的内容夹具");
|
|
assert.strictEqual(find("1002", ids[0]), null, "已知 ID 换谱后必须失败关闭");
|
|
assert.strictEqual(find("1001", "unknown"), null, "未知实体不得回退首条记录");
|
|
assert.strictEqual(find("", ids[0]), null, "缺少 genealogyId 必须失败关闭");
|
|
assert.strictEqual(find("1001", ""), null, "缺少实体 ID 必须失败关闭");
|
|
|
|
const listed = list("1001");
|
|
const original = find("1001", ids[0]);
|
|
listed[0].title = "被列表调用方修改";
|
|
assert.notStrictEqual(find("1001", ids[0]).title, "被列表调用方修改");
|
|
if (nestedField) {
|
|
const mutateNested = (item, value) => {
|
|
if (item[nestedField][0] && typeof item[nestedField][0] === "object") {
|
|
item[nestedField][0].__contractMutation = value;
|
|
} else {
|
|
item[nestedField][0] = value;
|
|
}
|
|
};
|
|
mutateNested(listed[0], "被列表调用方修改");
|
|
assert(!JSON.stringify(find("1001", ids[0])[nestedField]).includes("被列表调用方修改"));
|
|
mutateNested(original, "被详情调用方修改");
|
|
assert(!JSON.stringify(find("1001", ids[0])[nestedField]).includes("被详情调用方修改"));
|
|
}
|
|
};
|
|
|
|
const run = async () => {
|
|
const fixtures = await loadMockModule();
|
|
const {
|
|
listFamilyFeedFixtures,
|
|
findFamilyFeedFixture,
|
|
listFamilyArticleFixtures,
|
|
findFamilyArticleFixture,
|
|
listFamilyAlbumFixtures,
|
|
findFamilyAlbumFixture,
|
|
} = fixtures;
|
|
|
|
for (const selector of [
|
|
listFamilyFeedFixtures,
|
|
findFamilyFeedFixture,
|
|
listFamilyArticleFixtures,
|
|
findFamilyArticleFixture,
|
|
listFamilyAlbumFixtures,
|
|
findFamilyAlbumFixture,
|
|
]) {
|
|
assert.strictEqual(typeof selector, "function", "F 系列只读夹具必须由共享查询函数拥有");
|
|
}
|
|
|
|
assertScopedOwner({
|
|
list: listFamilyFeedFixtures,
|
|
find: findFamilyFeedFixture,
|
|
ids: ["1", "2"],
|
|
nestedField: "comments",
|
|
});
|
|
assertScopedOwner({
|
|
list: listFamilyArticleFixtures,
|
|
find: findFamilyArticleFixture,
|
|
ids: ["101", "102", "103"],
|
|
nestedField: "paragraphs",
|
|
});
|
|
assertScopedOwner({
|
|
list: listFamilyAlbumFixtures,
|
|
find: findFamilyAlbumFixture,
|
|
ids: ["201", "202", "203"],
|
|
nestedField: "photos",
|
|
});
|
|
|
|
for (const [list, entityName] of [
|
|
[listFamilyFeedFixtures, "feed"],
|
|
[listFamilyArticleFixtures, "article"],
|
|
[listFamilyAlbumFixtures, "album"],
|
|
]) {
|
|
for (const item of list("1001")) {
|
|
assert.strictEqual(typeof item.id, "string", `${entityName}.id 必须保持词法字符串`);
|
|
assert.strictEqual(item.genealogyId, "1001", `${entityName} 必须显式持有家谱身份`);
|
|
}
|
|
}
|
|
|
|
const firstFeed = findFamilyFeedFixture("1001", "1");
|
|
firstFeed.comments[0].content = "被详情调用方修改";
|
|
assert.notStrictEqual(
|
|
findFamilyFeedFixture("1001", "1").comments[0].content,
|
|
"被详情调用方修改",
|
|
);
|
|
|
|
globalThis.__familyFixtureOwner = fixtures;
|
|
const apiSource = fs
|
|
.readFileSync(path.join(__dirname, "../utils/api.js"), "utf8")
|
|
.replace(
|
|
/^import \{[\s\S]*?\} from '@\/data\/mock\.js'\r?\n/,
|
|
"const { currentUser, genealogies, publicGenealogies, treeMembers, notifications, joinApplications, listFamilyFeedFixtures, listFamilyArticleFixtures, listFamilyAlbumFixtures, listCeremonyFixtures, listGrowthRecordFixtures } = globalThis.__familyFixtureOwner;\n",
|
|
)
|
|
.replace(
|
|
/^import \{ hasRemoteConfig[^\n]+\r?\n/m,
|
|
"const hasRemoteConfig = () => false; const resolveRuntimeMode = () => 'mock'; const runtimeConfig = { baseUrl: '', clientId: 'test', tenantId: 'test' };\n",
|
|
)
|
|
.replace(
|
|
/^import \{ AUTH_TAC_SCENE, assertSmsCode \}[^\n]+\r?\n/m,
|
|
"const AUTH_TAC_SCENE = {}; const assertSmsCode = (value) => value;\n",
|
|
)
|
|
.replace(
|
|
/^import \{ GENEALOGY_ACCESS_PRESET, fromApiGenealogyAccess \}[^\n]+\r?\n/m,
|
|
"const GENEALOGY_ACCESS_PRESET = { MEMBER_ONLY: 'MEMBER_ONLY' }; const fromApiGenealogyAccess = () => GENEALOGY_ACCESS_PRESET.MEMBER_ONLY;\n",
|
|
)
|
|
.replace(
|
|
/^import \{ session \}[^\n]+\r?\n/m,
|
|
"const session = { getToken: () => '', saveToken: () => {} };\n",
|
|
);
|
|
const apiUrl = `data:text/javascript;base64,${Buffer.from(apiSource).toString("base64")}`;
|
|
const { appApi } = await import(apiUrl);
|
|
assert.deepStrictEqual((await appApi.getFeeds("1001")).map((item) => item.id), ["1", "2"]);
|
|
assert.deepStrictEqual((await appApi.getArticles("1001")).map((item) => item.id), ["101", "102", "103"]);
|
|
assert.deepStrictEqual((await appApi.getAlbums("1001")).map((item) => item.id), ["201", "202", "203"]);
|
|
assert.deepStrictEqual(await appApi.getFeeds("1002"), []);
|
|
await assert.rejects(
|
|
appApi.createFeed("1001", { feedContent: "不得写入正式夹具" }),
|
|
(error) => error?.code === "WRITE_UNAVAILABLE" && /不会保存/.test(error.message),
|
|
"mock createFeed 必须明确失败,不能污染只读内容 owner",
|
|
);
|
|
assert.deepStrictEqual(listFamilyFeedFixtures("1001").map((item) => item.id), ["1", "2"]);
|
|
|
|
process.stdout.write("FAMILY-FIXTURE-RUNTIME-SMOKE PASS\n");
|
|
};
|
|
|
|
run().catch((error) => {
|
|
process.stderr.write(`${error.stack || error.message}\n`);
|
|
process.exit(1);
|
|
});
|