refactoring of cmaps, widgets, etc.
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { CmapJsonExporter } from "../static/cmap/model/json-exporter.js";
|
||||
import { CmapJsonImporter } from "../static/cmap/model/json-importer.js";
|
||||
import {
|
||||
CmapRepository,
|
||||
StoredConceptMap
|
||||
} from "../static/cmap/model/cmap-repository.js";
|
||||
import { CmapModel } from "../static/cmap/model/concept-map.js";
|
||||
|
||||
const conceptId = "11111111-1111-4111-8111-111111111111";
|
||||
const rootMap = {
|
||||
slug: "root",
|
||||
title: "Root",
|
||||
document: {
|
||||
schemaVersion: 2,
|
||||
metadata: { explanationPageSlug: "root-page" },
|
||||
concepts: [{ id: conceptId, label: "Root concept" }],
|
||||
items: [{ id: 1, conceptId, kind: "concept", x: 10, y: 20 }],
|
||||
connectors: []
|
||||
}
|
||||
};
|
||||
const page = {
|
||||
slug: "root-page",
|
||||
title: "Root page",
|
||||
markdown: "",
|
||||
tags: []
|
||||
};
|
||||
const storedRootMap = new StoredConceptMap(rootMap, CmapModel.fromDocument(rootMap.document));
|
||||
const cmapRepository = { load: async () => { throw new Error("no linked map expected"); } };
|
||||
|
||||
test("CmapJsonExporter builds a complete bundle including attachments", async () => {
|
||||
const exporter = new CmapJsonExporter(
|
||||
cmapRepository,
|
||||
async () => page,
|
||||
async () => ({
|
||||
ok: true,
|
||||
headers: { get: () => "image/png" },
|
||||
arrayBuffer: async () => Uint8Array.from([1, 2, 3]).buffer
|
||||
}),
|
||||
"test"
|
||||
);
|
||||
|
||||
const bundle = await exporter.export(storedRootMap);
|
||||
|
||||
assert.equal(bundle.generator, "test");
|
||||
assert.equal(bundle.pages[0].attachments[0].contentBase64, "AQID");
|
||||
});
|
||||
|
||||
test("CmapJsonImporter reports conflicts and imports pages, attachments and maps", async () => {
|
||||
const calls = [];
|
||||
const api = async (path, options = {}) => {
|
||||
calls.push({ path, options });
|
||||
if (path.endsWith("/upload")) return { url: "/uploads/root-page/imported-image.png" };
|
||||
if (path === "/api/pages" && options.method === "POST") return { currentVersion: 1 };
|
||||
if (path === "/api/cmaps" && options.method === "POST") {
|
||||
const body = JSON.parse(options.body);
|
||||
return {
|
||||
slug: body.slug,
|
||||
title: body.title,
|
||||
currentVersion: 1,
|
||||
document: body.document
|
||||
};
|
||||
}
|
||||
return {};
|
||||
};
|
||||
const importer = new CmapJsonImporter(
|
||||
new CmapRepository(api), api, (_key, fallback) => fallback);
|
||||
const exporter = new CmapJsonExporter(
|
||||
cmapRepository,
|
||||
async () => page,
|
||||
async () => ({
|
||||
ok: true,
|
||||
headers: { get: () => "image/png" },
|
||||
arrayBuffer: async () => Uint8Array.from([1, 2, 3]).buffer
|
||||
})
|
||||
);
|
||||
const bundle = await exporter.export(storedRootMap);
|
||||
const file = { size: 100, text: async () => JSON.stringify(bundle) };
|
||||
|
||||
const parsed = await importer.read(file);
|
||||
assert.equal(parsed.rootCmapSlug, "root");
|
||||
assert.deepEqual(importer.conflicts(parsed, [{ slug: "root-page" }], []), {
|
||||
pages: [parsed.pages[0]],
|
||||
conceptMaps: []
|
||||
});
|
||||
|
||||
const result = await importer.import(parsed, {
|
||||
pages: [], conceptMaps: [], summary: "Imported"
|
||||
});
|
||||
assert.equal(result.pagesCreated, 1);
|
||||
assert.equal(result.mapsCreated, 1);
|
||||
assert.equal(result.attachmentsImported, 1);
|
||||
assert.deepEqual(calls.map((call) => `${call.options.method} ${call.path}`), [
|
||||
"POST /api/pages",
|
||||
"POST /api/pages/root-page/upload",
|
||||
"PUT /api/pages/root-page",
|
||||
"POST /api/cmaps"
|
||||
]);
|
||||
const pageUpdate = JSON.parse(calls[2].options.body);
|
||||
assert.match(pageUpdate.markdown, /imported-image\.png/);
|
||||
});
|
||||
Reference in New Issue
Block a user