Files
90-RED-ComfyUI-LinkRouter/tests/drag-policy.test.mjs
T
90-RED 3474927aee v1.3.0 — Web Worker routing, profiler disk export, stretch extraction
- Web Worker routing — A* search runs in a background Worker thread,
  keeping the UI responsive during large batch routes
- Worker watchdog — auto-falls back to main-thread routing on any failure
- Worker held-pause — drag-pause re-routes also run in worker
- stretch.js — extracted sticky-path logic, shared by main thread and worker
- Profiler disk export — POST /linkrouter/write_log endpoint saves reports
- Chunked worker processing — 8ms macrotask slices for cancel responsiveness
- New settings: Background worker routing, Held-pause in worker
2026-07-19 06:36:24 +08:00

154 lines
5.5 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import {
orderHeldRouteCandidates,
pathBounds,
pauseRevealCount,
shouldFreezeHiddenModeLink,
shouldQueueIdleCleanup,
shouldRacePauseLink,
shouldRouteHeldCollision,
shouldStretchDragPath,
shouldUseDragSettle,
} from "../web/drag-policy.js";
test("passive Vue node size updates do not enter drag-settle mode", () => {
assert.equal(
shouldUseDragSettle(true, { positionChanges: 0, sizeChanges: 1 }, {}),
false,
);
});
test("held reroutes prioritize self, viewport, then expand outward", () => {
const viewport = { x: 0, y: 0, x2: 100, y2: 100 };
const ordered = orderHeldRouteCandidates([
{ id: "far", direct: false, bounds: { x: 300, y: 0, x2: 320, y2: 20 } },
{ id: "visible", direct: false, bounds: { x: 20, y: 20, x2: 40, y2: 40 } },
{ id: "self", direct: true, bounds: { x: 500, y: 500, x2: 520, y2: 520 } },
{ id: "near", direct: false, bounds: { x: 120, y: 0, x2: 140, y2: 20 } },
], viewport);
assert.deepEqual(ordered.map((item) => item.id), ["self", "visible", "near", "far"]);
assert.deepEqual(pathBounds([{ x: 5, y: 9 }, { x: -2, y: 20 }]), {
x: -2, y: 9, x2: 5, y2: 20,
});
});
test("a held direct link bypasses the unrelated-link freeze branch", () => {
assert.equal(shouldFreezeHiddenModeLink(true, true, false), false);
assert.equal(shouldFreezeHiddenModeLink(false, true, false), true);
assert.equal(shouldFreezeHiddenModeLink(false, true, true), false);
});
test("idle cleanup only queues stale Freeze+Check paths after primary work", () => {
assert.equal(shouldQueueIdleCleanup("freeze-others", true, false, true), true);
assert.equal(shouldQueueIdleCleanup("freeze-others", true, true, true), false);
assert.equal(shouldQueueIdleCleanup("freeze-others-strict", true, false, true), false);
assert.equal(shouldQueueIdleCleanup("freeze-others", false, false, true), false);
});
test("frozen modes slowly route collisions while held still", () => {
assert.equal(shouldRouteHeldCollision("none", true, true), false);
assert.equal(shouldRouteHeldCollision("freeze-others", true, true), true);
assert.equal(shouldRouteHeldCollision("freeze-others-strict", false, true), false);
assert.equal(shouldRouteHeldCollision("freeze-others-strict", true, false), false);
assert.equal(shouldRouteHeldCollision("freeze-others-strict", true, true), true);
assert.equal(shouldRouteHeldCollision("hide-self", true, true), true);
assert.equal(shouldRouteHeldCollision("hide-self", true, true, true), false);
});
test("real node movement and resize handles still use drag settle", () => {
assert.equal(shouldUseDragSettle(true, { positionChanges: 1 }, {}), true);
assert.equal(
shouldUseDragSettle(true, { positionChanges: 0, sizeChanges: 1 }, { resizing_node: {} }),
true,
);
assert.equal(shouldUseDragSettle(false, { positionChanges: 1 }, {}), false);
});
test("sticky stretching never masks live avoidance for a collided link", () => {
assert.equal(
shouldStretchDragPath({
dragging: true,
hasCachedPath: true,
endsMoved: false,
hitDirty: true,
effectiveMode: "freeze-others",
}),
false,
);
assert.equal(
shouldStretchDragPath({
dragging: true,
hasCachedPath: true,
endsMoved: true,
hitDirty: false,
effectiveMode: "freeze-others-strict",
}),
true,
);
assert.equal(
shouldStretchDragPath({
dragging: true,
hasCachedPath: true,
endsMoved: true,
hitDirty: true,
effectiveMode: "freeze-others-strict",
}),
false,
);
});
test("small and medium live modes may stretch only after geometry validates the path", () => {
for (const effectiveMode of ["none", "freeze-others"]) {
assert.equal(
shouldStretchDragPath({
dragging: true,
hasCachedPath: true,
endsMoved: true,
hitDirty: false,
effectiveMode,
}),
true,
`${effectiveMode} should keep a collision-free path stable`,
);
}
});
test("pause reveal drains the whole queue in one frame", () => {
assert.equal(pauseRevealCount(0), 0);
assert.equal(pauseRevealCount(-3), 0);
assert.equal(pauseRevealCount(1), 1);
assert.equal(pauseRevealCount(17), 17);
assert.equal(pauseRevealCount(500), 500);
const framesToDrain = (n) => {
let remaining = n;
let frames = 0;
while (remaining > 0) {
remaining -= Math.min(pauseRevealCount(remaining), remaining);
frames++;
}
return frames;
};
// Pacing was removed: measured pauses last ~100-130ms, so trickled reveals
// never reached the tail links before the drag resumed and discarded them.
for (let n = 1; n <= 500; n++)
assert.equal(framesToDrain(n), 1, `queue ${n} should drain in one frame`);
});
test("held-pause race only takes predicted-cheap links", () => {
assert.equal(shouldRacePauseLink(3, 8, 10), true);
assert.equal(shouldRacePauseLink(9.9, 8, 10), true);
assert.equal(shouldRacePauseLink(10, 8, 10), false); // boundary: not cheaper
assert.equal(shouldRacePauseLink(42, 8, 10), false);
// Unknown links fall back to the session average (usually cheap).
assert.equal(shouldRacePauseLink(undefined, 8, 10), true);
assert.equal(shouldRacePauseLink(undefined, 10, 10), false);
// The race call site now passes an infinite fallback: links without a
// main-thread-measured cost are never raced (worker timings and session
// averages mis-predicted 19-49ms routes as cheap).
assert.equal(shouldRacePauseLink(undefined, Infinity, 10), false);
assert.equal(shouldRacePauseLink(3, Infinity, 10), true);
});