Files

120 lines
3.5 KiB
JavaScript

import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import test from "node:test";
const NODE_NAME = "LegacyWidgetWidthFix";
async function loadExtension() {
let extension;
const animationFrames = [];
class LGraphNode {
constructor() {
this.widgets = [];
this.size = [200, 100];
}
addWidget(type, name, value, callback, options) {
const widget = { type, name, value, callback, options, width: 240 };
this.widgets.push(widget);
return widget;
}
addDOMWidget(name, type, element, options) {
const widget = { name, type, element, options, width: 250 };
this.widgets.push(widget);
return widget;
}
addCustomWidget(widget) {
this.widgets.push(widget);
return widget;
}
}
const graph = {
_nodes: [],
dirtyCalls: 0,
setDirtyCanvas() {
this.dirtyCalls += 1;
},
};
const app = {
graph,
registerExtension(value) {
extension = value;
},
};
globalThis.LGraphNode = LGraphNode;
globalThis.LiteGraph = { vueNodesMode: false };
globalThis.__lwwfTestApp = app;
globalThis.requestAnimationFrame = (callback) => {
animationFrames.push(callback);
};
const sourceUrl = new URL("../web/bugfix.js", import.meta.url);
const source = (await readFile(sourceUrl, "utf8")).replace(
'import { app } from "../../scripts/app.js";',
"const app = globalThis.__lwwfTestApp;",
);
const moduleUrl = `data:text/javascript;base64,${Buffer.from(source).toString("base64")}`;
await import(moduleUrl);
return { animationFrames, app, extension, graph, LGraphNode };
}
test("repairs existing and newly-created nodes without re-adding the fix node", async () => {
const { animationFrames, extension, graph, LGraphNode } = await loadExtension();
class FixNode extends LGraphNode {}
FixNode.comfyClass = NODE_NAME;
extension.beforeRegisterNodeDef(FixNode, { name: NODE_NAME });
const existingNode = new LGraphNode();
existingNode.widgets.push({ name: "existing", width: 180 });
graph._nodes.push(existingNode);
const fixNode = new FixNode();
extension.nodeCreated(fixNode);
graph._nodes.push(fixNode);
fixNode.onAdded();
assert.equal(existingNode.widgets[0].width, undefined);
const repairButton = fixNode.widgets.find(
(widget) => widget.name === "Repair widget widths now",
);
assert.ok(repairButton, "the fix node should expose a manual repair button");
const newNode = new LGraphNode();
const normalWidget = newNode.addWidget("number", "new", 0, null, {});
assert.equal(normalWidget.width, undefined);
const directWidget = { name: "direct", width: 300 };
newNode.widgets.push(directWidget);
extension.nodeCreated(newNode);
assert.equal(directWidget.width, undefined);
const deferredWidget = { name: "deferred", width: 320 };
newNode.widgets.push(deferredWidget);
graph._nodes.push(newNode);
animationFrames.splice(0).forEach((callback) => callback());
assert.equal(deferredWidget.width, undefined);
const unusualWidget = { name: "unusual", width: 500 };
existingNode.widgets.push(unusualWidget);
repairButton.callback();
assert.equal(unusualWidget.width, undefined);
directWidget.width = 410;
assert.equal(directWidget.width, undefined, "LiteGraph writes remain blocked");
globalThis.LiteGraph.vueNodesMode = true;
directWidget.width = 410;
assert.equal(directWidget.width, 410, "Vue mode writes remain untouched");
fixNode.onRemoved();
directWidget.width = 430;
assert.equal(directWidget.width, 430, "removal restores stock width writes");
});