diff --git a/src/core/graph/widgets/dynamicWidgets.ts b/src/core/graph/widgets/dynamicWidgets.ts index 3058e8131..21913dedd 100644 --- a/src/core/graph/widgets/dynamicWidgets.ts +++ b/src/core/graph/widgets/dynamicWidgets.ts @@ -277,6 +277,7 @@ function withComfyMatchType(node: LGraphNode): asserts node is MatchTypeNode { ) { const input = this.inputs[slot] if (contype !== LiteGraph.INPUT || !this.graph || !input) return + if (app.configuringGraph) return const [matchKey, matchGroup] = Object.entries( this.comfyDynamic.matchType ).find(([, group]) => input.name in group) ?? ['', undefined] diff --git a/src/core/graph/widgets/matchTypeConfiguring.test.ts b/src/core/graph/widgets/matchTypeConfiguring.test.ts new file mode 100644 index 000000000..45179b0f5 --- /dev/null +++ b/src/core/graph/widgets/matchTypeConfiguring.test.ts @@ -0,0 +1,129 @@ +import { createTestingPinia } from '@pinia/testing' +import { setActivePinia } from 'pinia' +import { beforeEach, describe, expect, test, vi } from 'vitest' + +import { LGraph, LGraphNode, LiteGraph } from '@/lib/litegraph/src/litegraph' +import { transformInputSpecV1ToV2 } from '@/schemas/nodeDef/migration' +import { app } from '@/scripts/app' +import { useLitegraphService } from '@/services/litegraphService' + +setActivePinia(createTestingPinia()) + +const { addNodeInput } = useLitegraphService() + +function createMatchTypeNode(graph: LGraph) { + const node = new LGraphNode('switch') + ;(node.constructor as { nodeData: unknown }).nodeData = { + name: 'ComfySwitchAny', + output_matchtypes: ['a'] + } + node.addOutput('out', '*') + graph.add(node) + + addNodeInput( + node, + transformInputSpecV1ToV2( + [ + 'COMFY_MATCHTYPE_V3', + { template: { allowed_types: '*', template_id: 'a' } } + ], + { name: 'on_true', isOptional: false } + ) + ) + addNodeInput( + node, + transformInputSpecV1ToV2( + [ + 'COMFY_MATCHTYPE_V3', + { template: { allowed_types: '*', template_id: 'a' } } + ], + { name: 'on_false', isOptional: false } + ) + ) + + return node +} + +function createSourceNode(graph: LGraph, type: string) { + const node = new LGraphNode('source') + node.addOutput('out', type) + graph.add(node) + return node +} + +describe('MatchType during configure', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + test('skips type recalculation when configuringGraph is true', () => { + const graph = new LGraph() + const switchNode = createMatchTypeNode(graph) + const source1 = createSourceNode(graph, 'IMAGE') + const source2 = createSourceNode(graph, 'IMAGE') + + source1.connect(0, switchNode, 0) + source2.connect(0, switchNode, 1) + + expect(switchNode.inputs[0].link).not.toBeNull() + expect(switchNode.inputs[1].link).not.toBeNull() + + const link1Id = switchNode.inputs[0].link! + const link2Id = switchNode.inputs[1].link! + + const outputTypeBefore = switchNode.outputs[0].type + ;( + app as unknown as { configuringGraphLevel: number } + ).configuringGraphLevel = 1 + + try { + const link1 = graph.links[link1Id] + switchNode.onConnectionsChange?.( + LiteGraph.INPUT, + 0, + true, + link1, + switchNode.inputs[0] + ) + + expect(switchNode.inputs[0].link).toBe(link1Id) + expect(switchNode.inputs[1].link).toBe(link2Id) + expect(graph.links[link1Id]).toBeDefined() + expect(graph.links[link2Id]).toBeDefined() + expect(switchNode.outputs[0].type).toBe(outputTypeBefore) + } finally { + ;( + app as unknown as { configuringGraphLevel: number } + ).configuringGraphLevel = 0 + } + }) + + test('performs type recalculation during normal operation', () => { + const graph = new LGraph() + const switchNode = createMatchTypeNode(graph) + const source1 = createSourceNode(graph, 'IMAGE') + + expect(app.configuringGraph).toBe(false) + + source1.connect(0, switchNode, 0) + + expect(switchNode.inputs[0].link).not.toBeNull() + expect(switchNode.outputs[0].type).toBe('IMAGE') + }) + + test('connects both inputs with same type', () => { + const graph = new LGraph() + const switchNode = createMatchTypeNode(graph) + const source1 = createSourceNode(graph, 'IMAGE') + const source2 = createSourceNode(graph, 'IMAGE') + + expect(app.configuringGraph).toBe(false) + + source1.connect(0, switchNode, 0) + source2.connect(0, switchNode, 1) + + expect(switchNode.inputs[0].link).not.toBeNull() + expect(switchNode.inputs[1].link).not.toBeNull() + expect(switchNode.outputs[0].type).toBe('IMAGE') + }) +})