Files
racket-wiki/test/cmap-connector-rewire.test.js
T
2026-09-02 08:38:03 +02:00

176 lines
4.1 KiB
JavaScript

"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
function fakeElement() {
return {
className: "rw-cmap-item",
style: {},
dataset: {},
querySelector: () => null,
querySelectorAll: () => [],
remove() {},
addEventListener() {},
classList: { add() {}, remove() {}, toggle() {} },
setAttribute() {},
removeAttribute() {}
};
}
function fakeNode(attributes) {
const state = { ...attributes };
return {
attr(value) {
if (typeof value === "string") return state[value];
Object.assign(state, value);
return this;
},
onRendered() {},
onMove() {},
onMoveEnd() {},
visible() {},
redraw() {},
toFront() {},
remove() {},
element: () => null
};
}
function fakeLink(attributes) {
const state = { ...attributes };
let source = null;
let target = null;
let connectionChangeHandler = null;
return {
attr(value) {
if (typeof value === "string") return state[value];
Object.assign(state, value);
return this;
},
sourceNode(value) {
if (arguments.length === 0) return source;
source = value;
return this;
},
targetNode(value) {
if (arguments.length === 0) return target;
target = value;
return this;
},
onConnectionChange(handler) { connectionChangeHandler = handler; },
triggerConnectionChange(type, node) {
if (type === "source") source = node;
if (type === "target") target = node;
connectionChangeHandler(this, type, node);
},
onRendered() {},
visible() {},
straighten() {},
draggable() {},
redraw() {},
remove() {},
element: () => null
};
}
async function loadEditorFactory() {
global.Element = class Element {};
global.document = {
currentScript: null,
styleSheets: [],
body: { append() {} },
createElement: () => fakeElement()
};
global.window = {
Cmap: null,
setTimeout,
clearTimeout,
requestAnimationFrame: (callback) => callback()
};
await import("../static/cmap/cmap-racket-wiki.js");
return global.window.RacketWikiCmap;
}
test("a dragged connector endpoint survives collapsing and expanding its submap", async () => {
const factory = await loadEditorFactory();
const links = [];
const map = {
onSelection() {},
onActivation() {},
node: (attributes) => fakeNode(attributes),
link(attributes) {
const link = fakeLink(attributes);
links.push(link);
return link;
}
};
const canvas = {
addEventListener() {},
querySelector: () => null,
clientWidth: 1200,
clientHeight: 800,
scrollLeft: 0,
scrollTop: 0,
isConnected: true
};
const editor = factory.createEditor(canvas, { Cmap: () => map });
const submap = editor.addItem({
id: 1,
kind: "submap",
label: "Problemen en Symptomen LTS Model",
x: 300,
y: 200,
width: 320,
height: 70
});
submap.expanded = true;
submap.submapInitialized = true;
const problems = editor.addItem({
id: 2,
kind: "phrase",
label: "problemen",
parentSubmap: submap,
submapDepth: 1,
x: 400,
y: 300
});
const symptoms = editor.addItem({
id: 3,
kind: "phrase",
label: "Symptomen",
parentSubmap: submap,
submapDepth: 1,
x: 400,
y: 500
});
const concept = editor.addItem({
id: 4,
kind: "concept",
label: "Rob maakt veel fouten",
parentSubmap: submap,
submapDepth: 1,
x: 800,
y: 400
});
const connector = editor.addConnector(problems, concept, true, { id: 1 });
links[0].triggerConnectionChange("source", symptoms.node);
assert.equal(connector.source, symptoms,
"the editor model follows the endpoint dragged by the drawing library");
editor.toggleSubmap(submap, false);
editor.toggleSubmap(submap, true);
assert.equal(connector.source, symptoms);
assert.equal(connector.link.sourceNode(), symptoms.node);
assert.deepEqual(editor.toDocument().connectors, [{
id: 1,
sourceId: symptoms.id,
targetId: concept.id,
hasArrow: true,
lineColor: "#333",
lineWidth: 2
}]);
});