"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 }; } function loadEditorFactory() { global.Element = class Element {}; global.document = { currentScript: null, styleSheets: [], body: { append() {} }, createElement: () => fakeElement() }; global.window = { Cmap: null, setTimeout, clearTimeout, requestAnimationFrame: (callback) => callback() }; require("../static/cmap/cmap-racket-wiki.js"); return global.window.RacketWikiCmap; } test("a dragged connector endpoint survives collapsing and expanding its submap", () => { const factory = 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 }]); });