From 22aad57bc42279fd09af38b58c8cf8d6de0590e6 Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Mon, 15 May 2023 22:26:03 -0500 Subject: [PATCH] shouldFollowSubgraphs test --- src/tests/ComfyPromptSerializerTests.ts | 134 ++++++++++++++++++++++++ src/tests/UnitTest.ts | 4 + src/tests/main.ts | 78 ++++++++++++++ src/tests/testSuite.ts | 1 + 4 files changed, 217 insertions(+) create mode 100644 src/tests/ComfyPromptSerializerTests.ts create mode 100644 src/tests/UnitTest.ts create mode 100644 src/tests/main.ts create mode 100644 src/tests/testSuite.ts diff --git a/src/tests/ComfyPromptSerializerTests.ts b/src/tests/ComfyPromptSerializerTests.ts new file mode 100644 index 0000000..44723c9 --- /dev/null +++ b/src/tests/ComfyPromptSerializerTests.ts @@ -0,0 +1,134 @@ +import { LGraph, LiteGraph, Subgraph, type SlotLayout } from "@litegraph-ts/core" +import { Watch } from "@litegraph-ts/nodes-basic" +import { expect } from 'vitest' +import UnitTest from "./UnitTest" +import ComfyGraph from "$lib/ComfyGraph"; +import ComfyPromptSerializer from "$lib/components/ComfyPromptSerializer"; +import { ComfyBackendNode } from "$lib/nodes/ComfyBackendNode"; +import ComfyGraphNode from "$lib/nodes/ComfyGraphNode"; + +class MockBackendInput extends ComfyGraphNode { + override isBackendNode = true; + comfyClass: string = "MockBackendInput"; + + static slotLayout: SlotLayout = { + inputs: [ + { name: "in", type: "*" }, + ], + } +} + +LiteGraph.registerNodeType({ + class: MockBackendInput, + title: "Test.MockBackendInput", + desc: "one input", + type: "test/input" +}) + +class MockBackendLink extends ComfyGraphNode { + override isBackendNode = true; + comfyClass: string = "MockBackendLink"; + + static slotLayout: SlotLayout = { + inputs: [ + { name: "in", type: "*" }, + ], + outputs: [ + { name: "out", type: "*" }, + ], + } +} + +LiteGraph.registerNodeType({ + class: MockBackendLink, + title: "Test.MockBackendLink", + desc: "one input, one output", + type: "test/link" +}) + +class MockBackendOutput extends ComfyGraphNode { + override isBackendNode = true; + comfyClass: string = "MockBackendOutput"; + + static slotLayout: SlotLayout = { + outputs: [ + { name: "out", type: "*" }, + ], + } +} + +LiteGraph.registerNodeType({ + class: MockBackendOutput, + title: "Test.MockBackendOutput", + desc: "one output", + type: "test/output" +}) + +export default class ComfyPromptSerializerTests extends UnitTest { + test__serialize__shouldIgnoreFrontend() { + const ser = new ComfyPromptSerializer(); + const graph = new ComfyGraph(); + + const nodeA = LiteGraph.createNode(Watch) + const nodeB = LiteGraph.createNode(Watch) + + graph.add(nodeA) + graph.add(nodeB) + + const result = ser.serialize(graph) + + expect(result.output).toEqual({}) + } + + test__serialize__shouldSerializeBackendNodes() { + const ser = new ComfyPromptSerializer(); + const graph = new ComfyGraph(); + + const input = LiteGraph.createNode(MockBackendInput) + const link = LiteGraph.createNode(MockBackendLink) + const output = LiteGraph.createNode(MockBackendOutput) + + graph.add(input) + graph.add(link) + graph.add(output) + + output.connect(0, link, 0) + link.connect(0, input, 0) + + const result = ser.serialize(graph) + + expect(Object.keys(result.output)).toHaveLength(3); + expect(Object.keys(result.output[input.id].inputs)).toHaveLength(1); + expect(Object.keys(result.output[link.id].inputs)).toHaveLength(1); + expect(Object.keys(result.output[output.id].inputs)).toHaveLength(0); + } + + test__serialize__shouldFollowSubgraphs() { + const ser = new ComfyPromptSerializer(); + const graph = new ComfyGraph(); + + const output = LiteGraph.createNode(MockBackendOutput) + const link = LiteGraph.createNode(MockBackendLink) + const input = LiteGraph.createNode(MockBackendInput) + + const subgraph = LiteGraph.createNode(Subgraph) + const graphInput = subgraph.addGraphInput("testIn", "number") + const graphOutput = subgraph.addGraphOutput("testOut", "number") + + graph.add(output) + subgraph.subgraph.add(link) + graph.add(input) + + output.connect(0, subgraph, 0) + graphInput.innerNode.connect(0, link, 0) + link.connect(0, graphOutput.innerNode, 0) + subgraph.connect(0, input, 0) + + const result = ser.serialize(graph) + + expect(Object.keys(result.output)).toHaveLength(3); + expect(Object.keys(result.output[input.id].inputs)).toHaveLength(1); + expect(Object.keys(result.output[link.id].inputs)).toHaveLength(1); + expect(Object.keys(result.output[output.id].inputs)).toHaveLength(0); + } +} diff --git a/src/tests/UnitTest.ts b/src/tests/UnitTest.ts new file mode 100644 index 0000000..49f3f37 --- /dev/null +++ b/src/tests/UnitTest.ts @@ -0,0 +1,4 @@ +export default abstract class UnitTest { + setUp() { } + tearDown() { } +} diff --git a/src/tests/main.ts b/src/tests/main.ts new file mode 100644 index 0000000..b603b26 --- /dev/null +++ b/src/tests/main.ts @@ -0,0 +1,78 @@ +import { vi, describe, it } from "vitest" +import UnitTest from "./UnitTest" +import * as testSuite from "./testSuite" + +import { LiteGraph } from "@litegraph-ts/core" +import "@litegraph-ts/core" +import "@litegraph-ts/nodes-basic" + +LiteGraph.use_uuids = true; + +// I don't like BDD syntax... +// Emulate minitest instead... +function runTests(ctor: new () => T) { + const instance = new ctor() + const ctorName = instance.constructor.name + const idx = ctorName.indexOf("Tests") + if (idx === -1) { + throw `Invalid test name ${ctorName}, must end with "Tests"` + } + const classCategory = ctorName.substring(0, idx) + describe(classCategory, () => { + const allTopLevelTests: [string, Function][] = [] + const allTests: Record = {} + for (const key of Object.getOwnPropertyNames(Object.getPrototypeOf(instance))) { + if (key.startsWith("test")) { + const keys = key.split("__") + let _ = null; + let category = null; + let testName = null; + if (keys.length == 2) { + [_, testName] = keys + } + else { + [_, category, testName] = keys + } + + const value = instance[key] + if (typeof value === "function") { + const testFn = () => { + instance.setUp() + value.apply(instance) + instance.tearDown() + } + + if (category != null) { + allTests[category] ||= [] + allTests[category].push([testName, testFn]) + } + else { + allTopLevelTests.push([testName, testFn]) + } + } + } + } + + for (const [name, testFn] of allTopLevelTests) { + const should = name.split(/\.?(?=[A-Z])/).join(' ').toLowerCase(); + it(should, testFn.bind(instance)) + } + + for (const [category, tests] of Object.entries(allTests)) { + describe(category, () => { + for (const [name, testFn] of tests) { + const should = name.split(/\.?(?=[A-Z])/).join(' ').toLowerCase(); + it(should, testFn.bind(instance)) + } + }) + } + }) +} + +function runTestSuite() { + for (const ctor of Object.values(testSuite)) { + runTests(ctor as any) + } +} + +runTestSuite(); diff --git a/src/tests/testSuite.ts b/src/tests/testSuite.ts new file mode 100644 index 0000000..f11df41 --- /dev/null +++ b/src/tests/testSuite.ts @@ -0,0 +1 @@ +export { default as ComfyPromptSerializerTests } from "./ComfyPromptSerializerTests"