import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { runInNewContext } from "node:vm"; const source = readFileSync(new URL("../web/js/omniFlashVideo.js", import.meta.url), "utf8") .replace(/^import .*;\s*/m, ""); const migrationSource = readFileSync(new URL("../web/js/migrateWorkflow.js", import.meta.url), "utf8") .replace(/^import .*;\s*/gm, ""); let extension; const queued = []; const app = { registerExtension(value) { extension = value; }, async queuePrompt(...args) { queued.push(args); }, }; runInNewContext(source, { app }); const node = { comfyClass: "O1keyOmniFlashVideo", id: 42, widgets: [], addWidget(_type, name, _value, callback, options) { const widget = { name, callback, options }; this.widgets.push(widget); return widget; }, }; extension.nodeCreated(node); extension.loadedGraphNode(node); assert.equal(node.widgets.length, 1); assert.equal(node.widgets[0].name, "开始生成"); assert.equal(node.widgets[0].options.serialize, false); await node.widgets[0].callback(); assert.deepEqual(JSON.parse(JSON.stringify(queued)), [[0, 1, [42]]]); const mode = { name: "生成模式", value: "文生视频", callback() {} }; const autogrow = { names: ["参考图片1", "参考图片2"], min: 0 }; const removedLinks = []; const videoNode = { comfyClass: "O1keyOmniFlashVideo", id: 43, widgets: [mode], comfyDynamic: { autogrow: { 参考图片: autogrow } }, inputs: [ { name: "参考图片.参考图片1", type: "IMAGE", link: null }, { name: "首帧图片", type: "IMAGE", link: null }, { name: "尾帧图片", type: "IMAGE", link: null }, { name: "源视频", type: "VIDEO", link: null }, { name: "提示词", type: "STRING", link: 99 }, ], addWidget: node.addWidget, addInput(name, type, options) { this.inputs.push({ name, type, ...options, link: null }); }, removeInput(index) { if (this.inputs[index].link != null) removedLinks.push(this.inputs[index].link); this.onConnectionsChange?.(1, index, false); this.inputs.splice(index, 1); }, }; const names = () => videoNode.inputs.map((input) => input.name); extension.nodeCreated(videoNode); assert.deepEqual(names(), ["提示词"]); mode.value = "参考图视频"; mode.callback(mode.value); assert.deepEqual(names(), ["提示词", "参考图片.参考图片1"]); videoNode.inputs.at(-1).link = 12; mode.value = "视频编辑"; mode.callback(mode.value); assert.deepEqual(names(), ["提示词", "参考图片.参考图片1", "源视频"]); assert.equal(videoNode.inputs.find((input) => input.name === "参考图片.参考图片1").link, 12); mode.value = "首尾帧"; mode.callback(mode.value); assert.deepEqual(names(), ["提示词", "首帧图片", "尾帧图片"]); assert.deepEqual(removedLinks, [12]); assert.equal(videoNode.comfyDynamic.autogrow.参考图片, undefined); extension.loadedGraphNode(videoNode); assert.deepEqual(names(), ["提示词", "首帧图片", "尾帧图片"]); mode.value = "文生视频"; mode.callback(mode.value); assert.deepEqual(names(), ["提示词"]); mode.value = "参考图视频"; mode.callback(mode.value); assert.equal(videoNode.comfyDynamic.autogrow.参考图片, autogrow); assert.deepEqual(names(), ["提示词", "参考图片.参考图片1"]); let migrationExtension; runInNewContext(migrationSource, { app: { registerExtension(extension) { migrationExtension = extension; } }, console: { log() {}, warn() {} }, }); const legacyValues = ["提示词", "文生视频", "omni_flash_8s", "1080p", "9:16"]; const graph = { nodes: [{ type: "O1keyOmniFlashVideo", widgets_values: legacyValues }] }; migrationExtension.beforeConfigureGraph(graph); assert.deepEqual(legacyValues, ["提示词", "文生视频", "1080p", "9:16"]); migrationExtension.beforeConfigureGraph(graph); assert.deepEqual(legacyValues, ["提示词", "文生视频", "1080p", "9:16"]);