# Conflicts: # CHANGELOG.md # example_workflows/LTX 2.3 Video Outpaint (AusBoss).json # js/input_preview/index.js
126 lines
4.5 KiB
JavaScript
126 lines
4.5 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
CORE_IMAGE_PREVIEW_WIDGET,
|
|
CORE_VIDEO_PREVIEW_WIDGET,
|
|
hideCanvasWidget,
|
|
suppressCoreImagePreview,
|
|
suppressCoreVideoPreview,
|
|
} from "../js/shared/core_preview.mjs";
|
|
|
|
function fakeNode() {
|
|
const node = {
|
|
widgets: [],
|
|
addCustomWidget(widget) {
|
|
this.widgets.push(widget);
|
|
return widget;
|
|
},
|
|
addDOMWidget(name, type, element) {
|
|
const widget = { name, type, element };
|
|
this.widgets.push(widget);
|
|
return widget;
|
|
},
|
|
};
|
|
return node;
|
|
}
|
|
|
|
const isHidden = (widget) =>
|
|
widget.hidden === true && widget.computeSize()[1] === -4 &&
|
|
widget.computeLayoutSize().minHeight === 0;
|
|
|
|
test("a widget the frontend adds later is hidden on arrival", () => {
|
|
const node = fakeNode();
|
|
suppressCoreImagePreview(node);
|
|
const widget = node.addCustomWidget({ name: CORE_IMAGE_PREVIEW_WIDGET });
|
|
assert.ok(isHidden(widget));
|
|
});
|
|
|
|
test("a widget already on the node when we arrive is swept up", () => {
|
|
const node = fakeNode();
|
|
const widget = { name: CORE_IMAGE_PREVIEW_WIDGET };
|
|
node.widgets.push(widget);
|
|
suppressCoreImagePreview(node);
|
|
assert.ok(isHidden(widget));
|
|
});
|
|
|
|
test("only the core preview widget is touched", () => {
|
|
const node = fakeNode();
|
|
suppressCoreImagePreview(node);
|
|
const mine = node.addCustomWidget({ name: "ausboss_input_preview" });
|
|
assert.equal(mine.hidden, undefined);
|
|
assert.equal(typeof mine.computeSize, "undefined");
|
|
});
|
|
|
|
test("the image suppressor also stands down Nodes 2.0's own copy", () => {
|
|
// Nodes 2.0 draws a node's output images under its widgets unless the node
|
|
// sets hideOutputImages (classic never reads it). Left on, Save Image showed
|
|
// the result twice there and grew past the node under it.
|
|
const node = fakeNode();
|
|
assert.equal(node.hideOutputImages, undefined);
|
|
suppressCoreImagePreview(node);
|
|
assert.equal(node.hideOutputImages, true);
|
|
});
|
|
|
|
test("the image and video suppressors do not stand in for each other", () => {
|
|
// They wrap different methods and are flagged separately, so a node that
|
|
// draws both kinds can ask for both.
|
|
const node = fakeNode();
|
|
suppressCoreImagePreview(node);
|
|
const video = node.addDOMWidget(CORE_VIDEO_PREVIEW_WIDGET, "video", {
|
|
style: {},
|
|
});
|
|
assert.equal(video.hidden, undefined, "image suppression must not hide the video widget");
|
|
|
|
suppressCoreVideoPreview(node);
|
|
const second = node.addDOMWidget(CORE_VIDEO_PREVIEW_WIDGET, "video", { style: {} });
|
|
assert.ok(isHidden(second));
|
|
// ...and the one added before suppression is swept on the way in.
|
|
assert.ok(isHidden(video));
|
|
});
|
|
|
|
test("suppressing twice keeps one wrapper, not a growing chain", () => {
|
|
const node = fakeNode();
|
|
const original = node.addCustomWidget;
|
|
suppressCoreImagePreview(node);
|
|
const wrapped = node.addCustomWidget;
|
|
suppressCoreImagePreview(node);
|
|
assert.notEqual(wrapped, original);
|
|
assert.equal(node.addCustomWidget, wrapped);
|
|
});
|
|
|
|
test("hiding is idempotent and never re-stashes a live method", () => {
|
|
const widget = { name: CORE_IMAGE_PREVIEW_WIDGET };
|
|
hideCanvasWidget(widget);
|
|
const hiddenDraw = widget.draw;
|
|
hideCanvasWidget(widget);
|
|
assert.equal(widget.draw, hiddenDraw);
|
|
});
|
|
|
|
test("the DOM widget's element is hidden along with it", () => {
|
|
const node = fakeNode();
|
|
suppressCoreVideoPreview(node);
|
|
const element = { style: {} };
|
|
node.addDOMWidget(CORE_VIDEO_PREVIEW_WIDGET, "video", element);
|
|
assert.equal(element.style.display, "none");
|
|
});
|
|
|
|
// The Crop + Rotate + Pad nodes send no picture of their own, so a core
|
|
// preview on one can only be another node's result: in practice a run from
|
|
// another workflow tab, filed under the same node id. All three kinds stand
|
|
// both core previews down, not just the image node.
|
|
test("every transform node stands down both core previews", async () => {
|
|
const { readFileSync } = await import("node:fs");
|
|
const source = readFileSync(new URL("../js/shared/transform_editor.mjs", import.meta.url), "utf-8");
|
|
const install = source.slice(source.indexOf("export function installTransformNode"), source.indexOf("function installVideoDrop"));
|
|
assert.match(install, /\n\s*suppressCoreImagePreview\(node\);/);
|
|
assert.match(install, /\n\s*suppressCoreVideoPreview\(node\);/);
|
|
assert.doesNotMatch(install, /if \(kind === "image"\) suppressCoreImagePreview/);
|
|
});
|
|
|
|
test("the video suppression also stands down Nodes 2.0's own output copy", () => {
|
|
const node = fakeNode();
|
|
suppressCoreVideoPreview(node);
|
|
assert.equal(node.hideOutputImages, true);
|
|
});
|