120 lines
3.5 KiB
JavaScript
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");
|
|
});
|