@@ -3,12 +3,13 @@ import { describe, expect, it, vi } from "vitest";
33
44import { NodeManager } from "@/nodeManager" ;
55import 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
1415import { 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 ;
@@ -124,7 +125,7 @@ const createMockInputNode = (
124125 position,
125126 data : {
126127 label : inputName ,
127- inputSpec : { ...mockInputSpec , name : inputName } ,
128+ spec : { ...mockInputSpec , name : inputName } ,
128129 } ,
129130 selected : false ,
130131 dragging : false ,
@@ -145,7 +146,7 @@ const createMockOutputNode = (
145146 position,
146147 data : {
147148 label : outputName ,
148- outputSpec : { ...mockOutputSpec , name : outputName } ,
149+ spec : { ...mockOutputSpec , name : outputName } ,
149150 } ,
150151 selected : false ,
151152 dragging : false ,
@@ -211,7 +212,7 @@ describe("duplicateNodes", () => {
211212 if ( "graph" in result . updatedComponentSpec . implementation ! ) {
212213 expect (
213214 result . updatedComponentSpec . implementation . graph . tasks ,
214- ) . toHaveProperty ( "original-task 2 " ) ;
215+ ) . toHaveProperty ( "original-task (2) " ) ;
215216 }
216217 } ) ;
217218
@@ -237,14 +238,14 @@ describe("duplicateNodes", () => {
237238 expect ( result . newNodes ) . toHaveLength ( 1 ) ;
238239 expect ( result . newNodes [ 0 ] . type ) . toBe ( "input" ) ;
239240 expect ( result . newNodes [ 0 ] . id ) . toBe (
240- nodeManager . getNodeId ( "original-input 2 " , "input" ) ,
241+ nodeManager . getNodeId ( "original-input (2) " , "input" ) ,
241242 ) ;
242243 expect ( result . newNodes [ 0 ] . position ) . toEqual ( { x : 60 , y : 60 } ) ;
243244
244245 expect ( result . updatedComponentSpec . inputs ) . toHaveLength ( 2 ) ;
245246 expect (
246247 result . updatedComponentSpec . inputs ?. some (
247- ( input ) => input . name === "original-input 2 " ,
248+ ( input ) => input . name === "original-input (2) " ,
248249 ) ,
249250 ) . toBe ( true ) ;
250251 } ) ;
@@ -275,14 +276,14 @@ describe("duplicateNodes", () => {
275276 expect ( result . newNodes ) . toHaveLength ( 1 ) ;
276277 expect ( result . newNodes [ 0 ] . type ) . toBe ( "output" ) ;
277278 expect ( result . newNodes [ 0 ] . id ) . toBe (
278- nodeManager . getNodeId ( "original-output 2 " , "output" ) ,
279+ nodeManager . getNodeId ( "original-output (2) " , "output" ) ,
279280 ) ;
280281 expect ( result . newNodes [ 0 ] . position ) . toEqual ( { x : 310 , y : 310 } ) ;
281282
282283 expect ( result . updatedComponentSpec . outputs ) . toHaveLength ( 2 ) ;
283284 expect (
284285 result . updatedComponentSpec . outputs ?. some (
285- ( output ) => output . name === "original-output 2 " ,
286+ ( output ) => output . name === "original-output (2) " ,
286287 ) ,
287288 ) . toBe ( true ) ;
288289 } ) ;
@@ -305,13 +306,13 @@ describe("duplicateNodes", () => {
305306 const result = duplicateNodes ( componentSpec , nodes , nodeManager ) ;
306307
307308 expect ( result . newNodes ) . toHaveLength ( 2 ) ;
308- if ( "graph" in result . updatedComponentSpec . implementation ! ) {
309+ if ( isGraphImplementation ( result . updatedComponentSpec . implementation ) ) {
309310 expect (
310311 result . updatedComponentSpec . implementation . graph . tasks ,
311- ) . toHaveProperty ( "task1 2 " ) ;
312+ ) . toHaveProperty ( "task1 (2) " ) ;
312313 expect (
313314 result . updatedComponentSpec . implementation . graph . tasks ,
314- ) . toHaveProperty ( "task2 2 " ) ;
315+ ) . toHaveProperty ( "task2 (2) " ) ;
315316 }
316317 } ) ;
317318 } ) ;
@@ -419,7 +420,7 @@ describe("duplicateNodes", () => {
419420
420421 if ( "graph" in result . updatedComponentSpec . implementation ! ) {
421422 const duplicatedTask2 =
422- result . updatedComponentSpec . implementation . graph . tasks [ "task2 2 " ] ;
423+ result . updatedComponentSpec . implementation . graph . tasks [ "task2 (2) " ] ;
423424 expect ( duplicatedTask2 . arguments ) . toEqual ( { } ) ;
424425 }
425426 } ) ;
@@ -443,10 +444,10 @@ describe("duplicateNodes", () => {
443444
444445 if ( "graph" in result . updatedComponentSpec . implementation ! ) {
445446 const duplicatedTask2 =
446- result . updatedComponentSpec . implementation . graph . tasks [ "task2 2 " ] ;
447+ result . updatedComponentSpec . implementation . graph . tasks [ "task2 (2) " ] ;
447448 expect ( duplicatedTask2 . arguments ?. input1 ) . toEqual ( {
448449 taskOutput : {
449- taskId : "task1 2 " ,
450+ taskId : "task1 (2) " ,
450451 outputName : "output1" ,
451452 } ,
452453 } ) ;
@@ -496,7 +497,7 @@ describe("duplicateNodes", () => {
496497
497498 if ( "graph" in result . updatedComponentSpec . implementation ! ) {
498499 const duplicatedTask2 =
499- result . updatedComponentSpec . implementation . graph . tasks [ "task2 2 " ] ;
500+ result . updatedComponentSpec . implementation . graph . tasks [ "task2 (2) " ] ;
500501
501502 // Should remove internal connection to task1 (since task1 is being duplicated)
502503 expect ( duplicatedTask2 . arguments ?. input1 ) . toBeUndefined ( ) ;
@@ -530,10 +531,10 @@ describe("duplicateNodes", () => {
530531
531532 if ( "graph" in result . updatedComponentSpec . implementation ! ) {
532533 const duplicatedTask2 =
533- result . updatedComponentSpec . implementation . graph . tasks [ "task2 2 " ] ;
534+ result . updatedComponentSpec . implementation . graph . tasks [ "task2 (2) " ] ;
534535 expect ( duplicatedTask2 . arguments ?. input1 ) . toEqual ( {
535536 taskOutput : {
536- taskId : "task1 2 " ,
537+ taskId : "task1 (2) " ,
537538 outputName : "output1" ,
538539 } ,
539540 } ) ;
@@ -571,26 +572,45 @@ describe("duplicateNodes", () => {
571572 connection : "all" ,
572573 } ) ;
573574
574- if ( "graph" in result . updatedComponentSpec . implementation ! ) {
575+ if ( isGraphImplementation ( result . updatedComponentSpec . implementation ) ) {
575576 const duplicatedTask =
576- result . updatedComponentSpec . implementation . graph . tasks [ "task1 2 " ] ;
577+ result . updatedComponentSpec . implementation . graph . tasks [ "task1 (2) " ] ;
577578 expect ( duplicatedTask . arguments ?. input1 ) . toEqual ( {
578579 graphInput : {
579- inputName : "graph-input 2 " ,
580+ inputName : "graph-input (2) " ,
580581 } ,
581582 } ) ;
582583 }
583584 } ) ;
584585
585586 it ( "should handle graph output connections" , ( ) => {
587+ const outputSpec : OutputSpec = {
588+ ...mockOutputSpec ,
589+ name : "graph-output-node" ,
590+ } ;
591+
592+ const taskComponentSpec : ComponentSpec = {
593+ name : "task-component" ,
594+ inputs : [ ] ,
595+ outputs : [
596+ {
597+ name : "graph-output" ,
598+ type : "String" ,
599+ annotations : { } ,
600+ } ,
601+ ] ,
602+ implementation : {
603+ container : { image : "task-image" } ,
604+ } ,
605+ } ;
606+
586607 const taskSpec : TaskSpec = {
587608 ...mockTaskSpec ,
588609 arguments : { } ,
589- } ;
590-
591- const outputSpec : OutputSpec = {
592- ...mockOutputSpec ,
593- name : "graph-output" ,
610+ componentRef : {
611+ name : "task-component" ,
612+ spec : taskComponentSpec ,
613+ } ,
594614 } ;
595615
596616 const componentSpec = createMockComponentSpecWithOutputs (
@@ -602,23 +622,23 @@ describe("duplicateNodes", () => {
602622 const nodeManager = createMockNodeManager ( ) ;
603623 const nodes = [
604624 createMockTaskNode ( "task1" , taskSpec , nodeManager ) ,
605- createMockOutputNode ( "graph-output" , nodeManager ) ,
625+ createMockOutputNode ( "graph-output-node " , nodeManager ) ,
606626 ] ;
607627
608628 const result = duplicateNodes ( componentSpec , nodes , nodeManager , {
609629 connection : "all" ,
610630 } ) ;
611631
612632 // Check that outputValues are updated for duplicated outputs
613- if ( "graph" in result . updatedComponentSpec . implementation ! ) {
633+ if ( isGraphImplementation ( result . updatedComponentSpec . implementation ) ) {
614634 const outputValues =
615635 result . updatedComponentSpec . implementation . graph . outputValues ;
616636
617637 // Duplicated output should reference duplicated task
618- expect ( outputValues ?. [ "graph-output 2 " ] ) . toEqual ( {
638+ expect ( outputValues ?. [ "graph-output-node (2) " ] ) . toEqual ( {
619639 taskOutput : {
620- taskId : "task1 2 " ,
621- outputName : "result " ,
640+ taskId : "task1 (2) " ,
641+ outputName : "graph-output-node " ,
622642 } ,
623643 } ) ;
624644 }
@@ -656,7 +676,7 @@ describe("duplicateNodes", () => {
656676 it ( "should handle nodes without position annotations" , ( ) => {
657677 const taskSpecWithoutPosition = {
658678 ...mockTaskSpec ,
659- annotations : { } , // No position annotation
679+ annotations : { } ,
660680 } ;
661681
662682 const componentSpec = createMockComponentSpec ( {
0 commit comments