This commit is contained in:
2026-07-12 21:26:08 +08:00
commit 9dd41afd48
502 changed files with 129901 additions and 0 deletions
+189
View File
@@ -0,0 +1,189 @@
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { createGraphRuntimeState, DEFAULT_RENDERER_VIEWPORT } from "../src/render";
describe("GraphRuntimeState", () => {
it("starts with explicit graph-local state defaults", () => {
const state = createGraphRuntimeState();
assert.deepEqual(state.snapshot(), {
viewport: DEFAULT_RENDERER_VIEWPORT,
positions: {},
pins: {},
hover: null,
selection: null,
selectionSurface: null,
focus: null,
activeGesture: null
});
});
it("updates viewport, hover, selection, focus, pins, positions, and active gesture through one owner", () => {
const state = createGraphRuntimeState({
positions: { a: { x: 100, y: 200 } },
pins: { "wiki/a.md": { x: 100, y: 200 } }
});
state.setViewport({ x: -120, y: 64, scale: 1.75 });
state.setHover({ kind: "node", id: "a" });
state.setSelection({ kind: "node", id: "a" }, "reader");
state.setFocus({ kind: "community", id: "c1" });
state.commitPosition("a", { x: 130, y: 215 });
state.setPins({ "wiki/a.md": { x: 130, y: 215 } });
state.setActiveGesture({
kind: "node-drag",
pointerId: 7,
nodeId: "a",
grabOffset: { x: 12, y: -4 },
startWorldPoint: { x: 100, y: 200 },
wasPinned: true,
locked: true
});
assert.deepEqual(state.snapshot(), {
viewport: { x: -120, y: 64, scale: 1.75 },
positions: { a: { x: 130, y: 215 } },
pins: { "wiki/a.md": { x: 130, y: 215 } },
hover: { kind: "node", id: "a" },
selection: { kind: "node", id: "a" },
selectionSurface: "reader",
focus: { kind: "community", id: "c1" },
activeGesture: {
kind: "node-drag",
pointerId: 7,
nodeId: "a",
grabOffset: { x: 12, y: -4 },
startWorldPoint: { x: 100, y: 200 },
wasPinned: true,
locked: true
}
});
});
it("supports multi selection, community hover, viewport pan gesture, and subscribers", () => {
const state = createGraphRuntimeState();
const snapshots: unknown[] = [];
const unsubscribe = state.subscribe((snapshot) => snapshots.push(snapshot));
state.setSelection({ kind: "nodes", ids: ["a", "b"] });
state.setHover({ kind: "community", id: "c1" });
state.setActiveGesture({
kind: "viewport-pan",
pointerId: 12,
lastScreenPoint: { x: 320, y: 240 },
locked: false
});
unsubscribe();
state.setHover({ kind: "edge", id: "edge-1" });
assert.equal(snapshots.length, 3);
assert.deepEqual(state.snapshot().selection, { kind: "nodes", ids: ["a", "b"] });
assert.equal(state.snapshot().selectionSurface, "selection-panel");
assert.deepEqual(state.snapshot().hover, { kind: "edge", id: "edge-1" });
assert.deepEqual(state.snapshot().activeGesture, {
kind: "viewport-pan",
pointerId: 12,
lastScreenPoint: { x: 320, y: 240 },
locked: false
});
});
it("keeps simulation proposals out of committed positions until explicitly committed", () => {
const state = createGraphRuntimeState({
positions: { a: { x: 100, y: 200 } }
});
const proposal = { a: { x: 300, y: 400 } };
assert.deepEqual(state.snapshot().positions, { a: { x: 100, y: 200 } });
state.setPositions(proposal);
proposal.a.x = 999;
assert.deepEqual(state.snapshot().positions, { a: { x: 300, y: 400 } });
state.commitPosition("a", { x: 320, y: 420 });
assert.deepEqual(state.snapshot().positions, { a: { x: 320, y: 420 } });
});
it("returns cloned snapshots so callers cannot mutate hidden state", () => {
const state = createGraphRuntimeState({
positions: { a: { x: 100, y: 200 } },
pins: { "wiki/a.md": { x: 100, y: 200, coordinateSpace: "world" } },
selection: { kind: "nodes", ids: ["a"] },
activeGesture: {
kind: "node-drag",
pointerId: 1,
nodeId: "a",
grabOffset: { x: 4, y: 5 },
startWorldPoint: { x: 100, y: 200 },
wasPinned: true,
locked: true
}
});
const snapshot = state.snapshot();
snapshot.positions.a.x = 999;
snapshot.pins["wiki/a.md"].x = 999;
if (snapshot.selection?.kind === "nodes") snapshot.selection.ids.push("b");
if (snapshot.activeGesture?.kind === "node-drag") snapshot.activeGesture.grabOffset.x = 999;
if (snapshot.activeGesture?.kind === "node-drag") snapshot.activeGesture.startWorldPoint.x = 999;
assert.deepEqual(state.snapshot().positions, { a: { x: 100, y: 200 } });
assert.deepEqual(state.snapshot().pins, { "wiki/a.md": { x: 100, y: 200, coordinateSpace: "world" } });
assert.deepEqual(state.snapshot().selection, { kind: "nodes", ids: ["a"] });
assert.equal(state.snapshot().selectionSurface, "selection-panel");
assert.deepEqual(state.snapshot().activeGesture, {
kind: "node-drag",
pointerId: 1,
nodeId: "a",
grabOffset: { x: 4, y: 5 },
startWorldPoint: { x: 100, y: 200 },
wasPinned: true,
locked: true
});
});
it("clears graph interaction state without changing viewport, positions, or pins", () => {
const state = createGraphRuntimeState({
viewport: { x: -20, y: 10, scale: 1.5 },
positions: { a: { x: 100, y: 200 } },
pins: { "wiki/a.md": { x: 100, y: 200 } },
hover: { kind: "node", id: "a" },
selection: { kind: "node", id: "a" },
selectionSurface: "reader",
focus: { kind: "community", id: "c1" },
activeGesture: { kind: "community-click", pointerId: 9, communityId: "c1", locked: false }
});
state.clearInteraction();
assert.deepEqual(state.snapshot(), {
viewport: { x: -20, y: 10, scale: 1.5 },
positions: { a: { x: 100, y: 200 } },
pins: { "wiki/a.md": { x: 100, y: 200 } },
hover: null,
selection: null,
selectionSurface: null,
focus: null,
activeGesture: null
});
});
it("preserves pin coordinate space markers across runtime snapshots", () => {
const state = createGraphRuntimeState({
pins: {
"wiki/world.md": { x: 8, y: -12, coordinateSpace: "world" },
"wiki/legacy.md": { x: 80, y: 50, coordinateSpace: "legacy-percent" }
}
});
state.setPins({
"wiki/world.md": { x: 9, y: -13, coordinateSpace: "world" },
"wiki/old.md": { x: 75, y: 40 }
});
assert.deepEqual(state.snapshot().pins, {
"wiki/world.md": { x: 9, y: -13, coordinateSpace: "world" },
"wiki/old.md": { x: 75, y: 40 }
});
});
});