Skip to content

Commit 70314be

Browse files
committed
Fix IO Node Copy + Paste
1 parent 174009d commit 70314be

File tree

4 files changed

+170
-114
lines changed

4 files changed

+170
-114
lines changed

src/components/shared/ReactFlow/FlowCanvas/utils/addTask.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ describe("addTask", () => {
123123
? Object.keys(newComponentSpec.implementation.graph.tasks)
124124
: [];
125125
expect(taskIds.length).toBe(2);
126-
expect(taskIds).toContain("TestTask 2");
126+
expect(taskIds).toContain("TestTask (2)");
127127
});
128128

129129
it("should create unique names for inputs when duplicates exist", () => {
@@ -139,7 +139,7 @@ describe("addTask", () => {
139139
};
140140

141141
expect(newComponentSpec.inputs.length).toBe(2);
142-
expect(newComponentSpec.inputs[1].name).toBe("Input 2");
142+
expect(newComponentSpec.inputs[1].name).toBe("Input (2)");
143143
});
144144

145145
it("should create unique names for outputs when duplicates exist", () => {
@@ -155,6 +155,6 @@ describe("addTask", () => {
155155
};
156156

157157
expect(newComponentSpec.outputs.length).toBe(2);
158-
expect(newComponentSpec.outputs[1].name).toBe("Output 2");
158+
expect(newComponentSpec.outputs[1].name).toBe("Output (2)");
159159
});
160160
});

src/components/shared/ReactFlow/FlowCanvas/utils/duplicateNodes.test.ts

Lines changed: 57 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import { describe, expect, it, vi } from "vitest";
33

44
import { NodeManager } from "@/nodeManager";
55
import type { TaskNodeData } from "@/types/nodes";
6-
import type {
7-
ComponentSpec,
8-
InputSpec,
9-
OutputSpec,
10-
TaskOutputArgument,
11-
TaskSpec,
6+
import {
7+
type ComponentSpec,
8+
type InputSpec,
9+
isGraphImplementation,
10+
type OutputSpec,
11+
type TaskOutputArgument,
12+
type TaskSpec,
1213
} from "@/utils/componentSpec";
1314

1415
import { duplicateNodes } from "./duplicateNodes";
@@ -63,7 +64,7 @@ const createMockComponentSpecWithOutputs = (
6364
acc[output.name] = {
6465
taskOutput: {
6566
taskId: "task1",
66-
outputName: "result",
67+
outputName: output.name,
6768
},
6869
};
6970
return acc;
@@ -123,7 +124,7 @@ const createMockInputNode = (
123124
position,
124125
data: {
125126
label: inputName,
126-
inputSpec: { ...mockInputSpec, name: inputName },
127+
spec: { ...mockInputSpec, name: inputName },
127128
},
128129
selected: false,
129130
dragging: false,
@@ -144,7 +145,7 @@ const createMockOutputNode = (
144145
position,
145146
data: {
146147
label: outputName,
147-
outputSpec: { ...mockOutputSpec, name: outputName },
148+
spec: { ...mockOutputSpec, name: outputName },
148149
},
149150
selected: false,
150151
dragging: false,
@@ -210,7 +211,7 @@ describe("duplicateNodes", () => {
210211
if ("graph" in result.updatedComponentSpec.implementation!) {
211212
expect(
212213
result.updatedComponentSpec.implementation.graph.tasks,
213-
).toHaveProperty("original-task 2");
214+
).toHaveProperty("original-task (2)");
214215
}
215216
});
216217

@@ -236,14 +237,14 @@ describe("duplicateNodes", () => {
236237
expect(result.newNodes).toHaveLength(1);
237238
expect(result.newNodes[0].type).toBe("input");
238239
expect(result.newNodes[0].id).toBe(
239-
nodeManager.getNodeId("original-input 2", "input"),
240+
nodeManager.getNodeId("original-input (2)", "input"),
240241
);
241242
expect(result.newNodes[0].position).toEqual({ x: 60, y: 60 });
242243

243244
expect(result.updatedComponentSpec.inputs).toHaveLength(2);
244245
expect(
245246
result.updatedComponentSpec.inputs?.some(
246-
(input) => input.name === "original-input 2",
247+
(input) => input.name === "original-input (2)",
247248
),
248249
).toBe(true);
249250
});
@@ -274,14 +275,14 @@ describe("duplicateNodes", () => {
274275
expect(result.newNodes).toHaveLength(1);
275276
expect(result.newNodes[0].type).toBe("output");
276277
expect(result.newNodes[0].id).toBe(
277-
nodeManager.getNodeId("original-output 2", "output"),
278+
nodeManager.getNodeId("original-output (2)", "output"),
278279
);
279280
expect(result.newNodes[0].position).toEqual({ x: 310, y: 310 });
280281

281282
expect(result.updatedComponentSpec.outputs).toHaveLength(2);
282283
expect(
283284
result.updatedComponentSpec.outputs?.some(
284-
(output) => output.name === "original-output 2",
285+
(output) => output.name === "original-output (2)",
285286
),
286287
).toBe(true);
287288
});
@@ -304,13 +305,13 @@ describe("duplicateNodes", () => {
304305
const result = duplicateNodes(componentSpec, nodes, nodeManager);
305306

306307
expect(result.newNodes).toHaveLength(2);
307-
if ("graph" in result.updatedComponentSpec.implementation!) {
308+
if (isGraphImplementation(result.updatedComponentSpec.implementation)) {
308309
expect(
309310
result.updatedComponentSpec.implementation.graph.tasks,
310-
).toHaveProperty("task1 2");
311+
).toHaveProperty("task1 (2)");
311312
expect(
312313
result.updatedComponentSpec.implementation.graph.tasks,
313-
).toHaveProperty("task2 2");
314+
).toHaveProperty("task2 (2)");
314315
}
315316
});
316317
});
@@ -418,7 +419,7 @@ describe("duplicateNodes", () => {
418419

419420
if ("graph" in result.updatedComponentSpec.implementation!) {
420421
const duplicatedTask2 =
421-
result.updatedComponentSpec.implementation.graph.tasks["task2 2"];
422+
result.updatedComponentSpec.implementation.graph.tasks["task2 (2)"];
422423
expect(duplicatedTask2.arguments).toEqual({});
423424
}
424425
});
@@ -442,10 +443,10 @@ describe("duplicateNodes", () => {
442443

443444
if ("graph" in result.updatedComponentSpec.implementation!) {
444445
const duplicatedTask2 =
445-
result.updatedComponentSpec.implementation.graph.tasks["task2 2"];
446+
result.updatedComponentSpec.implementation.graph.tasks["task2 (2)"];
446447
expect(duplicatedTask2.arguments?.input1).toEqual({
447448
taskOutput: {
448-
taskId: "task1 2",
449+
taskId: "task1 (2)",
449450
outputName: "output1",
450451
},
451452
});
@@ -495,7 +496,7 @@ describe("duplicateNodes", () => {
495496

496497
if ("graph" in result.updatedComponentSpec.implementation!) {
497498
const duplicatedTask2 =
498-
result.updatedComponentSpec.implementation.graph.tasks["task2 2"];
499+
result.updatedComponentSpec.implementation.graph.tasks["task2 (2)"];
499500

500501
// Should remove internal connection to task1 (since task1 is being duplicated)
501502
expect(duplicatedTask2.arguments?.input1).toBeUndefined();
@@ -529,10 +530,10 @@ describe("duplicateNodes", () => {
529530

530531
if ("graph" in result.updatedComponentSpec.implementation!) {
531532
const duplicatedTask2 =
532-
result.updatedComponentSpec.implementation.graph.tasks["task2 2"];
533+
result.updatedComponentSpec.implementation.graph.tasks["task2 (2)"];
533534
expect(duplicatedTask2.arguments?.input1).toEqual({
534535
taskOutput: {
535-
taskId: "task1 2",
536+
taskId: "task1 (2)",
536537
outputName: "output1",
537538
},
538539
});
@@ -570,26 +571,45 @@ describe("duplicateNodes", () => {
570571
connection: "all",
571572
});
572573

573-
if ("graph" in result.updatedComponentSpec.implementation!) {
574+
if (isGraphImplementation(result.updatedComponentSpec.implementation)) {
574575
const duplicatedTask =
575-
result.updatedComponentSpec.implementation.graph.tasks["task1 2"];
576+
result.updatedComponentSpec.implementation.graph.tasks["task1 (2)"];
576577
expect(duplicatedTask.arguments?.input1).toEqual({
577578
graphInput: {
578-
inputName: "graph-input 2",
579+
inputName: "graph-input (2)",
579580
},
580581
});
581582
}
582583
});
583584

584585
it("should handle graph output connections", () => {
586+
const outputSpec: OutputSpec = {
587+
...mockOutputSpec,
588+
name: "graph-output-node",
589+
};
590+
591+
const taskComponentSpec: ComponentSpec = {
592+
name: "task-component",
593+
inputs: [],
594+
outputs: [
595+
{
596+
name: "graph-output",
597+
type: "String",
598+
annotations: {},
599+
},
600+
],
601+
implementation: {
602+
container: { image: "task-image" },
603+
},
604+
};
605+
585606
const taskSpec: TaskSpec = {
586607
...mockTaskSpec,
587608
arguments: {},
588-
};
589-
590-
const outputSpec: OutputSpec = {
591-
...mockOutputSpec,
592-
name: "graph-output",
609+
componentRef: {
610+
name: "task-component",
611+
spec: taskComponentSpec,
612+
},
593613
};
594614

595615
const componentSpec = createMockComponentSpecWithOutputs(
@@ -601,23 +621,23 @@ describe("duplicateNodes", () => {
601621
const nodeManager = createMockNodeManager();
602622
const nodes = [
603623
createMockTaskNode("task1", taskSpec, nodeManager),
604-
createMockOutputNode("graph-output", nodeManager),
624+
createMockOutputNode("graph-output-node", nodeManager),
605625
];
606626

607627
const result = duplicateNodes(componentSpec, nodes, nodeManager, {
608628
connection: "all",
609629
});
610630

611631
// Check that outputValues are updated for duplicated outputs
612-
if ("graph" in result.updatedComponentSpec.implementation!) {
632+
if (isGraphImplementation(result.updatedComponentSpec.implementation)) {
613633
const outputValues =
614634
result.updatedComponentSpec.implementation.graph.outputValues;
615635

616636
// Duplicated output should reference duplicated task
617-
expect(outputValues?.["graph-output 2"]).toEqual({
637+
expect(outputValues?.["graph-output-node (2)"]).toEqual({
618638
taskOutput: {
619-
taskId: "task1 2",
620-
outputName: "result",
639+
taskId: "task1 (2)",
640+
outputName: "graph-output-node",
621641
},
622642
});
623643
}
@@ -655,7 +675,7 @@ describe("duplicateNodes", () => {
655675
it("should handle nodes without position annotations", () => {
656676
const taskSpecWithoutPosition = {
657677
...mockTaskSpec,
658-
annotations: {}, // No position annotation
678+
annotations: {},
659679
};
660680

661681
const componentSpec = createMockComponentSpec({

0 commit comments

Comments
 (0)