diff --git a/src/composables/graph/useGraphNodeManager.ts b/src/composables/graph/useGraphNodeManager.ts index 68e74c0b5..786e23f4e 100644 --- a/src/composables/graph/useGraphNodeManager.ts +++ b/src/composables/graph/useGraphNodeManager.ts @@ -245,17 +245,10 @@ export function useGraphNodeManager(graph: LGraph): GraphNodeManager { }) // Update only widgets with new slot metadata, keeping other widget data intact - const updatedWidgets = currentData.widgets?.map((widget) => { + for (const widget of currentData.widgets ?? []) { const slotInfo = slotMetadata.get(widget.name) - return slotInfo ? { ...widget, slotMetadata: slotInfo } : widget - }) - - vueNodeData.set(nodeId, { - ...currentData, - widgets: updatedWidgets, - inputs: nodeRef.inputs ? [...nodeRef.inputs] : undefined, - outputs: nodeRef.outputs ? [...nodeRef.outputs] : undefined - }) + if (slotInfo) widget.slotMetadata = slotInfo + } } // Extract safe data from LiteGraph node for Vue consumption diff --git a/tests-ui/tests/composables/graph/useGraphNodeManager.test.ts b/tests-ui/tests/composables/graph/useGraphNodeManager.test.ts new file mode 100644 index 000000000..ba22d98cd --- /dev/null +++ b/tests-ui/tests/composables/graph/useGraphNodeManager.test.ts @@ -0,0 +1,49 @@ +import { setActivePinia } from 'pinia' +import { createTestingPinia } from '@pinia/testing' +import { describe, expect, it, vi } from 'vitest' +import { nextTick, watch } from 'vue' + +import { useGraphNodeManager } from '@/composables/graph/useGraphNodeManager' +import { LGraph, LGraphNode } from '@/lib/litegraph/src/litegraph' +import { NodeSlotType } from '@/lib/litegraph/src/types/globalEnums' + +setActivePinia(createTestingPinia()) + +function createTestGraph() { + const graph = new LGraph() + const node = new LGraphNode('test') + node.addInput('input', 'INT') + node.addWidget('number', 'testnum', 2, () => undefined, {}) + graph.add(node) + + const { vueNodeData } = useGraphNodeManager(graph) + const onReactivityUpdate = vi.fn() + watch(vueNodeData, onReactivityUpdate) + + return [node, graph, onReactivityUpdate] as const +} + +describe('Node Reactivity', () => { + it('should trigger on callback', async () => { + const [node, , onReactivityUpdate] = createTestGraph() + + node.widgets![0].callback!(2) + await nextTick() + expect(onReactivityUpdate).toHaveBeenCalledTimes(1) + }) + + it('should remain reactive after a connection is made', async () => { + const [node, graph, onReactivityUpdate] = createTestGraph() + + graph.trigger('node:slot-links:changed', { + nodeId: '1', + slotType: NodeSlotType.INPUT + }) + await nextTick() + onReactivityUpdate.mockClear() + + node.widgets![0].callback!(2) + await nextTick() + expect(onReactivityUpdate).toHaveBeenCalledTimes(1) + }) +})