Files
olivv-cs-ComfyUI-FunPack/app/ui/composer/tests/drag.test.js
T

153 lines
5.0 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { setupDom, teardownDom } from "./_dom.js";
import { drag } from "../internals/drag.js";
test.beforeEach(() => setupDom());
test.after(() => teardownDom());
function handle() {
const n = document.createElement("div");
document.body.appendChild(n);
// jsdom has PointerEvent but not the capture API; the kit guards for both, so
// record the calls to prove the guards do the right thing.
n.captured = [];
n.setPointerCapture = (id) => n.captured.push(id);
n.releasePointerCapture = (id) => { n.captured = n.captured.filter((c) => c !== id); };
n.hasPointerCapture = (id) => n.captured.includes(id);
return n;
}
const pointer = (node, type, { x = 0, y = 0, id = 1, button = 0 } = {}) =>
node.dispatchEvent(new window.PointerEvent(type, {
clientX: x, clientY: y, pointerId: id, button, bubbles: true, cancelable: true,
}));
test("reports movement relative to where the drag began", () => {
const h = handle();
const moves = [];
drag(h, { onMove: (m) => moves.push([m.dx, m.dy]) });
pointer(h, "pointerdown", { x: 100, y: 100 });
pointer(h, "pointermove", { x: 130, y: 90 });
pointer(h, "pointermove", { x: 100, y: 100 });
assert.deepEqual(moves, [[30, -10], [0, 0]]);
});
test("start, move and end all fire, with the final delta on end", () => {
const h = handle();
const seen = [];
drag(h, {
onStart: () => seen.push("start"),
onMove: () => seen.push("move"),
onEnd: (e) => seen.push(`end:${e.dx},${e.dy}`),
});
pointer(h, "pointerdown", { x: 10, y: 10 });
pointer(h, "pointermove", { x: 15, y: 20 });
pointer(h, "pointerup", { x: 25, y: 30 });
assert.deepEqual(seen, ["start", "move", "end:15,20"]);
});
test("the pointer is captured for the drag and released after", () => {
// Capture is what guarantees a pointerup even when the cursor leaves the
// window; without it a drag can be left running forever.
const h = handle();
drag(h);
pointer(h, "pointerdown", { x: 0, y: 0, id: 7 });
assert.deepEqual(h.captured, [7]);
pointer(h, "pointerup", { x: 0, y: 0, id: 7 });
assert.deepEqual(h.captured, []);
});
test("moves before a pointerdown are ignored", () => {
const h = handle();
let moved = false;
drag(h, { onMove: () => { moved = true; } });
pointer(h, "pointermove", { x: 50, y: 50 });
assert.equal(moved, false);
});
test("moves after the drag ends are ignored", () => {
const h = handle();
let moves = 0;
drag(h, { onMove: () => { moves += 1; } });
pointer(h, "pointerdown", { x: 0, y: 0 });
pointer(h, "pointermove", { x: 5, y: 5 });
pointer(h, "pointerup", { x: 5, y: 5 });
pointer(h, "pointermove", { x: 99, y: 99 });
assert.equal(moves, 1);
});
test("a second pointer does not hijack a drag in progress", () => {
// Two fingers on a trim handle would otherwise interleave deltas from both.
const h = handle();
const moves = [];
drag(h, { onMove: (m) => moves.push(m.dx) });
pointer(h, "pointerdown", { x: 0, y: 0, id: 1 });
pointer(h, "pointermove", { x: 10, y: 0, id: 2 });
pointer(h, "pointermove", { x: 20, y: 0, id: 1 });
assert.deepEqual(moves, [20]);
});
test("a second pointerdown while dragging is ignored", () => {
const h = handle();
let starts = 0;
drag(h, { onStart: () => { starts += 1; } });
pointer(h, "pointerdown", { x: 0, y: 0, id: 1 });
pointer(h, "pointerdown", { x: 5, y: 5, id: 2 });
assert.equal(starts, 1);
});
test("only the configured button starts a drag", () => {
const h = handle();
let starts = 0;
drag(h, { onStart: () => { starts += 1; } });
pointer(h, "pointerdown", { x: 0, y: 0, button: 2 }); // right-click
assert.equal(starts, 0);
pointer(h, "pointerdown", { x: 0, y: 0, button: 0 });
assert.equal(starts, 1);
});
test("pointercancel ends the drag and says it was cancelled", () => {
const h = handle();
let end = null;
drag(h, { onEnd: (e) => { end = e; } });
pointer(h, "pointerdown", { x: 0, y: 0 });
pointer(h, "pointercancel", { x: 9, y: 9 });
assert.equal(end.cancelled, true);
assert.deepEqual(h.captured, [], "capture is released on cancel too");
});
test("pointerdown is prevented, so a drag does not also select text", () => {
const h = handle();
drag(h);
const event = new window.PointerEvent("pointerdown", {
clientX: 0, clientY: 0, pointerId: 1, button: 0, bubbles: true, cancelable: true,
});
h.dispatchEvent(event);
assert.equal(event.defaultPrevented, true);
});
test("dispose stops listening, mid-drag included", () => {
const h = handle();
let moves = 0;
const dispose = drag(h, { onMove: () => { moves += 1; } });
pointer(h, "pointerdown", { x: 0, y: 0 });
dispose();
pointer(h, "pointermove", { x: 10, y: 10 });
assert.equal(moves, 0);
assert.deepEqual(h.captured, [], "a disposed drag does not keep the pointer");
});
test("a drag with no callbacks does not throw", () => {
const h = handle();
drag(h);
assert.doesNotThrow(() => {
pointer(h, "pointerdown", { x: 0, y: 0 });
pointer(h, "pointermove", { x: 1, y: 1 });
pointer(h, "pointerup", { x: 1, y: 1 });
});
});