diff --git a/browser_tests/tests/subgraph.spec.ts b/browser_tests/tests/subgraph.spec.ts index 2bc4d97115..caf94521b4 100644 --- a/browser_tests/tests/subgraph.spec.ts +++ b/browser_tests/tests/subgraph.spec.ts @@ -372,6 +372,68 @@ test.describe('Subgraph Operations', () => { const deletedNode = await comfyPage.getNodeRefById('2') expect(await deletedNode.exists()).toBe(false) }) + + test.describe('Subgraph copy and paste', () => { + test('Can copy subgraph node by dragging + alt', async ({ + comfyPage + }) => { + await comfyPage.loadWorkflow('basic-subgraph') + + const subgraphNode = await comfyPage.getNodeRefById('2') + + // Get position of subgraph node + const subgraphPos = await subgraphNode.getPosition() + + // Alt + Click on the subgraph node + await comfyPage.page.mouse.move(subgraphPos.x + 16, subgraphPos.y + 16) + await comfyPage.page.keyboard.down('Alt') + await comfyPage.page.mouse.down() + await comfyPage.nextFrame() + + // Drag slightly to trigger the copy + await comfyPage.page.mouse.move(subgraphPos.x + 64, subgraphPos.y + 64) + await comfyPage.page.mouse.up() + await comfyPage.page.keyboard.up('Alt') + + // Find all subgraph nodes + const subgraphNodes = + await comfyPage.getNodeRefsByTitle(NEW_SUBGRAPH_TITLE) + + // Expect a second subgraph node to be created (2 total) + expect(subgraphNodes.length).toBe(2) + }) + + test('Copying subgraph node by dragging + alt creates a new subgraph node with unique type', async ({ + comfyPage + }) => { + await comfyPage.loadWorkflow('basic-subgraph') + + const subgraphNode = await comfyPage.getNodeRefById('2') + + // Get position of subgraph node + const subgraphPos = await subgraphNode.getPosition() + + // Alt + Click on the subgraph node + await comfyPage.page.mouse.move(subgraphPos.x + 16, subgraphPos.y + 16) + await comfyPage.page.keyboard.down('Alt') + await comfyPage.page.mouse.down() + await comfyPage.nextFrame() + + // Drag slightly to trigger the copy + await comfyPage.page.mouse.move(subgraphPos.x + 64, subgraphPos.y + 64) + await comfyPage.page.mouse.up() + await comfyPage.page.keyboard.up('Alt') + + // Find all subgraph nodes and expect all unique IDs + const subgraphNodes = + await comfyPage.getNodeRefsByTitle(NEW_SUBGRAPH_TITLE) + + // Expect the second subgraph node to have a unique type + const nodeType1 = await subgraphNodes[0].getType() + const nodeType2 = await subgraphNodes[1].getType() + expect(nodeType1).not.toBe(nodeType2) + }) + }) }) test.describe('Operations Inside Subgraphs', () => { diff --git a/src/lib/litegraph/src/LGraphCanvas.ts b/src/lib/litegraph/src/LGraphCanvas.ts index 3344fe5ae2..8b11af9ef8 100644 --- a/src/lib/litegraph/src/LGraphCanvas.ts +++ b/src/lib/litegraph/src/LGraphCanvas.ts @@ -2299,6 +2299,8 @@ export class LGraphCanvas const node_data = node.clone()?.serialize() if (node_data?.type != null) { + // Ensure the cloned node is configured against the correct type (especially for SubgraphNodes) + node_data.type = newType const cloned = LiteGraph.createNode(newType) if (cloned) { cloned.configure(node_data)