From 8482af614b771cd97059f7ff0a896fcec12c1446 Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Tue, 10 Sep 2024 16:34:19 +0200
Subject: [PATCH 01/13] debut test getSetAttributsNodes

---
 src/composables/GetSetAttributsNodes.ts       |  12 +-
 .../__tests__/GetSetAttributsNodes.spec.ts    | 325 +++++++++++++++++-
 2 files changed, 326 insertions(+), 11 deletions(-)

diff --git a/src/composables/GetSetAttributsNodes.ts b/src/composables/GetSetAttributsNodes.ts
index 5da8874..306db75 100644
--- a/src/composables/GetSetAttributsNodes.ts
+++ b/src/composables/GetSetAttributsNodes.ts
@@ -67,7 +67,7 @@ import { NetworkLayout } from "../types/NetworkLayout";
 
 
 
-const sideCompoundAttribute="isSideCompound";
+export const sideCompoundAttribute="isSideCompound";
 
 /**
  * Return if the node is declare as side compound
@@ -76,7 +76,7 @@ const sideCompoundAttribute="isSideCompound";
  * @returns node is a side compound ?
  */
 export function isSideCompound(node:Node):boolean{
-    return Boolean(node.metadata && node.metadata[sideCompoundAttribute]);
+    return Boolean(node.metadata && node.metadata[getAttributSideCompounds()]);
 }
 
 /**
@@ -95,7 +95,7 @@ export function getAttributSideCompounds():string{
 export function setAsSideCompound(network:Network,nodeID:string):void{
     if(!network.nodes[nodeID]) throw new Error("Node not found");
     if(!network.nodes[nodeID].metadata) network.nodes[nodeID].metadata={};
-    network.nodes[nodeID].metadata[sideCompoundAttribute]=true;
+    network.nodes[nodeID].metadata[getAttributSideCompounds()]=true;
 }
 
 
@@ -104,7 +104,7 @@ export function setAsSideCompound(network:Network,nodeID:string):void{
 
 
 
-const classDuplicate="duplicate";
+export const classDuplicate="duplicate";
 
 /**
  * Checks if a node in the network is a duplicate.
@@ -131,7 +131,7 @@ export function getClassDuplicate():string{
 //___________________________________________________2.  Reversible __________________________________________________________________________
 
 const classReversible="reversible";
-const reversibleAttribute="reversible";
+export const reversibleAttribute="reversible";
 const reactionClass="reaction";
 
 /**
@@ -253,7 +253,7 @@ export function inCycle(network: NetworkLayout, idNode: string): boolean {
     let inCycle:boolean=false;
     if ( network.nodes[idNode].metadataLayout && TypeSubgraph.CYCLE in network.nodes[idNode].metadataLayout){
             const cycles=network.nodes[idNode].metadataLayout[TypeSubgraph.CYCLE];
-            if (cycles.length>0) inCycle=true;
+            if (cycles && cycles.length>0) inCycle=true;
     }
     return inCycle;
 }
diff --git a/src/composables/__tests__/GetSetAttributsNodes.spec.ts b/src/composables/__tests__/GetSetAttributsNodes.spec.ts
index 99eb479..b69ebb5 100644
--- a/src/composables/__tests__/GetSetAttributsNodes.spec.ts
+++ b/src/composables/__tests__/GetSetAttributsNodes.spec.ts
@@ -1,16 +1,331 @@
-import "../GetSetAttributsNodes";
+// Type imports
+import { Node } from "@metabohub/viz-core/src/types/Node";
+import { Network } from "@metabohub/viz-core/src/types/Network";
+
+// Composables imports
+import * as GetSetAttributsNodes from "../GetSetAttributsNodes";
+
+
+
 
 describe('GetSetAttributsNodes', () => {
-    test("name test",  () => {
+    
+// 0.  Side Compounds  *****************************************************************
+
+    test("getAttributSideCompounds",  () => {
+
+        // TEST
+        const resultNameAttribut=GetSetAttributsNodes.getAttributSideCompounds();
+
+        // EXPECT
+        expect(resultNameAttribut).toEqual(GetSetAttributsNodes.sideCompoundAttribute);
+
+    });
+
+    it("should not be a side compound",  () => {
         // DATA
-        
+        const nodeEmpty:Node ={
+            id: "node",
+            x: 10,
+            y: 10
+        };
+        const nodeEmptyMetadata:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{}
+        };
+        const nodeNotSideCompound:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{[GetSetAttributsNodes.getAttributSideCompounds()]:false}
+        };
+
         // TEST
+        const resultNodeEmpy=GetSetAttributsNodes.isSideCompound(nodeEmpty);
+        const resultNodeEmptyMetadata=GetSetAttributsNodes.isSideCompound(nodeEmptyMetadata);
+        const resultNodeNotSideCompound=GetSetAttributsNodes.isSideCompound(nodeNotSideCompound);
+
 
         // EXPECT
-        expect(false).toEqual(true);
+        expect(resultNodeEmpy).toEqual(false);
+        expect(resultNodeEmptyMetadata).toEqual(false);
+        expect(resultNodeNotSideCompound).toEqual(false);
+
     });
 
-    it('should return true', () => {
+    it("should be a side compound",  () => {
+        // DATA
+        const nodeSideCompound:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{[GetSetAttributsNodes.getAttributSideCompounds()]:true}
+        };
+
+        // TEST
+        const resultNodeSideCompound=GetSetAttributsNodes.isSideCompound(nodeSideCompound);
+
+        // EXPECT
+        expect(resultNodeSideCompound).toEqual(true);
+
+    });
+
+    test("setAsSideCompound",  () => {
+
+        // DATA
+        let network:Network = {
+            id:"networkTest",
+            nodes: {
+                node1 :{
+                    id: "node1",
+                    x: 10,
+                    y: 10,
+                },
+                node2: {
+                    id: "node2",
+                    x: 20,
+                    y: 20,
+                    metadata: {}
+                },
+                node3: {
+                    id: "node3",
+                    x: 30,
+                    y: 30,
+                    metadata: {[GetSetAttributsNodes.getAttributSideCompounds()]:false as boolean}
+                },
+                node4: {
+                    id: "node4",
+                    x: 40,
+                    y: 40,
+                    metadata: {[GetSetAttributsNodes.getAttributSideCompounds()]:true as boolean}
+                }
+            },
+            links: []
+        };
+
+        const networkNode1:Network = {
+            id:"networkTest",
+            nodes: {
+                node1 :{
+                    id: "node1",
+                    x: 10,
+                    y: 10,
+                    metadata: {[GetSetAttributsNodes.getAttributSideCompounds()]:true as boolean}
+                },
+                node2: {
+                    id: "node2",
+                    x: 20,
+                    y: 20,
+                    metadata: {}
+                },
+                node3: {
+                    id: "node3",
+                    x: 30,
+                    y: 30,
+                    metadata: {[GetSetAttributsNodes.getAttributSideCompounds()]:false as boolean}
+                },
+                node4: {
+                    id: "node4",
+                    x: 40,
+                    y: 40,
+                    metadata: {[GetSetAttributsNodes.getAttributSideCompounds()]:true as boolean}
+                }
+            },
+            links: []
+        };
+
+        
+
+        // TEST & EXPECT
+        GetSetAttributsNodes.setAsSideCompound(network,"node1");
+        expect(network).toEqual(networkNode1);
+
+        // ...????
         expect(false).toEqual(true);
+
+        expect(() => {
+            GetSetAttributsNodes.setAsSideCompound(network, "node5");
+          }).toThrow();
+
+    });
+
+// 1.  Duplicate *****************************************************************
+
+    test("getClassDuplicate",  () => {
+
+        // TEST
+        const resultNameClass=GetSetAttributsNodes.getClassDuplicate();
+
+        // EXPECT
+        expect(resultNameClass).toEqual(GetSetAttributsNodes.classDuplicate);
+
+    });
+
+    it("should not be a duplicate",  () => {
+        // DATA
+        const network:Network = {
+            id:"networkTest",
+            nodes: {
+                node1 :{
+                    id: "node1",
+                    x: 10,
+                    y: 10,
+                },
+                node2: {
+                    id: "node2",
+                    x: 20,
+                    y: 20,
+                    classes:[]
+                },
+                node3: {
+                    id: "node3",
+                    x: 30,
+                    y: 30,
+                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test"]
+                },
+            },
+            links: []
+        };
+
+
+        // TEST
+        const resultNodeEmpy=GetSetAttributsNodes.isDuplicate(network,"node1");
+        const resultNodeEmptyClasses=GetSetAttributsNodes.isDuplicate(network,"node2");
+        const resultNodeNotSideCompound=GetSetAttributsNodes.isDuplicate(network,"node3");
+
+
+        // EXPECT
+        expect(resultNodeEmpy).toEqual(false);
+        expect(resultNodeEmptyClasses).toEqual(false);
+        expect(resultNodeNotSideCompound).toEqual(false);
+
     });
+
+    it("should throw an error because node not in network for checking duplicate",  () => {
+        // DATA
+        const network:Network = {
+            id:"networkTest",
+            nodes: {
+                node1 :{
+                    id: "node1",
+                    x: 10,
+                    y: 10,
+                },
+                node2: {
+                    id: "node2",
+                    x: 20,
+                    y: 20,
+                    classes:[]
+                },
+                node3: {
+                    id: "node3",
+                    x: 30,
+                    y: 30,
+                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test"]
+                },
+            },
+            links: []
+        };
+
+
+        // TEST & EXPECT
+        expect(() => {
+            GetSetAttributsNodes.isDuplicate(network,"node4");
+          }).toThrow();
+
+    });
+
+    it("should be a duplicate",  () => {
+        // DATA
+        let network:Network = {
+            id:"networkTest",
+            nodes: {
+                node1: {
+                    id: "node1",
+                    x: 10,
+                    y: 10,
+                    classes:[GetSetAttributsNodes.getClassDuplicate()]
+                },
+                node2: {
+                    id: "node2",
+                    x: 20,
+                    y: 20,
+                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test"]
+                },
+                node3: {
+                    id: "node3",
+                    x: 30,
+                    y: 30,
+                    classes:[]
+                },
+            },
+            links: []
+        };
+
+        const networkExpected:Network = {
+            id:"networkTest",
+            nodes: {
+                node1: {
+                    id: "node1",
+                    x: 10,
+                    y: 10,
+                    classes:[GetSetAttributsNodes.getClassDuplicate()],
+                    metadata: {[GetSetAttributsNodes.reversibleAttribute]:true}
+                },
+                node2: {
+                    id: "node2",
+                    x: 20,
+                    y: 20,
+                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test"],
+                },
+                node3: {
+                    id: "node3",
+                    x: 30,
+                    y: 30,
+                    classes:[],
+                },
+            },
+            links: []
+        };
+        // TEST
+        const resultNetwork=GetSetAttributsNodes.addMetadataReversibleWithClass(network);
+
+        // EXPECT
+        expect(resultNetwork).toEqual(networkExpected);
+        expect(true).toEqual(false); // pas fait tous les cas
+
+    });
+    
+// 2.  Reversible *****************************************************************
+
+    test("addMetadataReversibleWithClass",  () => {
+        // DATA
+        const network:Network = {
+            id:"networkTest",
+            nodes: {
+                node1: {
+                    id: "node1",
+                    x: 10,
+                    y: 10,
+                    classes:[GetSetAttributsNodes.getClassDuplicate()]
+                },
+                node2: {
+                    id: "node2",
+                    x: 20,
+                    y: 20,
+                    classes:[GetSetAttributsNodes.getClassDuplicate(),GetSetAttributsNodes.getClassDuplicate()+"_test"]
+                },
+                node3: {
+                    id: "node3",
+                    x: 30,
+                    y: 30,
+                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test",GetSetAttributsNodes.getClassDuplicate()]
+                },
+            },
+            links: []
+        };
+
+
 });
-- 
GitLab


From df4eeef5968e5c165d0fa26f4021c56eccbdd2cd Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Wed, 11 Sep 2024 09:13:51 +0200
Subject: [PATCH 02/13]  presque tous les test de getSetAttribut

---
 src/composables/GetSetAttributsNodes.ts       |   4 +-
 .../__tests__/GetSetAttributsNodes.spec.ts    | 531 ++++++++++++++++--
 2 files changed, 473 insertions(+), 62 deletions(-)

diff --git a/src/composables/GetSetAttributsNodes.ts b/src/composables/GetSetAttributsNodes.ts
index 306db75..348e63c 100644
--- a/src/composables/GetSetAttributsNodes.ts
+++ b/src/composables/GetSetAttributsNodes.ts
@@ -130,9 +130,9 @@ export function getClassDuplicate():string{
 /*******************************************************************************************************************************************************/
 //___________________________________________________2.  Reversible __________________________________________________________________________
 
-const classReversible="reversible";
+export const classReversible="reversible";
 export const reversibleAttribute="reversible";
-const reactionClass="reaction";
+export const reactionClass="reaction";
 
 /**
  * Checks if a node in the network is reversible by checking its classes.
diff --git a/src/composables/__tests__/GetSetAttributsNodes.spec.ts b/src/composables/__tests__/GetSetAttributsNodes.spec.ts
index b69ebb5..f79d71f 100644
--- a/src/composables/__tests__/GetSetAttributsNodes.spec.ts
+++ b/src/composables/__tests__/GetSetAttributsNodes.spec.ts
@@ -1,6 +1,10 @@
 // Type imports
 import { Node } from "@metabohub/viz-core/src/types/Node";
 import { Network } from "@metabohub/viz-core/src/types/Network";
+import { Link } from "@metabohub/viz-core/src/types/Link";
+import { NetworkLayout } from "../../types/NetworkLayout";
+import { TypeSubgraph } from "../../types/Subgraph";
+
 
 // Composables imports
 import * as GetSetAttributsNodes from "../GetSetAttributsNodes";
@@ -8,6 +12,7 @@ import * as GetSetAttributsNodes from "../GetSetAttributsNodes";
 
 
 
+
 describe('GetSetAttributsNodes', () => {
     
 // 0.  Side Compounds  *****************************************************************
@@ -42,16 +47,36 @@ describe('GetSetAttributsNodes', () => {
             metadata:{[GetSetAttributsNodes.getAttributSideCompounds()]:false}
         };
 
+        const nodeNotSideCompound2:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{[GetSetAttributsNodes.getAttributSideCompounds()]:false,
+                [GetSetAttributsNodes.getAttributSideCompounds()+"_test"]:true
+            }
+        };
+
+        const nodeNotSideCompound3:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{[GetSetAttributsNodes.getAttributSideCompounds()+"_test"]:true}
+        };
+
         // TEST
         const resultNodeEmpy=GetSetAttributsNodes.isSideCompound(nodeEmpty);
         const resultNodeEmptyMetadata=GetSetAttributsNodes.isSideCompound(nodeEmptyMetadata);
         const resultNodeNotSideCompound=GetSetAttributsNodes.isSideCompound(nodeNotSideCompound);
+        const resultNodeNotSideCompound2=GetSetAttributsNodes.isSideCompound(nodeNotSideCompound2);
+        const resultNodeNotSideCompound3=GetSetAttributsNodes.isSideCompound(nodeNotSideCompound3);
 
 
         // EXPECT
         expect(resultNodeEmpy).toEqual(false);
         expect(resultNodeEmptyMetadata).toEqual(false);
         expect(resultNodeNotSideCompound).toEqual(false);
+        expect(resultNodeNotSideCompound2).toEqual(false);
+        expect(resultNodeNotSideCompound3).toEqual(false);
 
     });
 
@@ -64,11 +89,22 @@ describe('GetSetAttributsNodes', () => {
             metadata:{[GetSetAttributsNodes.getAttributSideCompounds()]:true}
         };
 
+        const nodeSideCompound2:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{[GetSetAttributsNodes.getAttributSideCompounds()]:true,
+                [GetSetAttributsNodes.getAttributSideCompounds()+"_test"]:false
+            }
+        };
+
         // TEST
         const resultNodeSideCompound=GetSetAttributsNodes.isSideCompound(nodeSideCompound);
+        const resultNodeSideCompound2=GetSetAttributsNodes.isSideCompound(nodeSideCompound2);
 
         // EXPECT
         expect(resultNodeSideCompound).toEqual(true);
+        expect(resultNodeSideCompound2).toEqual(true);
 
     });
 
@@ -104,47 +140,48 @@ describe('GetSetAttributsNodes', () => {
             },
             links: []
         };
-
-        const networkNode1:Network = {
-            id:"networkTest",
-            nodes: {
-                node1 :{
-                    id: "node1",
-                    x: 10,
-                    y: 10,
-                    metadata: {[GetSetAttributsNodes.getAttributSideCompounds()]:true as boolean}
-                },
-                node2: {
-                    id: "node2",
-                    x: 20,
-                    y: 20,
-                    metadata: {}
-                },
-                node3: {
-                    id: "node3",
-                    x: 30,
-                    y: 30,
-                    metadata: {[GetSetAttributsNodes.getAttributSideCompounds()]:false as boolean}
-                },
-                node4: {
-                    id: "node4",
-                    x: 40,
-                    y: 40,
-                    metadata: {[GetSetAttributsNodes.getAttributSideCompounds()]:true as boolean}
-                }
-            },
-            links: []
-        };
-
-        
+        const initialNetwork:Network = JSON.parse(JSON.stringify(network));
+    
 
         // TEST & EXPECT
-        GetSetAttributsNodes.setAsSideCompound(network,"node1");
-        expect(network).toEqual(networkNode1);
-
-        // ...????
-        expect(false).toEqual(true);
-
+        expect(true).toEqual(false);
+        // node without metadata
+    //     GetSetAttributsNodes.setAsSideCompound(network,"node1");
+    //     expect(network.nodes['node1'].metadata).toBeDefined();
+    //     expect(network.nodes['node1'].metadata).toBeInstanceOf(Object);
+    //     expect(network.nodes['node1'].metadata).toHaveProperty(GetSetAttributsNodes.getAttributSideCompounds());
+    //     expect(network.nodes['node1'].metadata[GetSetAttributsNodes.getAttributSideCompounds()] as boolean).toEqual(true);
+    //     delete network.nodes['node1'].metadata;
+    //     expect(network).toEqual(initialNetwork);
+
+
+    //     // node with empty metadata
+    //     GetSetAttributsNodes.setAsSideCompound(network,"node2");
+    //     expect(network.nodes['node2'].metadata).toBeDefined();
+    //     expect(network.nodes['node2'].metadata).toBeInstanceOf(Object);
+    //     expect(network.nodes['node2'].metadata).toHaveProperty(GetSetAttributsNodes.getAttributSideCompounds());
+    //     expect(network.nodes['node2'].metadata[GetSetAttributsNodes.getAttributSideCompounds()] as boolean).toEqual(true);
+    //     delete network.nodes['node2'].metadata[GetSetAttributsNodes.getAttributSideCompounds()];
+    //     expect(network).toEqual(initialNetwork);
+
+    //     // node with false sideCompound
+    //     GetSetAttributsNodes.setAsSideCompound(network,"node3");
+    //     expect(network.nodes['node3'].metadata).toBeDefined();
+    //     expect(network.nodes['node3'].metadata).toBeInstanceOf(Object);
+    //     expect(network.nodes['node3'].metadata).toHaveProperty(GetSetAttributsNodes.getAttributSideCompounds());
+    //     expect(network.nodes['node3'].metadata[GetSetAttributsNodes.getAttributSideCompounds()] as boolean).toEqual(true);
+    //     network.nodes['node3'].metadata[GetSetAttributsNodes.getAttributSideCompounds()]=false;
+    //     expect(network).toEqual(initialNetwork);
+
+    //    // node with true sideCompound
+    //      GetSetAttributsNodes.setAsSideCompound(network,"node4");
+    //     expect(network.nodes['node4'].metadata).toBeDefined();
+    //     expect(network.nodes['node4'].metadata).toBeInstanceOf(Object);
+    //     expect(network.nodes['node4'].metadata).toHaveProperty(GetSetAttributsNodes.getAttributSideCompounds());
+    //     expect(network.nodes['node4'].metadata[GetSetAttributsNodes.getAttributSideCompounds()] as boolean).toEqual(true);
+    //     expect(network).toEqual(initialNetwork);
+
+        // node not in network
         expect(() => {
             GetSetAttributsNodes.setAsSideCompound(network, "node5");
           }).toThrow();
@@ -239,7 +276,7 @@ describe('GetSetAttributsNodes', () => {
 
     it("should be a duplicate",  () => {
         // DATA
-        let network:Network = {
+        const network:Network = {
             id:"networkTest",
             nodes: {
                 node1: {
@@ -252,80 +289,454 @@ describe('GetSetAttributsNodes', () => {
                     id: "node2",
                     x: 20,
                     y: 20,
-                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test"]
+                    classes:[GetSetAttributsNodes.getClassDuplicate(),GetSetAttributsNodes.getClassDuplicate()+"_test"]
                 },
                 node3: {
                     id: "node3",
                     x: 30,
                     y: 30,
-                    classes:[]
+                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test",GetSetAttributsNodes.getClassDuplicate()]
                 },
             },
             links: []
         };
 
-        const networkExpected:Network = {
+        // TEST
+        const resultNode1=GetSetAttributsNodes.isDuplicate(network,"node1");
+        const resultNode2=GetSetAttributsNodes.isDuplicate(network,"node2");
+        const resultNode3=GetSetAttributsNodes.isDuplicate(network,"node3");
+
+        // EXPECT
+        expect(resultNode1).toEqual(true);
+        expect(resultNode2).toEqual(true);
+        expect(resultNode3).toEqual(true);
+
+    });
+    
+// 2.  Reversible *****************************************************************
+
+     test("addMetadataReversibleWithClass",  async () => {
+        // DATA
+        let network:Network = {
             id:"networkTest",
             nodes: {
-                node1: {
+                node1 :{
                     id: "node1",
                     x: 10,
                     y: 10,
-                    classes:[GetSetAttributsNodes.getClassDuplicate()],
-                    metadata: {[GetSetAttributsNodes.reversibleAttribute]:true}
                 },
                 node2: {
                     id: "node2",
                     x: 20,
                     y: 20,
-                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test"],
+                    classes: [GetSetAttributsNodes.classReversible+"_test"]
                 },
                 node3: {
                     id: "node3",
                     x: 30,
                     y: 30,
-                    classes:[],
+                    classes: [GetSetAttributsNodes.classReversible]
                 },
+                node4: {
+                    id: "node4",
+                    x: 40,
+                    y: 40,
+                    classes: [GetSetAttributsNodes.classReversible+"_test",GetSetAttributsNodes.classReversible]
+                }
             },
             links: []
         };
+
+        let networkExpected:Network = {
+            id:"networkTest",
+            nodes: {
+                node1 :{
+                    id: "node1",
+                    x: 10,
+                    y: 10,
+                },
+                node2: {
+                    id: "node2",
+                    x: 20,
+                    y: 20,
+                    classes: [GetSetAttributsNodes.classReversible+"_test"]
+                },
+                node3: {
+                    id: "node3",
+                    x: 30,
+                    y: 30,
+                    classes: [GetSetAttributsNodes.classReversible],
+                    metadata: {[GetSetAttributsNodes.reversibleAttribute]:true}
+                },
+                node4: {
+                    id: "node4",
+                    x: 40,
+                    y: 40,
+                    classes: [GetSetAttributsNodes.classReversible+"_test",GetSetAttributsNodes.classReversible],
+                    metadata: {[GetSetAttributsNodes.reversibleAttribute]:true}
+                }
+            },
+            links: []
+        };
+
         // TEST
-        const resultNetwork=GetSetAttributsNodes.addMetadataReversibleWithClass(network);
+        await GetSetAttributsNodes.addMetadataReversibleWithClass(network);
 
         // EXPECT
-        expect(resultNetwork).toEqual(networkExpected);
-        expect(true).toEqual(false); // pas fait tous les cas
+        expect(network).toEqual(networkExpected);
 
-    });
-    
-// 2.  Reversible *****************************************************************
+     });
 
-    test("addMetadataReversibleWithClass",  () => {
+     test("addReversibleNetwork",  () => {
         // DATA
-        const network:Network = {
+        let network:Network = {
             id:"networkTest",
             nodes: {
-                node1: {
+                node1 :{
                     id: "node1",
                     x: 10,
                     y: 10,
-                    classes:[GetSetAttributsNodes.getClassDuplicate()]
                 },
                 node2: {
                     id: "node2",
                     x: 20,
                     y: 20,
-                    classes:[GetSetAttributsNodes.getClassDuplicate(),GetSetAttributsNodes.getClassDuplicate()+"_test"]
+                    metadata: {}
                 },
                 node3: {
                     id: "node3",
                     x: 30,
                     y: 30,
-                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test",GetSetAttributsNodes.getClassDuplicate()]
+                    metadata: {[GetSetAttributsNodes.reversibleAttribute]:false as boolean}
                 },
+                node4: {
+                    id: "node4",
+                    x: 40,
+                    y: 40,
+                    metadata: {[GetSetAttributsNodes.reversibleAttribute]:true as boolean}
+                }
             },
             links: []
         };
 
+        // TEST
+
+        // EXPECT
+        expect(true).toEqual(false);
+
+     });
+
+     test("addReversible",  () => {
+        // DATA
+        const nodeEmpty:Node ={
+            id: "node",
+            x: 10,
+            y: 10
+        };
+        const nodeEmptyMetadata:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{}
+        };
+        const nodeNotReversible:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{[GetSetAttributsNodes.reversibleAttribute]:false}
+        };
+        const nodeReversible:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{[GetSetAttributsNodes.reversibleAttribute]:true}
+        };
+
+        const nodeExpectedReversible:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{[GetSetAttributsNodes.reversibleAttribute]:true}
+        };
+
+
+        const nodeNotReversible2:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{[GetSetAttributsNodes.reversibleAttribute]:false,
+                [GetSetAttributsNodes.reversibleAttribute+"_test"]:false
+            }
+        };
+
+        const nodeReversible2:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{[GetSetAttributsNodes.reversibleAttribute]:true,
+                [GetSetAttributsNodes.reversibleAttribute+"_test"]:false
+            }
+        };
+
+        const nodeExpectedReversible2:Node ={
+            id: "node",
+            x: 10,
+            y: 10,
+            metadata:{[GetSetAttributsNodes.reversibleAttribute]:true,
+                [GetSetAttributsNodes.reversibleAttribute+"_test"]:false
+            }
+        };
+
+        // TEST
+        const resultNodeEmpty=GetSetAttributsNodes.addReversible(nodeEmpty);
+        const resultNodeEmptyMetadata=GetSetAttributsNodes.addReversible(nodeEmptyMetadata);
+        const resultNodeNotReversible=GetSetAttributsNodes.addReversible(nodeNotReversible);
+        const resultNodeReversible=GetSetAttributsNodes.addReversible(nodeReversible);
+        const resultNodeNotReversible2=GetSetAttributsNodes.addReversible(nodeNotReversible2);
+        const resultNodeReversible2=GetSetAttributsNodes.addReversible(nodeReversible2);
+
+        // EXPECT
+        expect(resultNodeEmpty).toEqual(nodeExpectedReversible);
+        expect(resultNodeEmptyMetadata).toEqual(nodeExpectedReversible);
+        expect(resultNodeNotReversible).toEqual(nodeExpectedReversible);
+        expect(resultNodeReversible).toEqual(nodeExpectedReversible);
+        expect(resultNodeNotReversible2).toEqual(nodeExpectedReversible2);
+        expect(resultNodeReversible2).toEqual(nodeExpectedReversible2);
+
+     });
+
+            test("addLinkClassReversible", () => {
+            // DATA
+            const node1: Node = {
+                id: "node1",
+                x: 10,
+                y: 10
+            };
+            const node2: Node = {
+                id: "node2",
+                x: 20,
+                y: 20
+            };
+            const linkEmpty: Link = {
+                id: "link",
+                source: node1,
+                target: node2
+            };
+            const linkEmptyClasses: Link = {
+                id: "link",
+                source: node1,
+                target: node2,
+                classes: []
+            };
+            const linkWithOtherClass: Link = {
+                id: "link",
+                source: node1,
+                target: node2,
+                classes: [GetSetAttributsNodes.classReversible+"_test"]
+            };
+            const linkWithReversibleClass: Link = {
+                id: "link",
+                source: node1,
+                target: node2,
+                classes: [GetSetAttributsNodes.classReversible]
+            };
+
+            const linkExpectedReversible: Link = {
+                id: "link",
+                source: node1,
+                target: node2,
+                classes: [GetSetAttributsNodes.classReversible]
+            };
+
+            const linkExpectedReversibleWithOtherClass: Link = {
+                id: "link",
+                source: node1,
+                target: node2,
+                classes: [GetSetAttributsNodes.classReversible+"_test", GetSetAttributsNodes.classReversible]
+            };
+
+            // TEST
+            const resultLinkEmpty = GetSetAttributsNodes.addLinkClassReversible(linkEmpty);
+            const resultLinkEmptyClasses = GetSetAttributsNodes.addLinkClassReversible(linkEmptyClasses);
+            const resultLinkWithOtherClass = GetSetAttributsNodes.addLinkClassReversible(linkWithOtherClass);
+            const resultLinkWithReversibleClass = GetSetAttributsNodes.addLinkClassReversible(linkWithReversibleClass);
+
+            // EXPECT
+            expect(resultLinkEmpty).toEqual(linkExpectedReversible);
+            expect(resultLinkEmptyClasses).toEqual(linkExpectedReversible);
+            expect(resultLinkWithOtherClass).toEqual(linkExpectedReversibleWithOtherClass);
+            expect(resultLinkWithReversibleClass).toEqual(linkWithReversibleClass); 
+        });
+
+        test("pushUniqueString", () => {
+            // DATA
+            const arrayEmpty: string[] = [];
+            const arrayWithValues: string[] = ["value1", "value2"];
+            const arrayForDuplicate: string[] = ["value1", "value2"];
+
+            // TEST
+            const resultEmptyArray = GetSetAttributsNodes.pushUniqueString(arrayEmpty, "value1");
+            const resultArrayWithValues = GetSetAttributsNodes.pushUniqueString(arrayWithValues, "value3");
+            const resultArrayWithDuplicate = GetSetAttributsNodes.pushUniqueString(arrayForDuplicate, "value1");
+
+            // EXPECT
+            expect(resultEmptyArray).toEqual(["value1"]);
+            expect(resultArrayWithValues).toEqual(["value1", "value2", "value3"]);
+            expect(resultArrayWithDuplicate).toEqual(["value1", "value2"]);
+        });
+
+        test("isReversible", () => {
+            // DATA
+            const network: Network = {
+                id: "networkTest",
+                nodes: {
+                    node1: {
+                        id: "node1",
+                        x: 10,
+                        y: 10,
+                        metadata: { [GetSetAttributsNodes.reversibleAttribute]: true }
+                    },
+                    node2: {
+                        id: "node2",
+                        x: 20,
+                        y: 20,
+                        metadata: { [GetSetAttributsNodes.reversibleAttribute]: false }
+                    },
+                    node3: {
+                        id: "node3",
+                        x: 30,
+                        y: 30,
+                        metadata: {}
+                    },
+                    node4: {
+                        id: "node4",
+                        x: 40,
+                        y: 40
+                    }
+                },
+                links: []
+            };
+
+            // TEST & EXPECT
+            expect(GetSetAttributsNodes.isReversible(network, "node1")).toEqual(true);
+            expect(GetSetAttributsNodes.isReversible(network, "node2")).toEqual(false);
+            expect(GetSetAttributsNodes.isReversible(network, "node3")).toEqual(false);
+            expect(GetSetAttributsNodes.isReversible(network, "node4")).toEqual(false);
+
+            // node not in network
+            expect(() => {
+                GetSetAttributsNodes.isReversible(network, "node5");
+            }).toThrow();
+        });
+
+        test("isReaction", () => {
+            // DATA
+            const nodeWithoutClasses: Node = {
+                id: "node1",
+                x: 10,
+                y: 10
+            };
+            const nodeWithEmptyClasses: Node = {
+                id: "node2",
+                x: 20,
+                y: 20,
+                classes: []
+            };
+            const nodeWithoutReactionClass: Node = {
+                id: "node3",
+                x: 30,
+                y: 30,
+                classes: [GetSetAttributsNodes.reactionClass + "_test"]
+            };
+            const nodeWithReactionClass: Node = {
+                id: "node4",
+                x: 40,
+                y: 40,
+                classes: [GetSetAttributsNodes.reactionClass]
+            };
+            const nodeWithMultipleClasses: Node = {
+                id: "node5",
+                x: 50,
+                y: 50,
+                classes: [GetSetAttributsNodes.reactionClass, GetSetAttributsNodes.reactionClass + "_test"]
+            };
+
+            // TEST
+            const resultNodeWithoutClasses = GetSetAttributsNodes.isReaction(nodeWithoutClasses);
+            const resultNodeWithEmptyClasses = GetSetAttributsNodes.isReaction(nodeWithEmptyClasses);
+            const resultNodeWithoutReactionClass = GetSetAttributsNodes.isReaction(nodeWithoutReactionClass);
+            const resultNodeWithReactionClass = GetSetAttributsNodes.isReaction(nodeWithReactionClass);
+            const resultNodeWithMultipleClasses = GetSetAttributsNodes.isReaction(nodeWithMultipleClasses);
+
+            // EXPECT
+            expect(resultNodeWithoutClasses).toEqual(false);
+            expect(resultNodeWithEmptyClasses).toEqual(false);
+            expect(resultNodeWithoutReactionClass).toEqual(false);
+            expect(resultNodeWithReactionClass).toEqual(true);
+            expect(resultNodeWithMultipleClasses).toEqual(true);
+        });
+
+        test("inCycle", () => {
+            // DATA
+            const network: NetworkLayout = {
+            id: "networkTest",
+            nodes: {
+                node0: {
+                    id: "node0",
+                    x: 10,
+                    y: 10,
+                    metadataLayout: {
+                        [TypeSubgraph.CYCLE]: ["cycle1","cycle2"]
+                    }
+                },
+                node1: {
+                id: "node1",
+                x: 10,
+                y: 10,
+                metadataLayout: {
+                    [TypeSubgraph.CYCLE]: ["cycle1"]
+                }
+                },
+                node2: {
+                id: "node2",
+                x: 20,
+                y: 20,
+                metadataLayout: {
+                    [TypeSubgraph.CYCLE]: []
+                }
+                },
+                node3: {
+                id: "node3",
+                x: 30,
+                y: 30,
+                metadataLayout: {}
+                },
+                node4: {
+                id: "node4",
+                x: 40,
+                y: 40
+                }
+            },
+            links: []
+            };
+
+            // TEST & EXPECT
+            expect(GetSetAttributsNodes.inCycle(network, "node0")).toEqual(true);
+            expect(GetSetAttributsNodes.inCycle(network, "node1")).toEqual(true);
+            expect(GetSetAttributsNodes.inCycle(network, "node2")).toEqual(false);
+            expect(GetSetAttributsNodes.inCycle(network, "node3")).toEqual(false);
+            expect(GetSetAttributsNodes.inCycle(network, "node4")).toEqual(false);
+
+            // node not in network
+            expect(() => {
+            GetSetAttributsNodes.inCycle(network, "node5");
+            }).toThrow();
+        });
+
+
+
+
+
 
 });
+
-- 
GitLab


From 94f9ff8ef206f5c766bbf5c8cfc6865d5ba1ce0b Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Wed, 11 Sep 2024 14:40:55 +0200
Subject: [PATCH 03/13] premiere version test GetSetAttributs

---
 package.json                                  |   8 +-
 src/composables/CalculateSize.ts              |  33 +--
 src/composables/GetSetAttributsNodes.ts       |  30 +--
 src/composables/LayoutManageSideCompounds.ts  |   6 +-
 .../__tests__/CalculateSize.tests.ts          | 160 +++++++++++
 ....spec.ts => GetSetAttributsNodes.tests.ts} | 249 ++++++++----------
 src/types/SubgraphNetwork.ts                  |  10 +-
 7 files changed, 308 insertions(+), 188 deletions(-)
 create mode 100644 src/composables/__tests__/CalculateSize.tests.ts
 rename src/composables/__tests__/{GetSetAttributsNodes.spec.ts => GetSetAttributsNodes.tests.ts} (78%)

diff --git a/package.json b/package.json
index 9638aad..949cd36 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
   "private": false,
   "scripts": {
     "build": "tsup",
-    "test": "jest"
+    "test": "jest --coverage"
   },
   "dependencies": {
     "@mdi/font": "^7.4.47",
@@ -15,6 +15,8 @@
     "xml2js": "^0.6.2"
   },
   "devDependencies": {
+    "@eslint/js": "^9.10.0",
+    "@types/eslint__js": "^8.42.3",
     "@types/jest": "^29.5.12",
     "@types/jsdom": "^21.1.6",
     "@types/node": "^20.11.14",
@@ -24,6 +26,7 @@
     "cytoscape-cose-bilkent": "^3.0.0",
     "cytoscape-fcose": "^2.2.0",
     "dagrejs": "^0.2.1",
+    "eslint": "^9.10.0",
     "graph-data-structure": "^3.5.0",
     "jest": "^29.7.0",
     "jsdom": "^24.0.0",
@@ -31,7 +34,8 @@
     "ts-jest": "^29.1.2",
     "ts-node": "^10.9.2",
     "tsup": "^8.0.2",
-    "typescript": "^5.4.5",
+    "typescript": "^5.6.2",
+    "typescript-eslint": "^8.5.0",
     "xml-js": "^1.6.11"
   },
   "main": "./dist/index.js",
diff --git a/src/composables/CalculateSize.ts b/src/composables/CalculateSize.ts
index 4a8f814..b0e3b9c 100644
--- a/src/composables/CalculateSize.ts
+++ b/src/composables/CalculateSize.ts
@@ -10,7 +10,6 @@ import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStylePr
 import { inCycle, isSideCompound } from "./GetSetAttributsNodes";
 
 // General imports
-import { e } from "vitest/dist/reporters-1evA5lom";
 
 
 
@@ -92,7 +91,7 @@ const defaultWidthNode = 25;
  * @returns The converted value in inches.
  */
 export function pixelsToInches(pixels: number, dpi: number = 72): number {
-    if (!pixels) throw new Error("No pixels to convert to inches");
+    if (dpi===0) throw new Error("DPI value cannot be 0");
     return parseFloat((pixels / dpi).toFixed(2));
 }
 
@@ -114,23 +113,17 @@ export function inchesToPixels(inches: number, dpi: number = 72): number {
  * @returns An object containing the height and width of the node in pixels.
  */
 export function getSizeNodePixel(node:Node,styleNetwork:GraphStyleProperties):Size{
-    let height:number;
-    let width:number;
-    if (node.classes && styleNetwork.nodeStyles){
+    let height:number=defaultHeightNode;
+    let width:number=defaultWidthNode;
+    if (node.classes){
         node.classes.forEach((classe)=>{
-            if (classe in styleNetwork.nodeStyles){;
+            if (styleNetwork.nodeStyles && classe in styleNetwork.nodeStyles){;
                 const style=styleNetwork.nodeStyles[classe];
                 height = style.height? style.height:height;
                 width = style.width? style.width:width;
             }
         });
     }
-    if (!height){
-        height = defaultHeightNode;
-    }
-    if (!width){
-        width = defaultWidthNode;
-    }
 
     return {height:height,width:width};
 }
@@ -349,9 +342,11 @@ export function rectangleSize(listCoordinates:Coordinate[],listID?:string[],subg
  * @returns The subgraphNetwork with the size of all group cycles calculated.
  */
 export function getSizeAllGroupCycles(subgraphNetwork:SubgraphNetwork):SubgraphNetwork{
-    Object.values(subgraphNetwork[TypeSubgraph.CYCLEGROUP]).forEach(groupCycle => {
-        subgraphNetwork=getSizeGroupCycles(subgraphNetwork,groupCycle);
-    });
+    if (subgraphNetwork[TypeSubgraph.CYCLEGROUP]){
+        Object.values(subgraphNetwork[TypeSubgraph.CYCLEGROUP]).forEach(groupCycle => {
+            subgraphNetwork=getSizeGroupCycles(subgraphNetwork,groupCycle);
+        });
+    }
 
     return subgraphNetwork;
 }
@@ -364,12 +359,12 @@ export function getSizeAllGroupCycles(subgraphNetwork:SubgraphNetwork):SubgraphN
  * @returns The subgraphNetwork with the size of the group cycle calculated.
  */
 function getSizeGroupCycles(subgraphNetwork:SubgraphNetwork,groupCycle:Subgraph):SubgraphNetwork{
-    if (groupCycle.metadata){
+    if (groupCycle.precalculatedNodesPosition){
         // get all nodes with x and y coordinates
         console.warn('modifier getSizeGroupCycle avec nouveau attribut position');
-        const listNodesMetadata = Object.entries(groupCycle.metadata)
-                        .filter(([_,item]) => item["x"] !== undefined && item["y"] !== undefined);
-        const listCoordinates = listNodesMetadata.map(([_,item]) => {return {x:item["x"],y:item["y"]}});
+        const listNodesMetadata = Object.entries(groupCycle.precalculatedNodesPosition)
+                        .filter(([_,item]) => item.x !== undefined && item.y !== undefined);
+        const listCoordinates = listNodesMetadata.map(([_,item]) => {return {x:item.x,y:item.y}});
         const listID = listNodesMetadata.map(([id,_]) => {return id});
         // get the size of the rectangle
         const {width,height,center}=rectangleSize(listCoordinates,listID,subgraphNetwork);
diff --git a/src/composables/GetSetAttributsNodes.ts b/src/composables/GetSetAttributsNodes.ts
index 348e63c..711f6d3 100644
--- a/src/composables/GetSetAttributsNodes.ts
+++ b/src/composables/GetSetAttributsNodes.ts
@@ -14,9 +14,6 @@ import { NetworkLayout } from "../types/NetworkLayout";
  * -> isSideCompound :
  *      Return if the node is declare as side compound
  * 
- * -> getAttributSideCompounds :
- *     Returns the attribut for side compound nodes.
- * 
  * -> setAsSideCompound :
  *    Set the node as side compound
  * 
@@ -27,8 +24,6 @@ import { NetworkLayout } from "../types/NetworkLayout";
  * -> isDuplicate :
  *          Checks if a node in the network is a duplicate.
  * 
- * -> getClassDuplicate :
- *           Returns the class name for duplicated nodes.
  * 
  * *********************************
  * 2. Reversible
@@ -76,16 +71,9 @@ export const sideCompoundAttribute="isSideCompound";
  * @returns node is a side compound ?
  */
 export function isSideCompound(node:Node):boolean{
-    return Boolean(node.metadata && node.metadata[getAttributSideCompounds()]);
+    return Boolean(node.metadata && node.metadata[sideCompoundAttribute]);
 }
 
-/**
- * Returns the attribut for side compound nodes.
- * @returns the attribut for side compound nodes
- */
-export function getAttributSideCompounds():string{
-    return sideCompoundAttribute;
-}
 
 /**
  * Set the node as side compound
@@ -95,7 +83,7 @@ export function getAttributSideCompounds():string{
 export function setAsSideCompound(network:Network,nodeID:string):void{
     if(!network.nodes[nodeID]) throw new Error("Node not found");
     if(!network.nodes[nodeID].metadata) network.nodes[nodeID].metadata={};
-    network.nodes[nodeID].metadata[getAttributSideCompounds()]=true;
+    network.nodes[nodeID].metadata[sideCompoundAttribute]=true;
 }
 
 
@@ -117,14 +105,6 @@ export function isDuplicate(network:Network,nodeID:string):boolean{
     return Boolean(network.nodes[nodeID].classes && network.nodes[nodeID].classes.includes(classDuplicate));
 }
 
-/**
- * Returns the class name for duplicated nodes.
- * @returns the class name for duplicate nodes
- */
-export function getClassDuplicate():string{
-    return classDuplicate;
-}
-
 
 
 /*******************************************************************************************************************************************************/
@@ -158,10 +138,7 @@ export function addReversibleNetwork(network:Network,nodeID:string):void{
     if (!network.nodes[nodeID]){
         throw new Error("Node not found to set as reversible ");
     }
-    if(!network.nodes[nodeID].metadata){
-        network.nodes[nodeID].metadata={};
-    }
-    network.nodes[nodeID].metadata[reversibleAttribute]=true;
+    network.nodes[nodeID]=addReversible(network.nodes[nodeID]);
 }
 
 /**
@@ -249,7 +226,6 @@ export function inCycle(network: NetworkLayout, idNode: string): boolean {
         throw new Error("Node not found in network");
     }
     // no metadata or no cycle metadata or empty cycle metadata : that is, not in a cycle
-    console.warn("change matadatlayout inCycle");
     let inCycle:boolean=false;
     if ( network.nodes[idNode].metadataLayout && TypeSubgraph.CYCLE in network.nodes[idNode].metadataLayout){
             const cycles=network.nodes[idNode].metadataLayout[TypeSubgraph.CYCLE];
diff --git a/src/composables/LayoutManageSideCompounds.ts b/src/composables/LayoutManageSideCompounds.ts
index 95819f7..3422389 100644
--- a/src/composables/LayoutManageSideCompounds.ts
+++ b/src/composables/LayoutManageSideCompounds.ts
@@ -11,7 +11,7 @@ import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStylePr
 import { getContentFromURL } from "./importNetwork";
 import { removeAllSelectedNodes , duplicateAllNodesByAttribut} from "@metabohub/viz-core";
 import { getMeanNodesSizePixel, inchesToPixels, minEdgeLength as minEdgeLength, pixelsToInches } from "./CalculateSize";
-import { getAttributSideCompounds, isDuplicate, isReaction, isSideCompound, setAsSideCompound } from "./GetSetAttributsNodes";
+import { sideCompoundAttribute,isDuplicate, isReaction, isSideCompound, setAsSideCompound } from "./GetSetAttributsNodes";
 
 // General imports
 import { e, S } from "vitest/dist/reporters-1evA5lom";
@@ -145,7 +145,7 @@ import { error } from "console";
  * @param network 
  * @param pathListSideCompounds path to the list of id of side compounds
  */
-export async function addSideCompoundAttributeFromList(subgraphNetwork:SubgraphNetwork, pathListSideCompounds):Promise<void>{
+export async function addSideCompoundAttributeFromList(subgraphNetwork:SubgraphNetwork, pathListSideCompounds:string):Promise<void>{
     const listIDSideCompounds = await getIDSideCompoundsInNetworkFromFile(subgraphNetwork,pathListSideCompounds);
     listIDSideCompounds.forEach((sideCompoundID) => {
         setAsSideCompound(subgraphNetwork.network.value,sideCompoundID);
@@ -237,7 +237,7 @@ export async function duplicateSideCompound(subgraphNetwork:SubgraphNetwork):Pro
     const network = subgraphNetwork.network.value;
     const networkStyle = subgraphNetwork.networkStyle.value;
     // duplication of side compounds
-    duplicateAllNodesByAttribut(network, networkStyle, getAttributSideCompounds());
+    duplicateAllNodesByAttribut(network, networkStyle, sideCompoundAttribute);
     // add attributes to side compounds duplicates
     sideCompoundAttributeOnDuplicate(subgraphNetwork);
 }
diff --git a/src/composables/__tests__/CalculateSize.tests.ts b/src/composables/__tests__/CalculateSize.tests.ts
new file mode 100644
index 0000000..1523eeb
--- /dev/null
+++ b/src/composables/__tests__/CalculateSize.tests.ts
@@ -0,0 +1,160 @@
+// // Type imports
+// import { Node} from '@metabohub/viz-core/src/types/Node';
+// import { Network } from '@metabohub/viz-core/src/types/Network';
+// import { GraphStyleProperties } from '@metabohub/viz-core/src/types/GraphStyleProperties';
+
+// // Composable imports
+// import { pixelsToInches, inchesToPixels, getSizeNodePixel, 
+//     getMeanNodesSizePixel, getSepAttributesInches, getSepAttributesPixel, 
+//     minEdgeLength, medianEdgeLength, rectangleSize } from '../CalculateSize';
+
+// describe('CalculateSize', () => {
+//     const mockNodeClass1: Node = {
+//         id: '1',
+//         classes: ['class1'],
+//         x: 0,
+//         y: 0
+//     };
+//     const mockNodeClass2: Node = {
+//         id: '2',
+//         classes: ['class2'],
+//         x: 0,
+//         y: 0
+//     };
+//     const mockNodeClass12: Node = {
+//         id: '3',
+//         classes: ['class1','class2'],
+//         x: 0,
+//         y: 0
+//     };
+//     const mockNodeClass21: Node = {
+//         id: '4',
+//         classes: ['class2','class1'],
+//         x: 0,
+//         y: 0
+//     };
+
+//     const mockNodeClass3: Node = {
+//         id: '4',
+//         classes: ['class3'],
+//         x: 0,
+//         y: 0
+//     };
+
+//     const mockNodeClass23: Node = {
+//         id: '4',
+//         classes: ['class2','class3'],
+//         x: 0,
+//         y: 0
+//     };
+
+//     const mockNodeClassEmpty: Node = {
+//         id: '4',
+//         classes: [],
+//         x: 0,
+//         y: 0
+//     };
+
+//     const mockNodeNoClass: Node = {
+//         id: '4',
+//         x: 0,
+//         y: 0
+//     };
+
+
+//     const mockStyle: GraphStyleProperties = {
+//         nodeStyles: {
+//             class1: {
+//                 height: 50,
+//                 width: 50
+//             },
+//             class2: {
+//                 height: 25,
+//                 width: 25
+//             }
+//         }
+//     };
+
+//     const mockStyleEmpty: GraphStyleProperties = {};
+
+//     const mockStyleEmptyNodeStyle: GraphStyleProperties = {
+//         nodeStyles: {}
+//     };
+
+//     const mockNetwork: Network = {
+//         id: 'network',
+//         nodes: {
+//             '1': mockNodeClass1,
+//             '2': mockNodeClass2,
+//             '3': mockNodeClass12,
+//             '4': mockNodeClass21
+//         },
+//         links: [
+//             { id:"link", source: mockNodeClass1, target: { ...mockNodeClass1, id: '2', x: 100, y: 100 } }
+//         ]
+//     };
+
+//     it('should convert pixels to inches', () => {
+//         expect(pixelsToInches(96)).toBe(1.33);
+//     });
+
+//     it('should convert inches to pixels', () => {
+//         expect(inchesToPixels(1)).toBe(72);
+//     });
+
+//     test('getSizeNodePixel', () => {
+//         // TEST
+//         const size1 = getSizeNodePixel(mockNodeClass1, mockStyle);
+//         const size2 = getSizeNodePixel(mockNodeClass2, mockStyle);
+//         const size12 = getSizeNodePixel(mockNodeClass12, mockStyle);
+//         const size21 = getSizeNodePixel(mockNodeClass21, mockStyle);
+//         const size3 = getSizeNodePixel(mockNodeClass3, mockStyle);
+//         const size23 = getSizeNodePixel(mockNodeClass23, mockStyle);
+//         const sizeEmpty = getSizeNodePixel(mockNodeClassEmpty, mockStyle);
+//         const sizeNoClass = getSizeNodePixel(mockNodeNoClass, mockStyle);
+
+//         const sizeNoStyle= getSizeNodePixel(mockNodeClass1, mockStyleEmpty);
+//         const sizeEmptyStyle = getSizeNodePixel(mockNodeClass1, mockStyleEmptyNodeStyle);
+
+//         // EXPECT
+//         expect(size).toEqual({ height: 50, width: 50 });
+//     });
+
+//     it('should calculate the mean size of nodes in pixels', async () => {
+//         const size = await getMeanNodesSizePixel(Object.values(mockNetwork.nodes), mockStyle);
+//         expect(size).toEqual({ height: 50, width: 50 });
+//     });
+
+//     it('should calculate the rank and node separation in inches', async () => {
+//         const sep = await getSepAttributesInches(mockNetwork, mockStyle);
+//         expect(sep).toEqual({ rankSep: 0.69, nodeSep: 0.69 });
+//     });
+
+//     it('should calculate the rank and node separation in pixels', async () => {
+//         const sep = await getSepAttributesPixel(mockNetwork, mockStyle);
+//         expect(sep).toEqual({ rankSep: 50, nodeSep: 50 });
+//     });
+
+//     it('should calculate the minimum edge length', () => {
+//         const minLength = minEdgeLength(mockNetwork);
+//         expect(minLength).toBe(141.42);
+//     });
+
+//     it('should calculate the median edge length', () => {
+//         const medianLength = medianEdgeLength(mockNetwork);
+//         expect(medianLength).toBe(141.42);
+//     });
+
+//     it('should calculate the size and center coordinates of a rectangle', () => {
+//         const coordinates: Coordinate[] = [
+//             { x: 0, y: 0 },
+//             { x: 100, y: 100 }
+//         ];
+//         const size = rectangleSize(coordinates);
+//         expect(size).toEqual({
+//             width: 100,
+//             height: 100,
+//             center: { x: 50, y: 50 }
+//         });
+//     });
+// });
\ No newline at end of file
diff --git a/src/composables/__tests__/GetSetAttributsNodes.spec.ts b/src/composables/__tests__/GetSetAttributsNodes.tests.ts
similarity index 78%
rename from src/composables/__tests__/GetSetAttributsNodes.spec.ts
rename to src/composables/__tests__/GetSetAttributsNodes.tests.ts
index f79d71f..34ccdd2 100644
--- a/src/composables/__tests__/GetSetAttributsNodes.spec.ts
+++ b/src/composables/__tests__/GetSetAttributsNodes.tests.ts
@@ -17,15 +17,6 @@ describe('GetSetAttributsNodes', () => {
     
 // 0.  Side Compounds  *****************************************************************
 
-    test("getAttributSideCompounds",  () => {
-
-        // TEST
-        const resultNameAttribut=GetSetAttributsNodes.getAttributSideCompounds();
-
-        // EXPECT
-        expect(resultNameAttribut).toEqual(GetSetAttributsNodes.sideCompoundAttribute);
-
-    });
 
     it("should not be a side compound",  () => {
         // DATA
@@ -44,15 +35,15 @@ describe('GetSetAttributsNodes', () => {
             id: "node",
             x: 10,
             y: 10,
-            metadata:{[GetSetAttributsNodes.getAttributSideCompounds()]:false}
+            metadata:{[GetSetAttributsNodes.sideCompoundAttribute]:false}
         };
 
         const nodeNotSideCompound2:Node ={
             id: "node",
             x: 10,
             y: 10,
-            metadata:{[GetSetAttributsNodes.getAttributSideCompounds()]:false,
-                [GetSetAttributsNodes.getAttributSideCompounds()+"_test"]:true
+            metadata:{[GetSetAttributsNodes.sideCompoundAttribute]:false,
+                [GetSetAttributsNodes.sideCompoundAttribute+"_test"]:true
             }
         };
 
@@ -60,7 +51,7 @@ describe('GetSetAttributsNodes', () => {
             id: "node",
             x: 10,
             y: 10,
-            metadata:{[GetSetAttributsNodes.getAttributSideCompounds()+"_test"]:true}
+            metadata:{[GetSetAttributsNodes.sideCompoundAttribute+"_test"]:true}
         };
 
         // TEST
@@ -86,15 +77,15 @@ describe('GetSetAttributsNodes', () => {
             id: "node",
             x: 10,
             y: 10,
-            metadata:{[GetSetAttributsNodes.getAttributSideCompounds()]:true}
+            metadata:{[GetSetAttributsNodes.sideCompoundAttribute]:true}
         };
 
         const nodeSideCompound2:Node ={
             id: "node",
             x: 10,
             y: 10,
-            metadata:{[GetSetAttributsNodes.getAttributSideCompounds()]:true,
-                [GetSetAttributsNodes.getAttributSideCompounds()+"_test"]:false
+            metadata:{[GetSetAttributsNodes.sideCompoundAttribute]:true,
+                [GetSetAttributsNodes.sideCompoundAttribute+"_test"]:false
             }
         };
 
@@ -109,96 +100,92 @@ describe('GetSetAttributsNodes', () => {
     });
 
     test("setAsSideCompound",  () => {
+         // DATA
+        let networkWithoutMetadata: Network = {
+            nodes: {
+                node1: {
+                    id: 'node1',
+                    x: 10,
+                    y: 10
+                }
+            },
+            links: [],
+            id: 'test'
+        }
 
-        // DATA
-        let network:Network = {
-            id:"networkTest",
+        let networkWithEmptyMetadata: Network = {
             nodes: {
-                node1 :{
-                    id: "node1",
+                node1: {
+                    id: 'node1',
                     x: 10,
                     y: 10,
-                },
-                node2: {
-                    id: "node2",
-                    x: 20,
-                    y: 20,
                     metadata: {}
-                },
-                node3: {
-                    id: "node3",
-                    x: 30,
-                    y: 30,
-                    metadata: {[GetSetAttributsNodes.getAttributSideCompounds()]:false as boolean}
-                },
-                node4: {
-                    id: "node4",
-                    x: 40,
-                    y: 40,
-                    metadata: {[GetSetAttributsNodes.getAttributSideCompounds()]:true as boolean}
                 }
             },
-            links: []
-        };
-        const initialNetwork:Network = JSON.parse(JSON.stringify(network));
-    
+            links: [],
+            id: 'test'
+        }
 
-        // TEST & EXPECT
-        expect(true).toEqual(false);
-        // node without metadata
-    //     GetSetAttributsNodes.setAsSideCompound(network,"node1");
-    //     expect(network.nodes['node1'].metadata).toBeDefined();
-    //     expect(network.nodes['node1'].metadata).toBeInstanceOf(Object);
-    //     expect(network.nodes['node1'].metadata).toHaveProperty(GetSetAttributsNodes.getAttributSideCompounds());
-    //     expect(network.nodes['node1'].metadata[GetSetAttributsNodes.getAttributSideCompounds()] as boolean).toEqual(true);
-    //     delete network.nodes['node1'].metadata;
-    //     expect(network).toEqual(initialNetwork);
-
-
-    //     // node with empty metadata
-    //     GetSetAttributsNodes.setAsSideCompound(network,"node2");
-    //     expect(network.nodes['node2'].metadata).toBeDefined();
-    //     expect(network.nodes['node2'].metadata).toBeInstanceOf(Object);
-    //     expect(network.nodes['node2'].metadata).toHaveProperty(GetSetAttributsNodes.getAttributSideCompounds());
-    //     expect(network.nodes['node2'].metadata[GetSetAttributsNodes.getAttributSideCompounds()] as boolean).toEqual(true);
-    //     delete network.nodes['node2'].metadata[GetSetAttributsNodes.getAttributSideCompounds()];
-    //     expect(network).toEqual(initialNetwork);
-
-    //     // node with false sideCompound
-    //     GetSetAttributsNodes.setAsSideCompound(network,"node3");
-    //     expect(network.nodes['node3'].metadata).toBeDefined();
-    //     expect(network.nodes['node3'].metadata).toBeInstanceOf(Object);
-    //     expect(network.nodes['node3'].metadata).toHaveProperty(GetSetAttributsNodes.getAttributSideCompounds());
-    //     expect(network.nodes['node3'].metadata[GetSetAttributsNodes.getAttributSideCompounds()] as boolean).toEqual(true);
-    //     network.nodes['node3'].metadata[GetSetAttributsNodes.getAttributSideCompounds()]=false;
-    //     expect(network).toEqual(initialNetwork);
-
-    //    // node with true sideCompound
-    //      GetSetAttributsNodes.setAsSideCompound(network,"node4");
-    //     expect(network.nodes['node4'].metadata).toBeDefined();
-    //     expect(network.nodes['node4'].metadata).toBeInstanceOf(Object);
-    //     expect(network.nodes['node4'].metadata).toHaveProperty(GetSetAttributsNodes.getAttributSideCompounds());
-    //     expect(network.nodes['node4'].metadata[GetSetAttributsNodes.getAttributSideCompounds()] as boolean).toEqual(true);
-    //     expect(network).toEqual(initialNetwork);
+        let networkWithMetadataFalse: Network = {
+            nodes: {
+                node1: {
+                    id: 'node1',
+                    x: 10,
+                    y: 10,
+                    metadata: {[GetSetAttributsNodes.sideCompoundAttribute]: false}
+                }
+            },
+            links: [],
+            id: 'test'
+        }
 
+        let networkWithMetadataTrue: Network = {
+            nodes: {
+                node1: {
+                    id: 'node1',
+                    x: 10,
+                    y: 10,
+                    metadata: {[GetSetAttributsNodes.sideCompoundAttribute]: true}
+                }
+            },
+            links: [],
+            id: 'test'
+        }
+
+        const mockNetwork: Network = {
+            nodes: {
+                node1: {
+                    id: 'node1',
+                    x: 10,
+                    y: 10,
+                    metadata: {[GetSetAttributsNodes.sideCompoundAttribute]: true}
+                }
+            },
+            links: [],
+            id: 'test'
+        }
+
+        // TEST  
+        GetSetAttributsNodes.setAsSideCompound(networkWithoutMetadata, "node1")
+        GetSetAttributsNodes.setAsSideCompound(networkWithEmptyMetadata, "node1")
+        GetSetAttributsNodes.setAsSideCompound(networkWithMetadataFalse, "node1")
+        GetSetAttributsNodes.setAsSideCompound(networkWithMetadataTrue, "node1")
+
+        // EXPECT
+        expect(networkWithoutMetadata).toEqual(mockNetwork);
+        expect(networkWithEmptyMetadata).toEqual(mockNetwork);
+        expect(networkWithMetadataFalse).toEqual(mockNetwork);
+        expect(networkWithMetadataTrue).toEqual(mockNetwork);
+   
         // node not in network
         expect(() => {
-            GetSetAttributsNodes.setAsSideCompound(network, "node5");
+            GetSetAttributsNodes.setAsSideCompound(networkWithMetadataFalse, "node5");
           }).toThrow();
 
     });
 
 // 1.  Duplicate *****************************************************************
 
-    test("getClassDuplicate",  () => {
-
-        // TEST
-        const resultNameClass=GetSetAttributsNodes.getClassDuplicate();
-
-        // EXPECT
-        expect(resultNameClass).toEqual(GetSetAttributsNodes.classDuplicate);
-
-    });
 
     it("should not be a duplicate",  () => {
         // DATA
@@ -220,7 +207,7 @@ describe('GetSetAttributsNodes', () => {
                     id: "node3",
                     x: 30,
                     y: 30,
-                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test"]
+                    classes:[GetSetAttributsNodes.classDuplicate+"_test"]
                 },
             },
             links: []
@@ -249,19 +236,7 @@ describe('GetSetAttributsNodes', () => {
                     id: "node1",
                     x: 10,
                     y: 10,
-                },
-                node2: {
-                    id: "node2",
-                    x: 20,
-                    y: 20,
-                    classes:[]
-                },
-                node3: {
-                    id: "node3",
-                    x: 30,
-                    y: 30,
-                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test"]
-                },
+                }
             },
             links: []
         };
@@ -283,19 +258,19 @@ describe('GetSetAttributsNodes', () => {
                     id: "node1",
                     x: 10,
                     y: 10,
-                    classes:[GetSetAttributsNodes.getClassDuplicate()]
+                    classes:[GetSetAttributsNodes.classDuplicate]
                 },
                 node2: {
                     id: "node2",
                     x: 20,
                     y: 20,
-                    classes:[GetSetAttributsNodes.getClassDuplicate(),GetSetAttributsNodes.getClassDuplicate()+"_test"]
+                    classes:[GetSetAttributsNodes.classDuplicate,GetSetAttributsNodes.classDuplicate+"_test"]
                 },
                 node3: {
                     id: "node3",
                     x: 30,
                     y: 30,
-                    classes:[GetSetAttributsNodes.getClassDuplicate()+"_test",GetSetAttributsNodes.getClassDuplicate()]
+                    classes:[GetSetAttributsNodes.classDuplicate+"_test",GetSetAttributsNodes.classDuplicate]
                 },
             },
             links: []
@@ -316,7 +291,9 @@ describe('GetSetAttributsNodes', () => {
 // 2.  Reversible *****************************************************************
 
      test("addMetadataReversibleWithClass",  async () => {
-        // DATA
+
+        // DATA 
+
         let network:Network = {
             id:"networkTest",
             nodes: {
@@ -389,40 +366,54 @@ describe('GetSetAttributsNodes', () => {
 
      test("addReversibleNetwork",  () => {
         // DATA
-        let network:Network = {
+
+        let networkNodeNoReversible:Network = {
             id:"networkTest",
             nodes: {
-                node1 :{
-                    id: "node1",
-                    x: 10,
-                    y: 10,
-                },
-                node2: {
-                    id: "node2",
-                    x: 20,
-                    y: 20,
-                    metadata: {}
-                },
-                node3: {
-                    id: "node3",
-                    x: 30,
-                    y: 30,
+                node: {
+                    id: "node",
+                    x: 40,
+                    y: 40,
                     metadata: {[GetSetAttributsNodes.reversibleAttribute]:false as boolean}
                 },
-                node4: {
-                    id: "node4",
+                node1: {
+                    id: "node",
+                    x: 40,
+                    y: 40,
+                    metadata: {[GetSetAttributsNodes.reversibleAttribute]:false as boolean}
+                }
+            },
+            links: []
+        };
+
+        let networkexpected:Network = {
+            id:"networkTest",
+            nodes: {
+                node: {
+                    id: "node",
                     x: 40,
                     y: 40,
                     metadata: {[GetSetAttributsNodes.reversibleAttribute]:true as boolean}
+                },
+                node1: {
+                    id: "node",
+                    x: 40,
+                    y: 40,
+                    metadata: {[GetSetAttributsNodes.reversibleAttribute]:false as boolean}
                 }
             },
             links: []
         };
 
         // TEST
+        GetSetAttributsNodes.addReversibleNetwork(networkNodeNoReversible,"node");
 
         // EXPECT
-        expect(true).toEqual(false);
+        expect(networkNodeNoReversible).toEqual(networkexpected);
+
+        expect(() => {
+            GetSetAttributsNodes.addReversibleNetwork(networkNodeNoReversible,"node2");
+          }).toThrow();
 
      });
 
@@ -732,11 +723,5 @@ describe('GetSetAttributsNodes', () => {
             GetSetAttributsNodes.inCycle(network, "node5");
             }).toThrow();
         });
-
-
-
-
-
-
 });
 
diff --git a/src/types/SubgraphNetwork.ts b/src/types/SubgraphNetwork.ts
index f774499..bd52a5d 100644
--- a/src/types/SubgraphNetwork.ts
+++ b/src/types/SubgraphNetwork.ts
@@ -1,6 +1,6 @@
 import { Network } from "@metabohub/viz-core/src/types/Network";
 import { Node } from "@metabohub/viz-core/src/types/Node";
-import { Subgraph } from "./Subgraph";
+import { Subgraph, TypeSubgraph } from "./Subgraph";
 import { Ref } from "vue";
 import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties";
 import { NetworkLayout } from "./NetworkLayout";
@@ -17,17 +17,17 @@ export interface SubgraphNetwork {
 
 	attributs?: AttributesViz;
 
-	mainChains?: {
+	[TypeSubgraph.MAIN_CHAIN]?: {
 		[key: string]: Subgraph
 	}
-	secondaryChains?:{
+	[TypeSubgraph.SECONDARY_CHAIN]?:{
 		[key: string]: Subgraph
 	}
-	cycles?:{
+	[TypeSubgraph.CYCLE]?:{
 		[key:string]:Subgraph
 	}
 	// The cycle metanode :
-	cyclesGroup?:{
+	[TypeSubgraph.CYCLEGROUP]?:{
 		[key:string]:Subgraph
 	}
 
-- 
GitLab


From db57fe8ad99b43f09ac9722789015206ac92a728 Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Wed, 11 Sep 2024 16:06:27 +0200
Subject: [PATCH 04/13] debut debug calculate size

---
 src/composables/CalculateSize.ts              |  17 +-
 .../__tests__/CalculateSize.tests.ts          | 475 ++++++++++++------
 2 files changed, 323 insertions(+), 169 deletions(-)

diff --git a/src/composables/CalculateSize.ts b/src/composables/CalculateSize.ts
index b0e3b9c..d4e87da 100644
--- a/src/composables/CalculateSize.ts
+++ b/src/composables/CalculateSize.ts
@@ -80,8 +80,8 @@ import { inCycle, isSideCompound } from "./GetSetAttributsNodes";
 //___________________________________________________0.  Nodes __________________________________________________________________________
 
 
-const defaultHeightNode = 25;
-const defaultWidthNode = 25;
+export const defaultHeightNode = 25;
+export const defaultWidthNode = 25;
 
 
 /**
@@ -102,7 +102,6 @@ export function pixelsToInches(pixels: number, dpi: number = 72): number {
  * @returns The converted value in pixels.
  */
 export function inchesToPixels(inches: number, dpi: number = 72): number {
-    if (!inches) throw new Error("No inches to convert to pixels");
     return parseFloat((inches * dpi).toFixed(2));
 }
 
@@ -206,19 +205,19 @@ export function minEdgeLength(network: Network,cycleInclude:boolean=true): numbe
     let minDistance = Infinity;
     network.links.forEach((link) => {
         if (cycleInclude || (!inCycle(network,link.target.id) || !inCycle(network,link.source.id)) ){
-            const dx = link.source.x - link.target.x;
-            const dy = link.source.y - link.target.y;
-            const distance = Math.sqrt(dx * dx + dy * dy);
-            if (distance !==null && distance !== undefined && !isNaN(distance)){
+            const dx:number = link.source.x - link.target.x;
+            const dy:number = link.source.y - link.target.y;
+            const distance:number = Math.sqrt(dx * dx + dy * dy);
+            if (isFinite(distance)){
                 minDistance = Math.min(minDistance, distance);
             }
         }
     });
-    minDistance= parseFloat(minDistance.toFixed(2));
     if(!isFinite(minDistance)){
         return NaN;
+    }else{
+        return parseFloat(minDistance.toFixed(2));
     }
-    return minDistance;
 }
 
 /**
diff --git a/src/composables/__tests__/CalculateSize.tests.ts b/src/composables/__tests__/CalculateSize.tests.ts
index 1523eeb..03ab43b 100644
--- a/src/composables/__tests__/CalculateSize.tests.ts
+++ b/src/composables/__tests__/CalculateSize.tests.ts
@@ -1,160 +1,315 @@
-// // Type imports
-// import { Node} from '@metabohub/viz-core/src/types/Node';
-// import { Network } from '@metabohub/viz-core/src/types/Network';
-// import { GraphStyleProperties } from '@metabohub/viz-core/src/types/GraphStyleProperties';
-
-// // Composable imports
-// import { pixelsToInches, inchesToPixels, getSizeNodePixel, 
-//     getMeanNodesSizePixel, getSepAttributesInches, getSepAttributesPixel, 
-//     minEdgeLength, medianEdgeLength, rectangleSize } from '../CalculateSize';
-
-// describe('CalculateSize', () => {
-//     const mockNodeClass1: Node = {
-//         id: '1',
-//         classes: ['class1'],
-//         x: 0,
-//         y: 0
-//     };
-//     const mockNodeClass2: Node = {
-//         id: '2',
-//         classes: ['class2'],
-//         x: 0,
-//         y: 0
-//     };
-//     const mockNodeClass12: Node = {
-//         id: '3',
-//         classes: ['class1','class2'],
-//         x: 0,
-//         y: 0
-//     };
-//     const mockNodeClass21: Node = {
-//         id: '4',
-//         classes: ['class2','class1'],
-//         x: 0,
-//         y: 0
-//     };
-
-//     const mockNodeClass3: Node = {
-//         id: '4',
-//         classes: ['class3'],
-//         x: 0,
-//         y: 0
-//     };
-
-//     const mockNodeClass23: Node = {
-//         id: '4',
-//         classes: ['class2','class3'],
-//         x: 0,
-//         y: 0
-//     };
-
-//     const mockNodeClassEmpty: Node = {
-//         id: '4',
-//         classes: [],
-//         x: 0,
-//         y: 0
-//     };
-
-//     const mockNodeNoClass: Node = {
-//         id: '4',
-//         x: 0,
-//         y: 0
-//     };
-
-
-//     const mockStyle: GraphStyleProperties = {
-//         nodeStyles: {
-//             class1: {
-//                 height: 50,
-//                 width: 50
-//             },
-//             class2: {
-//                 height: 25,
-//                 width: 25
-//             }
-//         }
-//     };
-
-//     const mockStyleEmpty: GraphStyleProperties = {};
-
-//     const mockStyleEmptyNodeStyle: GraphStyleProperties = {
-//         nodeStyles: {}
-//     };
-
-//     const mockNetwork: Network = {
-//         id: 'network',
-//         nodes: {
-//             '1': mockNodeClass1,
-//             '2': mockNodeClass2,
-//             '3': mockNodeClass12,
-//             '4': mockNodeClass21
-//         },
-//         links: [
-//             { id:"link", source: mockNodeClass1, target: { ...mockNodeClass1, id: '2', x: 100, y: 100 } }
-//         ]
-//     };
-
-//     it('should convert pixels to inches', () => {
-//         expect(pixelsToInches(96)).toBe(1.33);
-//     });
-
-//     it('should convert inches to pixels', () => {
-//         expect(inchesToPixels(1)).toBe(72);
-//     });
-
-//     test('getSizeNodePixel', () => {
-//         // TEST
-//         const size1 = getSizeNodePixel(mockNodeClass1, mockStyle);
-//         const size2 = getSizeNodePixel(mockNodeClass2, mockStyle);
-//         const size12 = getSizeNodePixel(mockNodeClass12, mockStyle);
-//         const size21 = getSizeNodePixel(mockNodeClass21, mockStyle);
-//         const size3 = getSizeNodePixel(mockNodeClass3, mockStyle);
-//         const size23 = getSizeNodePixel(mockNodeClass23, mockStyle);
-//         const sizeEmpty = getSizeNodePixel(mockNodeClassEmpty, mockStyle);
-//         const sizeNoClass = getSizeNodePixel(mockNodeNoClass, mockStyle);
-
-//         const sizeNoStyle= getSizeNodePixel(mockNodeClass1, mockStyleEmpty);
-//         const sizeEmptyStyle = getSizeNodePixel(mockNodeClass1, mockStyleEmptyNodeStyle);
-
-//         // EXPECT
-//         expect(size).toEqual({ height: 50, width: 50 });
-//     });
-
-//     it('should calculate the mean size of nodes in pixels', async () => {
-//         const size = await getMeanNodesSizePixel(Object.values(mockNetwork.nodes), mockStyle);
-//         expect(size).toEqual({ height: 50, width: 50 });
-//     });
-
-//     it('should calculate the rank and node separation in inches', async () => {
-//         const sep = await getSepAttributesInches(mockNetwork, mockStyle);
-//         expect(sep).toEqual({ rankSep: 0.69, nodeSep: 0.69 });
-//     });
-
-//     it('should calculate the rank and node separation in pixels', async () => {
-//         const sep = await getSepAttributesPixel(mockNetwork, mockStyle);
-//         expect(sep).toEqual({ rankSep: 50, nodeSep: 50 });
-//     });
-
-//     it('should calculate the minimum edge length', () => {
-//         const minLength = minEdgeLength(mockNetwork);
-//         expect(minLength).toBe(141.42);
-//     });
-
-//     it('should calculate the median edge length', () => {
-//         const medianLength = medianEdgeLength(mockNetwork);
-//         expect(medianLength).toBe(141.42);
-//     });
-
-//     it('should calculate the size and center coordinates of a rectangle', () => {
-//         const coordinates: Coordinate[] = [
-//             { x: 0, y: 0 },
-//             { x: 100, y: 100 }
-//         ];
-//         const size = rectangleSize(coordinates);
-//         expect(size).toEqual({
-//             width: 100,
-//             height: 100,
-//             center: { x: 50, y: 50 }
-//         });
-//     });
-// });
\ No newline at end of file
+// Type imports
+import { Node} from '@metabohub/viz-core/src/types/Node';
+import { Network } from '@metabohub/viz-core/src/types/Network';
+import { GraphStyleProperties } from '@metabohub/viz-core/src/types/GraphStyleProperties';
+
+// Composable imports
+import { pixelsToInches, inchesToPixels, getSizeNodePixel, 
+    getMeanNodesSizePixel, getSepAttributesInches, getSepAttributesPixel, 
+    minEdgeLength, medianEdgeLength, rectangleSize, 
+    defaultHeightNode,
+    defaultWidthNode} from '../CalculateSize';
+import * as GetSetAttributsNodes from "../GetSetAttributsNodes";
+
+
+
+describe('CalculateSize', () => {
+    const nodeClass1: Node = {
+        id: '1',
+        classes: ['class1'],
+        x: 0,
+        y: 0,
+    };
+    const nodeClass2: Node = {
+        id: '2',
+        classes: ['class2'],
+        x: 0,
+        y: 0
+    };
+    const nodeClass12: Node = {
+        id: '3',
+        classes: ['class1','class2'],
+        x: 0,
+        y: 0
+    };
+    const nodeClass21: Node = {
+        id: '4',
+        classes: ['class2','class1'],
+        x: 0,
+        y: 0
+    };
+
+    const nodeClass3: Node = {
+        id: '4',
+        classes: ['class3'],
+        x: 0,
+        y: 0
+    };
+
+    const nodeClass23: Node = {
+        id: '4',
+        classes: ['class2','class3'],
+        x: 0,
+        y: 0
+    };
+
+    const nodeClassEmpty: Node = {
+        id: '4',
+        classes: [],
+        x: 0,
+        y: 0
+    };
+
+    const nodeNoClass: Node = {
+        id: '4',
+        x: 0,
+        y: 0
+    };
+
+
+    const networkStyle: GraphStyleProperties = {
+        nodeStyles: {
+            class1: {
+                height: 50,
+                width: 50
+            },
+            class2: {
+                height: 100,
+                width: 100
+            }
+        }
+    };
+
+    const networkStyleEmpty: GraphStyleProperties = {};
+
+    const networkStyleEmptyNodeStyle: GraphStyleProperties = {
+        nodeStyles: {}
+    };
+
+    const networkNodes: Network = {
+        id: 'network',
+        nodes: {
+            '1': nodeClass1,
+            '2': nodeClass2,
+        },
+        links: [
+        ]
+    };
+
+    const nodesForNetwork: {[key:string]:Node} = 
+    {
+        'node1': {...nodeClass1,id:"node1"},
+        'node2': {...nodeClass1, x:50,y:100, id:"node2"},
+        'node3': {...nodeClass1, x:100,y:100,id:"node3"},
+        'node4': {...nodeClass1, x:50,y:50,id:"node4"}
+    };
+
+    const network3Edges: Network = {
+        id: 'network',
+        nodes: nodesForNetwork,
+        links: [
+            {id:"link",source: nodesForNetwork.node1, target: nodesForNetwork.node2},
+            {id:"link",source: nodesForNetwork.node2, target: nodesForNetwork.node3},
+            {id:"link",source: nodesForNetwork.node3, target: nodesForNetwork.node1},
+        ]
+    };
+
+    const network4Edges: Network = {
+        id: 'network',
+        nodes: nodesForNetwork,
+        links: [
+            {id:"link",source: nodesForNetwork.node1, target: nodesForNetwork.node2},
+            {id:"link",source: nodesForNetwork.node2, target: nodesForNetwork.node3},
+            {id:"link",source: nodesForNetwork.node3, target: nodesForNetwork.node1},
+            {id:"link",source: nodesForNetwork.node4, target: nodesForNetwork.node1},
+        ]
+    };
+
+    it('should convert pixels to inches', () => {
+        expect(pixelsToInches(96)).toBe(1.33);
+        expect(pixelsToInches(432)).toBe(6);
+        expect(pixelsToInches(60,10)).toBe(6);
+        expect(pixelsToInches(10,10)).toBe(1);
+    });
+
+    it('should throw error because dpi = 0', () => {
+        expect(() => pixelsToInches(1,0)).toThrow();
+    });
+
+    it('should convert inches to pixels', () => {
+        expect(inchesToPixels(1)).toBe(72);
+        expect(inchesToPixels(6)).toBe(432);
+        expect(inchesToPixels(1,10)).toBe(10);
+        expect(inchesToPixels(6,10)).toBe(60);
+        expect(inchesToPixels(1,0)).toBe(0);
+    });
+
+    test('getSizeNodePixel', () => {
+        // TEST
+        const size1 = getSizeNodePixel(nodeClass1, networkStyle);
+        const size2 = getSizeNodePixel(nodeClass2, networkStyle);
+        const size12 = getSizeNodePixel(nodeClass12, networkStyle);
+        const size21 = getSizeNodePixel(nodeClass21, networkStyle);
+        const size3 = getSizeNodePixel(nodeClass3, networkStyle);
+        const size23 = getSizeNodePixel(nodeClass23, networkStyle);
+        const sizeEmpty = getSizeNodePixel(nodeClassEmpty, networkStyle);
+        const sizeNoClass = getSizeNodePixel(nodeNoClass, networkStyle);
+        const sizeNoStyle= getSizeNodePixel(nodeClass1, networkStyleEmpty);
+        const sizeEmptyStyle = getSizeNodePixel(nodeClass1, networkStyleEmptyNodeStyle);
+
+        // EXPECT
+        expect(size1).toEqual({ height: 50, width: 50 });
+        expect(size2).toEqual({ height: 100, width: 100 });
+        expect(size12).toEqual({ height: 100, width: 100 });
+        expect(size21).toEqual({ height: 50, width: 50 });
+        expect(size3).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
+        expect(size23).toEqual({ height: 100, width: 100 }); 
+        expect(sizeEmpty).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
+        expect(sizeNoClass).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
+        expect(sizeNoStyle).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
+        expect(sizeEmptyStyle).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
+    });
+
+    test('test mean size with all nodes', async () => {
+
+        // DATA 
+        const networkEmpty:Network = {  
+            id:"network",
+            nodes: {},
+            links: []
+        };
+
+        // TEST
+        const size = await getMeanNodesSizePixel(Object.values(networkNodes.nodes), networkStyle);
+        const sizeEmpty = await getMeanNodesSizePixel(Object.values(networkEmpty.nodes), networkStyle);
+
+        // EXPECT
+        expect(size).toEqual({ height: 75, width: 75 });
+        expect(sizeEmpty).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
+    });
+
+
+    test('test mean size for non side compound nodes', async () => {
+
+        // MOCK
+        const isSideCompoundMock = jest.spyOn(GetSetAttributsNodes, 'isSideCompound');
+
+        // Set up the mock implementation to return true for the first call and false for the second
+        isSideCompoundMock.mockImplementationOnce(() => true) // First call returns true
+                        .mockImplementationOnce(() => false); // Second call returns false
+
+        // TEST
+        const sizeNoSideCompound = await getMeanNodesSizePixel(Object.values(networkNodes.nodes), networkStyle,false);
+
+        // EXPECT
+        expect(sizeNoSideCompound).toEqual({ height: 100, width: 100 }); 
+
+        isSideCompoundMock.mockRestore();
+    });
+
+    test('getSepAttributesInches', async () => {
+        // TEST
+        const sep1 = await getSepAttributesInches(networkNodes, networkStyle);
+        const sep2 = await getSepAttributesInches(networkNodes, networkStyle,2);
+
+        // EXPECT
+        expect(sep1).toEqual({ rankSep: 1.04, nodeSep: 1.04 });
+        expect(sep2).toEqual({ rankSep: 2.08, nodeSep: 2.08 });
+    });
+
+    test('getSepAttributesPixel', async () => {
+        // TEST
+        const sep1 = await getSepAttributesPixel(networkNodes, networkStyle);
+        const sep2 = await getSepAttributesPixel(networkNodes, networkStyle,2);
+
+        // EXPECT
+        expect(sep1).toEqual({ rankSep: 75, nodeSep: 75 });
+        expect(sep2).toEqual({ rankSep: 150, nodeSep: 150 });
+    });
+
+    it('should calculate the minimum edge length when edges in cycle are included', () => {
+        // TEST
+        const minLength = minEdgeLength(network3Edges);
+
+        // EXPECT
+        expect(minLength).toBe(50);
+    });
+
+    it('should calculate the minimum edge and return NaN', () => {
+
+        // TEST
+        const minLength = minEdgeLength(networkNodes);
+
+        // EXPECT
+        expect(minLength).toBe(NaN);
+    });
+
+    it('should calculate the minimum edge when edges in cycle', () => {
+        // MOCK 
+        const inCycleMock = jest.spyOn(GetSetAttributsNodes, 'inCycle');
+
+        // Set up the mock implementation to put node 2 and 3 in a cycle
+        inCycleMock.mockImplementation((network3Edges,nodeID) => {
+            return !(nodeID === "node1");
+        });
+
+        // TEST
+        const minLength = minEdgeLength(network3Edges,false);
+
+        // EXPECT
+        expect(minLength).toBe(111.8);
+    });
+
+    it('should calculate the median edge length (with odd number of edge) when edges in cycle are included', () => {
+        // TEST
+        const medianLength = medianEdgeLength(network3Edges);
+
+        // EXPECT
+        expect(medianLength).toBe(111.8);
+    });
+
+    it('should calculate the median edge length (with even number of edge) when edges in cycle are included', () => {
+        // TEST
+        const medianLength = medianEdgeLength(network4Edges);
+
+        // EXPECT
+        expect(medianLength).toBe(91.26);
+    });
+
+    it('should calculate the median edge length but return 0 because no links', () => {
+        // TEST
+        const medianLength = medianEdgeLength(networkNodes);
+
+        // EXPECT
+        expect(medianLength).toBe(0);
+    });
+
+    it('should calculate the median edge length when edge in cycle not included', () => {
+        // MOCK 
+        const inCycleMock = jest.spyOn(GetSetAttributsNodes, 'inCycle');
+
+        // Set up the mock implementation to put node 2 and 3 in a cycle
+        inCycleMock.mockImplementation((network3Edges,nodeID) => {
+            return !(nodeID === "node1");
+        });
+
+        // TEST
+        const medianLength = medianEdgeLength(network3Edges,false);
+
+        // EXPECT
+        expect(medianLength).toBe(126.61);
+    });
+
+    // it('should calculate the size and center coordinates of a rectangle', () => {
+    //     const coordinates: Coordinate[] = [
+    //         { x: 0, y: 0 },
+    //         { x: 100, y: 100 }
+    //     ];
+    //     const size = rectangleSize(coordinates);
+    //     expect(size).toEqual({
+    //         width: 100,
+    //         height: 100,
+    //         center: { x: 50, y: 50 }
+    //     });
+    // });
+});
\ No newline at end of file
-- 
GitLab


From 63996bbe567ad652332a025e6b18f4d6c3d03f3c Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Wed, 11 Sep 2024 17:30:41 +0200
Subject: [PATCH 05/13] debut test calculate size

---
 src/composables/CalculateSize.ts              |  1 -
 .../__tests__/CalculateSize.tests.ts          | 92 ++++++++++++++++---
 .../__tests__/GetSetAttributsNodes.tests.ts   |  2 +
 3 files changed, 82 insertions(+), 13 deletions(-)

diff --git a/src/composables/CalculateSize.ts b/src/composables/CalculateSize.ts
index d4e87da..ef71104 100644
--- a/src/composables/CalculateSize.ts
+++ b/src/composables/CalculateSize.ts
@@ -360,7 +360,6 @@ export function getSizeAllGroupCycles(subgraphNetwork:SubgraphNetwork):SubgraphN
 function getSizeGroupCycles(subgraphNetwork:SubgraphNetwork,groupCycle:Subgraph):SubgraphNetwork{
     if (groupCycle.precalculatedNodesPosition){
         // get all nodes with x and y coordinates
-        console.warn('modifier getSizeGroupCycle avec nouveau attribut position');
         const listNodesMetadata = Object.entries(groupCycle.precalculatedNodesPosition)
                         .filter(([_,item]) => item.x !== undefined && item.y !== undefined);
         const listCoordinates = listNodesMetadata.map(([_,item]) => {return {x:item.x,y:item.y}});
diff --git a/src/composables/__tests__/CalculateSize.tests.ts b/src/composables/__tests__/CalculateSize.tests.ts
index 03ab43b..4a4856b 100644
--- a/src/composables/__tests__/CalculateSize.tests.ts
+++ b/src/composables/__tests__/CalculateSize.tests.ts
@@ -2,6 +2,9 @@
 import { Node} from '@metabohub/viz-core/src/types/Node';
 import { Network } from '@metabohub/viz-core/src/types/Network';
 import { GraphStyleProperties } from '@metabohub/viz-core/src/types/GraphStyleProperties';
+import { Coordinate } from '../../types/CoordinatesSize';
+import { SubgraphNetwork } from '../../types/SubgraphNetwork';
+import { NetworkLayout } from '../../types/NetworkLayout';
 
 // Composable imports
 import { pixelsToInches, inchesToPixels, getSizeNodePixel, 
@@ -11,6 +14,9 @@ import { pixelsToInches, inchesToPixels, getSizeNodePixel,
     defaultWidthNode} from '../CalculateSize';
 import * as GetSetAttributsNodes from "../GetSetAttributsNodes";
 
+// General imports
+import { ref } from 'vue'; // Import the 'ref' function from the 'vue' module
+
 
 
 describe('CalculateSize', () => {
@@ -125,6 +131,8 @@ describe('CalculateSize', () => {
         ]
     };
 
+    // 0. Nodes
+
     it('should convert pixels to inches', () => {
         expect(pixelsToInches(96)).toBe(1.33);
         expect(pixelsToInches(432)).toBe(6);
@@ -227,6 +235,8 @@ describe('CalculateSize', () => {
         expect(sep2).toEqual({ rankSep: 150, nodeSep: 150 });
     });
 
+//  1.  Edges
+
     it('should calculate the minimum edge length when edges in cycle are included', () => {
         // TEST
         const minLength = minEdgeLength(network3Edges);
@@ -300,16 +310,74 @@ describe('CalculateSize', () => {
         expect(medianLength).toBe(126.61);
     });
 
-    // it('should calculate the size and center coordinates of a rectangle', () => {
-    //     const coordinates: Coordinate[] = [
-    //         { x: 0, y: 0 },
-    //         { x: 100, y: 100 }
-    //     ];
-    //     const size = rectangleSize(coordinates);
-    //     expect(size).toEqual({
-    //         width: 100,
-    //         height: 100,
-    //         center: { x: 50, y: 50 }
-    //     });
-    // });
+    // 2.  Subgraphs
+
+    it('should calculate the size and center coordinates of a rectangle, when no style', () => {
+
+        // DATA
+        const coordinates: Coordinate[] = [
+            { x: 0, y: 0 },
+            { x: 100, y: 100 }
+        ];
+        // TEST
+        const size = rectangleSize(coordinates);
+
+        // EXPECT
+        expect(size).toEqual({
+            width: 100,
+            height: 100,
+            center: { x: 50, y: 50 }
+        });
+    });
+
+    it('should calculate the size and center coordinates of a rectangle, when style', () => {
+
+        // DATA
+        const subgraphNetwork:SubgraphNetwork = {
+            network: ref<NetworkLayout>(network3Edges),
+            networkStyle: ref<GraphStyleProperties>(networkStyle)
+        };
+        const listID = ["node1","node2"]
+        const coordinates: Coordinate[] = [
+            { x: 0, y: 0 },
+            { x: 100, y: 100 }
+        ];
+        // TEST
+        const size = rectangleSize(coordinates,listID,subgraphNetwork);
+
+        // EXPECT
+        expect(size).toEqual({
+            width: 150,
+            height: 150,
+            center: { x: 50, y: 50 }
+        });
+    });
+
+    test('getSizeAllGroupCycles', () => {
+        expect(true).toBe(false);
+    });
+
+    test('getSizeGroupCycles', () => {
+        expect(true).toBe(false);
+    });
+
+
+// 3.  Shift coordinates depending on size
+
+
+    test('shiftAllToGetTopLeftCoord', () => {
+        expect(true).toBe(false);
+    });
+
+    test('getTopLeftCoordFromCenter', () => {
+        expect(true).toBe(false);
+    });
+
+
+    test('getCenterCoordFromTopLeft', () => {
+        expect(true).toBe(false);
+    });
+
+
+
 });
\ No newline at end of file
diff --git a/src/composables/__tests__/GetSetAttributsNodes.tests.ts b/src/composables/__tests__/GetSetAttributsNodes.tests.ts
index 34ccdd2..7e249fa 100644
--- a/src/composables/__tests__/GetSetAttributsNodes.tests.ts
+++ b/src/composables/__tests__/GetSetAttributsNodes.tests.ts
@@ -292,6 +292,7 @@ describe('GetSetAttributsNodes', () => {
 
      test("addMetadataReversibleWithClass",  async () => {
 
+        const addReversibleNetworkMock = jest.spyOn(GetSetAttributsNodes, 'addReversibleNetwork');
         // DATA 
 
         let network:Network = {
@@ -360,6 +361,7 @@ describe('GetSetAttributsNodes', () => {
         await GetSetAttributsNodes.addMetadataReversibleWithClass(network);
 
         // EXPECT
+        //expect(addReversibleNetworkMock).toHaveBeenCalled();
         expect(network).toEqual(networkExpected);
 
      });
-- 
GitLab


From 66144dae9cd27ced9aa65c6705cc12b124d72c58 Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Thu, 12 Sep 2024 08:40:00 +0200
Subject: [PATCH 06/13] test mock intern but doesnt work

---
 .../__tests__/CalculateSize.tests.ts          | 204 ++++++++++++------
 1 file changed, 140 insertions(+), 64 deletions(-)

diff --git a/src/composables/__tests__/CalculateSize.tests.ts b/src/composables/__tests__/CalculateSize.tests.ts
index 4a4856b..c429293 100644
--- a/src/composables/__tests__/CalculateSize.tests.ts
+++ b/src/composables/__tests__/CalculateSize.tests.ts
@@ -4,15 +4,13 @@ import { Network } from '@metabohub/viz-core/src/types/Network';
 import { GraphStyleProperties } from '@metabohub/viz-core/src/types/GraphStyleProperties';
 import { Coordinate } from '../../types/CoordinatesSize';
 import { SubgraphNetwork } from '../../types/SubgraphNetwork';
-import { NetworkLayout } from '../../types/NetworkLayout';
+import { NetworkLayout, NodeLayout } from '../../types/NetworkLayout';
+import { Subgraph, TypeSubgraph } from '../../types/Subgraph';
+
 
 // Composable imports
-import { pixelsToInches, inchesToPixels, getSizeNodePixel, 
-    getMeanNodesSizePixel, getSepAttributesInches, getSepAttributesPixel, 
-    minEdgeLength, medianEdgeLength, rectangleSize, 
-    defaultHeightNode,
-    defaultWidthNode} from '../CalculateSize';
 import * as GetSetAttributsNodes from "../GetSetAttributsNodes";
+import * as CalculateSize from "../CalculateSize";
 
 // General imports
 import { ref } from 'vue'; // Import the 'ref' function from the 'vue' module
@@ -20,53 +18,53 @@ import { ref } from 'vue'; // Import the 'ref' function from the 'vue' module
 
 
 describe('CalculateSize', () => {
-    const nodeClass1: Node = {
+    const nodeClass1: NodeLayout = {
         id: '1',
         classes: ['class1'],
         x: 0,
         y: 0,
     };
-    const nodeClass2: Node = {
+    const nodeClass2: NodeLayout = {
         id: '2',
         classes: ['class2'],
         x: 0,
-        y: 0
+        y: 0,
     };
-    const nodeClass12: Node = {
+    const nodeClass12: NodeLayout = {
         id: '3',
         classes: ['class1','class2'],
         x: 0,
         y: 0
     };
-    const nodeClass21: Node = {
+    const nodeClass21: NodeLayout = {
         id: '4',
         classes: ['class2','class1'],
         x: 0,
         y: 0
     };
 
-    const nodeClass3: Node = {
+    const nodeClass3: NodeLayout = {
         id: '4',
         classes: ['class3'],
         x: 0,
         y: 0
     };
 
-    const nodeClass23: Node = {
+    const nodeClass23: NodeLayout = {
         id: '4',
         classes: ['class2','class3'],
         x: 0,
         y: 0
     };
 
-    const nodeClassEmpty: Node = {
+    const nodeClassEmpty: NodeLayout = {
         id: '4',
         classes: [],
         x: 0,
         y: 0
     };
 
-    const nodeNoClass: Node = {
+    const nodeNoClass: NodeLayout = {
         id: '4',
         x: 0,
         y: 0
@@ -92,7 +90,7 @@ describe('CalculateSize', () => {
         nodeStyles: {}
     };
 
-    const networkNodes: Network = {
+    const networkNodes: NetworkLayout = {
         id: 'network',
         nodes: {
             '1': nodeClass1,
@@ -102,7 +100,7 @@ describe('CalculateSize', () => {
         ]
     };
 
-    const nodesForNetwork: {[key:string]:Node} = 
+    const nodesForNetwork: {[key:string]:NodeLayout} = 
     {
         'node1': {...nodeClass1,id:"node1"},
         'node2': {...nodeClass1, x:50,y:100, id:"node2"},
@@ -110,7 +108,7 @@ describe('CalculateSize', () => {
         'node4': {...nodeClass1, x:50,y:50,id:"node4"}
     };
 
-    const network3Edges: Network = {
+    const network3Edges: NetworkLayout = {
         id: 'network',
         nodes: nodesForNetwork,
         links: [
@@ -120,7 +118,7 @@ describe('CalculateSize', () => {
         ]
     };
 
-    const network4Edges: Network = {
+    const network4Edges: NetworkLayout = {
         id: 'network',
         nodes: nodesForNetwork,
         links: [
@@ -134,48 +132,48 @@ describe('CalculateSize', () => {
     // 0. Nodes
 
     it('should convert pixels to inches', () => {
-        expect(pixelsToInches(96)).toBe(1.33);
-        expect(pixelsToInches(432)).toBe(6);
-        expect(pixelsToInches(60,10)).toBe(6);
-        expect(pixelsToInches(10,10)).toBe(1);
+        expect(CalculateSize.pixelsToInches(96)).toBe(1.33);
+        expect(CalculateSize.pixelsToInches(432)).toBe(6);
+        expect(CalculateSize.pixelsToInches(60,10)).toBe(6);
+        expect(CalculateSize.pixelsToInches(10,10)).toBe(1);
     });
 
     it('should throw error because dpi = 0', () => {
-        expect(() => pixelsToInches(1,0)).toThrow();
+        expect(() => CalculateSize.pixelsToInches(1,0)).toThrow();
     });
 
     it('should convert inches to pixels', () => {
-        expect(inchesToPixels(1)).toBe(72);
-        expect(inchesToPixels(6)).toBe(432);
-        expect(inchesToPixels(1,10)).toBe(10);
-        expect(inchesToPixels(6,10)).toBe(60);
-        expect(inchesToPixels(1,0)).toBe(0);
+        expect(CalculateSize.inchesToPixels(1)).toBe(72);
+        expect(CalculateSize.inchesToPixels(6)).toBe(432);
+        expect(CalculateSize.inchesToPixels(1,10)).toBe(10);
+        expect(CalculateSize.inchesToPixels(6,10)).toBe(60);
+        expect(CalculateSize.inchesToPixels(1,0)).toBe(0);
     });
 
     test('getSizeNodePixel', () => {
         // TEST
-        const size1 = getSizeNodePixel(nodeClass1, networkStyle);
-        const size2 = getSizeNodePixel(nodeClass2, networkStyle);
-        const size12 = getSizeNodePixel(nodeClass12, networkStyle);
-        const size21 = getSizeNodePixel(nodeClass21, networkStyle);
-        const size3 = getSizeNodePixel(nodeClass3, networkStyle);
-        const size23 = getSizeNodePixel(nodeClass23, networkStyle);
-        const sizeEmpty = getSizeNodePixel(nodeClassEmpty, networkStyle);
-        const sizeNoClass = getSizeNodePixel(nodeNoClass, networkStyle);
-        const sizeNoStyle= getSizeNodePixel(nodeClass1, networkStyleEmpty);
-        const sizeEmptyStyle = getSizeNodePixel(nodeClass1, networkStyleEmptyNodeStyle);
+        const size1 = CalculateSize.getSizeNodePixel(nodeClass1, networkStyle);
+        const size2 = CalculateSize.getSizeNodePixel(nodeClass2, networkStyle);
+        const size12 = CalculateSize.getSizeNodePixel(nodeClass12, networkStyle);
+        const size21 = CalculateSize.getSizeNodePixel(nodeClass21, networkStyle);
+        const size3 = CalculateSize.getSizeNodePixel(nodeClass3, networkStyle);
+        const size23 = CalculateSize.getSizeNodePixel(nodeClass23, networkStyle);
+        const sizeEmpty = CalculateSize.getSizeNodePixel(nodeClassEmpty, networkStyle);
+        const sizeNoClass = CalculateSize.getSizeNodePixel(nodeNoClass, networkStyle);
+        const sizeNoStyle= CalculateSize.getSizeNodePixel(nodeClass1, networkStyleEmpty);
+        const sizeEmptyStyle = CalculateSize.getSizeNodePixel(nodeClass1, networkStyleEmptyNodeStyle);
 
         // EXPECT
         expect(size1).toEqual({ height: 50, width: 50 });
         expect(size2).toEqual({ height: 100, width: 100 });
         expect(size12).toEqual({ height: 100, width: 100 });
         expect(size21).toEqual({ height: 50, width: 50 });
-        expect(size3).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
+        expect(size3).toEqual({ height: CalculateSize.defaultHeightNode, width: CalculateSize.defaultWidthNode }); // default value
         expect(size23).toEqual({ height: 100, width: 100 }); 
-        expect(sizeEmpty).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
-        expect(sizeNoClass).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
-        expect(sizeNoStyle).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
-        expect(sizeEmptyStyle).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
+        expect(sizeEmpty).toEqual({ height: CalculateSize.defaultHeightNode, width: CalculateSize.defaultWidthNode }); // default value
+        expect(sizeNoClass).toEqual({ height: CalculateSize.defaultHeightNode, width: CalculateSize.defaultWidthNode }); // default value
+        expect(sizeNoStyle).toEqual({ height: CalculateSize.defaultHeightNode, width: CalculateSize.defaultWidthNode }); // default value
+        expect(sizeEmptyStyle).toEqual({ height: CalculateSize.defaultHeightNode, width: CalculateSize.defaultWidthNode }); // default value
     });
 
     test('test mean size with all nodes', async () => {
@@ -188,12 +186,12 @@ describe('CalculateSize', () => {
         };
 
         // TEST
-        const size = await getMeanNodesSizePixel(Object.values(networkNodes.nodes), networkStyle);
-        const sizeEmpty = await getMeanNodesSizePixel(Object.values(networkEmpty.nodes), networkStyle);
+        const size = await CalculateSize.getMeanNodesSizePixel(Object.values(networkNodes.nodes), networkStyle);
+        const sizeEmpty = await CalculateSize.getMeanNodesSizePixel(Object.values(networkEmpty.nodes), networkStyle);
 
         // EXPECT
         expect(size).toEqual({ height: 75, width: 75 });
-        expect(sizeEmpty).toEqual({ height: defaultHeightNode, width: defaultWidthNode }); // default value
+        expect(sizeEmpty).toEqual({ height: CalculateSize.defaultHeightNode, width: CalculateSize.defaultWidthNode }); // default value
     });
 
 
@@ -207,7 +205,7 @@ describe('CalculateSize', () => {
                         .mockImplementationOnce(() => false); // Second call returns false
 
         // TEST
-        const sizeNoSideCompound = await getMeanNodesSizePixel(Object.values(networkNodes.nodes), networkStyle,false);
+        const sizeNoSideCompound = await CalculateSize.getMeanNodesSizePixel(Object.values(networkNodes.nodes), networkStyle,false);
 
         // EXPECT
         expect(sizeNoSideCompound).toEqual({ height: 100, width: 100 }); 
@@ -217,8 +215,8 @@ describe('CalculateSize', () => {
 
     test('getSepAttributesInches', async () => {
         // TEST
-        const sep1 = await getSepAttributesInches(networkNodes, networkStyle);
-        const sep2 = await getSepAttributesInches(networkNodes, networkStyle,2);
+        const sep1 = await CalculateSize.getSepAttributesInches(networkNodes, networkStyle);
+        const sep2 = await CalculateSize.getSepAttributesInches(networkNodes, networkStyle,2);
 
         // EXPECT
         expect(sep1).toEqual({ rankSep: 1.04, nodeSep: 1.04 });
@@ -227,8 +225,8 @@ describe('CalculateSize', () => {
 
     test('getSepAttributesPixel', async () => {
         // TEST
-        const sep1 = await getSepAttributesPixel(networkNodes, networkStyle);
-        const sep2 = await getSepAttributesPixel(networkNodes, networkStyle,2);
+        const sep1 = await CalculateSize.getSepAttributesPixel(networkNodes, networkStyle);
+        const sep2 = await CalculateSize.getSepAttributesPixel(networkNodes, networkStyle,2);
 
         // EXPECT
         expect(sep1).toEqual({ rankSep: 75, nodeSep: 75 });
@@ -239,7 +237,7 @@ describe('CalculateSize', () => {
 
     it('should calculate the minimum edge length when edges in cycle are included', () => {
         // TEST
-        const minLength = minEdgeLength(network3Edges);
+        const minLength = CalculateSize.minEdgeLength(network3Edges);
 
         // EXPECT
         expect(minLength).toBe(50);
@@ -248,7 +246,7 @@ describe('CalculateSize', () => {
     it('should calculate the minimum edge and return NaN', () => {
 
         // TEST
-        const minLength = minEdgeLength(networkNodes);
+        const minLength = CalculateSize.minEdgeLength(networkNodes);
 
         // EXPECT
         expect(minLength).toBe(NaN);
@@ -264,7 +262,7 @@ describe('CalculateSize', () => {
         });
 
         // TEST
-        const minLength = minEdgeLength(network3Edges,false);
+        const minLength = CalculateSize.minEdgeLength(network3Edges,false);
 
         // EXPECT
         expect(minLength).toBe(111.8);
@@ -272,7 +270,7 @@ describe('CalculateSize', () => {
 
     it('should calculate the median edge length (with odd number of edge) when edges in cycle are included', () => {
         // TEST
-        const medianLength = medianEdgeLength(network3Edges);
+        const medianLength = CalculateSize.medianEdgeLength(network3Edges);
 
         // EXPECT
         expect(medianLength).toBe(111.8);
@@ -280,7 +278,7 @@ describe('CalculateSize', () => {
 
     it('should calculate the median edge length (with even number of edge) when edges in cycle are included', () => {
         // TEST
-        const medianLength = medianEdgeLength(network4Edges);
+        const medianLength = CalculateSize.medianEdgeLength(network4Edges);
 
         // EXPECT
         expect(medianLength).toBe(91.26);
@@ -288,7 +286,7 @@ describe('CalculateSize', () => {
 
     it('should calculate the median edge length but return 0 because no links', () => {
         // TEST
-        const medianLength = medianEdgeLength(networkNodes);
+        const medianLength = CalculateSize.medianEdgeLength(networkNodes);
 
         // EXPECT
         expect(medianLength).toBe(0);
@@ -304,7 +302,7 @@ describe('CalculateSize', () => {
         });
 
         // TEST
-        const medianLength = medianEdgeLength(network3Edges,false);
+        const medianLength = CalculateSize.medianEdgeLength(network3Edges,false);
 
         // EXPECT
         expect(medianLength).toBe(126.61);
@@ -320,7 +318,7 @@ describe('CalculateSize', () => {
             { x: 100, y: 100 }
         ];
         // TEST
-        const size = rectangleSize(coordinates);
+        const size = CalculateSize.rectangleSize(coordinates);
 
         // EXPECT
         expect(size).toEqual({
@@ -343,7 +341,7 @@ describe('CalculateSize', () => {
             { x: 100, y: 100 }
         ];
         // TEST
-        const size = rectangleSize(coordinates,listID,subgraphNetwork);
+        const size = CalculateSize.rectangleSize(coordinates,listID,subgraphNetwork);
 
         // EXPECT
         expect(size).toEqual({
@@ -353,12 +351,90 @@ describe('CalculateSize', () => {
         });
     });
 
-    test('getSizeAllGroupCycles', () => {
+    test('getSizeGroupCycles', () => {
         expect(true).toBe(false);
     });
 
-    test('getSizeGroupCycles', () => {
-        expect(true).toBe(false);
+    it('should put the size and center of the rectangle for all cycle group subgraph in the subgraph', () => {
+        
+        // DATA
+        let subgraph0:Subgraph = {
+            name: "groupCycle_0",
+            nodes:["node1","node2"],
+            precalculatedNodesPosition:{
+                   node1: { x: 0, y: 0 },
+                   node2:{ x: 100, y: 100 }
+            }
+        };
+        let subgraph1:Subgraph = {
+            name: "groupCycle_1",
+            nodes:["node3","node4"],
+            precalculatedNodesPosition:{
+                node3: { x: 10, y: 50 },
+                node4:{ x: 73, y: 25 }
+            }
+        };
+        let subgraphNetwork:SubgraphNetwork = {
+            network: ref<NetworkLayout>(network3Edges),
+            networkStyle: ref<GraphStyleProperties>(networkStyle),
+            [TypeSubgraph.CYCLEGROUP]:{
+                "groupCycle_0": subgraph0,
+                "groupCycle_1":subgraph1
+            }
+        };
+
+        const subgraphNetworkExpected:SubgraphNetwork = {
+            network: ref<NetworkLayout>(network3Edges),
+            networkStyle: ref<GraphStyleProperties>(networkStyle),
+            [TypeSubgraph.CYCLEGROUP]:{
+                "groupCycle_0": {
+                    ...subgraph0, 
+                    width : -1,
+                    height :-1,
+                    originalPosition: { x: 0, y: 0 }
+                },
+                "groupCycle_1": {
+                    ...subgraph1, 
+                    width : -1,
+                    height :-1,
+                    originalPosition: { x: 0, y: 0 }
+                }
+            }
+        };
+
+        const listIDExpected1 = ["node3","node4"]
+        const coordinatesExpected1: Coordinate[] = [
+            { x: 10, y: 50 },
+            { x: 73, y: 25 }
+        ];
+
+        const listIDExpected2 = ["node1","node2"]
+        const coordinatesExpected2: Coordinate[] = [
+            { x: 0, y: 0 },
+            { x: 100, y: 100 }
+        ];
+
+        // MOCK 
+        const rectangleSizeMock = jest.spyOn(CalculateSize, 'rectangleSize');
+
+        // Set up the mock implementation 
+        rectangleSizeMock.mockImplementation((coordinates,listID,subgraphNetwork) => {
+            return {
+                width: -1,
+                height: -1,
+                center: { x: 0, y: 0 }
+            }; 
+        });
+
+
+        // TEST
+        subgraphNetwork=CalculateSize.getSizeAllGroupCycles(subgraphNetwork);
+        expect(rectangleSizeMock).toHaveBeenCalledTimes(2); 
+        expect(rectangleSizeMock).toHaveBeenCalledWith(coordinatesExpected1, listIDExpected1, subgraphNetwork);
+        expect(rectangleSizeMock).toHaveBeenCalledWith(coordinatesExpected2, listIDExpected2, subgraphNetwork);
+
+        expect(subgraphNetwork).toEqual(subgraphNetworkExpected);
+
     });
 
 
-- 
GitLab


From dd6c66af4beab55c3f51dfabf3d99bc29c421e5a Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Thu, 12 Sep 2024 09:21:47 +0200
Subject: [PATCH 07/13] test calculate size

---
 src/composables/CalculateSize.ts              |   4 +
 .../__tests__/CalculateSize.tests.ts          | 229 +++++++++++-------
 2 files changed, 140 insertions(+), 93 deletions(-)

diff --git a/src/composables/CalculateSize.ts b/src/composables/CalculateSize.ts
index ef71104..b1366aa 100644
--- a/src/composables/CalculateSize.ts
+++ b/src/composables/CalculateSize.ts
@@ -290,6 +290,7 @@ export function rectangleSize(listCoordinates:Coordinate[],listID?:string[],subg
             minX = -defaultWidthNode/2;
         } else {
             const minXNode = listID[minXIndex];
+            if (!(minXNode in subgraphNetwork.network.value.nodes)) throw new Error("Node not in network");
             const sizeMinXNode = getSizeNodePixel(subgraphNetwork.network.value.nodes[minXNode],subgraphNetwork.networkStyle.value);
             minX = minX - sizeMinXNode.width/2;
         }
@@ -299,6 +300,7 @@ export function rectangleSize(listCoordinates:Coordinate[],listID?:string[],subg
             maxX = defaultWidthNode/2;
         }else {
             const maxXNode = listID[maxXIndex];
+            if (!(maxXNode in subgraphNetwork.network.value.nodes)) throw new Error("Node not in network");
             const sizeMaxXNode = getSizeNodePixel(subgraphNetwork.network.value.nodes[maxXNode],subgraphNetwork.networkStyle.value);
             maxX = maxX + sizeMaxXNode.width/2;
         }
@@ -308,6 +310,7 @@ export function rectangleSize(listCoordinates:Coordinate[],listID?:string[],subg
             minY = -defaultHeightNode/2;
         } else {
             const minYNode = listID[minYIndex];
+            if (!(minYNode in subgraphNetwork.network.value.nodes)) throw new Error("Node not in network");
             const sizeMinYNode = getSizeNodePixel(subgraphNetwork.network.value.nodes[minYNode],subgraphNetwork.networkStyle.value);
             minY = minY - sizeMinYNode.height/2;
         }
@@ -317,6 +320,7 @@ export function rectangleSize(listCoordinates:Coordinate[],listID?:string[],subg
             maxY = defaultHeightNode/2;
         } else {
             const maxYNode = listID[maxYIndex];
+            if (!(maxYNode in subgraphNetwork.network.value.nodes)) throw new Error("Node not in network");
             const sizeMaxYNode = getSizeNodePixel(subgraphNetwork.network.value.nodes[maxYNode],subgraphNetwork.networkStyle.value);
             maxY = maxY + sizeMaxYNode.height/2;
         }
diff --git a/src/composables/__tests__/CalculateSize.tests.ts b/src/composables/__tests__/CalculateSize.tests.ts
index c429293..f344418 100644
--- a/src/composables/__tests__/CalculateSize.tests.ts
+++ b/src/composables/__tests__/CalculateSize.tests.ts
@@ -18,18 +18,64 @@ import { ref } from 'vue'; // Import the 'ref' function from the 'vue' module
 
 
 describe('CalculateSize', () => {
-    const nodeClass1: NodeLayout = {
-        id: '1',
-        classes: ['class1'],
-        x: 0,
-        y: 0,
-    };
-    const nodeClass2: NodeLayout = {
-        id: '2',
-        classes: ['class2'],
-        x: 0,
-        y: 0,
-    };
+    let nodeClass1: NodeLayout;
+    let nodeClass2: NodeLayout;
+    let networkNodes: NetworkLayout;
+    let nodesForNetwork: {[key: string]: NodeLayout};
+    let network3Edges: NetworkLayout;
+    let network4Edges: NetworkLayout;
+
+    beforeEach(() => {
+        nodeClass1 = {
+            id: '1',
+            classes: ['class1'],
+            x: 0,
+            y: 0,
+        };
+        nodeClass2 = {
+            id: '2',
+            classes: ['class2'],
+            x: 0,
+            y: 0,
+        };
+        networkNodes = {
+            id: 'network',
+            nodes: {
+                '1': nodeClass1,
+                '2': nodeClass2,
+            },
+            links: [
+            ]
+        };
+        nodesForNetwork = 
+        {
+            'node1': {...nodeClass1,id:"node1"},
+            'node2': {...nodeClass1, x:50,y:100, id:"node2"},
+            'node3': {...nodeClass1, x:100,y:100,id:"node3"},
+            'node4': {...nodeClass1, x:50,y:50,id:"node4"}
+        };
+
+        network3Edges = {
+            id: 'network',
+            nodes: nodesForNetwork,
+            links: [
+                {id:"link",source: nodesForNetwork.node1, target: nodesForNetwork.node2},
+                {id:"link",source: nodesForNetwork.node2, target: nodesForNetwork.node3},
+                {id:"link",source: nodesForNetwork.node3, target: nodesForNetwork.node1},
+            ]
+        };
+
+        network4Edges = {
+            id: 'network',
+            nodes: nodesForNetwork,
+            links: [
+                {id:"link",source: nodesForNetwork.node1, target: nodesForNetwork.node2},
+                {id:"link",source: nodesForNetwork.node2, target: nodesForNetwork.node3},
+                {id:"link",source: nodesForNetwork.node3, target: nodesForNetwork.node1},
+                {id:"link",source: nodesForNetwork.node4, target: nodesForNetwork.node1},
+            ]
+        };
+    });
     const nodeClass12: NodeLayout = {
         id: '3',
         classes: ['class1','class2'],
@@ -90,44 +136,7 @@ describe('CalculateSize', () => {
         nodeStyles: {}
     };
 
-    const networkNodes: NetworkLayout = {
-        id: 'network',
-        nodes: {
-            '1': nodeClass1,
-            '2': nodeClass2,
-        },
-        links: [
-        ]
-    };
-
-    const nodesForNetwork: {[key:string]:NodeLayout} = 
-    {
-        'node1': {...nodeClass1,id:"node1"},
-        'node2': {...nodeClass1, x:50,y:100, id:"node2"},
-        'node3': {...nodeClass1, x:100,y:100,id:"node3"},
-        'node4': {...nodeClass1, x:50,y:50,id:"node4"}
-    };
-
-    const network3Edges: NetworkLayout = {
-        id: 'network',
-        nodes: nodesForNetwork,
-        links: [
-            {id:"link",source: nodesForNetwork.node1, target: nodesForNetwork.node2},
-            {id:"link",source: nodesForNetwork.node2, target: nodesForNetwork.node3},
-            {id:"link",source: nodesForNetwork.node3, target: nodesForNetwork.node1},
-        ]
-    };
-
-    const network4Edges: NetworkLayout = {
-        id: 'network',
-        nodes: nodesForNetwork,
-        links: [
-            {id:"link",source: nodesForNetwork.node1, target: nodesForNetwork.node2},
-            {id:"link",source: nodesForNetwork.node2, target: nodesForNetwork.node3},
-            {id:"link",source: nodesForNetwork.node3, target: nodesForNetwork.node1},
-            {id:"link",source: nodesForNetwork.node4, target: nodesForNetwork.node1},
-        ]
-    };
+    
 
     // 0. Nodes
 
@@ -351,8 +360,23 @@ describe('CalculateSize', () => {
         });
     });
 
-    test('getSizeGroupCycles', () => {
-        expect(true).toBe(false);
+    it('should throw an error when calculate the size a rectangle because node not in network', () => {
+
+        // DATA
+        const subgraphNetwork:SubgraphNetwork = {
+            network: ref<NetworkLayout>(network3Edges),
+            networkStyle: ref<GraphStyleProperties>(networkStyle)
+        };
+        const listID = ["node1","nodeNotNetwork"]
+        const coordinates: Coordinate[] = [
+            { x: 0, y: 0 },
+            { x: 100, y: 100 }
+        ];
+
+        // EXPECT
+        expect( 
+            ()=> CalculateSize.rectangleSize(coordinates,listID,subgraphNetwork)
+        ).toThrow();
     });
 
     it('should put the size and center of the rectangle for all cycle group subgraph in the subgraph', () => {
@@ -360,7 +384,7 @@ describe('CalculateSize', () => {
         // DATA
         let subgraph0:Subgraph = {
             name: "groupCycle_0",
-            nodes:["node1","node2"],
+            nodes:[],
             precalculatedNodesPosition:{
                    node1: { x: 0, y: 0 },
                    node2:{ x: 100, y: 100 }
@@ -368,7 +392,7 @@ describe('CalculateSize', () => {
         };
         let subgraph1:Subgraph = {
             name: "groupCycle_1",
-            nodes:["node3","node4"],
+            nodes:[],
             precalculatedNodesPosition:{
                 node3: { x: 10, y: 50 },
                 node4:{ x: 73, y: 25 }
@@ -389,50 +413,23 @@ describe('CalculateSize', () => {
             [TypeSubgraph.CYCLEGROUP]:{
                 "groupCycle_0": {
                     ...subgraph0, 
-                    width : -1,
-                    height :-1,
-                    originalPosition: { x: 0, y: 0 }
+                    width : 150,
+                    height :150,
+                    originalPosition: { x: 50, y: 50 }
                 },
                 "groupCycle_1": {
                     ...subgraph1, 
-                    width : -1,
-                    height :-1,
-                    originalPosition: { x: 0, y: 0 }
+                    width : 113,
+                    height :75,
+                    originalPosition: { x: 41.5, y: 37.5 }
                 }
             }
         };
 
-        const listIDExpected1 = ["node3","node4"]
-        const coordinatesExpected1: Coordinate[] = [
-            { x: 10, y: 50 },
-            { x: 73, y: 25 }
-        ];
-
-        const listIDExpected2 = ["node1","node2"]
-        const coordinatesExpected2: Coordinate[] = [
-            { x: 0, y: 0 },
-            { x: 100, y: 100 }
-        ];
-
-        // MOCK 
-        const rectangleSizeMock = jest.spyOn(CalculateSize, 'rectangleSize');
-
-        // Set up the mock implementation 
-        rectangleSizeMock.mockImplementation((coordinates,listID,subgraphNetwork) => {
-            return {
-                width: -1,
-                height: -1,
-                center: { x: 0, y: 0 }
-            }; 
-        });
 
 
         // TEST
         subgraphNetwork=CalculateSize.getSizeAllGroupCycles(subgraphNetwork);
-        expect(rectangleSizeMock).toHaveBeenCalledTimes(2); 
-        expect(rectangleSizeMock).toHaveBeenCalledWith(coordinatesExpected1, listIDExpected1, subgraphNetwork);
-        expect(rectangleSizeMock).toHaveBeenCalledWith(coordinatesExpected2, listIDExpected2, subgraphNetwork);
-
         expect(subgraphNetwork).toEqual(subgraphNetworkExpected);
 
     });
@@ -440,20 +437,66 @@ describe('CalculateSize', () => {
 
 // 3.  Shift coordinates depending on size
 
+    it('should return coordinate of top left corner instead of center', () => {
+        // TEST
+        const coord= CalculateSize.getTopLeftCoordFromCenter(nodeClass1, networkStyle);
 
-    test('shiftAllToGetTopLeftCoord', () => {
-        expect(true).toBe(false);
+        // EXPECT
+        expect(coord).toEqual({ x: -25, y: -25 });
     });
 
-    test('getTopLeftCoordFromCenter', () => {
-        expect(true).toBe(false);
+
+    it('should return coordinate of center instead of top left corner', () => {
+        // TEST
+        const coord= CalculateSize.getCenterCoordFromTopLeft(nodeClass1, networkStyle);
+
+        // EXPECT
+        expect(coord).toEqual({ x: 25, y: 25 });
     });
 
+    it('should shift all coordinate to left top corner', () => {
+        // DATA
+
+        const networkShiftedExpected: NetworkLayout = {
+            id: 'network',
+            nodes: {
+                '1': { ...nodeClass1, x: -25, y: -25 },
+                '2': { ...nodeClass2, x: -50, y: -50 },
+            },
+            links: [
+            ]
+        };
+        // TEST
+        CalculateSize.shiftAllToGetTopLeftCoord(networkNodes, networkStyle);
 
-    test('getCenterCoordFromTopLeft', () => {
-        expect(true).toBe(false);
+        // EXPECT
+        expect(networkNodes).toEqual(networkShiftedExpected);
     });
 
+    it('should not shift all coordinate to left top corner (not the cycle)', () => {
+        // MOCK
+        const inCycleMock = jest.spyOn(GetSetAttributsNodes, 'inCycle');
+        inCycleMock.mockImplementation((network,nodeID) => {
+                return nodeID === "1";
+        });
+                    
+
+        // DATA
+
+        const networkShiftedExpected: NetworkLayout = {
+            id: 'network',
+            nodes: {
+                '1': { ...nodeClass1, x: 0, y: 0 },
+                '2': { ...nodeClass2, x: -50, y: -50 },
+            },
+            links: [
+            ]
+        };
+        // TEST
+        CalculateSize.shiftAllToGetTopLeftCoord(networkNodes, networkStyle,false);
 
+        // EXPECT
+        expect(networkNodes).toEqual(networkShiftedExpected);
+    });
 
 });
\ No newline at end of file
-- 
GitLab


From a4e27995b57bd282046079d04d472c90c3efd8d2 Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Thu, 12 Sep 2024 11:58:26 +0200
Subject: [PATCH 08/13] re clean de fichier avec nouveau linter

---
 src/composables/CalculateRelationCycle.ts     | 116 ++++----
 src/composables/CalculateStartNodes.ts        |  59 ++--
 src/composables/ConvertFromNetwork.ts         | 269 +++++++++---------
 src/composables/ConvertToNetwork.ts           | 102 ++++---
 src/composables/LayoutManageSideCompounds.ts  |  52 ++--
 src/composables/LayoutReversibleReactions.ts  |  13 +-
 .../__tests__/CalculateStartNodes.tests.ts    | 102 +++++++
 7 files changed, 410 insertions(+), 303 deletions(-)
 create mode 100644 src/composables/__tests__/CalculateStartNodes.tests.ts

diff --git a/src/composables/CalculateRelationCycle.ts b/src/composables/CalculateRelationCycle.ts
index 2266b2b..ccde993 100644
--- a/src/composables/CalculateRelationCycle.ts
+++ b/src/composables/CalculateRelationCycle.ts
@@ -8,6 +8,7 @@ import { LinkLayout, NetworkLayout } from "../types/NetworkLayout";
 
 // Composable imports
 import { inCycle } from "./GetSetAttributsNodes";
+import { Coordinate } from "../types/CoordinatesSize";
 
 
 /**
@@ -90,28 +91,35 @@ import { inCycle } from "./GetSetAttributsNodes";
  * @returns An array of cycle IDs representing the neighboring cycles.
  */
 export function neighborsGroupCycle(subgraphNetwork:SubgraphNetwork,cycleGroupId:string, parentOrChild:"parent"|"child",xSort:boolean=true):string[]{
-    if (cycleGroupId in subgraphNetwork[TypeSubgraph.CYCLEGROUP] && subgraphNetwork[TypeSubgraph.CYCLEGROUP][cycleGroupId].precalculatedNodesPosition){
-        // get the id of nodes in group cycle
-        const nodes=getNodesIDPlacedInGroupCycle(subgraphNetwork,cycleGroupId);
-        // sort nodes of the group cycle by x
-        if (xSort){
-            nodes.sort((nodeIdA, nodeIdB) => {
-                const nodeA = subgraphNetwork[TypeSubgraph.CYCLEGROUP][cycleGroupId].precalculatedNodesPosition[nodeIdA];
-                const nodeB = subgraphNetwork[TypeSubgraph.CYCLEGROUP][cycleGroupId].precalculatedNodesPosition[nodeIdB];
-                return nodeA.x - nodeB.x;
-            });
-        }
-        if (parentOrChild==="parent"){
-            // get parent nodes
-            const parentCycles = Array.from(new Set(parentNodeNotInCycle(subgraphNetwork, nodes).flat()));
-            return parentCycles;
-        } else {
-            // get child nodes
-            const childCycles = Array.from(new Set(childNodeNotInCycle(subgraphNetwork, nodes).flat()));
-            return childCycles;
+    if (subgraphNetwork[TypeSubgraph.CYCLEGROUP] && cycleGroupId in subgraphNetwork[TypeSubgraph.CYCLEGROUP]){
+        const cycleGroup=subgraphNetwork[TypeSubgraph.CYCLEGROUP][cycleGroupId];   
+        if (cycleGroup.precalculatedNodesPosition){
+            const positionNodesCycleGroup=cycleGroup.precalculatedNodesPosition;
+            // get the id of nodes in group cycle
+            const nodes=getNodesIDPlacedInGroupCycle(subgraphNetwork,cycleGroupId);
+            // sort nodes of the group cycle by x
+            if (xSort){
+                nodes.sort((nodeIdA, nodeIdB) => {
+                    if(!(nodeIdA in positionNodesCycleGroup) || !(nodeIdB in positionNodesCycleGroup)) throw new Error("Node not plaed inside groupe cycle");
+                    const nodeA = positionNodesCycleGroup[nodeIdA];
+                    const nodeB = positionNodesCycleGroup[nodeIdB];
+                    return nodeA.x - nodeB.x;
+                });
+            }
+            if (parentOrChild==="parent"){
+                // get parent nodes
+                const parentCycles = Array.from(new Set(parentNodeNotInCycle(subgraphNetwork, nodes).flat()));
+                return parentCycles;
+            } else {
+                // get child nodes
+                const childCycles = Array.from(new Set(childNodeNotInCycle(subgraphNetwork, nodes).flat()));
+                return childCycles;
+            }
+        }else{
+            return []; // no node placed inside cyclegroup
         }
     }else{
-        return [];
+        throw new Error("Group cycle not in subgraphNetwork");
     }
 }
 
@@ -165,12 +173,18 @@ export function childNodeNotInCycle(subgraphNetwork: SubgraphNetwork, listNodes:
  * @returns An array of strings representing the IDs of the nodes placed in the group cycle.
  */
 export function getNodesIDPlacedInGroupCycle(subgraphNetwork:SubgraphNetwork,groupCycleID:string):string[]{
-    if (groupCycleID in subgraphNetwork[TypeSubgraph.CYCLEGROUP] && subgraphNetwork[TypeSubgraph.CYCLEGROUP][groupCycleID].precalculatedNodesPosition){
-        return Object.entries(subgraphNetwork[TypeSubgraph.CYCLEGROUP][groupCycleID].precalculatedNodesPosition)
+    if (subgraphNetwork[TypeSubgraph.CYCLEGROUP] && groupCycleID in subgraphNetwork[TypeSubgraph.CYCLEGROUP]){
+        const groupCycle =subgraphNetwork[TypeSubgraph.CYCLEGROUP][groupCycleID];
+        if (groupCycle.precalculatedNodesPosition){
+            const positionNodesCycleGroup=groupCycle.precalculatedNodesPosition;
+            return Object.entries(positionNodesCycleGroup)
                 .filter(([_,item]) => item.x !== undefined && item.y !== undefined)
                 .map(([key,_])=>key);
+        }else{
+            return [];
+        }
     }else{
-        return [];
+        throw new Error("Cycle group not in subgraphNetwork");
     }
 }
 
@@ -185,8 +199,11 @@ export function getNodesIDPlacedInGroupCycle(subgraphNetwork:SubgraphNetwork,gro
  *          If the group cycle ID is not found or the precalculated node positions are not available, null is returned.
  */
 export function getNodesPlacedInGroupCycle(subgraphNetwork:SubgraphNetwork,groupCycleID:string,positionAsFixed:boolean=false):{ id: string,x?:number, y?:number, fx?:number, fy?:number }[]{
-    if (groupCycleID in subgraphNetwork[TypeSubgraph.CYCLEGROUP] && subgraphNetwork[TypeSubgraph.CYCLEGROUP][groupCycleID].precalculatedNodesPosition){
-            return Object.entries(subgraphNetwork[TypeSubgraph.CYCLEGROUP][groupCycleID].precalculatedNodesPosition)
+    if (subgraphNetwork[TypeSubgraph.CYCLEGROUP] && groupCycleID in subgraphNetwork[TypeSubgraph.CYCLEGROUP]){
+        const groupCycle =subgraphNetwork[TypeSubgraph.CYCLEGROUP][groupCycleID];
+        if (groupCycle.precalculatedNodesPosition){
+            const positionNodesCycleGroup=groupCycle.precalculatedNodesPosition;
+            return Object.entries(positionNodesCycleGroup)
                     .filter(([_, item]) => { return item.x !== undefined && item.y !== undefined })
                     .map(([key, item]) => { 
                         if (item.x!==null || item.y!==null){
@@ -197,8 +214,11 @@ export function getNodesPlacedInGroupCycle(subgraphNetwork:SubgraphNetwork,group
                             return { id: key }
                         }
             }); 
+        }else{
+            return [];
+        }
     }else{
-        return null;
+        throw new Error("Cycle group not in subgraphNetwork");
     }
 }
 
@@ -212,18 +232,24 @@ export function getNodesPlacedInGroupCycle(subgraphNetwork:SubgraphNetwork,group
  * @returns An object representing the nodes placed in the group cycle. Each value contains the x and y coordinates.
  *          If the group cycle ID is not found or the precalculated node positions are not available, null is returned.
  */
-export function getNodesPlacedInGroupCycleAsObject(subgraphNetwork:SubgraphNetwork,groupCycleID:string):{ [key:string]:{x:number,y:number }}{
-    if (groupCycleID in subgraphNetwork[TypeSubgraph.CYCLEGROUP] && subgraphNetwork[TypeSubgraph.CYCLEGROUP][groupCycleID].precalculatedNodesPosition){
-        return Object.entries(subgraphNetwork[TypeSubgraph.CYCLEGROUP][groupCycleID].precalculatedNodesPosition)
+export function getNodesPlacedInGroupCycleAsObject(subgraphNetwork:SubgraphNetwork,groupCycleID:string):{[key:string]:Coordinate}{
+    if (subgraphNetwork[TypeSubgraph.CYCLEGROUP] && groupCycleID in subgraphNetwork[TypeSubgraph.CYCLEGROUP]){
+        const groupCycle =subgraphNetwork[TypeSubgraph.CYCLEGROUP][groupCycleID];
+        if (groupCycle.precalculatedNodesPosition){
+            const positionNodesCycleGroup=groupCycle.precalculatedNodesPosition;
+            return Object.entries(positionNodesCycleGroup)
                         .filter(([_, item]) => { return item.x !== undefined && item.y !== undefined })
-                        .reduce((acc, node) => { 
+                        .reduce<{ [key:string]:Coordinate}>((acc, node) => { 
                             if (node[1].x!==null || node[1].y!==null){
                                  acc[node[0]]={ x:node[1].x, y:node[1].y } 
                             }
                             return acc;
                         },{});
-    }else{
-        return null;
+        }else{
+            return {};
+        }
+    } else {
+        throw new Error("Cycle group not in subgraphNetwork");
     }
 }
 
@@ -318,7 +344,7 @@ export function sortLinksWithAllGroupCycle(subgraphNetwork:SubgraphNetwork,order
  */
 function sortLinksWithGroupCycle(subgraphNetwork:SubgraphNetwork,groupCycle:string):{subgraphNetwork:SubgraphNetwork,linksOrdered:LinkLayout[]}{
     let links:LinkLayout[]=[];
-    if( groupCycle in subgraphNetwork.cyclesGroup){
+    if( subgraphNetwork[TypeSubgraph.CYCLEGROUP] && groupCycle in subgraphNetwork[TypeSubgraph.CYCLEGROUP]){
         // sort parent of cycle by x of the child in the cycle
         // (first : parent of the left node of group cycle)
         const parents=neighborsGroupCycle(subgraphNetwork,groupCycle,"parent",true);
@@ -448,30 +474,10 @@ export function getListNodeLinksForCycleGroupAsObject(subgraphNetwork:SubgraphNe
  * @returns the name of the parent cycle of the cycle, if not, return the name of the cycle
  */
 export function parentCycle(cycleName:string,subgraphNetwork:SubgraphNetwork):string{
+    if (!subgraphNetwork[TypeSubgraph.CYCLE] || !subgraphNetwork[TypeSubgraph.CYCLE][cycleName]) throw new Error("cycle not in subgraphNetwork");
     if (subgraphNetwork[TypeSubgraph.CYCLE][cycleName].parentSubgraph && subgraphNetwork[TypeSubgraph.CYCLE][cycleName].parentSubgraph.type==TypeSubgraph.CYCLE){
             return subgraphNetwork[TypeSubgraph.CYCLE][cycleName].parentSubgraph.name;
     }else{ 
         return cycleName;
     }
-}
-
-
-
-
-// function getLinkParent2GroupCycle(subgraphNetwork:SubgraphNetwork,parentId:string,groupCycle:string){
-//     return Object.values(subgraphNetwork.network.value.links).filter((link) => {
-//         return link.source.id === parentId && link.target.metadata && TypeSubgraph.CYCLEGROUP in link.target.metadata && link.target.metadata[TypeSubgraph.CYCLEGROUP] === groupCycle;
-//     });
-// }
-
-// function listOfCycles(cycleList:string[],subgraphNetwork:SubgraphNetwork):string[]{
-//     const newCyclesList=[];
-//     cycleList.forEach(cycle=>{
-//         // if cycle is a 'child' of another cycle : no new metanode, it is considered as the parent cycle metanode (else it is the cycle)
-//         const biggerCycle=inBiggerCycle(cycle,subgraphNetwork); 
-//         if (!newCyclesList.includes(biggerCycle)){
-//             newCyclesList.push(biggerCycle);
-//         }
-//     });
-//     return newCyclesList;
-// }
+}
\ No newline at end of file
diff --git a/src/composables/CalculateStartNodes.ts b/src/composables/CalculateStartNodes.ts
index e46dd26..bc9a4e4 100644
--- a/src/composables/CalculateStartNodes.ts
+++ b/src/composables/CalculateStartNodes.ts
@@ -1,7 +1,7 @@
 // Types imports
 import { StartNodesType } from "../types/EnumArgs";
 import { Network } from "@metabohub/viz-core/src/types/Network";
-import { NodeLayout } from "../types/NetworkLayout";
+import { NetworkLayout, NodeLayout } from "../types/NetworkLayout";
 
 // Composable imports
 import { networkToGDSGraph } from "./ConvertFromNetwork";
@@ -36,12 +36,16 @@ import { networkToGDSGraph } from "./ConvertFromNetwork";
  * 
  */
 
+
 /**
- * Take network and all the unique y coordinate. Add the rank (y position : first, second...; not coordinate) and order ( x position in the rank: first, second,....) to metadata of network.
- * @param {Network} Network object
- * @param unique_y array of all unique y for node position
+ * Assigns rank and order to nodes in a network layout based on their x and y coordinates.
+ * 
+ * @param network - The network object.
+ * @param unique_y - An array of unique y coordinates that indicates the y that will be associated with rank.
+ *                  If a node in the network have a "y" not in this array, it will not be assigned a rank (and order)
+ * @param onlyRank - Optional parameter to indicate whether to assign only the rank or both rank and order. Default is true.
  */
-export function assignRankOrder(network: Network, unique_y: Array<number>):void {
+export function assignRankOrder(network: NetworkLayout, unique_y: Array<number>,onlyRank:boolean=true):void {
 
     // sort the y to know the associated rank for a y coordinate
     unique_y.sort((a:number, b:number) => a - b);
@@ -50,15 +54,17 @@ export function assignRankOrder(network: Network, unique_y: Array<number>):void
     const xNodeByRank: number[][] = Array.from({ length: unique_y.length }, () => []);
     Object.values(network.nodes).forEach((node) => {
         const rank = unique_y.indexOf(node.y);
+        if (!node.metadataLayout) node.metadataLayout={}; 
         if(rank >-1){
-            node.metadata = node.metadata || {}; 
-            node.metadata.rank = rank;
-            xNodeByRank[rank].push(node.x);
-        }else{
-            node.metadata.rank = undefined;
+            node.metadataLayout.rank = rank;
+            if (!onlyRank){
+                xNodeByRank[rank].push(node.x);
+            }
         }
     });
 
+    if (onlyRank) return;
+
     // sort the y by rank
     xNodeByRank.forEach(sublist => {
         sublist.sort((a, b) => a - b); 
@@ -66,17 +72,12 @@ export function assignRankOrder(network: Network, unique_y: Array<number>):void
 
     // get the order for each node 
     Object.values(network.nodes).forEach((node) => {
-        if (node.metadata && Object.keys(node.metadata).includes("rank") && node.metadata.rank !== undefined){
-            const rank = node.metadata.rank;
-            if (typeof rank === 'number') {
+        if (node.metadataLayout && node.metadataLayout.rank){
+            const rank = node.metadataLayout.rank;
+            if (rank<xNodeByRank.length){
                 const order = xNodeByRank[rank].indexOf(node.x);
-                node.metadata.order = order;
-            } else {
-                console.error("Le rang n'est pas un nombre");
-                node.metadata.order = undefined;
+                node.metadataLayout.order = order;
             }
-        }else{
-            node.metadata.order = undefined;
         }
     });
 }
@@ -101,9 +102,9 @@ export async function getStartNodes(network:Network, typeSource:StartNodesType):
         return Object.keys(network.nodes).sort();
     }
 
-    const start_rank=[];
-    const start_source=[];
-    const start_all=[];
+    const start_rank:string[]=[];
+    const start_source:string[]=[];
+    const start_all:string[]=[];
 
     // get object for data-graph-structure if indegree information needed (when source nodes needed)
     let graph:{[key:string]:Function};
@@ -130,25 +131,13 @@ export async function getStartNodes(network:Network, typeSource:StartNodesType):
 }
 
 
-// function getSourcesParam(network:Network,sourceType:SourceType):string[]{
-//   let sources:string[]=[];
-//     if(onlyUserSources){
-//       sources=userSources;
-//     }else{
-//       sources = concatSources(userSources as string[],getSources(network,sourceType));
-//     }
-//     return sources;
-// }
-
-
 /**
  * Node has rank 0 in metadata ?
  * @param node Node
  * @returns boolean
  */
 function hasRank0(node:NodeLayout):boolean{
-    console.warn('change rank attr');
-    return (node.metadata && Object.keys(node.metadata).includes("rank") && node.metadata.rank===0);
+    return node.metadataLayout?.rank === 0;
 }
 
 /**
diff --git a/src/composables/ConvertFromNetwork.ts b/src/composables/ConvertFromNetwork.ts
index 90240fc..cf4cc22 100644
--- a/src/composables/ConvertFromNetwork.ts
+++ b/src/composables/ConvertFromNetwork.ts
@@ -14,14 +14,14 @@ import { cycleMetanodeLink, sortLinksWithAllGroupCycle } from './CalculateRelati
 
 
 // General imports
-import  dagre  from 'dagrejs/dist/dagre.js';
+//import  dagre  from 'dagrejs/dist/dagre.js';
 import { Graph } from "@viz-js/viz";
 import * as GDS from 'graph-data-structure';
 import { h } from 'vue';
 import { link } from 'fs';
-import { s } from 'vitest/dist/reporters-1evA5lom';
+//import { s } from 'vitest/dist/reporters-1evA5lom';
 import { get } from 'http';
-import cytoscape, { ElementDefinition,Stylesheet } from 'cytoscape';
+//import cytoscape, { ElementDefinition,Stylesheet } from 'cytoscape';
 import { layout } from 'dagrejs';
 import { dot } from 'node:test/reporters';
 
@@ -173,28 +173,28 @@ export function networkToAdjacentObject(network:Network):{[key : string]:string[
  * @param  graphAttributes for dagre layout (see https://github.com/dagrejs/dagre/wiki)
  * @returns {dagre.graphlib.Graph} Return dagre.graphlib.Graph object 
  */
-export function networkToDagre(network: Network,graphAttributes={}): dagre.graphlib.Graph{
+// export function networkToDagre(network: Network,graphAttributes={}): dagre.graphlib.Graph{
 
-    // initialisation dagre graph
-    var g = new dagre.graphlib.Graph();
-    g.setGraph(graphAttributes);
-    g.setDefaultEdgeLabel(() => ({}));
+//     // initialisation dagre graph
+//     var g = new dagre.graphlib.Graph();
+//     g.setGraph(graphAttributes);
+//     g.setDefaultEdgeLabel(() => ({}));
 
-    // insert nodes into graph
-    Object.values(network.nodes).forEach((node) => {
-        const { id, label, x, y } = node;
-        g.setNode(id, { label, width: 100, height: 100, x, y });
-    });
+//     // insert nodes into graph
+//     Object.values(network.nodes).forEach((node) => {
+//         const { id, label, x, y } = node;
+//         g.setNode(id, { label, width: 100, height: 100, x, y });
+//     });
 
-    // insert edges into graph
-    network.links.forEach((link) => {
-        const { source, target } = link;
-        g.setEdge(source.id, target.id);
-    });
+//     // insert edges into graph
+//     network.links.forEach((link) => {
+//         const { source, target } = link;
+//         g.setEdge(source.id, target.id);
+//     });
 
-    return g;
+//     return g;
 
-}
+// }
 
 
   
@@ -205,47 +205,47 @@ export function networkToDagre(network: Network,graphAttributes={}): dagre.graph
  * @param initialPosition - Optional. Specifies whether to initialize the position of the nodes. Default is false.
  * @returns The converted Cytoscape object.
  */
-export function networkToCytoscape(network: Network, initialPosition:boolean=false): cytoscape.Core {
-
-    // Convert nodes
-    const nodes: ElementDefinition[] = Object.values(network.nodes).map(node => ({
-        data: {
-          id: node.id,
-        },
-        position: {
-          x: node.x,
-          y: node.y,
-        },
-      }));
+// export function networkToCytoscape(network: Network, initialPosition:boolean=false): cytoscape.Core {
+
+//     // Convert nodes
+//     const nodes: ElementDefinition[] = Object.values(network.nodes).map(node => ({
+//         data: {
+//           id: node.id,
+//         },
+//         position: {
+//           x: node.x,
+//           y: node.y,
+//         },
+//       }));
   
-    // Convert links
-    const edges: ElementDefinition[] = [];
-    network.links.forEach(link => {
-        edges.push({
-        data: {
-          id: link.id,
-          source: link.source.id,
-          target: link.target.id,
-        }
-      });
-    });
+//     // Convert links
+//     const edges: ElementDefinition[] = [];
+//     network.links.forEach(link => {
+//         edges.push({
+//         data: {
+//           id: link.id,
+//           source: link.source.id,
+//           target: link.target.id,
+//         }
+//       });
+//     });
 
 
-    if (initialPosition){
-        return cytoscape({
-            container: undefined, 
-            elements: {nodes:nodes, edges:edges},
-            layout: { 
-              name: 'preset', // to initialize the position of the nodes
-            },
-    });
-    }else{
-        return cytoscape({
-        container: undefined, 
-        elements: {nodes:nodes, edges:edges},
-        });
-  }
-}
+//     if (initialPosition){
+//         return cytoscape({
+//             container: undefined, 
+//             elements: {nodes:nodes, edges:edges},
+//             layout: { 
+//               name: 'preset', // to initialize the position of the nodes
+//             },
+//     });
+//     }else{
+//         return cytoscape({
+//         container: undefined, 
+//         elements: {nodes:nodes, edges:edges},
+//         });
+//   }
+// }
 
 
 /**
@@ -294,7 +294,7 @@ export function networkToViz(subgraphNetwork:SubgraphNetwork,cycle:boolean=true,
         .sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
         .forEach(([key, node])=> { 
             const nodeViz=nodeForViz(subgraphNetwork,node,cycle,groupOrCluster);
-            if (nodeViz && !graphViz.nodes.some(node => node.name === nodeViz.name)){
+            if (nodeViz && graphViz.nodes && !graphViz.nodes.some(node => node.name === nodeViz.name)){
                 graphViz.nodes.push(nodeViz);   
             }   
         });
@@ -308,7 +308,7 @@ export function networkToViz(subgraphNetwork:SubgraphNetwork,cycle:boolean=true,
     links.forEach((link)=>{   
         // get tail and head (take into account cycle metanode)
         const {tail,head}=cycleMetanodeLink(link,cycle);
-        if (tail!==head &&  !graphViz.edges.some(edge => edge.tail === tail && edge.head === head)){
+        if (tail!==head &&  graphViz.edges && !graphViz.edges.some(edge => edge.tail === tail && edge.head === head)){
             graphViz.edges.push({
                 tail: tail,
                 head: head,
@@ -318,8 +318,9 @@ export function networkToViz(subgraphNetwork:SubgraphNetwork,cycle:boolean=true,
         
 
     // insert mainChain cluster 
-    if (groupOrCluster==="cluster" && Object.keys(subgraphNetwork).includes(TypeSubgraph.MAIN_CHAIN)){
-        Object.keys(subgraphNetwork[TypeSubgraph.MAIN_CHAIN]).sort((a, b) => subgraphNetwork[TypeSubgraph.MAIN_CHAIN][b].nodes.length - subgraphNetwork[TypeSubgraph.MAIN_CHAIN][a].nodes.length) // sort depending on size : bigger first
+    if (groupOrCluster==="cluster" && subgraphNetwork[TypeSubgraph.MAIN_CHAIN]){
+        const mainChain = subgraphNetwork[TypeSubgraph.MAIN_CHAIN];
+        Object.keys(mainChain).sort((a, b) => mainChain[b].nodes.length - mainChain[a].nodes.length) // sort depending on size : bigger first
             .forEach((nameMainChain) => {
                 graphViz=addMainChainClusterViz(graphViz,nameMainChain,subgraphNetwork,cycle);
         });
@@ -327,19 +328,41 @@ export function networkToViz(subgraphNetwork:SubgraphNetwork,cycle:boolean=true,
 
     // insert cycle metanode
     if (cycle && subgraphNetwork[TypeSubgraph.CYCLEGROUP]){
-        Object.values(subgraphNetwork[TypeSubgraph.CYCLEGROUP]).sort((a, b) => { // sort depending on size : bigger first
-            const areaB = b.width * b.height;
-            const areaA = a.width * a.height;
-            return areaB - areaA;
+        const cycleGroup=subgraphNetwork[TypeSubgraph.CYCLEGROUP];
+        Object.values(cycleGroup).sort((a, b) => { // sort depending on size : bigger first
+            const widthA = a?.width;
+            const widthB = b?.width;
+            const heightA = a?.height;
+            const heightB = b?.height;
+            if (widthA && widthB && heightA && heightB){
+                const areaB = widthB * heightB;
+                const areaA = widthA * heightA;
+                return areaB - areaA;
+            }else{
+                throw new Error("Cycle group without width or height");
+            }
         })
         .forEach((cycleGroup) => {
-            const height=pixelsToInches(cycleGroup.height);
-            const width=pixelsToInches(cycleGroup.width);
-            let ordering=Ordering.DEFAULT;
-            if(orderChange){
-                ordering=cycleGroup.ordering;
+            const attributes:AttributesViz={fixedsize:true};
+
+            const heightPixel=cycleGroup?.height;
+            const widthPixel=cycleGroup?.width;
+            if(heightPixel && widthPixel){
+                const height=pixelsToInches(heightPixel);
+                const width=pixelsToInches(widthPixel);
+                attributes.height=height;
+                attributes.width=width;
+            }else{
+                throw new Error("Cycle group without width or height");
             }
-            graphViz.nodes.push({name:cycleGroup.name, attributes:{height:height,width:width,ordering:ordering,fixedsize:true}});
+
+            if(orderChange && cycleGroup.ordering){
+                attributes.ordering=cycleGroup.ordering;
+            }else{
+                throw new Error("Demand of change order but cycle group without ordering");
+            }
+            if (!graphViz.nodes) graphViz.nodes=[];
+            graphViz.nodes.push({name:cycleGroup.name, attributes:attributes});
         });
     }
     return graphViz;
@@ -354,7 +377,7 @@ export function networkToViz(subgraphNetwork:SubgraphNetwork,cycle:boolean=true,
  * @param groupOrCluster - Specifies whether the node belongs to a group or cluster.
  * @returns An object containing the name and attributes of the converted node.
  */
-function nodeForViz(subgraphNetwork:SubgraphNetwork,node:NodeLayout,cycle:boolean,groupOrCluster:"group"|"cluster"):{name:string,attributes:AttributesViz}{
+function nodeForViz(subgraphNetwork:SubgraphNetwork,node:NodeLayout,cycle:boolean,groupOrCluster:"group"|"cluster"):{name:string,attributes:AttributesViz}|undefined{
     // if cycle not taken into account or not in cycle
     if (!cycle || !inCycle(subgraphNetwork.network.value,node.id)){
         const attributes:AttributesViz={};
@@ -389,54 +412,67 @@ function nodeForViz(subgraphNetwork:SubgraphNetwork,node:NodeLayout,cycle:boolea
  */
 export function graphVizToDot(vizGraph:Graph, subgraphFirst:boolean=true):string{
     // initialisation viz graph with graph attributs
-    let dotString="strict digraph G {\n graph "+customStringify(vizGraph.graphAttributes)+"\n";
+    let dotString="strict digraph G {\n graph "+customStringify(vizGraph.graphAttributes as AttributesViz)+"\n";
     
     if (subgraphFirst){
         // clusters
-        vizGraph.subgraphs.forEach((subgraph) => {
-            dotString+=addClusterDot(subgraph as SubgraphViz);
-        });
+        if (vizGraph.subgraphs) {
+            vizGraph.subgraphs.forEach((subgraph) => {
+                dotString+=addClusterDot(subgraph as SubgraphViz);
+            });
+        }
 
         // nodes 
-        vizGraph.nodes.forEach((node) => {
-            const nodeAttributes= customStringify(node.attributes);
-            dotString+=`${node.name}  ${nodeAttributes};\n`;
-        });
+        if (vizGraph.nodes){
+            vizGraph.nodes.forEach((node) => {
+                const nodeAttributes= customStringify(node.attributes as AttributesViz);
+                dotString+=`${node.name}  ${nodeAttributes};\n`;
+            });
+        }
 
         // edges 
-        vizGraph.edges.forEach((edge) => {
-            dotString+=`${edge.tail} -> ${edge.head};\n`;
-        });
+        if (vizGraph.edges){
+            vizGraph.edges.forEach((edge) => {
+                dotString+=`${edge.tail} -> ${edge.head};\n`;
+            });
+        }
     } else {
 
         // nodes 
-        vizGraph.nodes.forEach((node) => {
-            const nodeAttributes= customStringify(node.attributes);
-            dotString+=`${node.name}  ${nodeAttributes};\n`;
-        });
+        if (vizGraph.nodes){
+            vizGraph.nodes.forEach((node) => {
+                const nodeAttributes= customStringify(node.attributes as AttributesViz);
+                dotString+=`${node.name}  ${nodeAttributes};\n`;
+            });
+        }
         // edges 
-        vizGraph.edges.forEach((edge) => {
-            dotString+=`${edge.tail} -> ${edge.head};\n`;
-        });
+        if (vizGraph.edges){
+            vizGraph.edges.forEach((edge) => {
+                dotString+=`${edge.tail} -> ${edge.head};\n`;
+            });
+        }
 
         // clusters
-        vizGraph.subgraphs.forEach((subgraph) => {
-            dotString+=addClusterDot(subgraph as SubgraphViz);
-        });
+        if (vizGraph.subgraphs) {
+            vizGraph.subgraphs.forEach((subgraph) => {
+                dotString+=addClusterDot(subgraph as SubgraphViz);
+            });
+        }
     }
     
     return dotString+"}";
 }
 
 
+
 /**
- * Converts an object into a custom string representation.
+ * Converts an object to a string representation with attribute-value pairs.
  * 
- * @param obj - The object to be converted.
- * @returns The custom string representation of the object.
+ * @param obj - The object to convert.
+ * @returns A string representation of the object with attribute-value pairs.
  */
-function customStringify(obj) {
-    if (Object.keys(obj).length === 0) {
+function customStringify(obj:AttributesViz|undefined) {
+    if (!obj || Object.keys(obj).length === 0) {
         return "";
     }
     let str = '[';
@@ -446,37 +482,4 @@ function customStringify(obj) {
     str = str.slice(0, -2); // remove trailing comma and space
     str += ']';
     return str;
-}
-
-
-
-
-
-// /**
-//  * Return a copy of the network
-//  * @param network 
-//  * @returns a copy of the network
-//  */
-// export function networkCopy(network: Network): Network {
-//     const newNetwork: Network = {
-//         id: network.id,
-//         label: network.label,
-//         nodes: {},
-//         links: []
-//     };
-
-//     Object.keys(network.nodes).forEach(key=>{  
-//         newNetwork.nodes[key] = Object.assign({}, network.nodes[key]);   
-//     })
-
-//     network.links.forEach(item=>{
-//         //get all info from links
-//         const newlink=Object.assign({}, item);
-//         // update the node to have a pointeur
-//         newlink.source=newNetwork.nodes[item.source.id];
-//         newlink.target=newNetwork.nodes[item.target.id];
-//         newNetwork.links.push(newlink);
-//     });
-//     return newNetwork;
-// }
-
+}
\ No newline at end of file
diff --git a/src/composables/ConvertToNetwork.ts b/src/composables/ConvertToNetwork.ts
index 2367645..76bd682 100644
--- a/src/composables/ConvertToNetwork.ts
+++ b/src/composables/ConvertToNetwork.ts
@@ -11,8 +11,8 @@ import { assignRankOrder } from './CalculateStartNodes';
 import { getSizeNodePixel } from './CalculateSize';
 
 // General imports
-import cytoscape, { ElementDefinition } from 'cytoscape';
-import  dagre  from 'dagrejs/dist/dagre.js';
+// import cytoscape, { ElementDefinition } from 'cytoscape';
+// import  dagre  from 'dagrejs/dist/dagre.js';
 import { type } from 'os';
 import { TypeSubgraph } from '../types/Subgraph';
 
@@ -53,31 +53,31 @@ export function networkLayoutToNetwork(networkLayout: NetworkLayout): Network {
 }
 
 
-/**
- * Take dagre.graphlib.Graph object and the network associated (with the graph) : change the position and metadata (rank and order) of network's node by the one of the graph.
- * The graph and network need to have the same nodes !
- * @param {dagre.graphlib.Graph}  dagre.graphlib.Graph object 
- * @param {Network} Network object (value of pointer)
- */
-export async function changeNetworkFromDagre(graph: dagre.graphlib.Graph,network: NetworkLayout): Promise<void>{
-    Object.entries(graph["_nodes"]).forEach(([node, nodeData]:[string, dagre.graphlib.Node]) => {
-        if (!network.nodes[node].metadataLayout) {
-            network.nodes[node].metadataLayout = {};
-        }
-        const { x, y, _order,_rank  } = nodeData;
-        // if there is some position x and y : network is updated
-        if (x !== undefined && y !== undefined){
-            if (network.nodes[node]) {
-                network.nodes[node].x = x;
-                network.nodes[node].y = y;
-            } else {
-                throw new Error(`Node '${node}' not found in the network.`);
-            }
-            network.nodes[node].metadataLayout.order = _order;
-            network.nodes[node].metadataLayout.rank = _rank / 2; // because rank 0 is 0, and the next is 2, 4, ...
-        }
-    });
-}
+// /**
+//  * Take dagre.graphlib.Graph object and the network associated (with the graph) : change the position and metadata (rank and order) of network's node by the one of the graph.
+//  * The graph and network need to have the same nodes !
+//  * @param {dagre.graphlib.Graph}  dagre.graphlib.Graph object 
+//  * @param {Network} Network object (value of pointer)
+//  */
+// export async function changeNetworkFromDagre(graph: dagre.graphlib.Graph,network: NetworkLayout): Promise<void>{
+//     Object.entries(graph["_nodes"]).forEach(([node, nodeData]:[string, dagre.graphlib.Node]) => {
+//         if (!network.nodes[node].metadataLayout) {
+//             network.nodes[node].metadataLayout = {};
+//         }
+//         const { x, y, _order,_rank  } = nodeData;
+//         // if there is some position x and y : network is updated
+//         if (x !== undefined && y !== undefined){
+//             if (network.nodes[node]) {
+//                 network.nodes[node].x = x;
+//                 network.nodes[node].y = y;
+//             } else {
+//                 throw new Error(`Node '${node}' not found in the network.`);
+//             }
+//             network.nodes[node].metadataLayout.order = _order;
+//             network.nodes[node].metadataLayout.rank = _rank / 2; // because rank 0 is 0, and the next is 2, 4, ...
+//         }
+//     });
+// }
 
 
 /**
@@ -95,8 +95,8 @@ export async function changeNetworkFromViz(json: JsonViz, subgraphNetwork: Subgr
         const nodeId = node.name;
 
         // if node is a 'classic' node
-        if (nodeId in network.nodes && 'pos' in node){
-                const pos = node.pos.split(',');
+        if (nodeId in network.nodes && Object.keys(node).includes("pos")){
+                const pos = node["pos"]?.split(',') ?? [];
                 let x = parseFloat(pos[0]);
                 let y = parseFloat(pos[1]);
                 
@@ -107,15 +107,13 @@ export async function changeNetworkFromViz(json: JsonViz, subgraphNetwork: Subgr
                     unique_y.push(y);
                 }
 
-        }else if (subgraphNetwork[TypeSubgraph.CYCLEGROUP] && nodeId in subgraphNetwork[TypeSubgraph.CYCLEGROUP] && 'pos' in node){
+        }else if (subgraphNetwork[TypeSubgraph.CYCLEGROUP] && nodeId in subgraphNetwork[TypeSubgraph.CYCLEGROUP] && Object.keys(node).includes("pos")){
 
             //if node is a cycle metanode
-            const pos = node.pos.split(',');
+            const pos = node["pos"]?.split(',') ?? [];
             const x = parseFloat(pos[0]);
             const y = parseFloat(pos[1]);
-            // if (!subgraphNetwork[TypeSubgraph.CYCLEGROUP][nodeId].metadata){
-            //     subgraphNetwork[TypeSubgraph.CYCLEGROUP][nodeId].metadata={};
-            // }
+          
             subgraphNetwork[TypeSubgraph.CYCLEGROUP][nodeId].position={x:x,y:y};
             
         }else{
@@ -131,24 +129,24 @@ export async function changeNetworkFromViz(json: JsonViz, subgraphNetwork: Subgr
 }
 
 
-/**
- * Updates the positions of nodes in the network based on the provided Cytoscape JSON.
- * 
- * @param jsonCytoscape - The Cytoscape JSON containing the elements and their positions.
- * @param network - The network to update.
- */
-export function changeNetworkFromCytoscape(jsonCytoscape: {elements:  { nodes:ElementDefinition[] } }, network:Network) : void {
-
-    jsonCytoscape.elements.nodes.forEach((node: any) => {
-        const idNode= node.data.id;
-        if (Object.keys(network.nodes).includes(idNode)) {
-            network.nodes[idNode].x = node.position.x;
-            network.nodes[idNode].y = node.position.y;
-        }else{
-            throw new Error(`Node '${idNode}' not found in the network.`);
-        }
-    });
-}
+// /**
+//  * Updates the positions of nodes in the network based on the provided Cytoscape JSON.
+//  * 
+//  * @param jsonCytoscape - The Cytoscape JSON containing the elements and their positions.
+//  * @param network - The network to update.
+//  */
+// export function changeNetworkFromCytoscape(jsonCytoscape: {elements:  { nodes:ElementDefinition[] } }, network:Network) : void {
+
+//     jsonCytoscape.elements.nodes.forEach((node: any) => {
+//         const idNode= node.data.id;
+//         if (Object.keys(network.nodes).includes(idNode)) {
+//             network.nodes[idNode].x = node.position.x;
+//             network.nodes[idNode].y = node.position.y;
+//         }else{
+//             throw new Error(`Node '${idNode}' not found in the network.`);
+//         }
+//     });
+// }
 
 
 
diff --git a/src/composables/LayoutManageSideCompounds.ts b/src/composables/LayoutManageSideCompounds.ts
index 3422389..6809e85 100644
--- a/src/composables/LayoutManageSideCompounds.ts
+++ b/src/composables/LayoutManageSideCompounds.ts
@@ -14,7 +14,7 @@ import { getMeanNodesSizePixel, inchesToPixels, minEdgeLength as minEdgeLength,
 import { sideCompoundAttribute,isDuplicate, isReaction, isSideCompound, setAsSideCompound } from "./GetSetAttributsNodes";
 
 // General imports
-import { e, S } from "vitest/dist/reporters-1evA5lom";
+//import { e, S } from "vitest/dist/reporters-1evA5lom";
 import { c } from "vite/dist/node/types.d-aGj9QkWt";
 import { resolve } from "path";
 import { error } from "console";
@@ -269,24 +269,25 @@ function removeSideCompoundsFromNetwork(subgraphNetwork:SubgraphNetwork): Subgra
 
     const network = subgraphNetwork.network.value;
     subgraphNetwork.sideCompounds={};
+    const sideCompounds = subgraphNetwork.sideCompounds;
     const listIDCoftactors:string[]=[];
 
     // for each link, see if the source or target is in the list of side compounds : add information in subgraphNetwork.sideCompounds
     network.links.forEach((link) => {
         // if source is side compound
         if (isSideCompound(link.source)) {
-            if(!(link.target.id in subgraphNetwork.sideCompounds)){
-                subgraphNetwork.sideCompounds[link.target.id]={reactants:[],products:[]};
+            if(!(link.target.id in sideCompounds)){
+                sideCompounds[link.target.id]={reactants:[],products:[]};
             }
-            subgraphNetwork.sideCompounds[link.target.id].reactants.push(link.source);
+            sideCompounds[link.target.id].reactants.push(link.source);
             listIDCoftactors.push(link.source.id);
         }
         // if target is side compound
         if (isSideCompound(link.target)) {
-            if(!(link.source.id in subgraphNetwork.sideCompounds)){
-                subgraphNetwork.sideCompounds[link.source.id]={reactants:[],products:[]};
+            if(!(link.source.id in sideCompounds)){
+                sideCompounds[link.source.id]={reactants:[],products:[]};
             }
-            subgraphNetwork.sideCompounds[link.source.id].products.push(link.target);
+            sideCompounds[link.source.id].products.push(link.target);
             listIDCoftactors.push(link.target.id);
         }
     });
@@ -310,6 +311,7 @@ function removeSideCompoundsFromNetwork(subgraphNetwork:SubgraphNetwork): Subgra
  */
 export async function reinsertionSideCompounds(subgraphNetwork:SubgraphNetwork,factorMinEdgeLength:number=1/2,doReactionReversible:boolean):Promise<SubgraphNetwork>{
     if(subgraphNetwork.sideCompounds){
+        const sideCompounds = subgraphNetwork.sideCompounds 
         // get information for length of edge for side compounds :
         // get the min length of edge in the network (if not, use default value)
         let minLength=minEdgeLength(subgraphNetwork.network.value,false);
@@ -328,7 +330,7 @@ export async function reinsertionSideCompounds(subgraphNetwork:SubgraphNetwork,f
         }
 
         // for each reaction, apply motif stamp
-        Object.keys(subgraphNetwork.sideCompounds).forEach( async (reactionID)=>{
+        Object.keys(sideCompounds).forEach( async (reactionID)=>{
             subgraphNetwork= await motifStampSideCompound(subgraphNetwork,reactionID,factorMinEdgeLength);
         });       
     }
@@ -348,10 +350,13 @@ async function minEdgeLengthDefault(subgraphNetwork:SubgraphNetwork,factorMinEdg
     const networkStyle = subgraphNetwork.networkStyle.value;
     const meanSize=await getMeanNodesSizePixel(Object.values(network.nodes),networkStyle, false);
     const defaultSep=(meanSize.height+meanSize.width)/2;
-    const rankSep=subgraphNetwork.attributs[VizArgs.RANKSEP]?inchesToPixels(subgraphNetwork.attributs[VizArgs.RANKSEP] as number):defaultSep;
-    const nodeSep=subgraphNetwork.attributs[VizArgs.NODESEP]?inchesToPixels(subgraphNetwork.attributs[VizArgs.NODESEP] as number):defaultSep;
-    //const invFactor=factorMinEdgeLength===0?1:1/factorMinEdgeLength;
-    return (nodeSep+rankSep)/2*factorMinEdgeLength; 
+    if(subgraphNetwork.attributs){
+        const rankSep=subgraphNetwork.attributs[VizArgs.RANKSEP]?inchesToPixels(subgraphNetwork.attributs[VizArgs.RANKSEP] as number):defaultSep;
+        const nodeSep=subgraphNetwork.attributs[VizArgs.NODESEP]?inchesToPixels(subgraphNetwork.attributs[VizArgs.NODESEP] as number):defaultSep;
+        return (nodeSep+rankSep)/2*factorMinEdgeLength; 
+    }else{
+        return defaultSep * factorMinEdgeLength;
+    }
 }
 
 /**
@@ -361,16 +366,19 @@ async function minEdgeLengthDefault(subgraphNetwork:SubgraphNetwork,factorMinEdg
  */
 async function updateSideCompoundsReversibleReaction(subgraphNetwork:SubgraphNetwork):Promise<SubgraphNetwork>{
     const network = subgraphNetwork.network.value;
-    Object.keys(subgraphNetwork.sideCompounds).forEach((reactionID)=>{
-        if (!(reactionID in network.nodes)) throw new Error("Reaction not in subgraphNetwork")
-        // if reaction has been reversed : exchange products and reactants
-        if(network.nodes[reactionID].metadataLayout && network.nodes[reactionID].metadataLayout.isReversedVersion){
-            const products=subgraphNetwork.sideCompounds[reactionID].products;
-            const reactants=subgraphNetwork.sideCompounds[reactionID].reactants;
-            subgraphNetwork.sideCompounds[reactionID].products=reactants;
-            subgraphNetwork.sideCompounds[reactionID].reactants=products;
-        }
-    });
+    if (subgraphNetwork.sideCompounds){
+        let sideCompounds=subgraphNetwork.sideCompounds;
+        Object.keys(sideCompounds).forEach((reactionID)=>{
+            if (!(reactionID in network.nodes)) throw new Error("Reaction not in subgraphNetwork")
+            // if reaction has been reversed : exchange products and reactants
+            if(network.nodes[reactionID].metadataLayout && network.nodes[reactionID].metadataLayout.isReversedVersion){
+                const products=sideCompounds[reactionID].products;
+                const reactants=sideCompounds[reactionID].reactants;
+                sideCompounds[reactionID].products=reactants;
+                sideCompounds[reactionID].reactants=products;
+            }
+        });
+    }
     return subgraphNetwork;
 }
 
diff --git a/src/composables/LayoutReversibleReactions.ts b/src/composables/LayoutReversibleReactions.ts
index d2faf2c..21c36c3 100644
--- a/src/composables/LayoutReversibleReactions.ts
+++ b/src/composables/LayoutReversibleReactions.ts
@@ -13,7 +13,7 @@ import { BFSWithSources } from "./AlgorithmBFS";
 import { addLinkClassReversible, addMetadataReversibleWithClass, isReaction, isReversible } from "./GetSetAttributsNodes";
 
 // General imports
-import { e } from "vitest/dist/reporters-1evA5lom";
+//import { e } from "vitest/dist/reporters-1evA5lom";
 import { l } from "vite/dist/node/types.d-aGj9QkWt";
 
 
@@ -91,7 +91,7 @@ export async function duplicateReversibleReactions(networkLayout:NetworkLayout):
       if (linkReversible.isReversible) {
         // Duplication of the reaction node
         let nodeToDuplicate: NodeLayout;
-        const reactionIsSource: boolean = linkReversible.sourceIsReversible;
+        const reactionIsSource: boolean|undefined = linkReversible.sourceIsReversible;
   
         if (reactionIsSource) {
           nodeToDuplicate = link.source;
@@ -135,7 +135,7 @@ export async function duplicateReversibleReactions(networkLayout:NetworkLayout):
  *   - `isReversible` - A boolean indicating if the link is reversible.
  *   - `sourceIsReversible` - A boolean indicating if it's the source of the link that is reversible.
  */
-function linkIsReversible(network:Network,link: Link): {isReversible:boolean,sourceIsReversible:boolean}{ 
+function linkIsReversible(network:Network,link: Link): {isReversible:boolean,sourceIsReversible:boolean|undefined}{ 
     if (isReaction(link.source) && isReversible(network,link.source.id)){
       return {isReversible:true,sourceIsReversible:true};
     } else if (isReaction(link.target) && isReversible(network,link.target.id)){
@@ -164,10 +164,11 @@ async function duplicateNodeReactionReversible(networkLayout: NetworkLayout, nod
                 throw new Error("Node not found to set as reversible");
             }
 
-            if (!networkLayout.nodes[nodeReaction.id].metadataLayout) {
-                networkLayout.nodes[nodeReaction.id].metadataLayout = {};
+            if (networkLayout.nodes[nodeReaction.id].metadataLayout) {
+                networkLayout.nodes[nodeReaction.id].metadataLayout.reversibleNodeVersion = newId;
+            }else{
+                networkLayout.nodes[nodeReaction.id].metadataLayout = {reversibleNodeVersion:newId};
             }
-            networkLayout.nodes[nodeReaction.id].metadataLayout.reversibleNodeVersion = newId;
 
             resolve(newReactionNode);
         } catch (error) {
diff --git a/src/composables/__tests__/CalculateStartNodes.tests.ts b/src/composables/__tests__/CalculateStartNodes.tests.ts
new file mode 100644
index 0000000..de95410
--- /dev/null
+++ b/src/composables/__tests__/CalculateStartNodes.tests.ts
@@ -0,0 +1,102 @@
+// Type imports
+import { StartNodesType } from '../../types/EnumArgs';
+import { NetworkLayout, NodeLayout } from '../../types/NetworkLayout';
+import { Network } from '@metabohub/viz-core/src/types/Network';
+
+// Composable imports
+import * as CalculateStartNodes from '../CalculateStartNodes';
+
+
+describe('assignRankOrder', () => {
+    let networkLayout: NetworkLayout;
+
+    beforeEach(() => {
+        networkLayout = {
+            id:"test",
+            nodes: {
+                node1: { id: 'node1', x: 1, y: 2, metadataLayout: {} },
+                node2: { id: 'node2', x: 2, y: 3, metadataLayout: {} },
+                node3: { id: 'node3', x: 3, y: 2, metadataLayout: {} },
+                node4: { id: 'node4', x: 3, y: 1, metadataLayout: {} },
+            },
+            links: []
+        };
+
+    });
+
+
+    it('should assign rank and order to nodes based on their coordinates', () => {
+        // DATA
+        const unique_y = [1,2, 3];
+        const networkExpected: NetworkLayout = {
+            id:"test",
+            nodes: {
+                node1: { id: 'node1', x: 1, y: 2, metadataLayout: {rank:1,order:0} },
+                node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:2,order:0} },
+                node3: { id: 'node3', x: 3, y: 2, metadataLayout: {rank:1,order:1} },
+                node4: { id: 'node4', x: 3, y: 1, metadataLayout: {rank:0,order:0} },
+            },
+            links: []
+        };
+
+        // TEST
+        CalculateStartNodes.assignRankOrder(networkLayout, unique_y, false);
+
+        // EXPECT
+        expect(networkLayout).toEqual(networkExpected);
+    });
+
+
+
+    // it('should assign only rank if onlyRank is true', () => {
+    //     const unique_y = [2, 3];
+    //     assignRankOrder(networkLayout, unique_y, true);
+
+    //     expect(networkLayout.nodes.node1.metadataLayout.rank).toBe(0);
+    //     expect(networkLayout.nodes.node1.metadataLayout.order).toBeUndefined();
+    //     expect(networkLayout.nodes.node2.metadataLayout.rank).toBe(1);
+    //     expect(networkLayout.nodes.node2.metadataLayout.order).toBeUndefined();
+    //     expect(networkLayout.nodes.node3.metadataLayout.rank).toBe(0);
+    //     expect(networkLayout.nodes.node3.metadataLayout.order).toBeUndefined();
+    // });
+});
+
+// describe('getStartNodes', () => {
+//     it('should return all nodes if typeSource is ALL', async () => {
+//         const result = await getStartNodes(mockNetwork, StartNodesType.ALL);
+//         expect(result).toEqual(['node1', 'node2', 'node3']);
+//     });
+
+//     it('should return nodes with rank 0 if typeSource is RANK_ONLY', async () => {
+//         const result = await getStartNodes(mockNetwork, StartNodesType.RANK_ONLY);
+//         expect(result).toEqual(['node1']);
+//     });
+
+//     // Add more tests for other StartNodesType values as needed
+// });
+
+// describe('concatSources', () => {
+//     it('should concatenate two arrays and remove duplicates', () => {
+//         const firstSources = ['a', 'b', 'c'];
+//         const secondSources = ['b', 'c', 'd'];
+//         const result = concatSources(firstSources, secondSources);
+
+//         expect(result).toEqual(['a', 'b', 'c', 'd']);
+//     });
+
+//     it('should return the first array if the second array is empty', () => {
+//         const firstSources = ['a', 'b', 'c'];
+//         const secondSources: string[] = [];
+//         const result = concatSources(firstSources, secondSources);
+
+//         expect(result).toEqual(['a', 'b', 'c']);
+//     });
+
+//     it('should return the second array if the first array is empty', () => {
+//         const firstSources: string[] = [];
+//         const secondSources = ['a', 'b', 'c'];
+//         const result = concatSources(firstSources, secondSources);
+
+//         expect(result).toEqual(['a', 'b', 'c']);
+//     });
+// });
\ No newline at end of file
-- 
GitLab


From 95c3001bcc97398a5c3b478287ad3703a9d89a89 Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Thu, 12 Sep 2024 13:56:03 +0200
Subject: [PATCH 09/13] re clean de fichier avec nouveau linter

---
 src/composables/LayoutManageSideCompounds.ts |  59 ++++++----
 src/composables/LayoutReversibleReactions.ts |   2 +-
 src/composables/LayoutSugiyamaForce.ts       | 109 +++++++++----------
 src/types/Reaction.ts                        |   4 +-
 4 files changed, 93 insertions(+), 81 deletions(-)

diff --git a/src/composables/LayoutManageSideCompounds.ts b/src/composables/LayoutManageSideCompounds.ts
index 6809e85..186395c 100644
--- a/src/composables/LayoutManageSideCompounds.ts
+++ b/src/composables/LayoutManageSideCompounds.ts
@@ -457,7 +457,9 @@ async function initializeReactionSideCompounds(subgraphNetwork:SubgraphNetwork,i
             throw error;
         }       
     }else if (!network.nodes[idReaction]){
-        throw new Error("Reaction not found");
+        throw new Error("Reaction not found in network");
+    }else{
+        throw new Error("No side compounds for reaction");
     }
 }
 
@@ -554,8 +556,8 @@ async function addSideCompoundsIntervals(reaction: Reaction):Promise<Reaction> {
         if (!reaction.intervalsAvailables || reaction.intervalsAvailables.length === 0) {
             reaction.intervalsAvailables =[{
                 typeInterval: 0, 
-                reactant: null,
-                product: null,
+                reactant: undefined,
+                product: undefined,
             }];
         }
 
@@ -628,6 +630,9 @@ function addInterval(reaction:Reaction,id1:string,type1:MetaboliteType,id2:strin
  */
 async function biggestInterval(reaction: Reaction): Promise<{interval:ReactionInterval,size:number}> {
     try {
+        if (!reaction.intervalsAvailables) {
+            throw new Error("intervalsAvailables does not exist");
+        }
         const intervals = reaction.intervalsAvailables;
         if (intervals.length === 0) {
             throw new Error("Empty intervals");
@@ -661,6 +666,7 @@ async function biggestInterval(reaction: Reaction): Promise<{interval:ReactionIn
 function sizeInterval(reaction:Reaction,intervalIndex:number):number{
     const angles=reaction.metabolitesAngles;
     if (angles===undefined) throw new Error("No angles");
+    if (!reaction.intervalsAvailables) throw new Error("No intervalsAvailables");
     const interval=reaction.intervalsAvailables[intervalIndex];
     if (interval===undefined) throw new Error("No interval");
     // if reactant or product null : return 2*PI 
@@ -678,7 +684,7 @@ function sizeInterval(reaction:Reaction,intervalIndex:number):number{
 //______________2.3  Stamp motif : find spacing
 
 
-async function findSpacingSideCompounds(reaction:Reaction,sizeInterval:number):Promise<{reactant:number,product:number}>{
+async function findSpacingSideCompounds(reaction:Reaction,sizeInterval:number):Promise<{reactant:number|undefined,product:number|undefined}>{
     const reactantNumber=reaction.sideCompoundsReactants.length;
     const productNumber=reaction.sideCompoundsProducts.length;
     return {
@@ -700,18 +706,19 @@ async function findSpacingSideCompounds(reaction:Reaction,sizeInterval:number):P
  * @returns The updated subgraph network with the calculated coordinates for the side compounds.
  */
 async function giveCoordAllSideCompounds(subgraphNetwork:SubgraphNetwork,reaction:Reaction,factorLength:number=1/2):Promise<SubgraphNetwork>{
-    const distance=calculateDistance(subgraphNetwork, factorLength);
-    const sideCompounds=subgraphNetwork.sideCompounds[reaction.id];
-    const reactionCoord=subgraphNetwork.network.value.nodes[reaction.id];
-    // Reactants Placement
-    if (sideCompounds.reactants && sideCompounds.reactants.length>0){
-        await placeSideCompounds(sideCompounds.reactants, reaction, reactionCoord, distance, true);
-    }
-    // Products Placement
-    if (sideCompounds.products && sideCompounds.products.length>0){
-        await placeSideCompounds(sideCompounds.products, reaction, reactionCoord, distance, false);
+    if (subgraphNetwork.sideCompounds){
+        const distance=calculateDistance(subgraphNetwork, factorLength);
+        const sideCompounds=subgraphNetwork.sideCompounds[reaction.id];
+        const reactionCoord=subgraphNetwork.network.value.nodes[reaction.id];
+        // Reactants Placement
+        if (sideCompounds.reactants && sideCompounds.reactants.length>0){
+            await placeSideCompounds(sideCompounds.reactants, reaction, reactionCoord, distance, true);
+        }
+        // Products Placement
+        if (sideCompounds.products && sideCompounds.products.length>0){
+            await placeSideCompounds(sideCompounds.products, reaction, reactionCoord, distance, false);
+        }
     }
-   
     return subgraphNetwork;
 }
 
@@ -726,7 +733,7 @@ async function giveCoordAllSideCompounds(subgraphNetwork:SubgraphNetwork,reactio
  */
 function calculateDistance(subgraphNetwork: SubgraphNetwork, factorLength: number): number {
     let baseLengthPixel: number;
-    if (subgraphNetwork.stats.minEdgeLengthPixel) {
+    if (subgraphNetwork.stats && subgraphNetwork.stats.minEdgeLengthPixel) {
         baseLengthPixel = subgraphNetwork.stats.minEdgeLengthPixel;
     } else {
         console.error("stats minEdgeLengthPixel not found, use default value 1 inch");
@@ -746,20 +753,24 @@ function calculateDistance(subgraphNetwork: SubgraphNetwork, factorLength: numbe
  * @param placeReactants - A boolean indicating whether to place reactants or products.
  */
 async function placeSideCompounds(sideCompounds: Array<Node>, reaction: Reaction, reactionCoord: Coordinate, distance: number, placeReactants: boolean): Promise<void> {
-    const startSideCompound = placeReactants ? reaction.intervalsAvailables[0].reactant : reaction.intervalsAvailables[0].product;
+    if (!reaction.intervalsAvailables || reaction.intervalsAvailables.length === 0){
+         throw new Error("No intervals available");
+    }
+    const interval = reaction.intervalsAvailables[0];
+    const startSideCompound = placeReactants ? interval.reactant : interval.product;
     if (!startSideCompound) {
         console.error("No start side compound found");
         return;
     }
     let startAngle = startSideCompound ? reaction.metabolitesAngles[startSideCompound].angle : 0;
     const angleSpacing = placeReactants ? reaction.angleSpacingReactant : reaction.angleSpacingProduct;
-    if (!isFinite(angleSpacing)) {
+    if (! angleSpacing! || isFinite(angleSpacing)) {
         console.error("No angle spacing found");
         return;
     }
 
     sideCompounds.forEach((sideCompoundNode, i) => {
-        const direction = determineDirection(reaction.intervalsAvailables[0].typeInterval, placeReactants);
+        const direction = determineDirection(interval.typeInterval, placeReactants);
         const angle = startAngle + direction * (i + 1) * angleSpacing;
         sideCompoundNode = giveCoordSideCompound(sideCompoundNode, angle, reactionCoord, distance);
     });
@@ -811,15 +822,17 @@ function giveCoordSideCompound(sideCompound:Node,angle:number,center:{x:number,y
  * @returns void
  */
 function insertAllSideCompoundsInNetwork(subgraphNetwork:SubgraphNetwork,reaction:Reaction):void{
+    if(subgraphNetwork.sideCompounds && subgraphNetwork.sideCompounds[reaction.id]){
     const sideCompounds=subgraphNetwork.sideCompounds[reaction.id];
     // Reactants
-    Object.keys(reaction.sideCompoundsReactants).forEach((reactant)=>{
-        insertSideCompoundInNetwork(subgraphNetwork,reaction.id,sideCompounds.reactants[reactant],MetaboliteType.REACTANT);
+    sideCompounds.reactants.forEach((reactant)=>{
+        insertSideCompoundInNetwork(subgraphNetwork,reaction.id,reactant,MetaboliteType.REACTANT);
     });
     // Products
-    Object.keys(reaction.sideCompoundsProducts).forEach((product)=>{
-        insertSideCompoundInNetwork(subgraphNetwork,reaction.id,sideCompounds.products[product],MetaboliteType.PRODUCT);
+    sideCompounds.products.forEach((product)=>{
+        insertSideCompoundInNetwork(subgraphNetwork,reaction.id,product,MetaboliteType.PRODUCT);
     });
+    }
 }
 
 /**
diff --git a/src/composables/LayoutReversibleReactions.ts b/src/composables/LayoutReversibleReactions.ts
index 21c36c3..5af2aab 100644
--- a/src/composables/LayoutReversibleReactions.ts
+++ b/src/composables/LayoutReversibleReactions.ts
@@ -307,7 +307,7 @@ export function keepFirstReversibleNode(subgraphNetwork:SubgraphNetwork,nodeOrde
       if(network.nodes[nodeID].metadataLayout.isReversedVersion){
         // the duplicated version is the one keeped, its id have to be renamed by the original id
         nodeToRename[nodeID]=reversibleNodeID;
-      }else if (!network.nodes[reversibleNodeID].metadataLayout.isReversedVersion){
+      }else if (!network.nodes[reversibleNodeID].metadataLayout || !network.nodes[reversibleNodeID].metadataLayout.isReversedVersion){
         throw new Error("One duplication of node lack attribut isReversedVersion");
       }
 
diff --git a/src/composables/LayoutSugiyamaForce.ts b/src/composables/LayoutSugiyamaForce.ts
index 99147e7..fe2ac67 100644
--- a/src/composables/LayoutSugiyamaForce.ts
+++ b/src/composables/LayoutSugiyamaForce.ts
@@ -6,17 +6,16 @@ import { SubgraphNetwork } from "../types/SubgraphNetwork";
 import { Network } from "@metabohub/viz-core/src/types/Network";
 
 // Composable imports
-import { getMeanNodesSizePixel } from "./CalculateSize";
-import { getSepAttributesInches, shiftAllToGetTopLeftCoord } from "./CalculateSize";
-import { networkToCytoscape, networkToDagre, graphVizToDot, networkToViz, networkToDOT } from './ConvertFromNetwork';
-import { changeNetworkFromCytoscape, changeNetworkFromDagre, changeNetworkFromViz } from './ConvertToNetwork';
+import { getSepAttributesInches } from "./CalculateSize";
+import {  networkToDOT } from './ConvertFromNetwork';
+import {  changeNetworkFromViz } from './ConvertToNetwork';
 
 // General imports
-import * as d3 from 'd3';
+//import * as d3 from 'd3';
 import { reactive } from "vue";
-import cytoscape from 'cytoscape';
-import fcose from 'cytoscape-fcose';
-import cosebilkent from 'cytoscape-cose-bilkent';
+// import cytoscape from 'cytoscape';
+// import fcose from 'cytoscape-fcose';
+// import cosebilkent from 'cytoscape-cose-bilkent';
 import dagre from 'dagrejs';
 import { Graph, instance } from "@viz-js/viz";
 
@@ -43,17 +42,17 @@ import { Graph, instance } from "@viz-js/viz";
  * @param  graphAttributes for dagre layout (see https://github.com/dagrejs/dagre/wiki)
  * @param [callbackFunction=() => {}] function to do after the layout is done
  */
-export function dagreLayout(network: Network,graphAttributes={},callbackFunction = () => {}):void {
-
-    setTimeout(async function() {
-        let graphDagre = networkToDagre(network,graphAttributes);
-        dagre.layout(graphDagre);
-        changeNetworkFromDagre(graphDagre, network).then(() => {
-            callbackFunction();
-        });
-    }, 1);
+// export function dagreLayout(network: Network,graphAttributes={},callbackFunction = () => {}):void {
+
+//     setTimeout(async function() {
+//         let graphDagre = networkToDagre(network,graphAttributes);
+//         dagre.layout(graphDagre);
+//         changeNetworkFromDagre(graphDagre, network).then(() => {
+//             callbackFunction();
+//         });
+//     }, 1);
         
-}
+// }
 
 
 /** 
@@ -92,46 +91,46 @@ export async function vizLayout(subgraphNetwork:SubgraphNetwork,assignRank:boole
  * @param shiftCoord - Optional. Specifies whether to shift the coordinates of the nodes to the top-left corner. Defaults to false.
  * @returns A Promise that resolves to the updated network after applying the layout.
  */
-export async function forceLayout(network: Network, networkStyle:GraphStyleProperties, shiftCoord: boolean = false): Promise<Network> {
-
-    //cytoscape.use(fcose);
-    cytoscape.use(cosebilkent);
-
-    const size=await getMeanNodesSizePixel(Object.values(network.nodes), networkStyle,false);
-    const edgeFactor=3;
-    const edgeLength = Math.max(size.height, size.width) * edgeFactor;
-
-    const layout ={
-        name:"cose-bilkent", //fcose
-        animate: false,
-        randomize: false,
-        idealEdgeLength: edgeLength,
-        nodeRepulsion: 70000, // high number if randomize = false
-        gravity : 0.001,
-        numIter: 3000
-
-    }
-
-    let cyto = networkToCytoscape(network,true);
-
-    await new Promise<void>((resolve) => {
-        cyto.ready(function () {
-            setTimeout(function () {
-                cyto.elements().layout(layout).run();
-                resolve();
-            }, 5000);
-        });
-    });
+// export async function forceLayout(network: Network, networkStyle:GraphStyleProperties, shiftCoord: boolean = false): Promise<Network> {
 
-    if (shiftCoord) {
-        shiftAllToGetTopLeftCoord(network, networkStyle);
-    }
+//     //cytoscape.use(fcose);
+//     cytoscape.use(cosebilkent);
 
-    const json = cyto.json();
-    changeNetworkFromCytoscape(json, network);
+//     const size=await getMeanNodesSizePixel(Object.values(network.nodes), networkStyle,false);
+//     const edgeFactor=3;
+//     const edgeLength = Math.max(size.height, size.width) * edgeFactor;
 
-    return network;
-}
+//     const layout ={
+//         name:"cose-bilkent", //fcose
+//         animate: false,
+//         randomize: false,
+//         idealEdgeLength: edgeLength,
+//         nodeRepulsion: 70000, // high number if randomize = false
+//         gravity : 0.001,
+//         numIter: 3000
+
+//     }
+
+//     let cyto = networkToCytoscape(network,true);
+
+//     await new Promise<void>((resolve) => {
+//         cyto.ready(function () {
+//             setTimeout(function () {
+//                 cyto.elements().layout(layout).run();
+//                 resolve();
+//             }, 5000);
+//         });
+//     });
+
+//     if (shiftCoord) {
+//         shiftAllToGetTopLeftCoord(network, networkStyle);
+//     }
+
+//     const json = cyto.json();
+//     changeNetworkFromCytoscape(json, network);
+
+//     return network;
+// }
   
   
 
diff --git a/src/types/Reaction.ts b/src/types/Reaction.ts
index 481365f..cf90a30 100644
--- a/src/types/Reaction.ts
+++ b/src/types/Reaction.ts
@@ -29,6 +29,6 @@ export interface ReactionInterval {
     typeInterval: number; 
     // 0 if reactant then product, 1 if product then reactant, 
     // but if the x-axis is between the two (special case) : it is 2 when reactant is the smaller angle, 3 when product is the smaller angle
-    reactant: string;
-    product: string;
+    reactant: string|undefined;
+    product: string|undefined;
 }
\ No newline at end of file
-- 
GitLab


From 77c912db96dfcd7f5aba07967ea0a3ea03fc7f68 Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Thu, 12 Sep 2024 14:54:25 +0200
Subject: [PATCH 10/13] clean subgraph files

---
 src/composables/ConvertFromNetwork.ts         |   8 +-
 src/composables/LayoutFindCycle.ts            |   4 +-
 src/composables/LayoutMainChain.ts            |   4 +-
 src/composables/LayoutManageSideCompounds.ts  |  24 +-
 src/composables/LayoutReversibleReactions.ts  |   9 +-
 src/composables/LayoutSugiyamaForce.ts        |   1 -
 src/composables/MetricsApplication.ts         | 652 +++++++--------
 src/composables/MetricsCalculation.ts         | 756 +++++++++---------
 src/composables/SBMLtoJSON.ts                 | 302 +++----
 ...twork.ts => SubgraphForSubgraphNetwork.ts} | 148 ++--
 src/composables/SubgraphForViz.ts             | 128 +++
 src/composables/countIsolatedNodes.ts         |  36 -
 src/composables/importNetwork.ts              | 156 ++--
 src/composables/useSubgraphs.ts               | 207 -----
 14 files changed, 1152 insertions(+), 1283 deletions(-)
 rename src/composables/{UseSubgraphNetwork.ts => SubgraphForSubgraphNetwork.ts} (52%)
 create mode 100644 src/composables/SubgraphForViz.ts
 delete mode 100644 src/composables/countIsolatedNodes.ts
 delete mode 100644 src/composables/useSubgraphs.ts

diff --git a/src/composables/ConvertFromNetwork.ts b/src/composables/ConvertFromNetwork.ts
index cf4cc22..af84107 100644
--- a/src/composables/ConvertFromNetwork.ts
+++ b/src/composables/ConvertFromNetwork.ts
@@ -7,7 +7,7 @@ import { LinkLayout, NetworkLayout, NodeLayout } from '../types/NetworkLayout';
 import { Ordering } from '../types/EnumArgs';
 
 // Composable imports
-import { addMainChainClusterViz,addClusterDot } from './useSubgraphs';
+import { addMainChainForViz,subgraphDot } from './SubgraphForViz';
 import { getSizeNodePixel, pixelsToInches } from './CalculateSize';
 import { inCycle } from './GetSetAttributsNodes';
 import { cycleMetanodeLink, sortLinksWithAllGroupCycle } from './CalculateRelationCycle';
@@ -322,7 +322,7 @@ export function networkToViz(subgraphNetwork:SubgraphNetwork,cycle:boolean=true,
         const mainChain = subgraphNetwork[TypeSubgraph.MAIN_CHAIN];
         Object.keys(mainChain).sort((a, b) => mainChain[b].nodes.length - mainChain[a].nodes.length) // sort depending on size : bigger first
             .forEach((nameMainChain) => {
-                graphViz=addMainChainClusterViz(graphViz,nameMainChain,subgraphNetwork,cycle);
+                graphViz=addMainChainForViz(graphViz,nameMainChain,subgraphNetwork,cycle);
         });
     }
 
@@ -418,7 +418,7 @@ export function graphVizToDot(vizGraph:Graph, subgraphFirst:boolean=true):string
         // clusters
         if (vizGraph.subgraphs) {
             vizGraph.subgraphs.forEach((subgraph) => {
-                dotString+=addClusterDot(subgraph as SubgraphViz);
+                dotString+=subgraphDot(subgraph as SubgraphViz);
             });
         }
 
@@ -455,7 +455,7 @@ export function graphVizToDot(vizGraph:Graph, subgraphFirst:boolean=true):string
         // clusters
         if (vizGraph.subgraphs) {
             vizGraph.subgraphs.forEach((subgraph) => {
-                dotString+=addClusterDot(subgraph as SubgraphViz);
+                dotString+=subgraphDot(subgraph as SubgraphViz);
             });
         }
     }
diff --git a/src/composables/LayoutFindCycle.ts b/src/composables/LayoutFindCycle.ts
index 52677f0..cde82c8 100644
--- a/src/composables/LayoutFindCycle.ts
+++ b/src/composables/LayoutFindCycle.ts
@@ -1,6 +1,6 @@
 import { SubgraphNetwork } from "../types/SubgraphNetwork";
 import { Network } from "@metabohub/viz-core/src/types/Network";
-import { addNewSubgraph, createSubgraph, updateNodeMetadataSubgraph } from "./UseSubgraphNetwork";
+import { addSubgraphToNetwork, createSubgraph, updateNodeMetadataSubgraph } from "./SubgraphForSubgraphNetwork";
 import { TypeSubgraph } from "../types/Subgraph";
 import { keepFirstReversibleNode, renameAllIDNode } from "./LayoutReversibleReactions";
 
@@ -52,7 +52,7 @@ export function addDirectedCycleToSubgraphNetwork(subgraphNetwork:SubgraphNetwor
             }
             
             const subgraph=createSubgraph(cycle[0],cycle[1],[],TypeSubgraph.CYCLE);
-            subgraphNetwork=addNewSubgraph(subgraphNetwork,subgraph,TypeSubgraph.CYCLE);
+            subgraphNetwork=addSubgraphToNetwork(subgraphNetwork,subgraph,TypeSubgraph.CYCLE);
 
             // if combined cycle (with cycle i) : that is, if there are more than one common nodes
             if (commonNodes.length > 1) {  
diff --git a/src/composables/LayoutMainChain.ts b/src/composables/LayoutMainChain.ts
index 4ffa31c..36950fa 100644
--- a/src/composables/LayoutMainChain.ts
+++ b/src/composables/LayoutMainChain.ts
@@ -6,7 +6,7 @@ import { getStartNodes } from "./CalculateStartNodes";
 import { Network } from "@metabohub/viz-core/src/types/Network";
 import { BFS } from "./AlgorithmBFS";
 import {TypeSubgraph, type Subgraph} from "../types/Subgraph";
-import { addNewSubgraph, addNodeToSubgraph, createSubgraph, updateNodeMetadataSubgraph } from './UseSubgraphNetwork';
+import { addSubgraphToNetwork, createSubgraph, updateNodeMetadataSubgraph } from './SubgraphForSubgraphNetwork';
 
 
 /**
@@ -97,7 +97,7 @@ export function addMiniBranchToMainChain(subgraphNetwork:SubgraphNetwork):Subgra
         // add the nodes to a subgraph associated with the main chain
         if (nodesToAdd.length>0){
             const subgraph=createSubgraph("minibranch_"+mainChainID,nodesToAdd,[],TypeSubgraph.SECONDARY_CHAIN,{name:mainChainID,type:TypeSubgraph.MAIN_CHAIN});
-            subgraphNetwork=addNewSubgraph(subgraphNetwork,subgraph,TypeSubgraph.SECONDARY_CHAIN);
+            subgraphNetwork=addSubgraphToNetwork(subgraphNetwork,subgraph,TypeSubgraph.SECONDARY_CHAIN);
         }
     });
     return subgraphNetwork;
diff --git a/src/composables/LayoutManageSideCompounds.ts b/src/composables/LayoutManageSideCompounds.ts
index 186395c..908c587 100644
--- a/src/composables/LayoutManageSideCompounds.ts
+++ b/src/composables/LayoutManageSideCompounds.ts
@@ -8,7 +8,6 @@ import { Coordinate } from "../types/CoordinatesSize";
 import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties";
 
 // Composable imports
-import { getContentFromURL } from "./importNetwork";
 import { removeAllSelectedNodes , duplicateAllNodesByAttribut} from "@metabohub/viz-core";
 import { getMeanNodesSizePixel, inchesToPixels, minEdgeLength as minEdgeLength, pixelsToInches } from "./CalculateSize";
 import { sideCompoundAttribute,isDuplicate, isReaction, isSideCompound, setAsSideCompound } from "./GetSetAttributsNodes";
@@ -40,6 +39,9 @@ import { error } from "console";
  * -> getIDSideCompoundsFromFile :
  *      return the list of id of side compounds from a file
  * 
+ * -> getContentFromURL :
+ *     fetch url to return data
+ * 
  * 
  **********************************
  * 
@@ -190,6 +192,26 @@ async function getIDSideCompoundsFromFile(pathListSideCompounds:string):Promise<
     }
 }
 
+/**
+ * Fetch url to return data
+ * @param url URL to fetch 
+ * @returns Return response
+ */
+export async function getContentFromURL(url: string): Promise<string> {
+	try {
+	  const response = await fetch(url);
+	  if (!response.ok) {
+		throw new Error('La requête a échoué avec le statut ' + response.status);
+	  }
+	  const content = await response.text();
+	  return content;
+	} catch (error) {
+	  console.error('Une erreur s\'est produite lors de la récupération du contenu du fichier :', error);
+	  throw error;
+	}
+  }
+  
+
 
 /*******************************************************************************************************************************************************/
 //___________________________________________________1.  Duplicate and remove side compounds__________________________________________________________________________
diff --git a/src/composables/LayoutReversibleReactions.ts b/src/composables/LayoutReversibleReactions.ts
index 5af2aab..1bbe991 100644
--- a/src/composables/LayoutReversibleReactions.ts
+++ b/src/composables/LayoutReversibleReactions.ts
@@ -163,12 +163,11 @@ async function duplicateNodeReactionReversible(networkLayout: NetworkLayout, nod
             if (!networkLayout.nodes[nodeReaction.id]) {
                 throw new Error("Node not found to set as reversible");
             }
-
-            if (networkLayout.nodes[nodeReaction.id].metadataLayout) {
-                networkLayout.nodes[nodeReaction.id].metadataLayout.reversibleNodeVersion = newId;
-            }else{
-                networkLayout.nodes[nodeReaction.id].metadataLayout = {reversibleNodeVersion:newId};
+            let metadataLayout=networkLayout.nodes[nodeReaction.id].metadataLayout;
+            if (!metadataLayout) {
+               metadataLayout={};
             }
+            metadataLayout.reversibleNodeVersion = newId;
 
             resolve(newReactionNode);
         } catch (error) {
diff --git a/src/composables/LayoutSugiyamaForce.ts b/src/composables/LayoutSugiyamaForce.ts
index fe2ac67..4defdab 100644
--- a/src/composables/LayoutSugiyamaForce.ts
+++ b/src/composables/LayoutSugiyamaForce.ts
@@ -69,7 +69,6 @@ export async function vizLayout(subgraphNetwork:SubgraphNetwork,assignRank:boole
         await instance().then( async viz => {
         // attributes for viz
         const sep =await getSepAttributesInches(subgraphNetwork.network.value,subgraphNetwork.networkStyle.value,factorLenghtEdge);
-        console.log('sep',sep);
         subgraphNetwork.attributs={rankdir: "BT" , newrank:true, compound:true,splines:false,ranksep:sep.rankSep,nodesep:sep.nodeSep,dpi:dpi};
         const dot=networkToDOT(subgraphNetwork,cycle,addNodes,groupOrCluster,orderChange);
         if(printDot) console.log(dot);
diff --git a/src/composables/MetricsApplication.ts b/src/composables/MetricsApplication.ts
index 6fa8868..7a6b41b 100644
--- a/src/composables/MetricsApplication.ts
+++ b/src/composables/MetricsApplication.ts
@@ -1,329 +1,329 @@
-import { ref } from "vue";
-import { getContentFromURL, importNetworkFromURL } from "./importNetwork";
-import { Network } from "@metabohub/viz-core/src/types/Network";
-import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties";
-import { SubgraphNetwork } from "../types/SubgraphNetwork";
-import { addSideCompoundAttributeFromList, duplicateSideCompound, putDuplicatedSideCompoundAside } from "./LayoutManageSideCompounds";
-import { createStaticForceLayout } from "@metabohub/viz-core";
-import { Parameters,defaultParameters } from "../types/Parameters";
-import { forceLayout, vizLayout } from "./LayoutSugiyamaForce";
-import { Algo, PathType } from "../types/EnumArgs";
-import { countIntersectionEdgeNetwork, countOverlapNodeNetwork, countOverlapNodeEdgeNetwork, countDifferentCoordinatesNodeNetwork, countNodes, countEdges, coefficientOfVariationEdgeLength, analyseDirectorVector } from "./MetricsCalculation";
-import { TypeSubgraph } from "../types/Subgraph";
-import { networkToGDSGraph } from "./ConvertFromNetwork";
-import { allSteps } from "./LayoutMain";
-
-
-export async function analyseAllJSON(pathListJSON: string,algo:Algo=Algo.DEFAULT,metricGraph:boolean=true): Promise<void> {
-    const jsonFileString = await getContentFromURL(pathListJSON);
-    const allJson = jsonFileString.split('\n');
-    let resultGraphAllJSON: Array<Array<number>> = [];
-    let resultLayoutAllJSON: Array<Array<number>> = [];
-    let nameMetrics:{graph:string[],layout:string[]}= {graph:[],layout:[]};
-    let nameFile: string[] = [];
-
-    // which layout to apply
-    let applyLayout: (subgraph: SubgraphNetwork) => Promise<SubgraphNetwork> =defaultApplyLayout;
-    switch (algo) {
-        case Algo.FORCE:
-            console.log('apply Force');
-            applyLayout = applyForceLayout;
-            console.warn('Use of timeout so exec time is not accurate (no comparison possible)');
-            break;
-        case Algo.VIZ:
-            console.log('apply Viz');
-            applyLayout = applyVizLayout;
-            break;
-        case Algo.ALGO:
-            console.log('applyAlgo : default');
-            applyLayout = applyAlgo;
-            break;
-        case Algo.ALGO_V0:
-            console.log('applyAlgo_V0: no main chain');
-            applyLayout = applyAlgo_V0;
-            break;
-        case Algo.ALGO_V1:
-            console.log('applyAlgo_V1 : longuest');
-            applyLayout = applyAlgo_V1;
-            break;
-        case Algo.ALGO_V3:
-            console.log('applyAlgo_V3 : all');
-            applyLayout = applyAlgo_V3;
-            break;
-        default:
-            console.log('no change');
-            applyLayout = defaultApplyLayout;
-            break;
-    }
-    let firstJSON=true;
-    for (const json of allJson) {
-        console.log(json);
-        const resultJSON= await analyseJSON(json,metricGraph,applyLayout,false);
-        if (firstJSON){
-            nameMetrics.graph=resultJSON.graph.nameMetrics;
-            nameMetrics.layout=resultJSON.layout.nameMetrics;
-            firstJSON=false;
-        }
-        if (resultJSON.graph !== undefined){
-            resultGraphAllJSON.push(resultJSON.graph.result);
-        }
-        if (resultJSON.layout !== undefined){
-            nameFile.push(json);
-            resultLayoutAllJSON.push(resultJSON.layout.result);
-        }
+// import { ref } from "vue";
+// import { getContentFromURL, importNetworkFromURL } from "./importNetwork";
+// import { Network } from "@metabohub/viz-core/src/types/Network";
+// import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties";
+// import { SubgraphNetwork } from "../types/SubgraphNetwork";
+// import { addSideCompoundAttributeFromList, duplicateSideCompound, putDuplicatedSideCompoundAside } from "./LayoutManageSideCompounds";
+// import { createStaticForceLayout } from "@metabohub/viz-core";
+// import { Parameters,defaultParameters } from "../types/Parameters";
+// import { forceLayout, vizLayout } from "./LayoutSugiyamaForce";
+// import { Algo, PathType } from "../types/EnumArgs";
+// import { countIntersectionEdgeNetwork, countOverlapNodeNetwork, countOverlapNodeEdgeNetwork, countDifferentCoordinatesNodeNetwork, countNodes, countEdges, coefficientOfVariationEdgeLength, analyseDirectorVector } from "./MetricsCalculation";
+// import { TypeSubgraph } from "../types/Subgraph";
+// import { networkToGDSGraph } from "./ConvertFromNetwork";
+// import { allSteps } from "./LayoutMain";
+
+
+// export async function analyseAllJSON(pathListJSON: string,algo:Algo=Algo.DEFAULT,metricGraph:boolean=true): Promise<void> {
+//     const jsonFileString = await getContentFromURL(pathListJSON);
+//     const allJson = jsonFileString.split('\n');
+//     let resultGraphAllJSON: Array<Array<number>> = [];
+//     let resultLayoutAllJSON: Array<Array<number>> = [];
+//     let nameMetrics:{graph:string[],layout:string[]}= {graph:[],layout:[]};
+//     let nameFile: string[] = [];
+
+//     // which layout to apply
+//     let applyLayout: (subgraph: SubgraphNetwork) => Promise<SubgraphNetwork> =defaultApplyLayout;
+//     switch (algo) {
+//         case Algo.FORCE:
+//             console.log('apply Force');
+//             applyLayout = applyForceLayout;
+//             console.warn('Use of timeout so exec time is not accurate (no comparison possible)');
+//             break;
+//         case Algo.VIZ:
+//             console.log('apply Viz');
+//             applyLayout = applyVizLayout;
+//             break;
+//         case Algo.ALGO:
+//             console.log('applyAlgo : default');
+//             applyLayout = applyAlgo;
+//             break;
+//         case Algo.ALGO_V0:
+//             console.log('applyAlgo_V0: no main chain');
+//             applyLayout = applyAlgo_V0;
+//             break;
+//         case Algo.ALGO_V1:
+//             console.log('applyAlgo_V1 : longuest');
+//             applyLayout = applyAlgo_V1;
+//             break;
+//         case Algo.ALGO_V3:
+//             console.log('applyAlgo_V3 : all');
+//             applyLayout = applyAlgo_V3;
+//             break;
+//         default:
+//             console.log('no change');
+//             applyLayout = defaultApplyLayout;
+//             break;
+//     }
+//     let firstJSON=true;
+//     for (const json of allJson) {
+//         console.log(json);
+//         const resultJSON= await analyseJSON(json,metricGraph,applyLayout,false);
+//         if (firstJSON){
+//             nameMetrics.graph=resultJSON.graph.nameMetrics;
+//             nameMetrics.layout=resultJSON.layout.nameMetrics;
+//             firstJSON=false;
+//         }
+//         if (resultJSON.graph !== undefined){
+//             resultGraphAllJSON.push(resultJSON.graph.result);
+//         }
+//         if (resultJSON.layout !== undefined){
+//             nameFile.push(json);
+//             resultLayoutAllJSON.push(resultJSON.layout.result);
+//         }
        
-    }  
-
-    if (metricGraph){
-        print1DArray(nameMetrics.graph);
-        print2DArray(resultGraphAllJSON);
-    }
-    print1DArray(nameMetrics.layout);
-    print2DArray(resultLayoutAllJSON);
-
-    console.warn("If apply metrics on another layout : refresh the page, else results are the same than last time (idk why)");
-    console.warn('Some metrics are calculated without side compounds');
-}
-
-
-async function analyseJSON(json: string, metricGraph:boolean=true, applyLayout: (subgraph: SubgraphNetwork) => Promise<SubgraphNetwork> =defaultApplyLayout,printColumnName:boolean=true):
- Promise<{graph:{nameMetrics:string[],result:number[]},layout:{nameMetrics:string[],result:number[]}} | undefined> {
-
-    // initialize objects
-    const networkForJSON = ref<Network>({ id: '', nodes: {}, links: [] });
-    const networkStyleforJSON = ref<GraphStyleProperties>({
-        nodeStyles: {},
-        linkStyles: {}
-    });
-    let startTime:number;
-    let endTime:number;
-    let subgraphNetwork:SubgraphNetwork;
-    let resultGraph: {nameMetrics:string[],result:number[]}= {nameMetrics:[],result:[]};
-    let resultLayout:{nameMetrics:string[],result:number[]}= {nameMetrics:[],result:[]};
-
-    // import network from JSON, and process it
-    try {
-        await new Promise<void>((resolve, reject) => {
-            try {
-                importNetworkFromURL(json, networkForJSON, networkStyleforJSON, () => {
-                    //// Callback function (after network imported) :
-
-                    // set style (same for all)
-                    changeNodeStyles(networkStyleforJSON.value);
-                    // create subgraphNetwork object
-                    subgraphNetwork={network:networkForJSON,networkStyle:networkStyleforJSON,attributs:{},mainChains:{}};
-                    // duplicate side compounds 
-                    addSideCompoundAttributeFromList(subgraphNetwork,"/sideCompounds.txt").then(
-                        ()=>{
-                        duplicateSideCompound(subgraphNetwork);
-                        }
-                    ).then(
-                        ()=>{
-                        // calculate metrics of graph 
-                        if (metricGraph) {
-                            const metricsGraph=applyMetricsGraph(subgraphNetwork.network.value,printColumnName); 
-                            resultGraph.result=metricsGraph.metrics
-                            resultGraph.nameMetrics=metricsGraph.nameMetrics;
-                        }
-                        }
-                    ).then(
-                         ()=>{                       
-                            startTime = performance.now();
-                        }
-                    ).then(
-                        async ()=>{                       
-                        // apply layout
-                        subgraphNetwork=await applyLayout(subgraphNetwork);
-                        }
-                    ).then(
-                         ()=>{                       
-                            endTime = performance.now();
-                        }
-                    ).then(
-                        ()=>{
-                        // calculate metrics on resulting layout
-                        const metricsLayout=applyMetricsLayout(subgraphNetwork,true,printColumnName);     
-                        resultLayout.result= metricsLayout.metrics; 
-                        resultLayout.nameMetrics=metricsLayout.nameMetrics;          
-                        resolve();
-                        }
-                    );
+//     }  
+
+//     if (metricGraph){
+//         print1DArray(nameMetrics.graph);
+//         print2DArray(resultGraphAllJSON);
+//     }
+//     print1DArray(nameMetrics.layout);
+//     print2DArray(resultLayoutAllJSON);
+
+//     console.warn("If apply metrics on another layout : refresh the page, else results are the same than last time (idk why)");
+//     console.warn('Some metrics are calculated without side compounds');
+// }
+
+
+// async function analyseJSON(json: string, metricGraph:boolean=true, applyLayout: (subgraph: SubgraphNetwork) => Promise<SubgraphNetwork> =defaultApplyLayout,printColumnName:boolean=true):
+//  Promise<{graph:{nameMetrics:string[],result:number[]},layout:{nameMetrics:string[],result:number[]}} | undefined> {
+
+//     // initialize objects
+//     const networkForJSON = ref<Network>({ id: '', nodes: {}, links: [] });
+//     const networkStyleforJSON = ref<GraphStyleProperties>({
+//         nodeStyles: {},
+//         linkStyles: {}
+//     });
+//     let startTime:number;
+//     let endTime:number;
+//     let subgraphNetwork:SubgraphNetwork;
+//     let resultGraph: {nameMetrics:string[],result:number[]}= {nameMetrics:[],result:[]};
+//     let resultLayout:{nameMetrics:string[],result:number[]}= {nameMetrics:[],result:[]};
+
+//     // import network from JSON, and process it
+//     try {
+//         await new Promise<void>((resolve, reject) => {
+//             try {
+//                 importNetworkFromURL(json, networkForJSON, networkStyleforJSON, () => {
+//                     //// Callback function (after network imported) :
+
+//                     // set style (same for all)
+//                     changeNodeStyles(networkStyleforJSON.value);
+//                     // create subgraphNetwork object
+//                     subgraphNetwork={network:networkForJSON,networkStyle:networkStyleforJSON,attributs:{},mainChains:{}};
+//                     // duplicate side compounds 
+//                     addSideCompoundAttributeFromList(subgraphNetwork,"/sideCompounds.txt").then(
+//                         ()=>{
+//                         duplicateSideCompound(subgraphNetwork);
+//                         }
+//                     ).then(
+//                         ()=>{
+//                         // calculate metrics of graph 
+//                         if (metricGraph) {
+//                             const metricsGraph=applyMetricsGraph(subgraphNetwork.network.value,printColumnName); 
+//                             resultGraph.result=metricsGraph.metrics
+//                             resultGraph.nameMetrics=metricsGraph.nameMetrics;
+//                         }
+//                         }
+//                     ).then(
+//                          ()=>{                       
+//                             startTime = performance.now();
+//                         }
+//                     ).then(
+//                         async ()=>{                       
+//                         // apply layout
+//                         subgraphNetwork=await applyLayout(subgraphNetwork);
+//                         }
+//                     ).then(
+//                          ()=>{                       
+//                             endTime = performance.now();
+//                         }
+//                     ).then(
+//                         ()=>{
+//                         // calculate metrics on resulting layout
+//                         const metricsLayout=applyMetricsLayout(subgraphNetwork,true,printColumnName);     
+//                         resultLayout.result= metricsLayout.metrics; 
+//                         resultLayout.nameMetrics=metricsLayout.nameMetrics;          
+//                         resolve();
+//                         }
+//                     );
                     
-                });
-            } catch (error) {
-                reject(error);
-            }
-        });
-    } catch (error) {
-        console.error("error file : " + json + "\n" + error);
-        return undefined;
-    }
-    // add execution time of layout only (not duplication side compounds)
-    const executionTime = parseFloat((endTime - startTime).toFixed(3));
-    if (executionTime) {
-        resultLayout.result.push(executionTime);
-        resultLayout.nameMetrics.push('execution time (ms)');
-    }
+//                 });
+//             } catch (error) {
+//                 reject(error);
+//             }
+//         });
+//     } catch (error) {
+//         console.error("error file : " + json + "\n" + error);
+//         return undefined;
+//     }
+//     // add execution time of layout only (not duplication side compounds)
+//     const executionTime = parseFloat((endTime - startTime).toFixed(3));
+//     if (executionTime) {
+//         resultLayout.result.push(executionTime);
+//         resultLayout.nameMetrics.push('execution time (ms)');
+//     }
     
-    return {graph:resultGraph,layout:resultLayout};
-}
-
-
-function changeNodeStyles(networkStyle:GraphStyleProperties):void{
-	networkStyle.nodeStyles = {
-		metabolite: {
-			width: 25,
-			height: 25,
-			fill:  '#FFFFFF',
-			shape: 'circle'
-		},
-    sideCompound: {
-			width: 12,
-			height: 12,
-			fill:  '#f0e3e0',
-			shape: 'circle'
-		},
-		reaction: {
-			width: 15,
-			height: 15,
-			fill: "grey",
-			shape: 'rect'
-		},
-		// reversible : {
-		// 	fill : "green",
-		// 	shape:"inverseTriangle"
-		// },
-		// reversibleVersion:{
-		// 	fill:"red",
-		// 	shape: "triangle"
-		// }
-
-	}
-}
-
-function print1DArray(data: Array<string|number|boolean>): void {
-    const stringData = data.join(',');
-    console.log(stringData);
-}
-
-function print2DArray(data: Array<Array<string|number|boolean>>): void {
-    const stringData = data.map(row => row.join(',')).join('\n');
-    console.log(stringData);
-}
-
-
-
-const defaultApplyLayout = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
-    return subgraphNetwork;
-};
-
-const applyForceLayout = (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
-    const network=subgraphNetwork.network.value;
-    const styleNetwork= subgraphNetwork.networkStyle.value;
-    const subgraphNetworkPromise = new Promise<SubgraphNetwork>(async (resolve, reject) => {
-        try {
-            await forceLayout(network, styleNetwork, false);
-            resolve(subgraphNetwork);
-        } catch (error) {
-            reject(error);
-        }
-    });
-    return subgraphNetworkPromise;
-};
-
-const applyVizLayout = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
-    let parameters: Parameters = defaultParameters;
-    const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => {
-        resolve(vizLayout(subgraphNetwork, false, false, parameters.addNodes, parameters.groupOrCluster, false, false, parameters.dpi, parameters.numberNodeOnEdge))
-    })
-    return subgraphNetworkPromise;
-};
-
-const applyAlgo = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
-    let parameters: Parameters=defaultParameters;
-    const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => {
-        resolve(allSteps(subgraphNetwork,parameters,false));
-    })
-    return subgraphNetworkPromise;
-};
-
-const applyAlgo_V0 = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
-    let parameters: Parameters=defaultParameters;
-    parameters.doMainChain=false;
-    const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => {
-        resolve(allSteps(subgraphNetwork,parameters,false));
-    })
-    return subgraphNetworkPromise;
-};
-
-const applyAlgo_V1 = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
-    let parameters: Parameters=defaultParameters;
-    parameters.pathType=PathType.LONGEST;
-    const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => {
-        resolve(allSteps(subgraphNetwork,parameters,false));
-    })
-    return subgraphNetworkPromise;
-};
-
-const applyAlgo_V3 = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
-    let parameters: Parameters=defaultParameters;
-    parameters.pathType=PathType.ALL;
-    const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => {
-        resolve(allSteps(subgraphNetwork,parameters,false));
-    })
-    return subgraphNetworkPromise;
-};
-
-
-
-
-export function applyMetricsGraph(network: Network,printColumnName:boolean=true): {nameMetrics:string[],metrics:number[]} {
-    const networkGDS=networkToGDSGraph(network);
-    const result: number[]=[];
-
-    const nameColumnGraph: string[] = ['nodes', 'node not side compound','edges','edge  not side compound', 'hasDirectedCycle' ];
-    if (printColumnName) print1DArray(nameColumnGraph);
-
-    // number of nodes
-    result.push(countNodes(network,true));
-    // number of nodes not side compounds
-    result.push(countNodes(network,false));
-    // number of edges
-    result.push(countEdges(network,true));
-    // number of edges not side compounds
-    result.push(countEdges(network,false));
-    // has directed cycle
-    result.push(Number(networkGDS.hasCycle()));
-
-    return {nameMetrics:nameColumnGraph,metrics:result};
-}
-
-export function applyMetricsLayout(subgraphNetwork: SubgraphNetwork, coordAreCenter:boolean=true, printColumnName:boolean=true): {nameMetrics:string[],metrics:number[]} {
-    const network=subgraphNetwork.network.value;
-    const networkStyle=subgraphNetwork.networkStyle.value;
-    const networkGDS=networkToGDSGraph(network);
-    const result: number[]=[];
-
-    const nameColumnLayout: string[] = ['node overlap', 'edge node overlap', 'different x (not SD)' ,'different y (not SD)','edge intersections','coef var edge length (no SD)','% colineat axis (not SD)', 'coef var vect dir (not SD)'];
-    if (printColumnName) print1DArray(nameColumnLayout);
-
-
-    //number of node overlap
-    result.push(countOverlapNodeNetwork(network,networkStyle,coordAreCenter));
-    // number of edge node overlap
-    result.push(countOverlapNodeEdgeNetwork(network,networkStyle,coordAreCenter));
-    // number of different x and y coordinates (without side compounds)
-    const countDiffCoord=countDifferentCoordinatesNodeNetwork(network,networkStyle,coordAreCenter,false);
-    result.push(countDiffCoord.x);
-    result.push(countDiffCoord.y);
-    // number of edges intersections
-    result.push(countIntersectionEdgeNetwork(network,networkStyle,coordAreCenter));
-    // variance edge length (without side compounds?)
-    result.push(coefficientOfVariationEdgeLength(network,networkStyle,coordAreCenter,false));
-    // direction edge : % of edge colinear to axis and coef of variaton of angle
-    const resultDirection=analyseDirectorVector(network,networkStyle,coordAreCenter,true,false);
-    result.push(resultDirection.colinearAxis)
-    result.push(resultDirection.coefVariation)
-
-    return {nameMetrics:nameColumnLayout,metrics:result};
-}
+//     return {graph:resultGraph,layout:resultLayout};
+// }
+
+
+// function changeNodeStyles(networkStyle:GraphStyleProperties):void{
+// 	networkStyle.nodeStyles = {
+// 		metabolite: {
+// 			width: 25,
+// 			height: 25,
+// 			fill:  '#FFFFFF',
+// 			shape: 'circle'
+// 		},
+//     sideCompound: {
+// 			width: 12,
+// 			height: 12,
+// 			fill:  '#f0e3e0',
+// 			shape: 'circle'
+// 		},
+// 		reaction: {
+// 			width: 15,
+// 			height: 15,
+// 			fill: "grey",
+// 			shape: 'rect'
+// 		},
+// 		// reversible : {
+// 		// 	fill : "green",
+// 		// 	shape:"inverseTriangle"
+// 		// },
+// 		// reversibleVersion:{
+// 		// 	fill:"red",
+// 		// 	shape: "triangle"
+// 		// }
+
+// 	}
+// }
+
+// function print1DArray(data: Array<string|number|boolean>): void {
+//     const stringData = data.join(',');
+//     console.log(stringData);
+// }
+
+// function print2DArray(data: Array<Array<string|number|boolean>>): void {
+//     const stringData = data.map(row => row.join(',')).join('\n');
+//     console.log(stringData);
+// }
+
+
+
+// const defaultApplyLayout = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
+//     return subgraphNetwork;
+// };
+
+// const applyForceLayout = (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
+//     const network=subgraphNetwork.network.value;
+//     const styleNetwork= subgraphNetwork.networkStyle.value;
+//     const subgraphNetworkPromise = new Promise<SubgraphNetwork>(async (resolve, reject) => {
+//         try {
+//             await forceLayout(network, styleNetwork, false);
+//             resolve(subgraphNetwork);
+//         } catch (error) {
+//             reject(error);
+//         }
+//     });
+//     return subgraphNetworkPromise;
+// };
+
+// const applyVizLayout = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
+//     let parameters: Parameters = defaultParameters;
+//     const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => {
+//         resolve(vizLayout(subgraphNetwork, false, false, parameters.addNodes, parameters.groupOrCluster, false, false, parameters.dpi, parameters.numberNodeOnEdge))
+//     })
+//     return subgraphNetworkPromise;
+// };
+
+// const applyAlgo = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
+//     let parameters: Parameters=defaultParameters;
+//     const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => {
+//         resolve(allSteps(subgraphNetwork,parameters,false));
+//     })
+//     return subgraphNetworkPromise;
+// };
+
+// const applyAlgo_V0 = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
+//     let parameters: Parameters=defaultParameters;
+//     parameters.doMainChain=false;
+//     const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => {
+//         resolve(allSteps(subgraphNetwork,parameters,false));
+//     })
+//     return subgraphNetworkPromise;
+// };
+
+// const applyAlgo_V1 = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
+//     let parameters: Parameters=defaultParameters;
+//     parameters.pathType=PathType.LONGEST;
+//     const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => {
+//         resolve(allSteps(subgraphNetwork,parameters,false));
+//     })
+//     return subgraphNetworkPromise;
+// };
+
+// const applyAlgo_V3 = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => {
+//     let parameters: Parameters=defaultParameters;
+//     parameters.pathType=PathType.ALL;
+//     const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => {
+//         resolve(allSteps(subgraphNetwork,parameters,false));
+//     })
+//     return subgraphNetworkPromise;
+// };
+
+
+
+
+// export function applyMetricsGraph(network: Network,printColumnName:boolean=true): {nameMetrics:string[],metrics:number[]} {
+//     const networkGDS=networkToGDSGraph(network);
+//     const result: number[]=[];
+
+//     const nameColumnGraph: string[] = ['nodes', 'node not side compound','edges','edge  not side compound', 'hasDirectedCycle' ];
+//     if (printColumnName) print1DArray(nameColumnGraph);
+
+//     // number of nodes
+//     result.push(countNodes(network,true));
+//     // number of nodes not side compounds
+//     result.push(countNodes(network,false));
+//     // number of edges
+//     result.push(countEdges(network,true));
+//     // number of edges not side compounds
+//     result.push(countEdges(network,false));
+//     // has directed cycle
+//     result.push(Number(networkGDS.hasCycle()));
+
+//     return {nameMetrics:nameColumnGraph,metrics:result};
+// }
+
+// export function applyMetricsLayout(subgraphNetwork: SubgraphNetwork, coordAreCenter:boolean=true, printColumnName:boolean=true): {nameMetrics:string[],metrics:number[]} {
+//     const network=subgraphNetwork.network.value;
+//     const networkStyle=subgraphNetwork.networkStyle.value;
+//     const networkGDS=networkToGDSGraph(network);
+//     const result: number[]=[];
+
+//     const nameColumnLayout: string[] = ['node overlap', 'edge node overlap', 'different x (not SD)' ,'different y (not SD)','edge intersections','coef var edge length (no SD)','% colineat axis (not SD)', 'coef var vect dir (not SD)'];
+//     if (printColumnName) print1DArray(nameColumnLayout);
+
+
+//     //number of node overlap
+//     result.push(countOverlapNodeNetwork(network,networkStyle,coordAreCenter));
+//     // number of edge node overlap
+//     result.push(countOverlapNodeEdgeNetwork(network,networkStyle,coordAreCenter));
+//     // number of different x and y coordinates (without side compounds)
+//     const countDiffCoord=countDifferentCoordinatesNodeNetwork(network,networkStyle,coordAreCenter,false);
+//     result.push(countDiffCoord.x);
+//     result.push(countDiffCoord.y);
+//     // number of edges intersections
+//     result.push(countIntersectionEdgeNetwork(network,networkStyle,coordAreCenter));
+//     // variance edge length (without side compounds?)
+//     result.push(coefficientOfVariationEdgeLength(network,networkStyle,coordAreCenter,false));
+//     // direction edge : % of edge colinear to axis and coef of variaton of angle
+//     const resultDirection=analyseDirectorVector(network,networkStyle,coordAreCenter,true,false);
+//     result.push(resultDirection.colinearAxis)
+//     result.push(resultDirection.coefVariation)
+
+//     return {nameMetrics:nameColumnLayout,metrics:result};
+// }
diff --git a/src/composables/MetricsCalculation.ts b/src/composables/MetricsCalculation.ts
index 5843b71..522a6d3 100644
--- a/src/composables/MetricsCalculation.ts
+++ b/src/composables/MetricsCalculation.ts
@@ -1,448 +1,448 @@
-import { Link } from "@metabohub/viz-core/src/types/Link";
-import { Network } from "@metabohub/viz-core/src/types/Network";
-import { Node } from "@metabohub/viz-core/src/types/Node";
-import { getTopLeftCoordFromCenter, getSizeNodePixel, getCenterCoordFromTopLeft } from "./CalculateSize";
-import { checkIntersection } from "line-intersect";
-import { Coordinate,Size } from "../types/CoordinatesSize";
-import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties";
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//---------------------------------------------------- Utilitary Functions -----------------------------------------------------------//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-export function getCenterNode(node: Node,networkStyle:GraphStyleProperties,coordAreCenter:boolean=false): Coordinate {
-    let nodeCenter: {x:number,y:number};
-
-    if (coordAreCenter) {
-        nodeCenter={x:node.x,y:node.y};
-    }else{
-        nodeCenter=getCenterCoordFromTopLeft(node,networkStyle);
-    }
-    return nodeCenter;
-}
-
-
-function commonNodeBetween2Links(link1: Link,link2: Link): boolean {
-    if (link1.source==link2.source || link1.source==link2.target || link1.target==link2.source || link1.target==link2.target) {
-        return true;
-    }else {
-        return false;
-    }
-} 
-
-export function countNodes(network: Network, countSideCompound: boolean = true): number {
-    if (countSideCompound) {
-        return Object.keys(network.nodes).length;
-    } else {
-        let nodes = 0;
-        Object.keys(network.nodes).forEach((nodeID) => {
-            const node = network.nodes[nodeID];
-            if (!(node.metadata && node.metadata["isSideCompound"])) {
-                nodes += 1;
-            }
-        });
-        return nodes;
-    }
-}
-
-export function countEdges(network: Network, countSideCompound: boolean = true): number {
-    if (countSideCompound) {
-        return network.links.length;
-    } else {
-        let links = 0;
-        network.links.forEach(link => {
-            if (!(link.source.metadata && link.source.metadata["isSideCompound"]) && !(link.target.metadata && link.target.metadata["isSideCompound"])) {
-                links += 1;
-            }
-        });
-        return links;
-    }
-}
-
-function getNormalizedDirectorVector(link: Link, style: GraphStyleProperties, coordAreCenter: boolean = false): Coordinate {
-
-    const sourceCenter = getCenterNode(link.source, style, coordAreCenter);
-    const targetCenter = getCenterNode(link.target, style, coordAreCenter);
-
-    const dx = targetCenter.x - sourceCenter.x;
-    const dy = targetCenter.y - sourceCenter.y;
-
-    const length = edgeLength(link, style, coordAreCenter);
-
-    if (length === 0) {
-        return { x: 0, y: 0 }; // Handle case with zero length
-    }
-
-    return {
-        x: parseFloat((dx / length).toFixed(2)),
-        y:  parseFloat((dy / length).toFixed(2))
-    };
-}
+// import { Link } from "@metabohub/viz-core/src/types/Link";
+// import { Network } from "@metabohub/viz-core/src/types/Network";
+// import { Node } from "@metabohub/viz-core/src/types/Node";
+// import { getTopLeftCoordFromCenter, getSizeNodePixel, getCenterCoordFromTopLeft } from "./CalculateSize";
+// import { checkIntersection } from "line-intersect";
+// import { Coordinate,Size } from "../types/CoordinatesSize";
+// import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties";
+
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// //---------------------------------------------------- Utilitary Functions -----------------------------------------------------------//
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// export function getCenterNode(node: Node,networkStyle:GraphStyleProperties,coordAreCenter:boolean=false): Coordinate {
+//     let nodeCenter: {x:number,y:number};
+
+//     if (coordAreCenter) {
+//         nodeCenter={x:node.x,y:node.y};
+//     }else{
+//         nodeCenter=getCenterCoordFromTopLeft(node,networkStyle);
+//     }
+//     return nodeCenter;
+// }
+
+
+// function commonNodeBetween2Links(link1: Link,link2: Link): boolean {
+//     if (link1.source==link2.source || link1.source==link2.target || link1.target==link2.source || link1.target==link2.target) {
+//         return true;
+//     }else {
+//         return false;
+//     }
+// } 
+
+// export function countNodes(network: Network, countSideCompound: boolean = true): number {
+//     if (countSideCompound) {
+//         return Object.keys(network.nodes).length;
+//     } else {
+//         let nodes = 0;
+//         Object.keys(network.nodes).forEach((nodeID) => {
+//             const node = network.nodes[nodeID];
+//             if (!(node.metadata && node.metadata["isSideCompound"])) {
+//                 nodes += 1;
+//             }
+//         });
+//         return nodes;
+//     }
+// }
+
+// export function countEdges(network: Network, countSideCompound: boolean = true): number {
+//     if (countSideCompound) {
+//         return network.links.length;
+//     } else {
+//         let links = 0;
+//         network.links.forEach(link => {
+//             if (!(link.source.metadata && link.source.metadata["isSideCompound"]) && !(link.target.metadata && link.target.metadata["isSideCompound"])) {
+//                 links += 1;
+//             }
+//         });
+//         return links;
+//     }
+// }
+
+// function getNormalizedDirectorVector(link: Link, style: GraphStyleProperties, coordAreCenter: boolean = false): Coordinate {
+
+//     const sourceCenter = getCenterNode(link.source, style, coordAreCenter);
+//     const targetCenter = getCenterNode(link.target, style, coordAreCenter);
+
+//     const dx = targetCenter.x - sourceCenter.x;
+//     const dy = targetCenter.y - sourceCenter.y;
+
+//     const length = edgeLength(link, style, coordAreCenter);
+
+//     if (length === 0) {
+//         return { x: 0, y: 0 }; // Handle case with zero length
+//     }
+
+//     return {
+//         x: parseFloat((dx / length).toFixed(2)),
+//         y:  parseFloat((dy / length).toFixed(2))
+//     };
+// }
 
-function linkOfSideCompound(link:Link):boolean{
-    return (link.source.metadata && (link.source.metadata["isSideCompound"]) as boolean) || (link.target.metadata && (link.target.metadata["isSideCompound"]) as boolean);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//-------------------------------------------------------- Node Metrics --------------------------------------------------------------//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// function linkOfSideCompound(link:Link):boolean{
+//     return (link.source.metadata && (link.source.metadata["isSideCompound"]) as boolean) || (link.target.metadata && (link.target.metadata["isSideCompound"]) as boolean);
+// }
+
+
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// //-------------------------------------------------------- Node Metrics --------------------------------------------------------------//
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 
 
-/////////////////////////////////////////////////////
-// ------------------------- Node overlap
+// /////////////////////////////////////////////////////
+// // ------------------------- Node overlap
 
 
-export function countOverlapNodeNetwork(network: Network,networkStyle:GraphStyleProperties,coordAreCenter:boolean=false): number {
-    let nb=0;
-    const nodesID=Object.keys(network.nodes);
+// export function countOverlapNodeNetwork(network: Network,networkStyle:GraphStyleProperties,coordAreCenter:boolean=false): number {
+//     let nb=0;
+//     const nodesID=Object.keys(network.nodes);
 
-    for (let i=0 ; i<nodesID.length ; i++) {
-        for (let j=i+1 ; j<nodesID.length ; j++) {
-            // node1
-            const node1=network.nodes[nodesID[i]];
-            const coordNode1=getCenterNode(node1,networkStyle,coordAreCenter);
-            const sizeNode1=getSizeNodePixel(node1,networkStyle);
-            // node2
-            const node2=network.nodes[nodesID[j]];
-            const coordNode2=getCenterNode(node2,networkStyle,coordAreCenter);
-            const sizeNode2=getSizeNodePixel(node2,networkStyle);
+//     for (let i=0 ; i<nodesID.length ; i++) {
+//         for (let j=i+1 ; j<nodesID.length ; j++) {
+//             // node1
+//             const node1=network.nodes[nodesID[i]];
+//             const coordNode1=getCenterNode(node1,networkStyle,coordAreCenter);
+//             const sizeNode1=getSizeNodePixel(node1,networkStyle);
+//             // node2
+//             const node2=network.nodes[nodesID[j]];
+//             const coordNode2=getCenterNode(node2,networkStyle,coordAreCenter);
+//             const sizeNode2=getSizeNodePixel(node2,networkStyle);
 
-            if (nodesOverlap(coordNode1,sizeNode1,coordNode2,sizeNode2)){
-                nb+=1;
-            }
-        }
-    }
-    return nb;
-}
+//             if (nodesOverlap(coordNode1,sizeNode1,coordNode2,sizeNode2)){
+//                 nb+=1;
+//             }
+//         }
+//     }
+//     return nb;
+// }
 
 
 
-function nodesOverlap(coord1: Coordinate, size1: Size, coord2: Coordinate, size2: Size): boolean {
+// function nodesOverlap(coord1: Coordinate, size1: Size, coord2: Coordinate, size2: Size): boolean {
 
-    // coordinate are center
+//     // coordinate are center
 
-    if ( !size1.width || !size1.height || !size2.width || !size2.height || !coord1.x || !coord1.y || !coord2.x || !coord2.y) {
-        // Handle null or undefined inputs appropriately
-        return false;
-    }
+//     if ( !size1.width || !size1.height || !size2.width || !size2.height || !coord1.x || !coord1.y || !coord2.x || !coord2.y) {
+//         // Handle null or undefined inputs appropriately
+//         return false;
+//     }
 
-    // rectangle 1
-    const left1 = coord1.x - size1.width / 2;
-    const right1 = coord1.x + size1.width / 2;
-    const top1 = coord1.y - size1.height / 2;
-    const bottom1 = coord1.y + size1.height / 2;
+//     // rectangle 1
+//     const left1 = coord1.x - size1.width / 2;
+//     const right1 = coord1.x + size1.width / 2;
+//     const top1 = coord1.y - size1.height / 2;
+//     const bottom1 = coord1.y + size1.height / 2;
 
-    // rectangle 2
-    const left2 = coord2.x - size2.width / 2;
-    const right2 = coord2.x + size2.width / 2;
-    const top2 = coord2.y - size2.height / 2;
-    const bottom2 = coord2.y + size2.height / 2;
+//     // rectangle 2
+//     const left2 = coord2.x - size2.width / 2;
+//     const right2 = coord2.x + size2.width / 2;
+//     const top2 = coord2.y - size2.height / 2;
+//     const bottom2 = coord2.y + size2.height / 2;
 
-    // overlap?
-    const overlapX = left1 < right2 && right1 > left2;
-    const overlapY = top1 < bottom2 && bottom1 > top2;
+//     // overlap?
+//     const overlapX = left1 < right2 && right1 > left2;
+//     const overlapY = top1 < bottom2 && bottom1 > top2;
 
-    return overlapX && overlapY;
-}
+//     return overlapX && overlapY;
+// }
 
 
-/////////////////////////////////////////////////////
-// ------------------------- Node on edge
+// /////////////////////////////////////////////////////
+// // ------------------------- Node on edge
 
 
 
-export function countOverlapNodeEdgeNetwork(network: Network,networkStyle:GraphStyleProperties,coordAreCenter:boolean=false): number {
-    let nb=0;
-    const nodesID=Object.keys(network.nodes);
-    nodesID.forEach( (nodeID) =>{
+// export function countOverlapNodeEdgeNetwork(network: Network,networkStyle:GraphStyleProperties,coordAreCenter:boolean=false): number {
+//     let nb=0;
+//     const nodesID=Object.keys(network.nodes);
+//     nodesID.forEach( (nodeID) =>{
 
-        const node=network.nodes[nodeID];
-        const coordNode1=getCenterNode(node,networkStyle,coordAreCenter);
-        const sizeNode=getSizeNodePixel(node,networkStyle);
-        nb += countOverlapEdgeForNode(network,networkStyle,nodeID,coordNode1,sizeNode,coordAreCenter);
+//         const node=network.nodes[nodeID];
+//         const coordNode1=getCenterNode(node,networkStyle,coordAreCenter);
+//         const sizeNode=getSizeNodePixel(node,networkStyle);
+//         nb += countOverlapEdgeForNode(network,networkStyle,nodeID,coordNode1,sizeNode,coordAreCenter);
 
-    });
+//     });
 
-    return nb;
-}
+//     return nb;
+// }
 
-function countOverlapEdgeForNode(network:Network,networkStyle:GraphStyleProperties,nodeID:string,coordNode:Coordinate,sizeNode:Size,coordAreCenter:boolean=false): number {
-    let nb=0;
+// function countOverlapEdgeForNode(network:Network,networkStyle:GraphStyleProperties,nodeID:string,coordNode:Coordinate,sizeNode:Size,coordAreCenter:boolean=false): number {
+//     let nb=0;
 
-    network.links.forEach(link => {        
-        // if node not linked to the edge : check if it is on the edge
-        if(!(link.source.id==nodeID || link.target.id==nodeID)){
+//     network.links.forEach(link => {        
+//         // if node not linked to the edge : check if it is on the edge
+//         if(!(link.source.id==nodeID || link.target.id==nodeID)){
 
-            let coordSource=getCenterNode(link.source,networkStyle,coordAreCenter);
-            let coordTarget=getCenterNode(link.target,networkStyle,coordAreCenter);
+//             let coordSource=getCenterNode(link.source,networkStyle,coordAreCenter);
+//             let coordTarget=getCenterNode(link.target,networkStyle,coordAreCenter);
 
-            if (nodeEdgeOverlap(coordNode,sizeNode,coordSource,coordTarget)){
-                nb+=1;
-            }
-        }
-    });
-    return nb;
-}
+//             if (nodeEdgeOverlap(coordNode,sizeNode,coordSource,coordTarget)){
+//                 nb+=1;
+//             }
+//         }
+//     });
+//     return nb;
+// }
 
 
-function nodeEdgeOverlap(centerCoordNode: Coordinate, sizeNode: Size, coordSource: Coordinate, coordTarget: Coordinate): boolean { // CORRIGER !!!!!
+// function nodeEdgeOverlap(centerCoordNode: Coordinate, sizeNode: Size, coordSource: Coordinate, coordTarget: Coordinate): boolean { // CORRIGER !!!!!
     
-    // Treat the node as a rectangle (coordinates are center of node)
-    const rect = {
-        left: centerCoordNode.x - sizeNode.width / 2,
-        right: centerCoordNode.x + sizeNode.width / 2,
-        top: centerCoordNode.y - sizeNode.height / 2,
-        bottom: centerCoordNode.y + sizeNode.height / 2
-    };
-
-    // Check if any of the edge's endpoints is inside the rectangle => same as node overlap (to suppress ?)
-    const isPointInsideRect = (point: Coordinate) => 
-        point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.bottom;
-
-    if (isPointInsideRect(coordSource) || isPointInsideRect(coordTarget)) {
-        return true; // One of the endpoints is inside the rectangle
-    }
-
-    // Check for overlap between the edge and the sides of the rectangle
-    // Convert the sides of the rectangle into line segments
-    const rectangleEdges = [
-        { start: { x: rect.left, y: rect.top }, end: { x: rect.right, y: rect.top } }, // Top
-        { start: { x: rect.right, y: rect.top }, end: { x: rect.right, y: rect.bottom } }, // Right
-        { start: { x: rect.left, y: rect.bottom }, end: { x: rect.right, y: rect.bottom } }, // Bottom
-        { start: { x: rect.left, y: rect.top }, end: { x: rect.left, y: rect.bottom } } // Left
-    ];
-
-    // Use checkIntersection function to check if two line segments intersect
-    for (const edge of rectangleEdges) {
-        const result = checkIntersection(edge.start.x,edge.start.y, edge.end.x,edge.end.y, coordSource.x, coordSource.y,coordTarget.x,coordTarget.y);
-        if (result.type === "intersecting") {
-            return true; // There is an overlap
-        }
-    }
-
-    return false; // No overlap detected
-}
-
-
-/////////////////////////////////////////////////////
-// ------------------------- Node different coordinates
-
-export function countDifferentCoordinatesNodeNetwork(network: Network, networkStyle: GraphStyleProperties, coordAreCenter: boolean = false, countSideCompound:boolean=true,roundAt: number = 2): { x: number, y: number } {
-    let uniqueX = new Set<number>();
-    let uniqueY = new Set<number>();
-
-    Object.keys(network.nodes).forEach((nodeID) => {
-        const node = network.nodes[nodeID];
-        // Do not count side compounds if countSideCompound is false
-        if (countSideCompound ||  !(node.metadata && node.metadata["isSideCompound"])) {
-            const coordNode = getCenterNode(node, networkStyle, coordAreCenter);
+//     // Treat the node as a rectangle (coordinates are center of node)
+//     const rect = {
+//         left: centerCoordNode.x - sizeNode.width / 2,
+//         right: centerCoordNode.x + sizeNode.width / 2,
+//         top: centerCoordNode.y - sizeNode.height / 2,
+//         bottom: centerCoordNode.y + sizeNode.height / 2
+//     };
+
+//     // Check if any of the edge's endpoints is inside the rectangle => same as node overlap (to suppress ?)
+//     const isPointInsideRect = (point: Coordinate) => 
+//         point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.bottom;
+
+//     if (isPointInsideRect(coordSource) || isPointInsideRect(coordTarget)) {
+//         return true; // One of the endpoints is inside the rectangle
+//     }
+
+//     // Check for overlap between the edge and the sides of the rectangle
+//     // Convert the sides of the rectangle into line segments
+//     const rectangleEdges = [
+//         { start: { x: rect.left, y: rect.top }, end: { x: rect.right, y: rect.top } }, // Top
+//         { start: { x: rect.right, y: rect.top }, end: { x: rect.right, y: rect.bottom } }, // Right
+//         { start: { x: rect.left, y: rect.bottom }, end: { x: rect.right, y: rect.bottom } }, // Bottom
+//         { start: { x: rect.left, y: rect.top }, end: { x: rect.left, y: rect.bottom } } // Left
+//     ];
+
+//     // Use checkIntersection function to check if two line segments intersect
+//     for (const edge of rectangleEdges) {
+//         const result = checkIntersection(edge.start.x,edge.start.y, edge.end.x,edge.end.y, coordSource.x, coordSource.y,coordTarget.x,coordTarget.y);
+//         if (result.type === "intersecting") {
+//             return true; // There is an overlap
+//         }
+//     }
+
+//     return false; // No overlap detected
+// }
+
+
+// /////////////////////////////////////////////////////
+// // ------------------------- Node different coordinates
+
+// export function countDifferentCoordinatesNodeNetwork(network: Network, networkStyle: GraphStyleProperties, coordAreCenter: boolean = false, countSideCompound:boolean=true,roundAt: number = 2): { x: number, y: number } {
+//     let uniqueX = new Set<number>();
+//     let uniqueY = new Set<number>();
+
+//     Object.keys(network.nodes).forEach((nodeID) => {
+//         const node = network.nodes[nodeID];
+//         // Do not count side compounds if countSideCompound is false
+//         if (countSideCompound ||  !(node.metadata && node.metadata["isSideCompound"])) {
+//             const coordNode = getCenterNode(node, networkStyle, coordAreCenter);
             
-            // Round the coordinates based on roundAt
-            const roundedX = parseFloat(coordNode.x.toFixed(roundAt));
-            const roundedY = parseFloat(coordNode.y.toFixed(roundAt));
+//             // Round the coordinates based on roundAt
+//             const roundedX = parseFloat(coordNode.x.toFixed(roundAt));
+//             const roundedY = parseFloat(coordNode.y.toFixed(roundAt));
             
-            uniqueX.add(roundedX);
-            uniqueY.add(roundedY);
-        }
-    });
-
-    return { x: uniqueX.size, y: uniqueY.size };
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//-------------------------------------------------------- Edge Metrics --------------------------------------------------------------//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-
-/////////////////////////////////////////////////////
-// ------------------------- Edge intersection
-// (overlap not taken into account)
-
-
-/**
- * Counts how many crossings are in a network
- * @param network the network
- * @returns the number of crossings
- */
-export function countIntersectionEdgeNetwork(network: Network,style:GraphStyleProperties,coordAreCenter:boolean=false): number {
-    let nb: number = 0;
-    for (let i=0 ; i<network.links.length ; i++) {
-        for (let j=i+1 ; j<network.links.length ; j++) {
-            const link1=network.links[i];
-            const link2=network.links[j];
-            if (edgesIntersect(link1, link2,style,coordAreCenter)){
-                nb++;
-            }
-        }
-    }
-    return nb;
-}
-
-function edgesIntersect(link1: Link, link2: Link,style:GraphStyleProperties,coordAreCenter:boolean=false): boolean {
-
-    // Case of common node
-    if (commonNodeBetween2Links(link1,link2)) {
-        return false;
-    }
-
-    // Get center of node : where the link is attached
-    const node1Center=getCenterNode(link1.source,style,coordAreCenter);
-    const node2Center=getCenterNode(link1.target,style,coordAreCenter);
-    const node3Center=getCenterNode(link2.source,style,coordAreCenter);
-    const node4Center=getCenterNode(link2.target,style,coordAreCenter);
-
-
-    // Check intersection
-    const result = checkIntersection(node1Center.x, node1Center.y, node2Center.x, node2Center.y, node3Center.x, node3Center.y, node4Center.x, node4Center.y);
-    if (result.type == "intersecting") {
-        return true;
-    } else {
-        return false;
-    }
+//             uniqueX.add(roundedX);
+//             uniqueY.add(roundedY);
+//         }
+//     });
+
+//     return { x: uniqueX.size, y: uniqueY.size };
+// }
+
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// //-------------------------------------------------------- Edge Metrics --------------------------------------------------------------//
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+// /////////////////////////////////////////////////////
+// // ------------------------- Edge intersection
+// // (overlap not taken into account)
+
+
+// /**
+//  * Counts how many crossings are in a network
+//  * @param network the network
+//  * @returns the number of crossings
+//  */
+// export function countIntersectionEdgeNetwork(network: Network,style:GraphStyleProperties,coordAreCenter:boolean=false): number {
+//     let nb: number = 0;
+//     for (let i=0 ; i<network.links.length ; i++) {
+//         for (let j=i+1 ; j<network.links.length ; j++) {
+//             const link1=network.links[i];
+//             const link2=network.links[j];
+//             if (edgesIntersect(link1, link2,style,coordAreCenter)){
+//                 nb++;
+//             }
+//         }
+//     }
+//     return nb;
+// }
+
+// function edgesIntersect(link1: Link, link2: Link,style:GraphStyleProperties,coordAreCenter:boolean=false): boolean {
+
+//     // Case of common node
+//     if (commonNodeBetween2Links(link1,link2)) {
+//         return false;
+//     }
+
+//     // Get center of node : where the link is attached
+//     const node1Center=getCenterNode(link1.source,style,coordAreCenter);
+//     const node2Center=getCenterNode(link1.target,style,coordAreCenter);
+//     const node3Center=getCenterNode(link2.source,style,coordAreCenter);
+//     const node4Center=getCenterNode(link2.target,style,coordAreCenter);
+
+
+//     // Check intersection
+//     const result = checkIntersection(node1Center.x, node1Center.y, node2Center.x, node2Center.y, node3Center.x, node3Center.y, node4Center.x, node4Center.y);
+//     if (result.type == "intersecting") {
+//         return true;
+//     } else {
+//         return false;
+//     }
     
-}
+// }
 
-/////////////////////////////////////////////////////
-// ------------------------- Edge length
+// /////////////////////////////////////////////////////
+// // ------------------------- Edge length
 
 
-export function coefficientOfVariationEdgeLength(network: Network,style:GraphStyleProperties,coordAreCenter:boolean=false,includeSideCompounds:boolean=true): number {
+// export function coefficientOfVariationEdgeLength(network: Network,style:GraphStyleProperties,coordAreCenter:boolean=false,includeSideCompounds:boolean=true): number {
 
-    let links = network.links;
+//     let links = network.links;
 
-    if (!includeSideCompounds) {
-        links = links.filter(link => 
-            !(link.source.metadata && link.source.metadata["isSideCompound"]) && 
-            !(link.target.metadata && link.target.metadata["isSideCompound"])
-        );
-    }
+//     if (!includeSideCompounds) {
+//         links = links.filter(link => 
+//             !(link.source.metadata && link.source.metadata["isSideCompound"]) && 
+//             !(link.target.metadata && link.target.metadata["isSideCompound"])
+//         );
+//     }
 
-    if (links.length === 0) {
-        return 0; // Handle case with no edge 
-    }
+//     if (links.length === 0) {
+//         return 0; // Handle case with no edge 
+//     }
 
-    const lengths = links.map(link => edgeLength(link, style, coordAreCenter));
+//     const lengths = links.map(link => edgeLength(link, style, coordAreCenter));
     
-    const mean = lengths.reduce((a, b) => a + b, 0) / lengths.length;
-    if (mean === 0) {
-        return 0; // Handle case with no edge lengths
-    }
-    const variance = lengths.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / lengths.length;
-    const stdDeviation = Math.sqrt(variance);
-    const coefVariation = stdDeviation / Math.abs(mean);
-    return parseFloat(coefVariation.toFixed(3));
-}
-
-function edgeLength(link: Link,style:GraphStyleProperties,coordAreCenter:boolean=false): number {
-    const sourceCenter=getCenterNode(link.source,style,coordAreCenter);
-    const targetCenter=getCenterNode(link.target,style,coordAreCenter);
-
-    const dx = sourceCenter.x - targetCenter.x;
-    const dy = sourceCenter.y - targetCenter.y;
-    return Math.sqrt(dx * dx + dy * dy);
-}
-
-
-
-/////////////////////////////////////////////////////
-// ------------------------- Edge colinear with axis 
-// => function used with edge direction
-
-function calculateNormalizedDirectorVectors(links: Link[], style: GraphStyleProperties, coordAreCenter: boolean = false,includeSideCompounds:boolean=true): Coordinate[] {
-    const vectors: Coordinate[] = [];
-
-    links.forEach(link => {
-        if (includeSideCompounds || !linkOfSideCompound(link)){
-            const normalizedVector = getNormalizedDirectorVector(link, style, coordAreCenter);
-            vectors.push(normalizedVector);
-        }
+//     const mean = lengths.reduce((a, b) => a + b, 0) / lengths.length;
+//     if (mean === 0) {
+//         return 0; // Handle case with no edge lengths
+//     }
+//     const variance = lengths.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / lengths.length;
+//     const stdDeviation = Math.sqrt(variance);
+//     const coefVariation = stdDeviation / Math.abs(mean);
+//     return parseFloat(coefVariation.toFixed(3));
+// }
+
+// function edgeLength(link: Link,style:GraphStyleProperties,coordAreCenter:boolean=false): number {
+//     const sourceCenter=getCenterNode(link.source,style,coordAreCenter);
+//     const targetCenter=getCenterNode(link.target,style,coordAreCenter);
+
+//     const dx = sourceCenter.x - targetCenter.x;
+//     const dy = sourceCenter.y - targetCenter.y;
+//     return Math.sqrt(dx * dx + dy * dy);
+// }
+
+
+
+// /////////////////////////////////////////////////////
+// // ------------------------- Edge colinear with axis 
+// // => function used with edge direction
+
+// function calculateNormalizedDirectorVectors(links: Link[], style: GraphStyleProperties, coordAreCenter: boolean = false,includeSideCompounds:boolean=true): Coordinate[] {
+//     const vectors: Coordinate[] = [];
+
+//     links.forEach(link => {
+//         if (includeSideCompounds || !linkOfSideCompound(link)){
+//             const normalizedVector = getNormalizedDirectorVector(link, style, coordAreCenter);
+//             vectors.push(normalizedVector);
+//         }
        
-    });
+//     });
 
-    return vectors;
-}
+//     return vectors;
+// }
 
-function isColinearAxisNetwork(vector:Coordinate): boolean {
-        return vector.x === 0 || vector.y === 0;
-}
+// function isColinearAxisNetwork(vector:Coordinate): boolean {
+//         return vector.x === 0 || vector.y === 0;
+// }
 
-function countEdgeColinearAxisNetwork(vectors:Coordinate[], pourcentage:boolean=false): number {
+// function countEdgeColinearAxisNetwork(vectors:Coordinate[], pourcentage:boolean=false): number {
 
-    if (vectors.length === 0) {
-        return 0;
-    }
+//     if (vectors.length === 0) {
+//         return 0;
+//     }
 
-    let count = 0;
-    vectors.forEach(vector => {
-        if (isColinearAxisNetwork(vector)) {
-            count += 1;
-        }
-    });
-    if (pourcentage) {
-        return parseFloat((count / vectors.length).toFixed(2));
-    }
-    return count;
-}
+//     let count = 0;
+//     vectors.forEach(vector => {
+//         if (isColinearAxisNetwork(vector)) {
+//             count += 1;
+//         }
+//     });
+//     if (pourcentage) {
+//         return parseFloat((count / vectors.length).toFixed(2));
+//     }
+//     return count;
+// }
 
 
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//-------------------------------------------------------- Domain Metrics --------------------------------------------------------------//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// //-------------------------------------------------------- Domain Metrics --------------------------------------------------------------//
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 
-// WHEN CLEAN : fonction that said if sidecompound or not
+// // WHEN CLEAN : fonction that said if sidecompound or not
 
-/////////////////////////////////////////////////////
-// ------------------------- Edge direction
+// /////////////////////////////////////////////////////
+// // ------------------------- Edge direction
 
-export function analyseDirectorVector(network: Network, style: GraphStyleProperties, coordAreCenter: boolean = false, pourcentageColinearAxis:boolean=false, includeSideCompounds:boolean=true):{colinearAxis:number,coefVariation:number} { 
+// export function analyseDirectorVector(network: Network, style: GraphStyleProperties, coordAreCenter: boolean = false, pourcentageColinearAxis:boolean=false, includeSideCompounds:boolean=true):{colinearAxis:number,coefVariation:number} { 
     
-    const result: { colinearAxis: number, coefVariation: number } = { colinearAxis: undefined, coefVariation: undefined };
+//     const result: { colinearAxis: number, coefVariation: number } = { colinearAxis: undefined, coefVariation: undefined };
 
-    let links = network.links;
+//     let links = network.links;
 
-    if (!includeSideCompounds) {
-        links = links.filter(link => 
-            !(link.source.metadata && link.source.metadata["isSideCompound"]) && 
-            !(link.target.metadata && link.target.metadata["isSideCompound"])
-        );
-    }
+//     if (!includeSideCompounds) {
+//         links = links.filter(link => 
+//             !(link.source.metadata && link.source.metadata["isSideCompound"]) && 
+//             !(link.target.metadata && link.target.metadata["isSideCompound"])
+//         );
+//     }
     
-    // get all normalized director vectors
-    const vectors = calculateNormalizedDirectorVectors(links, style, coordAreCenter,includeSideCompounds);
-    if (vectors.length==0) return { colinearAxis: 0, coefVariation: 0 }
+//     // get all normalized director vectors
+//     const vectors = calculateNormalizedDirectorVectors(links, style, coordAreCenter,includeSideCompounds);
+//     if (vectors.length==0) return { colinearAxis: 0, coefVariation: 0 }
 
-    // count colinear with axis
-    result.colinearAxis = countEdgeColinearAxisNetwork(vectors,pourcentageColinearAxis);
+//     // count colinear with axis
+//     result.colinearAxis = countEdgeColinearAxisNetwork(vectors,pourcentageColinearAxis);
 
-    // coeficient of variation of angle
+//     // coeficient of variation of angle
 
-     // calculate angles of vectors
-     const angles = vectors.map(vector => Math.atan2(vector.y, vector.x));
+//      // calculate angles of vectors
+//      const angles = vectors.map(vector => Math.atan2(vector.y, vector.x));
 
-     // calculate mean of angles
-     const mean = angles.reduce((a, b) => a + b, 0) / angles.length;
-     if (mean === 0) {
-         result.coefVariation = 0; // Handle case with no angles
-         return result;
-     }
+//      // calculate mean of angles
+//      const mean = angles.reduce((a, b) => a + b, 0) / angles.length;
+//      if (mean === 0) {
+//          result.coefVariation = 0; // Handle case with no angles
+//          return result;
+//      }
  
-     // calculate variance of angles
-     const variance = angles.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / angles.length;
+//      // calculate variance of angles
+//      const variance = angles.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / angles.length;
  
-     // calculate standard deviation
-     const stdDeviation = Math.sqrt(variance);
+//      // calculate standard deviation
+//      const stdDeviation = Math.sqrt(variance);
  
-     // calculate coefficient of variation
-     const coefVariation = stdDeviation / mean;
-     result.coefVariation = parseFloat(coefVariation.toFixed(2));
+//      // calculate coefficient of variation
+//      const coefVariation = stdDeviation / mean;
+//      result.coefVariation = parseFloat(coefVariation.toFixed(2));
  
-     return result;
+//      return result;
 
-}
+// }
 
 
diff --git a/src/composables/SBMLtoJSON.ts b/src/composables/SBMLtoJSON.ts
index b57bce0..4a16b9f 100644
--- a/src/composables/SBMLtoJSON.ts
+++ b/src/composables/SBMLtoJSON.ts
@@ -1,160 +1,160 @@
-import { parseString } from 'xml2js';
-import type { JSONGraphFormat, XMLSpecies, XMLReactions } from '../types/JSONGraphFormat';
+// import { parseString } from 'xml2js';
+// import type { JSONGraphFormat, XMLSpecies, XMLReactions } from '../types/JSONGraphFormat';
 
-/**
- * Return a number between min (inclusive) and max (inclusive)
- * @param min 
- * @param max 
- * @returns a number
- */
-function getRandomInt(min: number, max: number): number {
-    min = Math.ceil(min);
-    max = Math.floor(max);
-    return Math.floor(Math.random() * (max - min + 1)) + min;
-}
+// /**
+//  * Return a number between min (inclusive) and max (inclusive)
+//  * @param min 
+//  * @param max 
+//  * @returns a number
+//  */
+// function getRandomInt(min: number, max: number): number {
+//     min = Math.ceil(min);
+//     max = Math.floor(max);
+//     return Math.floor(Math.random() * (max - min + 1)) + min;
+// }
 
-/**
- * Convert an xml graph into a JSON graph format
- * @param sbmlString the xml file as a string
- * @returns the graph as a Promise 
- */
-export async function sbml2json(sbmlString: string): Promise<JSONGraphFormat> {
-    return new Promise((resolve, reject) => {
-        parseString(sbmlString, { explicitArray: false }, (err, result) => {
-            if (err) {
-                console.log("Error during the parsing of the file");
-                console.log(err);
-                reject(err);
-            } else {
-                const model = result.sbml.model;
-                // graph to return
-                const graph: JSONGraphFormat = {
-                    graph: {
-                        id: model.$.id,
-                        type: 'metabolic',
-                        metadata: {
-                            style: {
-                                nodeStyles: {
-                                    metabolite: {
-                                        width: 25,
-                                        height: 25,
-                                        strokeWidth: 1,
-                                        shape: 'circle'
-                                    },
-                                    reaction: {
-                                        width: 15,
-                                        height: 15,
-                                        strokeWidth: 0.5,
-                                        shape: 'rect',
-                                        fill: 'grey'
-                                    },
-                                    reversible: {
-                                        fill: 'green',
-                                        shape: 'inverseTriangle'
-                                    },
-                                    reversibleVersion: {
-                                        fill: 'red',
-                                        shape: 'triangle'
-                                    }
-                                }
-                            }
-                        },
-                        nodes: {},
-                        edges: []
-                    }
-                };
+// /**
+//  * Convert an xml graph into a JSON graph format
+//  * @param sbmlString the xml file as a string
+//  * @returns the graph as a Promise 
+//  */
+// export async function sbml2json(sbmlString: string): Promise<JSONGraphFormat> {
+//     return new Promise((resolve, reject) => {
+//         parseString(sbmlString, { explicitArray: false }, (err, result) => {
+//             if (err) {
+//                 console.log("Error during the parsing of the file");
+//                 console.log(err);
+//                 reject(err);
+//             } else {
+//                 const model = result.sbml.model;
+//                 // graph to return
+//                 const graph: JSONGraphFormat = {
+//                     graph: {
+//                         id: model.$.id,
+//                         type: 'metabolic',
+//                         metadata: {
+//                             style: {
+//                                 nodeStyles: {
+//                                     metabolite: {
+//                                         width: 25,
+//                                         height: 25,
+//                                         strokeWidth: 1,
+//                                         shape: 'circle'
+//                                     },
+//                                     reaction: {
+//                                         width: 15,
+//                                         height: 15,
+//                                         strokeWidth: 0.5,
+//                                         shape: 'rect',
+//                                         fill: 'grey'
+//                                     },
+//                                     reversible: {
+//                                         fill: 'green',
+//                                         shape: 'inverseTriangle'
+//                                     },
+//                                     reversibleVersion: {
+//                                         fill: 'red',
+//                                         shape: 'triangle'
+//                                     }
+//                                 }
+//                             }
+//                         },
+//                         nodes: {},
+//                         edges: []
+//                     }
+//                 };
 
-                // Transform species to nodes
-                const speciesList = model.listOfSpecies.species;
-                // add a metabolite node for each species
-                speciesList.forEach((species: XMLSpecies) => {
-                    graph.graph.nodes[species.$.id] = {
-                        id: species.$.id,
-                        metadata: {
-                            classes: ['metabolite'],
-                            position: {
-                                x: getRandomInt(0, 100),
-                                y: getRandomInt(0, 100)
-                            }
-                        },
-                        label: species.$.name
-                    };
-                });
+//                 // Transform species to nodes
+//                 const speciesList = model.listOfSpecies.species;
+//                 // add a metabolite node for each species
+//                 speciesList.forEach((species: XMLSpecies) => {
+//                     graph.graph.nodes[species.$.id] = {
+//                         id: species.$.id,
+//                         metadata: {
+//                             classes: ['metabolite'],
+//                             position: {
+//                                 x: getRandomInt(0, 100),
+//                                 y: getRandomInt(0, 100)
+//                             }
+//                         },
+//                         label: species.$.name
+//                     };
+//                 });
 
-                // Transform reactions to nodes and edges
-                const reactions = model.listOfReactions.reaction;
-                reactions.forEach((reaction: XMLReactions) => {
-                    const reactionId = reaction.$.id;
+//                 // Transform reactions to nodes and edges
+//                 const reactions = model.listOfReactions.reaction;
+//                 reactions.forEach((reaction: XMLReactions) => {
+//                     const reactionId = reaction.$.id;
                     
-                    let classReversible :string;
-                    const isReversible=reaction.$.reversible;
-                    if (isReversible==="true"){
-                        classReversible = "reversible";
-                    }else{
-                        classReversible = "irreversible";
-                    }
+//                     let classReversible :string;
+//                     const isReversible=reaction.$.reversible;
+//                     if (isReversible==="true"){
+//                         classReversible = "reversible";
+//                     }else{
+//                         classReversible = "irreversible";
+//                     }
 
-                    // get the reactants and products for every reaction
-                    const reactants: string[] = [];
-                    if (reaction.listOfReactants.speciesReference != undefined && (reaction.listOfReactants.speciesReference as Partial<XMLSpecies>[]).length != undefined) {
-                        // type : array
-                        (reaction.listOfReactants.speciesReference as Partial<XMLSpecies>[]).forEach((ref: Partial<XMLSpecies>) => {
-                            reactants.push(ref.$.species);
-                        });
-                    } else if (reaction.listOfReactants.speciesReference != undefined) {
-                        // type : object
-                        reactants.push((reaction.listOfReactants.speciesReference as Partial<XMLSpecies>).$.species);
-                    }
-                    const products: string[] = [];
-                    if (reaction.listOfProducts.speciesReference != undefined && (reaction.listOfProducts.speciesReference as Partial<XMLSpecies>[]).length != undefined) {
-                        // type : array
-                        (reaction.listOfProducts.speciesReference as Partial<XMLSpecies>[]).forEach((ref: Partial<XMLSpecies>) => {
-                            products.push(ref.$.species);
-                        });
-                    } else if (reaction.listOfProducts.speciesReference != undefined) {
-                        // type : object
-                        products.push((reaction.listOfProducts.speciesReference as Partial<XMLSpecies>).$.species);
-                    }
+//                     // get the reactants and products for every reaction
+//                     const reactants: string[] = [];
+//                     if (reaction.listOfReactants.speciesReference != undefined && (reaction.listOfReactants.speciesReference as Partial<XMLSpecies>[]).length != undefined) {
+//                         // type : array
+//                         (reaction.listOfReactants.speciesReference as Partial<XMLSpecies>[]).forEach((ref: Partial<XMLSpecies>) => {
+//                             reactants.push(ref.$.species);
+//                         });
+//                     } else if (reaction.listOfReactants.speciesReference != undefined) {
+//                         // type : object
+//                         reactants.push((reaction.listOfReactants.speciesReference as Partial<XMLSpecies>).$.species);
+//                     }
+//                     const products: string[] = [];
+//                     if (reaction.listOfProducts.speciesReference != undefined && (reaction.listOfProducts.speciesReference as Partial<XMLSpecies>[]).length != undefined) {
+//                         // type : array
+//                         (reaction.listOfProducts.speciesReference as Partial<XMLSpecies>[]).forEach((ref: Partial<XMLSpecies>) => {
+//                             products.push(ref.$.species);
+//                         });
+//                     } else if (reaction.listOfProducts.speciesReference != undefined) {
+//                         // type : object
+//                         products.push((reaction.listOfProducts.speciesReference as Partial<XMLSpecies>).$.species);
+//                     }
 
-                    // add the reaction as a node
-                    graph.graph.nodes[reactionId] = {
-                        id: reactionId,
-                        metadata: {
-                            classes: ['reaction',classReversible],
-                            position: {
-                                x: getRandomInt(0, 100),
-                                y: getRandomInt(0, 100)
-                            }
-                        },
-                        label: reaction.$.name
-                    };
+//                     // add the reaction as a node
+//                     graph.graph.nodes[reactionId] = {
+//                         id: reactionId,
+//                         metadata: {
+//                             classes: ['reaction',classReversible],
+//                             position: {
+//                                 x: getRandomInt(0, 100),
+//                                 y: getRandomInt(0, 100)
+//                             }
+//                         },
+//                         label: reaction.$.name
+//                     };
 
-                    // add the edges for the reaction and its reactants and products
-                    reactants.forEach((reactant: string) => {
-                        graph.graph.edges.push({
-                            id: `${reactant}--${reactionId}`,
-                            source: reactant,
-                            target: reactionId,
-                            metadata: {
-                                classes: [classReversible]
-                            }
-                        });
-                    });
-                    products.forEach((product: string) => {
-                        graph.graph.edges.push({
-                            id: `${reactionId}--${product}`,
-                            source: reactionId,
-                            target: product,
-                            metadata: {
-                                classes: [classReversible]
-                            }
-                        });
-                    });
-                });
+//                     // add the edges for the reaction and its reactants and products
+//                     reactants.forEach((reactant: string) => {
+//                         graph.graph.edges.push({
+//                             id: `${reactant}--${reactionId}`,
+//                             source: reactant,
+//                             target: reactionId,
+//                             metadata: {
+//                                 classes: [classReversible]
+//                             }
+//                         });
+//                     });
+//                     products.forEach((product: string) => {
+//                         graph.graph.edges.push({
+//                             id: `${reactionId}--${product}`,
+//                             source: reactionId,
+//                             target: product,
+//                             metadata: {
+//                                 classes: [classReversible]
+//                             }
+//                         });
+//                     });
+//                 });
 
-                // return the graph object
-                resolve(graph);
-            }
-        });
-    });
-}
+//                 // return the graph object
+//                 resolve(graph);
+//             }
+//         });
+//     });
+// }
diff --git a/src/composables/UseSubgraphNetwork.ts b/src/composables/SubgraphForSubgraphNetwork.ts
similarity index 52%
rename from src/composables/UseSubgraphNetwork.ts
rename to src/composables/SubgraphForSubgraphNetwork.ts
index df5097c..1ad6b23 100644
--- a/src/composables/UseSubgraphNetwork.ts
+++ b/src/composables/SubgraphForSubgraphNetwork.ts
@@ -1,8 +1,26 @@
+// Type imports
 import { NetworkLayout } from "../types/NetworkLayout";
 import { Subgraph, TypeSubgraph } from "../types/Subgraph";
 import { SubgraphNetwork } from "../types/SubgraphNetwork";
-import { Network } from "@metabohub/viz-core/src/types/Network";
-import { Node } from "@metabohub/viz-core/src/types/Node";
+
+
+/**
+ * This file contains functions to manage subgraphs in a subgraphNetwork.
+ * 
+ * -> createSubgraph :
+ *      creates a new subgraph with the specified properties.
+ * 
+ * -> addSubgraphToNetwork :
+ *      adds a subgraph to the subgraph network.
+ * 
+ * -> updateNodeMetadataSubgraph :
+ *      updates the metadata of a node in the network by adding a subgraph ID to its list of subgraph.
+ * 
+ * -> updateParentSubgraphOf :
+ *       updates the parent of a subgraph by adding the subgraph to its list of child subgraph.
+ */
+
+
 
 
 /**
@@ -23,7 +41,15 @@ export function createSubgraph(name: string, nodes: Array<string>, classes: Arra
     };
 }
 
-export function addNewSubgraph(subgraphNetwork:SubgraphNetwork,subgraph:Subgraph,type:TypeSubgraph=TypeSubgraph.MAIN_CHAIN): SubgraphNetwork {
+/**
+ * Adds a subgraph to the subgraph network.
+ * 
+ * @param subgraphNetwork - The subgraph network to add the subgraph to.
+ * @param subgraph - The subgraph to add.
+ * @param type - The type of the subgraph. Defaults to TypeSubgraph.MAIN_CHAIN.
+ * @returns The updated subgraph network.
+ */
+export function addSubgraphToNetwork(subgraphNetwork:SubgraphNetwork,subgraph:Subgraph,type:TypeSubgraph=TypeSubgraph.MAIN_CHAIN): SubgraphNetwork {
     if (!subgraphNetwork[type]) subgraphNetwork[type]={};
     if(!(subgraph.name in subgraphNetwork[type])){
         // adding subgraph to subgraphNetwork
@@ -37,97 +63,12 @@ export function addNewSubgraph(subgraphNetwork:SubgraphNetwork,subgraph:Subgraph
           subgraphNetwork=updateParentSubgraphOf(subgraphNetwork,subgraph);
         }
     }else{
-        console.error("subgraph already in subgraphNetwork : "+subgraph.name);
+        throw new Error("subgraph already in subgraphNetwork : "+subgraph.name);
     }
     return subgraphNetwork;
     
 }
 
-export function updateParentSubgraphOf(subgraphNetwork:SubgraphNetwork,subgraph:Subgraph):SubgraphNetwork{
-    if (subgraph.parentSubgraph){
-        const nameParent=subgraph.parentSubgraph.name;
-        const typeParent=subgraph.parentSubgraph.type;
-        if (nameParent in subgraphNetwork[typeParent]){
-            if (!subgraphNetwork[typeParent][nameParent].childrenSubgraphs){
-                subgraphNetwork[typeParent][nameParent].childrenSubgraphs=[];
-            }
-            subgraphNetwork[typeParent][nameParent].childrenSubgraphs.push({name:subgraph.name,type:subgraph.type});
-        }else{
-            console.error("parent subgraph not in subgraphNetwork");
-        }
-    }
-    return subgraphNetwork;
-}
-
-/**
- * Adds a class to the cluster if it doesn't already exist.
- * @param subgraph The cluster to which the class will be added.
- * @param newClass The class to be added.
- * @returns The updated cluster.
- */
-export function addClassSubgraph(subgraph: Subgraph, newClass: string): Subgraph {
-    if (subgraph.classes && !subgraph.classes.includes(newClass)) {
-        subgraph.classes.push(newClass);
-    }
-    return subgraph;
-}
-
-/**
- * Removes a node from the cluster.
- * @param subgraph The cluster from which the node will be removed.
- * @param name The name of the node to be removed.
- * @returns The updated cluster.
- */
-export function removeNodeSubgraph(subgraph: Subgraph, name: string): Subgraph {
-    const index = subgraph.nodes.indexOf(name);
-    if (index !== -1) {
-        subgraph.nodes.splice(index, 1);
-    }
-    return subgraph;
-}
-
-/**
- * Removes a class from the cluster.
- * @param subgraph The cluster from which the class will be removed.
- * @param className The name of the class to be removed.
- * @returns The updated cluster.
- */
-export function removeClassSubgraph(subgraph: Subgraph, className: string): Subgraph {
-    if (subgraph.classes) {
-        const index = subgraph.classes.indexOf(className);
-        if (index !== -1) {
-            subgraph.classes.splice(index, 1);
-        }
-    }
-    return subgraph;
-}
-
-
-/**
- * Adds a node to a subgraph in the subgraph network, and update the metadata of the node (name of the subgraph to wich it belongs)
- * 
- * @param subgraphNetwork - The subgraph network object.
- * @param subgraphID - The ID of the subgraph.
- * @param nodeID - The ID of the node to be added.
- * @param subgraphType - The type of the subgraph (defaults to MAIN_CHAIN).
- * @returns The updated subgraph network object.
- */
-export function addNodeToSubgraph(subgraphNetwork:SubgraphNetwork,subgraphID:string,nodeID:string,subgraphType: TypeSubgraph = TypeSubgraph.MAIN_CHAIN):SubgraphNetwork{
-    const network=subgraphNetwork.network.value;
-
-    if (subgraphID in subgraphNetwork[subgraphType]){
-        // if node not already in subgraph :
-        if (!subgraphNetwork[subgraphType][subgraphID].nodes.includes(nodeID)){
-            // add to subgraph
-            subgraphNetwork[subgraphType][subgraphID].nodes.push(nodeID);
-            // update metadata of node
-            updateNodeMetadataSubgraph(network, nodeID, subgraphID,subgraphType);
-        }
-    }else{
-        console.error("subgraph not in subgraphNetwork");
-    }
-    return subgraphNetwork;
-}
 
 /**
  * Updates the metadata of a node in the network by adding a subgraph ID to its list of subgraph.
@@ -146,15 +87,38 @@ export function updateNodeMetadataSubgraph(networkLayout: NetworkLayout, nodeID:
   // if subgraphType is CYCLEGROUP, add the subgraphID to the metadataLayout directly
   if (subgraphType == TypeSubgraph.CYCLEGROUP){
     networkLayout.nodes[nodeID].metadataLayout[subgraphType]=subgraphID;
-    return;
+
   } else {
     // if subgraphType is not CYCLEGROUP, add the subgraphID to the metadataLayout[subgraphType] array
+    let listSubgraphOfNode: Array<string>;
     if (!(subgraphType in networkLayout.nodes[nodeID].metadataLayout)){
         networkLayout.nodes[nodeID].metadataLayout[subgraphType]=[];
     }
-    const listSubgraphOfNode=networkLayout.nodes[nodeID].metadataLayout[subgraphType];
+    listSubgraphOfNode=networkLayout.nodes[nodeID].metadataLayout[subgraphType] as Array<string>;
     if (!listSubgraphOfNode.includes(subgraphID)){ 
         listSubgraphOfNode.push(subgraphID);
     }
   }
-}
\ No newline at end of file
+}
+
+/**
+ * Updates the parent of a subgraph by adding the subgraph to its list of child subgraph.
+ * @param subgraphNetwork 
+ * @param subgraph 
+ * @returns subgraphNetwork updated
+ */
+export function updateParentSubgraphOf(subgraphNetwork:SubgraphNetwork,subgraph:Subgraph):SubgraphNetwork{
+    if (subgraph.parentSubgraph){
+        const nameParent=subgraph.parentSubgraph.name;
+        const typeParent=subgraph.parentSubgraph.type;
+        if (subgraphNetwork[typeParent] && nameParent in subgraphNetwork[typeParent]){
+            if (!subgraphNetwork[typeParent][nameParent].childrenSubgraphs){
+                subgraphNetwork[typeParent][nameParent].childrenSubgraphs=[];
+            }
+            subgraphNetwork[typeParent][nameParent].childrenSubgraphs.push({name:subgraph.name,type:subgraph.type as TypeSubgraph});
+        }else{
+           throw new Error("parent subgraph not in subgraphNetwork");
+        }
+    }
+    return subgraphNetwork;
+}
diff --git a/src/composables/SubgraphForViz.ts b/src/composables/SubgraphForViz.ts
new file mode 100644
index 0000000..797ccd5
--- /dev/null
+++ b/src/composables/SubgraphForViz.ts
@@ -0,0 +1,128 @@
+// Type imports
+import {  TypeSubgraph } from "../types/Subgraph";
+import { SubgraphNetwork } from "../types/SubgraphNetwork";
+
+// General imports
+import { Graph } from "@viz-js/viz";
+
+/**
+ * This file contains functions to manage subgraphs for viz graph.
+ * 
+ * -> addMainChainForViz :
+ *      Adds a main chain to the viz graph.
+ * 
+ * -> changeCycleMetanodes :
+ *      Changes list of nodes to replace nodes in cycle by the metanode.
+ * 
+ * -> subgraphDot :
+ *      Create a subgraph dot representation for viz.
+ */
+
+
+/**
+ * Adds a main chain to the viz graph.
+ * 
+ * @param vizGraph - The viz graph to add the main chain to.
+ * @param nameMainChain - The name of the main chain.
+ * @param subgraphNetwork - The subgraph network containing the main chain.
+ * @param cycle - Optional. Specifies whether to apply cycle changes to the nodes. Defaults to true.
+ * @param isCluster - Optional. Specifies whether the main chain should be treated as a cluster. Defaults to true.
+ * @returns The updated visualization graph.
+ * @throws Error if the main chain is not found in the subgraph network.
+ */
+export function addMainChainForViz(vizGraph: Graph, nameMainChain: string, subgraphNetwork:SubgraphNetwork,cycle:boolean=true,isCluster:boolean=true): Graph {
+    if ( !subgraphNetwork[TypeSubgraph.MAIN_CHAIN] || !subgraphNetwork[TypeSubgraph.MAIN_CHAIN][nameMainChain])  throw new Error("Main chain not found in subgraphNetwork");
+
+    // get values from cluster and change nodes format : new cluster format (for viz)
+    let { name, nodes ,childrenSubgraphs} = subgraphNetwork[TypeSubgraph.MAIN_CHAIN][nameMainChain];
+
+    if(cycle) {
+        nodes=changeCycleMetanodes(subgraphNetwork,nodes);
+    }
+
+    // change format
+    if (isCluster && !name.startsWith("cluster_")) {
+        name = "cluster_" + name;
+    }
+    const clusterViz: SubgraphViz = {
+        name: name,
+        nodes: nodes?.map((name: string) => ({ name:name })) || []
+    };
+
+    //add node of children subgraph           !!!!!BEWARE : only one level of children!!!!
+        if (childrenSubgraphs){
+            childrenSubgraphs.forEach(subgraph => {
+                const subgraphs=subgraphNetwork[subgraph.type];
+                if (subgraphs && subgraphs[subgraph.name]){
+                    let nodeToAdd =subgraphs[subgraph.name].nodes;
+                    if(cycle){
+                        nodeToAdd=changeCycleMetanodes(subgraphNetwork,nodeToAdd);
+                    }
+                    if (!clusterViz.nodes) clusterViz.nodes = [];
+                    clusterViz.nodes.push(...nodeToAdd.map((name: string) => ({ name:name })));   // add and change format    
+                }
+            });
+        }
+    
+
+    // push cluster for viz
+    if (!vizGraph.subgraphs) {
+        vizGraph.subgraphs = [];
+    }
+    vizGraph.subgraphs.push(clusterViz);
+
+    return vizGraph;
+}
+
+
+/**
+ * Changes list of nodes to replace nodes in cycle by the metanode.
+ * 
+ * @param subgraphNetwork - The subgraph network.
+ * @param listNodeBefore - The list of nodes before the change.
+ * @returns The list of nodes after the change.
+ * @throws {Error} If a node is not found in the network.
+ */
+function changeCycleMetanodes(subgraphNetwork:SubgraphNetwork,listNodeBefore:string[]):string[]{
+    const network=subgraphNetwork.network.value;
+    const listNodeAfter:string[]=[];
+    // for each nodes :
+    listNodeBefore.forEach(node =>{
+        // if node is in cycle metanode :
+        if (!(node in network.nodes)) throw new Error("Node not found in network");
+
+        let cycle:string;
+        if (network.nodes[node].metadataLayout && network.nodes[node].metadataLayout[TypeSubgraph.CYCLEGROUP]){
+            cycle = network.nodes[node].metadataLayout[TypeSubgraph.CYCLEGROUP]; 
+            //cycle=inBiggerCycle(cycle,subgraphNetwork)
+            if(!(listNodeAfter.includes(cycle))){
+                // push node cycle
+                listNodeAfter.push(cycle);
+            } 
+        }else{
+            listNodeAfter.push(node);
+        }
+    });
+    return listNodeAfter;
+}
+
+/**
+ * Create a subgraph dot representation for viz.
+ * 
+ * @param subgraph - The subgraph to add the dot representation for.
+ * @returns The dot representation of the subgraph.
+ * @throws {Error} If there are no nodes in the subgraph.
+ */
+export function subgraphDot(subgraph: SubgraphViz): string {
+
+    if (subgraph.nodes) {
+        let clusterString = `subgraph ${subgraph.name} {\n`;
+        subgraph.nodes.forEach((node) => {
+            clusterString+=`${node.name};`;
+        });
+        return clusterString+"}\n";
+    }else{
+        throw new Error("No nodes in subgraph");
+    }
+    
+  }
\ No newline at end of file
diff --git a/src/composables/countIsolatedNodes.ts b/src/composables/countIsolatedNodes.ts
deleted file mode 100644
index e6aec4e..0000000
--- a/src/composables/countIsolatedNodes.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { Network } from "@metabohub/viz-core/src/types/Network";
-
-/**
- * Count how many nodes have no edges in the network 
- * @param network the network
- * @returns the number of isolated nodes
- */
-export function countIsolatedNodes(network: Network): number {
-    let nb: number = 0;
-    const nodesCount: { [x: string]: number} = {};
-    Object.keys(network.nodes).forEach(nodeId => {
-        nodesCount[nodeId] = 0;
-    });
-
-    // count number of links for each node
-    network.links.forEach(link => {
-        nodesCount[link.source.id] += 1;
-        nodesCount[link.target.id] += 1;
-    });
-
-    /*
-    // get the nodes
-    for (const [key, value] of Object.entries(nodesCount)) {
-        ...  
-        // if value == 0
-        // get key
-    }
-    */
-    Object.values(nodesCount).forEach(count => {
-        if (count == 0) {
-            nb += 1;
-        }
-    });
-
-    return nb;
-}
\ No newline at end of file
diff --git a/src/composables/importNetwork.ts b/src/composables/importNetwork.ts
index 528dee0..ec7117c 100644
--- a/src/composables/importNetwork.ts
+++ b/src/composables/importNetwork.ts
@@ -1,93 +1,93 @@
-import type { Ref } from "vue";
-import type { Network } from "@metabohub/viz-core/src/types/Network";
-import type { GraphStyleProperties } from "@metabohub/viz-core/src//types/GraphStyleProperties";
+// import type { Ref } from "vue";
+// import type { Network } from "@metabohub/viz-core/src/types/Network";
+// import type { GraphStyleProperties } from "@metabohub/viz-core/src//types/GraphStyleProperties";
 
-//import { readJsonGraph } from "./readJson";
-import { readJsonGraph } from "@metabohub/viz-core";
-import { sbml2json } from "./SBMLtoJSON";
+// //import { readJsonGraph } from "./readJson";
+// import { readJsonGraph } from "@metabohub/viz-core";
+// import { sbml2json } from "./SBMLtoJSON";
 
 
 
-/**
- * Import network at JSONGraph format from an URL.
- * @param url URL to get network data
- * @param network Reference to network object
- * @param networkStyle Reference to networkStyle object
- * @param callbackFunction Function to call after network load (opt)
- */
-export function importNetworkFromURL(url: string, network: Ref<Network>, networkStyle: Ref<GraphStyleProperties>, callbackFunction = () => {}): void {
-	setTimeout(async function() {
-		let data:string = await getContentFromURL(url);
-		// Check if the data is XML
-		if (data.startsWith('<?xml')) {
-			// Convert XML to JSON
-			data = JSON.stringify(await sbml2json(data));
-		}
-		const graphData = readJsonGraph(data);
-		networkStyle.value = graphData.networkStyle;
-		loadNetwork(graphData.network, network).then(() => {
-      callbackFunction();
-		});
-	}, 1);
-}
+// /**
+//  * Import network at JSONGraph format from an URL.
+//  * @param url URL to get network data
+//  * @param network Reference to network object
+//  * @param networkStyle Reference to networkStyle object
+//  * @param callbackFunction Function to call after network load (opt)
+//  */
+// export function importNetworkFromURL(url: string, network: Ref<Network>, networkStyle: Ref<GraphStyleProperties>, callbackFunction = () => {}): void {
+// 	setTimeout(async function() {
+// 		let data:string = await getContentFromURL(url);
+// 		// Check if the data is XML
+// 		if (data.startsWith('<?xml')) {
+// 			// Convert XML to JSON
+// 			data = JSON.stringify(await sbml2json(data));
+// 		}
+// 		const graphData = readJsonGraph(data);
+// 		networkStyle.value = graphData.networkStyle;
+// 		loadNetwork(graphData.network, network).then(() => {
+//       callbackFunction();
+// 		});
+// 	}, 1);
+// }
 
 
-/**
- * Import network at JSONGraph format from a file.
- * @param file File to get network data
- * @param network Reference to network object
- * @param networkStyle Reference to networkStyle object
- * @param callbackFunction Function to call after network load (opt)
- */
+// /**
+//  * Import network at JSONGraph format from a file.
+//  * @param file File to get network data
+//  * @param network Reference to network object
+//  * @param networkStyle Reference to networkStyle object
+//  * @param callbackFunction Function to call after network load (opt)
+//  */
 
-export function importNetworkFromFile(file: File, network: Ref<Network>, networkStyle: Ref<GraphStyleProperties>, callbackFunction = () => {}): void {
-	const reader = new FileReader();
-	reader.onload = async function () {
-		let data = reader.result as string;
-		if (data.startsWith('<?xml')) {
-			// Convert XML to JSON
-			data = JSON.stringify(await sbml2json(data));
-		}
-		const networkData = readJsonGraph(data);
-		networkStyle.value = networkData.networkStyle;
-    loadNetwork(networkData.network, network).then(() => {
-			callbackFunction();
-		});
-	}
+// export function importNetworkFromFile(file: File, network: Ref<Network>, networkStyle: Ref<GraphStyleProperties>, callbackFunction = () => {}): void {
+// 	const reader = new FileReader();
+// 	reader.onload = async function () {
+// 		let data = reader.result as string;
+// 		if (data.startsWith('<?xml')) {
+// 			// Convert XML to JSON
+// 			data = JSON.stringify(await sbml2json(data));
+// 		}
+// 		const networkData = readJsonGraph(data);
+// 		networkStyle.value = networkData.networkStyle;
+//     loadNetwork(networkData.network, network).then(() => {
+// 			callbackFunction();
+// 		});
+// 	}
 
-	reader.readAsText(file);
-}
+// 	reader.readAsText(file);
+// }
 
 
-/**
- * Make async the step where the data are put in network reference. 
- * That permit to chain with another function like rescale.
- * @param data network data
- * @param network Reference to network object
- */
-async function loadNetwork(data: Network, network: Ref<Network>): Promise<void> {
-	network.value = data;
-  }
+// /**
+//  * Make async the step where the data are put in network reference. 
+//  * That permit to chain with another function like rescale.
+//  * @param data network data
+//  * @param network Reference to network object
+//  */
+// async function loadNetwork(data: Network, network: Ref<Network>): Promise<void> {
+// 	network.value = data;
+//   }
 
 
-/**
- * Fetch url to return data
- * @param url URL to fetch 
- * @returns Return response
- */
-export async function getContentFromURL(url: string): Promise<string> {
-	try {
-	  const response = await fetch(url);
-	  if (!response.ok) {
-		throw new Error('La requête a échoué avec le statut ' + response.status);
-	  }
-	  const content = await response.text();
-	  return content;
-	} catch (error) {
-	  console.error('Une erreur s\'est produite lors de la récupération du contenu du fichier :', error);
-	  throw error;
-	}
-  }
+// /**
+//  * Fetch url to return data
+//  * @param url URL to fetch 
+//  * @returns Return response
+//  */
+// export async function getContentFromURL(url: string): Promise<string> {
+// 	try {
+// 	  const response = await fetch(url);
+// 	  if (!response.ok) {
+// 		throw new Error('La requête a échoué avec le statut ' + response.status);
+// 	  }
+// 	  const content = await response.text();
+// 	  return content;
+// 	} catch (error) {
+// 	  console.error('Une erreur s\'est produite lors de la récupération du contenu du fichier :', error);
+// 	  throw error;
+// 	}
+//   }
   
   
 
diff --git a/src/composables/useSubgraphs.ts b/src/composables/useSubgraphs.ts
deleted file mode 100644
index 1e7a7d8..0000000
--- a/src/composables/useSubgraphs.ts
+++ /dev/null
@@ -1,207 +0,0 @@
-import { Subgraph, TypeSubgraph } from "../types/Subgraph";
-import { SubgraphNetwork } from "../types/SubgraphNetwork";
-import { Graph } from "@viz-js/viz";
-//import { inBiggerCycle } from "./ConvertFromNetwork";
-
-/**
- * 
- */
-export function addMainChainClusterViz(vizGraph: Graph, nameMainChain: string, subgraphNetwork:SubgraphNetwork,cycle:boolean=true,isCluster:boolean=true): Graph {
-
-    // get values from cluster and change nodes format : new cluster format (for viz)
-    let { name, nodes ,childrenSubgraphs: associatedSubgraphs} = subgraphNetwork.mainChains[nameMainChain];
-    if(cycle) {
-        nodes=changeCycleMetanodes(subgraphNetwork,nodes);
-    }
-
-    // change format
-    if (isCluster && !name.startsWith("cluster_")) {
-        name = "cluster_" + name;
-    }
-    const clusterViz: SubgraphViz = {
-        name: name,
-        nodes: nodes?.map((name: string) => ({ name:name })) || []
-    };
-
-    //add node of children subgraph           !!!!!BEWARE : only one level of children!!!!
-        if (associatedSubgraphs){
-            associatedSubgraphs.forEach(subgraph => {
-                let nodeToAdd =subgraphNetwork[subgraph.type][subgraph.name].nodes;
-                if(cycle){
-                    nodeToAdd=changeCycleMetanodes(subgraphNetwork,nodeToAdd);
-                }
-                clusterViz.nodes.push(...nodeToAdd.map((name: string) => ({ name:name })));   // add and change format    
-            });
-        }
-    
-
-    // push cluster for viz
-    if (!Object.keys(vizGraph).includes("subgraphs")) {
-        vizGraph.subgraphs = [];
-    }
-    vizGraph.subgraphs.push(clusterViz);
-
-    return vizGraph;
-}
-
-function changeCycleMetanodes(subgraphNetwork:SubgraphNetwork,listNodeBefore:string[]):string[]{
-    const network=subgraphNetwork.network.value;
-    const listNodeAfter:string[]=[];
-    // for each nodes :
-    listNodeBefore.forEach(node =>{
-        // if node is in cycle metanode :
-        let cycle:string;
-        if (network.nodes[node].metadata && network.nodes[node].metadata[TypeSubgraph.CYCLEGROUP]){
-            cycle = network.nodes[node].metadata[TypeSubgraph.CYCLEGROUP] as string; 
-            //cycle=inBiggerCycle(cycle,subgraphNetwork)
-        }
-        if(cycle!==undefined && !(listNodeAfter.includes(cycle))){
-            // push node cycle
-            listNodeAfter.push(cycle);
-        } 
-        if (cycle===undefined){
-            listNodeAfter.push(node);
-        }
-    })
-
-    return listNodeAfter;
-}
-
-export function addClusterDot(subgraph: SubgraphViz): string {
-
-
-    let clusterString = `subgraph ${subgraph.name} {\n`;
-    // add rank
-    // if ("rank" in subgraph){
-    //     clusterString+=`{rank="${subgraph.rank}";`;
-    // }
-
-    // add nodes
-    subgraph.nodes.forEach((node) => {
-        clusterString+=`${node.name};`;
-    });
-    // if ("rank" in subgraph){
-    //     clusterString+=`}\n`;
-    // }
-    return clusterString+"}\n";
-  }
-  
-
-
-
-// export function addNoConstraint(subgraphNetwork:SubgraphNetwork):SubgraphNetwork{
-//   let network=subgraphNetwork.network.value;
-//   network.links.forEach(link=>{
-//       let clusterSource: string[] = [];
-//       let clusterTarget: string[] = [];
-//       if ( Object.keys(link.source).includes("metadata") && Object.keys(link.source.metadata).includes("clusters")){
-//           clusterSource= link.source.metadata?.clusters ? link.source.metadata.clusters as string[] : [];
-//       }
-
-//       if ( Object.keys(link.target).includes("metadata") && Object.keys(link.target.metadata).includes("clusters")){
-//           clusterTarget= link.target.metadata?.clusters ? link.target.metadata.clusters as string[] : [];
-//       }        
-//       let sameClusters=true;
-//       // if same number of cluster : let's check if there are the same
-//       if (clusterTarget.length===clusterSource.length){
-//           clusterTarget.sort;
-//           clusterSource.sort;
-//           for (let i = 0; i < clusterTarget.length; ++i) {
-//               if (clusterTarget[i] !== clusterSource[i]){
-//                   sameClusters=false;
-//               }
-//           }
-//       }else{
-//           // if not the same number of cluster : the two nodes can't be in the exact same clusters
-//           sameClusters=false;
-//       }
-
-//       if (!sameClusters){
-//           if(!link.metadata){
-//               link.metadata={};
-//           }
-//           link.metadata["constraint"]=false;
-//       }
-//   });
-
-//   return subgraphNetwork;
-// }
-
-// export function addBoldLinkMainChain(subgraphNetwork:SubgraphNetwork):SubgraphNetwork{
-//     let network=subgraphNetwork.network.value;
-//     network.links.forEach(link=>{
-//         let mainChainSource: string[] = [];
-//         let mainChainTarget: string[] = [];
-//         if ( Object.keys(link.source).includes("metadata") && Object.keys(link.source.metadata).includes(TypeSubgraph.MAIN_CHAIN)){
-//             mainChainSource=  link.source.metadata.mainChains as string[];
-//         }
-  
-//         if ( Object.keys(link.target).includes("metadata") && Object.keys(link.target.metadata).includes(TypeSubgraph.MAIN_CHAIN)){
-//             mainChainTarget=  link.target.metadata.mainChains as string[];
-//         }        
-//         // let sameClusters=true;
-//         // // if same number of cluster, and in a cluster: let's check if there are the same
-//         // if (clusterTarget.length===clusterSource.length && clusterSource.length!==0){
-//         //     clusterTarget.sort;
-//         //     clusterSource.sort;
-//         //     for (let i = 0; i < clusterTarget.length; ++i) {
-//         //         if (clusterTarget[i] !== clusterSource[i]){
-//         //             sameClusters=false;
-//         //         }
-//         //     }
-//         // }else{
-//         //     // if not the same number of cluster : the two nodes can't be in the exact same clusters
-//         //     sameClusters=false;
-//         // }
-
-//         // Check if there is at least one common cluster
-//         let commonMainChain = mainChainSource.some(mainchain => mainChainTarget.includes(mainchain));
-
-//         if (commonMainChain){ 
-//             if(!link.classes){
-//                 link.classes=[];
-//             }
-//             if (!(link.classes.includes(TypeSubgraph.MAIN_CHAIN))){
-//                 link.classes.push(TypeSubgraph.MAIN_CHAIN);
-//             }
-//         }else{
-//             if(link.classes){
-//                 link.classes = link.classes.filter((c) => c !== TypeSubgraph.MAIN_CHAIN);
-//             }
-//         }
-//     });
-  
-//     return subgraphNetwork;
-//   }
-
-
-
-//   export function addRedLinkcycleGroup(subgraphNetwork:SubgraphNetwork):SubgraphNetwork{
-//     let network=subgraphNetwork.network.value;
-//     network.links.forEach(link=>{
-//         let cycleSource: string;
-//         let cycleTarget: string;
-//         if ( Object.keys(link.source).includes("metadata") && Object.keys(link.source.metadata).includes(TypeSubgraph.CYCLEGROUP)){
-//             cycleSource=link.source.metadata[TypeSubgraph.CYCLEGROUP]  as string;
-//         }
-  
-//         if ( Object.keys(link.target).includes("metadata") && Object.keys(link.target.metadata).includes(TypeSubgraph.CYCLEGROUP)){
-//             cycleTarget= link.target.metadata[TypeSubgraph.CYCLEGROUP] as string;
-//         }       
-//         if (cycleSource && cycleSource===cycleTarget){ 
-//             if(!link.classes){
-//                 link.classes=[];
-//             }
-//             if (!(link.classes.includes(TypeSubgraph.CYCLEGROUP))){
-//                 link.classes.push(TypeSubgraph.CYCLEGROUP);
-//             }
-//         }else{
-//             if(link.classes){
-//                 link.classes = link.classes.filter((c) => c !== TypeSubgraph.CYCLEGROUP);
-//             }
-//         }
-//     });
-  
-//     return subgraphNetwork;
-//   }
-  
-- 
GitLab


From 0515b67018f76c8d42c10419cd181ebf27b143c2 Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Thu, 12 Sep 2024 16:11:49 +0200
Subject: [PATCH 11/13] debut calculate startnode test

---
 src/composables/CalculateStartNodes.ts        |   4 +-
 .../__tests__/CalculateStartNodes.tests.ts    | 247 +++++++++++++-----
 2 files changed, 187 insertions(+), 64 deletions(-)

diff --git a/src/composables/CalculateStartNodes.ts b/src/composables/CalculateStartNodes.ts
index bc9a4e4..c56a1f8 100644
--- a/src/composables/CalculateStartNodes.ts
+++ b/src/composables/CalculateStartNodes.ts
@@ -54,8 +54,8 @@ export function assignRankOrder(network: NetworkLayout, unique_y: Array<number>,
     const xNodeByRank: number[][] = Array.from({ length: unique_y.length }, () => []);
     Object.values(network.nodes).forEach((node) => {
         const rank = unique_y.indexOf(node.y);
-        if (!node.metadataLayout) node.metadataLayout={}; 
         if(rank >-1){
+            if (!node.metadataLayout) node.metadataLayout={}; 
             node.metadataLayout.rank = rank;
             if (!onlyRank){
                 xNodeByRank[rank].push(node.x);
@@ -72,7 +72,7 @@ export function assignRankOrder(network: NetworkLayout, unique_y: Array<number>,
 
     // get the order for each node 
     Object.values(network.nodes).forEach((node) => {
-        if (node.metadataLayout && node.metadataLayout.rank){
+        if (node.metadataLayout && node.metadataLayout.rank!==undefined){
             const rank = node.metadataLayout.rank;
             if (rank<xNodeByRank.length){
                 const order = xNodeByRank[rank].indexOf(node.x);
diff --git a/src/composables/__tests__/CalculateStartNodes.tests.ts b/src/composables/__tests__/CalculateStartNodes.tests.ts
index de95410..4c2d1d7 100644
--- a/src/composables/__tests__/CalculateStartNodes.tests.ts
+++ b/src/composables/__tests__/CalculateStartNodes.tests.ts
@@ -9,17 +9,42 @@ import * as CalculateStartNodes from '../CalculateStartNodes';
 
 describe('assignRankOrder', () => {
     let networkLayout: NetworkLayout;
+    let networkExpectedRank: NetworkLayout;
 
     beforeEach(() => {
+
+        const nodes: { [key: string]: NodeLayout } = {
+            node1: { id: 'node1', x: 1, y: 2, metadataLayout: {} },
+            node2: { id: 'node2', x: 2, y: 3, metadataLayout: {} },
+            node3: { id: 'node3', x: 3, y: 2 },
+            node4: { id: 'node4', x: 3, y: 1, metadataLayout: {} },
+        };
+
+        const nodesRankOrder: { [key: string]: NodeLayout } =  {
+            node1: { id: 'node1', x: 1, y: 2, metadataLayout: {rank:1,order:0} },
+            node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:2,order:0} },
+            node3: { id: 'node3', x: 3, y: 2, metadataLayout: {rank:1,order:1} },
+            node4: { id: 'node4', x: 3, y: 1, metadataLayout: {rank:0,order:0} },
+        };
+
         networkLayout = {
             id:"test",
-            nodes: {
-                node1: { id: 'node1', x: 1, y: 2, metadataLayout: {} },
-                node2: { id: 'node2', x: 2, y: 3, metadataLayout: {} },
-                node3: { id: 'node3', x: 3, y: 2, metadataLayout: {} },
-                node4: { id: 'node4', x: 3, y: 1, metadataLayout: {} },
-            },
-            links: []
+            nodes: nodes,
+            links: [
+                { id:"link",source: nodes.node2, target: nodes.node1 },
+                { id:"link",source: nodes.node3, target: nodes.node2 },
+                { id:"link",source: nodes.node3, target: nodes.node4 }
+            ]
+        };
+
+        networkExpectedRank = {
+            id:"test",
+            nodes:nodesRankOrder,
+            links: [
+                { id:"link",source: nodesRankOrder.node2, target: nodesRankOrder.node1 },
+                { id:"link",source: nodesRankOrder.node3, target: nodesRankOrder.node2 },
+                { id:"link",source: nodesRankOrder.node3, target: nodesRankOrder.node4 }
+            ]
         };
 
     });
@@ -28,12 +53,47 @@ describe('assignRankOrder', () => {
     it('should assign rank and order to nodes based on their coordinates', () => {
         // DATA
         const unique_y = [1,2, 3];
-        const networkExpected: NetworkLayout = {
+        
+
+        // TEST
+        CalculateStartNodes.assignRankOrder(networkLayout, unique_y, false);
+
+        // EXPECT
+        expect(networkLayout).toEqual(networkExpectedRank);
+    });
+
+    it('should only assign rank', () => {
+        // DATA
+        const unique_y = [1,2, 3];
+        const networkExpectedRank = {
+            id:"test",
+            nodes: {
+                node1: { id: 'node1', x: 1, y: 2, metadataLayout: {rank:1} },
+                node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:2} },
+                node3: { id: 'node3', x: 3, y: 2, metadataLayout: {rank:1} },
+                node4: { id: 'node4', x: 3, y: 1, metadataLayout: {rank:0} },
+            },
+            links: []
+        };
+
+
+        // TEST
+        CalculateStartNodes.assignRankOrder(networkLayout, unique_y, true);
+
+        // EXPECT
+        expect(networkLayout).toEqual(networkExpectedRank);
+    });
+
+    
+    it('should assign rank and order, but not for all y', () => {
+        // DATA
+        const unique_y = [1, 3];
+        const networkExpectedRank: NetworkLayout = {
             id:"test",
             nodes: {
-                node1: { id: 'node1', x: 1, y: 2, metadataLayout: {rank:1,order:0} },
-                node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:2,order:0} },
-                node3: { id: 'node3', x: 3, y: 2, metadataLayout: {rank:1,order:1} },
+                node1: { id: 'node1', x: 1, y: 2, metadataLayout: {} },
+                node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:1,order:0} },
+                node3: { id: 'node3', x: 3, y: 2 },
                 node4: { id: 'node4', x: 3, y: 1, metadataLayout: {rank:0,order:0} },
             },
             links: []
@@ -43,60 +103,123 @@ describe('assignRankOrder', () => {
         CalculateStartNodes.assignRankOrder(networkLayout, unique_y, false);
 
         // EXPECT
-        expect(networkLayout).toEqual(networkExpected);
+        expect(networkLayout).toEqual(networkExpectedRank);
     });
 
+    it('should assign rank and order, but not for all y (and y associated with no nodes)', () => {
+        // DATA
+        const unique_y = [0,1, 1.5,3,6];
+        const networkExpectedRank: NetworkLayout = {
+            id:"test",
+            nodes: {
+                node1: { id: 'node1', x: 1, y: 2, metadataLayout: {} },
+                node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:3,order:0} },
+                node3: { id: 'node3', x: 3, y: 2 },
+                node4: { id: 'node4', x: 3, y: 1, metadataLayout: {rank:1,order:0} },
+            },
+            links: []
+        };
 
+        // TEST
+        CalculateStartNodes.assignRankOrder(networkLayout, unique_y, false);
 
-    // it('should assign only rank if onlyRank is true', () => {
-    //     const unique_y = [2, 3];
-    //     assignRankOrder(networkLayout, unique_y, true);
+        // EXPECT
+        expect(networkLayout).toEqual(networkExpectedRank);
+    });
 
-    //     expect(networkLayout.nodes.node1.metadataLayout.rank).toBe(0);
-    //     expect(networkLayout.nodes.node1.metadataLayout.order).toBeUndefined();
-    //     expect(networkLayout.nodes.node2.metadataLayout.rank).toBe(1);
-    //     expect(networkLayout.nodes.node2.metadataLayout.order).toBeUndefined();
-    //     expect(networkLayout.nodes.node3.metadataLayout.rank).toBe(0);
-    //     expect(networkLayout.nodes.node3.metadataLayout.order).toBeUndefined();
-    // });
-});
 
-// describe('getStartNodes', () => {
-//     it('should return all nodes if typeSource is ALL', async () => {
-//         const result = await getStartNodes(mockNetwork, StartNodesType.ALL);
-//         expect(result).toEqual(['node1', 'node2', 'node3']);
-//     });
-
-//     it('should return nodes with rank 0 if typeSource is RANK_ONLY', async () => {
-//         const result = await getStartNodes(mockNetwork, StartNodesType.RANK_ONLY);
-//         expect(result).toEqual(['node1']);
-//     });
-
-//     // Add more tests for other StartNodesType values as needed
-// });
-
-// describe('concatSources', () => {
-//     it('should concatenate two arrays and remove duplicates', () => {
-//         const firstSources = ['a', 'b', 'c'];
-//         const secondSources = ['b', 'c', 'd'];
-//         const result = concatSources(firstSources, secondSources);
-
-//         expect(result).toEqual(['a', 'b', 'c', 'd']);
-//     });
-
-//     it('should return the first array if the second array is empty', () => {
-//         const firstSources = ['a', 'b', 'c'];
-//         const secondSources: string[] = [];
-//         const result = concatSources(firstSources, secondSources);
-
-//         expect(result).toEqual(['a', 'b', 'c']);
-//     });
-
-//     it('should return the second array if the first array is empty', () => {
-//         const firstSources: string[] = [];
-//         const secondSources = ['a', 'b', 'c'];
-//         const result = concatSources(firstSources, secondSources);
-
-//         expect(result).toEqual(['a', 'b', 'c']);
-//     });
-// });
\ No newline at end of file
+    it('should return start nodes ALL', async () => {
+        // DATA
+
+        // TEST
+
+        // EXPECT
+        expect(true).toEqual(false);
+    });
+
+    it('should return start nodes RANK_SOURCE_ALL', async () => {
+        // DATA
+
+        // TEST
+
+        // EXPECT
+        expect(true).toEqual(false);
+    });
+
+    it('should return start nodes RANK_SOURCE', async () => {
+        // DATA
+
+        // TEST
+
+        // EXPECT
+        expect(true).toEqual(false);
+    });
+
+    it('should return start nodes RANK_ONLY', async () => {
+        // DATA
+
+        // TEST
+
+        // EXPECT
+        expect(true).toEqual(false);
+    });
+
+    it('should return start nodes SOURCE_ALL', async () => {
+        // DATA
+
+        // TEST
+
+        // EXPECT
+        expect(true).toEqual(false);
+    });
+
+    it('should return start nodes SOURCE_ONLY', async () => {
+        // DATA
+
+        // TEST
+
+        // EXPECT
+        expect(true).toEqual(false);
+    });
+
+
+
+
+    it('should concatenate two arrays and remove duplicates', () => {
+        // DATA
+        const firstSources = ['a', 'b', 'c'];
+        const secondSources = ['b', 'c', 'd'];
+
+        // TEST
+        const result = CalculateStartNodes.concatSources(firstSources, secondSources);
+
+        // EXPECT
+        expect(result).toEqual(['a', 'b', 'c', 'd']);
+    });
+
+    it('should return the first array if the second array is empty', () => {
+        // DATA
+        const firstSources = ['a', 'b', 'c'];
+        const secondSources: string[] = [];
+
+        // TEST
+        const result = CalculateStartNodes.concatSources(firstSources, secondSources);
+
+        // EXPECT
+        expect(result).toEqual(['a', 'b', 'c']);
+    });
+
+    it('should return the second array if the first array is empty', () => {
+        // DATA
+        const firstSources: string[] = [];
+        const secondSources = ['a', 'b', 'c'];
+
+        // TEST
+        const result = CalculateStartNodes.concatSources(firstSources, secondSources);
+
+        // EXPECT
+        expect(result).toEqual(['a', 'b', 'c']);
+    });
+
+
+});
-- 
GitLab


From 35f15d89667b65e237ec1bca42e9b55f3702222a Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Fri, 13 Sep 2024 08:37:23 +0200
Subject: [PATCH 12/13] test Calculate start node

---
 .../__tests__/CalculateStartNodes.tests.ts    | 152 ++++++++++++++----
 1 file changed, 122 insertions(+), 30 deletions(-)

diff --git a/src/composables/__tests__/CalculateStartNodes.tests.ts b/src/composables/__tests__/CalculateStartNodes.tests.ts
index 4c2d1d7..940373c 100644
--- a/src/composables/__tests__/CalculateStartNodes.tests.ts
+++ b/src/composables/__tests__/CalculateStartNodes.tests.ts
@@ -5,6 +5,8 @@ import { Network } from '@metabohub/viz-core/src/types/Network';
 
 // Composable imports
 import * as CalculateStartNodes from '../CalculateStartNodes';
+import * as ConvertFromNetwork from '../ConvertFromNetwork';
+import { TypeSubgraph } from '../../types/Subgraph';
 
 
 describe('assignRankOrder', () => {
@@ -13,6 +15,8 @@ describe('assignRankOrder', () => {
 
     beforeEach(() => {
 
+        // DATA
+
         const nodes: { [key: string]: NodeLayout } = {
             node1: { id: 'node1', x: 1, y: 2, metadataLayout: {} },
             node2: { id: 'node2', x: 2, y: 3, metadataLayout: {} },
@@ -49,6 +53,9 @@ describe('assignRankOrder', () => {
 
     });
 
+    afterEach(() => {
+        jest.clearAllMocks();
+    });
 
     it('should assign rank and order to nodes based on their coordinates', () => {
         // DATA
@@ -65,15 +72,20 @@ describe('assignRankOrder', () => {
     it('should only assign rank', () => {
         // DATA
         const unique_y = [1,2, 3];
+        const nodesExpected={
+            node1: { id: 'node1', x: 1, y: 2, metadataLayout: {rank:1} },
+            node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:2} },
+            node3: { id: 'node3', x: 3, y: 2, metadataLayout: {rank:1} },
+            node4: { id: 'node4', x: 3, y: 1, metadataLayout: {rank:0} },
+        }
         const networkExpectedRank = {
             id:"test",
-            nodes: {
-                node1: { id: 'node1', x: 1, y: 2, metadataLayout: {rank:1} },
-                node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:2} },
-                node3: { id: 'node3', x: 3, y: 2, metadataLayout: {rank:1} },
-                node4: { id: 'node4', x: 3, y: 1, metadataLayout: {rank:0} },
-            },
-            links: []
+            nodes:nodesExpected ,
+            links: [
+                { id:"link",source: nodesExpected.node2, target: nodesExpected.node1 },
+                { id:"link",source: nodesExpected.node3, target: nodesExpected.node2 },
+                { id:"link",source: nodesExpected.node3, target: nodesExpected.node4 }
+            ]
         };
 
 
@@ -88,15 +100,20 @@ describe('assignRankOrder', () => {
     it('should assign rank and order, but not for all y', () => {
         // DATA
         const unique_y = [1, 3];
+        const nodesExpected={
+            node1: { id: 'node1', x: 1, y: 2, metadataLayout: {} },
+            node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:1,order:0} },
+            node3: { id: 'node3', x: 3, y: 2 },
+            node4: { id: 'node4', x: 3, y: 1, metadataLayout: {rank:0,order:0} },
+        };
         const networkExpectedRank: NetworkLayout = {
             id:"test",
-            nodes: {
-                node1: { id: 'node1', x: 1, y: 2, metadataLayout: {} },
-                node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:1,order:0} },
-                node3: { id: 'node3', x: 3, y: 2 },
-                node4: { id: 'node4', x: 3, y: 1, metadataLayout: {rank:0,order:0} },
-            },
-            links: []
+            nodes: nodesExpected,
+            links: [
+                { id:"link",source: nodesExpected.node2, target: nodesExpected.node1 },
+                { id:"link",source: nodesExpected.node3, target: nodesExpected.node2 },
+                { id:"link",source: nodesExpected.node3, target: nodesExpected.node4 }
+            ]
         };
 
         // TEST
@@ -109,15 +126,20 @@ describe('assignRankOrder', () => {
     it('should assign rank and order, but not for all y (and y associated with no nodes)', () => {
         // DATA
         const unique_y = [0,1, 1.5,3,6];
+        const expectedNode:{[key:string]:NodeLayout}={
+            node1: { id: 'node1', x: 1, y: 2, metadataLayout: {} },
+            node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:3,order:0} },
+            node3: { id: 'node3', x: 3, y: 2 },
+            node4: { id: 'node4', x: 3, y: 1, metadataLayout: {rank:1,order:0} },
+        }
         const networkExpectedRank: NetworkLayout = {
             id:"test",
-            nodes: {
-                node1: { id: 'node1', x: 1, y: 2, metadataLayout: {} },
-                node2: { id: 'node2', x: 2, y: 3, metadataLayout: {rank:3,order:0} },
-                node3: { id: 'node3', x: 3, y: 2 },
-                node4: { id: 'node4', x: 3, y: 1, metadataLayout: {rank:1,order:0} },
-            },
-            links: []
+            nodes: expectedNode,
+            links: [
+                { id:"link",source: expectedNode.node2, target: expectedNode.node1 },
+                { id:"link",source: expectedNode.node3, target: expectedNode.node2 },
+                { id:"link",source: expectedNode.node3, target: expectedNode.node4 }
+            ]
         };
 
         // TEST
@@ -129,60 +151,130 @@ describe('assignRankOrder', () => {
 
 
     it('should return start nodes ALL', async () => {
-        // DATA
+        // DATA 
+        const expectedStartNodes = ['node1', 'node2', 'node3', 'node4'];
 
         // TEST
+        const startNodes=await CalculateStartNodes.getStartNodes(networkExpectedRank,StartNodesType.ALL);
 
         // EXPECT
-        expect(true).toEqual(false);
+        expect(startNodes).toEqual(expectedStartNodes);
     });
 
     it('should return start nodes RANK_SOURCE_ALL', async () => {
+        // MOCK
+        const networkToGDSGraphMock = jest.spyOn(ConvertFromNetwork, 'networkToGDSGraph');
+        networkToGDSGraphMock.mockImplementation(async (network)=>{
+            return {
+                indegree: jest.fn((id: string) => {
+                    if (id === 'node3') return 0;
+                    return 1;
+                })
+            }
+        });
+
         // DATA
+        const expectedStartNodes = ['node4', 'node3', 'node1', 'node2'];
 
         // TEST
+        const startNodes=await CalculateStartNodes.getStartNodes(networkExpectedRank,StartNodesType.RANK_SOURCE_ALL);
 
         // EXPECT
-        expect(true).toEqual(false);
+        expect(startNodes).toEqual(expectedStartNodes);
+        expect(networkToGDSGraphMock).toHaveBeenCalledTimes(1);
     });
 
     it('should return start nodes RANK_SOURCE', async () => {
+        // MOCK
+        const networkToGDSGraphMock = jest.spyOn(ConvertFromNetwork, 'networkToGDSGraph');
+        networkToGDSGraphMock.mockImplementation(async (network)=>{
+            return {
+                indegree: jest.fn((id: string) => {
+                    if (id === 'node3') return 0;
+                    return 1;
+                })
+            }
+        });
+
         // DATA
+        const expectedStartNodes = ['node4', 'node3'];
 
         // TEST
+        const startNodes=await CalculateStartNodes.getStartNodes(networkExpectedRank,StartNodesType.RANK_SOURCE);
 
         // EXPECT
-        expect(true).toEqual(false);
+        expect(startNodes).toEqual(expectedStartNodes);
+        expect(networkToGDSGraphMock).toHaveBeenCalledTimes(1);
     });
 
     it('should return start nodes RANK_ONLY', async () => {
         // DATA
+        const exepectedStartNodes = ['node4'];
 
         // TEST
+        const startNodes=await CalculateStartNodes.getStartNodes(networkExpectedRank,StartNodesType.RANK_ONLY);
 
         // EXPECT
-        expect(true).toEqual(false);
+        expect(startNodes).toEqual(exepectedStartNodes);
     });
 
-    it('should return start nodes SOURCE_ALL', async () => {
+    it('should return start nodes RANK_ONLY when no rank', async () => {
         // DATA
+        const expectedStartNodes:string[]= [];
 
         // TEST
+        const startNodes=await CalculateStartNodes.getStartNodes(networkLayout,StartNodesType.RANK_ONLY);
 
         // EXPECT
-        expect(true).toEqual(false);
+        expect(startNodes).toEqual(expectedStartNodes);
     });
 
-    it('should return start nodes SOURCE_ONLY', async () => {
+
+    it('should return start nodes SOURCE_ALL', async () => {
+        // MOCK
+        const networkToGDSGraphMock = jest.spyOn(ConvertFromNetwork, 'networkToGDSGraph');
+        networkToGDSGraphMock.mockImplementation(async (network)=>{
+            return {
+                indegree: jest.fn((id: string) => {
+                    if (id === 'node3') return 0;
+                    return 1;
+                })
+            }
+        });
+
         // DATA
+        const expectedStartNodes = ['node3','node1','node2', 'node4'];
 
         // TEST
+        const startNodes=await CalculateStartNodes.getStartNodes(networkExpectedRank,StartNodesType.SOURCE_ALL);
 
         // EXPECT
-        expect(true).toEqual(false);
+        expect(startNodes).toEqual(expectedStartNodes);
+        expect(networkToGDSGraphMock).toHaveBeenCalledTimes(1);
     });
 
+    it('should return start nodes SOURCE_ONLY', async () => {
+        // MOCK
+        const networkToGDSGraphMock = jest.spyOn(ConvertFromNetwork, 'networkToGDSGraph');
+        networkToGDSGraphMock.mockImplementation(async (network)=>{
+            return {
+                indegree: jest.fn((id: string) => {
+                    if (id === 'node3') return 0;
+                    return 1;
+                })
+            }
+        });
+
+        // DATA
+        const expectedStartNodes = ['node3'];
 
+        // TEST
+        const startNodes=await CalculateStartNodes.getStartNodes(networkExpectedRank,StartNodesType.SOURCE_ONLY);
+
+        // EXPECT
+        expect(startNodes).toEqual(expectedStartNodes);
+        expect(networkToGDSGraphMock).toHaveBeenCalledTimes(1);
+    });
 
 
     it('should concatenate two arrays and remove duplicates', () => {
-- 
GitLab


From ddbfea7da958e498cea868e6d8672b1629ec54ec Mon Sep 17 00:00:00 2001
From: Elora-V <elora95.vigo@gmail.com>
Date: Fri, 13 Sep 2024 13:57:40 +0200
Subject: [PATCH 13/13] debut calculate relation cycle test

---
 src/composables/CalculateRelationCycle.ts     |   4 +-
 .../__tests__/CalculateRelationCycle.tests.ts | 345 ++++++++++++++++++
 2 files changed, 347 insertions(+), 2 deletions(-)
 create mode 100644 src/composables/__tests__/CalculateRelationCycle.tests.ts

diff --git a/src/composables/CalculateRelationCycle.ts b/src/composables/CalculateRelationCycle.ts
index ccde993..2ce533a 100644
--- a/src/composables/CalculateRelationCycle.ts
+++ b/src/composables/CalculateRelationCycle.ts
@@ -4,11 +4,11 @@ import { Link } from "@metabohub/viz-core/src/types/Link";
 import { Ordering } from "../types/EnumArgs";
 import { TypeSubgraph } from "../types/Subgraph";
 import { LinkLayout, NetworkLayout } from "../types/NetworkLayout";
-
+import { Coordinate } from "../types/CoordinatesSize";
 
 // Composable imports
 import { inCycle } from "./GetSetAttributsNodes";
-import { Coordinate } from "../types/CoordinatesSize";
+
 
 
 /**
diff --git a/src/composables/__tests__/CalculateRelationCycle.tests.ts b/src/composables/__tests__/CalculateRelationCycle.tests.ts
new file mode 100644
index 0000000..3a00b87
--- /dev/null
+++ b/src/composables/__tests__/CalculateRelationCycle.tests.ts
@@ -0,0 +1,345 @@
+// Type imports
+import { SubgraphNetwork } from '../../types/SubgraphNetwork';
+import { Subgraph, TypeSubgraph } from '../../types/Subgraph';
+import { LinkLayout, NetworkLayout, NodeLayout } from '../../types/NetworkLayout';
+import { Coordinate } from '../../types/CoordinatesSize';
+import { GraphStyleProperties } from '@metabohub/viz-core/src/types/GraphStyleProperties';
+
+// Composable imports
+import * as CalculateRelationCycle from '../CalculateRelationCycle';
+import * as GetSetAttributsNodes from "../GetSetAttributsNodes";
+
+
+// General imports
+import { ref } from 'vue'; // Import the 'ref' function from the 'vue' module
+import { link } from 'fs';
+
+
+
+describe('CalculateRelationCycle', () => {
+
+    let subgraphNetwork: SubgraphNetwork;
+    let nodes: {[key: string]:NodeLayout};
+    let links : LinkLayout[];
+    let network: NetworkLayout;
+
+    beforeEach(() => {
+
+        nodes={
+            node0: { id: 'node0', x: 0, y: 0, metadataLayout: {} },
+            node1: { id: 'node1', x: 1, y: 2, metadataLayout: {} },
+            node2: { id: 'node2', x: 2, y: 3, metadataLayout: {} },
+            node3: { id: 'node3', x: 3, y: 2 },
+            node4: { id: 'node4', x: 3, y: 1, metadataLayout: {} },
+        };
+        links=[
+            {id:"link", source: nodes.node2 , target: nodes.node1 },
+            {id:"link", source: nodes.node3 , target: nodes.node2 },
+            {id:"link", source: nodes.node4 , target: nodes.node3 },
+            {id:"link", source: nodes.node3 , target: nodes.node4 },
+            {id:"link", source: nodes.node1 , target: nodes.node4 },
+            {id:"link", source: nodes.node3 , target: nodes.node0 },
+            {id:"link", source: nodes.node0 , target: nodes.node3 }
+        ];
+        network = {
+            id: "network",
+            nodes: nodes,
+            links: links
+        }
+        const networkStyle: GraphStyleProperties = {};
+
+        subgraphNetwork = {
+            network: ref<NetworkLayout>(network),
+            networkStyle:  ref<GraphStyleProperties>(networkStyle),
+        };
+
+    });
+
+    afterEach(() => {
+        jest.clearAllMocks();
+    });
+
+// 0. Get nodes *****************************************************************
+
+        it('should throw error because cycle group not defined in subgraphNetwork when trying to get node id placed inside ', () => {
+            // EXPECT
+            expect(()=>{CalculateRelationCycle.getNodesIDPlacedInGroupCycle(subgraphNetwork,"groupCycle")}).toThrow();
+
+        });
+        it('should get nodes id placed inside group cycle ', () => {
+            // DATA
+            const cycleGroup:Subgraph={
+                name: "groupCycle",
+                nodes: ["node2","node3","node4"],
+                precalculatedNodesPosition:  {
+                    node2: { x: 2, y: 3 },
+                    node3: { x: 3, y: 2 }
+                }
+            };
+
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]={};
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]["groupCycle"] = cycleGroup;
+
+            const nodesIDExpected=["node2","node3"];
+
+            // TEST
+            const nodesID=CalculateRelationCycle.getNodesIDPlacedInGroupCycle(subgraphNetwork,"groupCycle");
+
+            // EXPECT
+            expect(nodesID).toEqual(nodesIDExpected);
+
+        });
+
+        it('should throw error because cycle group not defined in subgraphNetwork when trying to get node placed inside ', () => {
+            // EXPECT
+            expect(()=>{CalculateRelationCycle.getNodesPlacedInGroupCycle(subgraphNetwork,"groupCycle")}).toThrow();
+
+        });
+
+        it('should get nodes placed inside group cycle (fixed or not) ', () => {
+            // DATA
+            const cycleGroup:Subgraph={
+                name: "groupCycle",
+                nodes: ["node2","node3","node4"],
+                precalculatedNodesPosition:  {
+                    node2: { x: 2, y: 3 },
+                    node3: { x: 3, y: 2 }
+                }
+            };
+
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]={};
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]["groupCycle"] = cycleGroup;
+
+            const nodesExpected=[
+                {id:"node2", x:2, y:3},
+                {id:"node3", x:3, y:2}
+            ];
+
+            const nodesExpectedFixed=[
+                {id:"node2", fx:2, fy:3},
+                {id:"node3", fx:3, fy:2}
+            ];
+
+            // TEST
+            const nodes=CalculateRelationCycle.getNodesPlacedInGroupCycle(subgraphNetwork,"groupCycle");
+            const nodesFixed=CalculateRelationCycle.getNodesPlacedInGroupCycle(subgraphNetwork,"groupCycle",true);
+
+            // EXPECT
+            expect(nodes).toEqual(nodesExpected);
+            expect(nodesFixed).toEqual(nodesExpectedFixed);
+
+        });
+
+        it('should get nodes placed inside group cycle, but no precalculatedNodesPosition ', () => {
+            // DATA
+            const cycleGroup:Subgraph={
+                name: "groupCycle",
+                nodes: ["node2","node3","node4"],
+            };
+
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]={};
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]["groupCycle"] = cycleGroup;
+
+            const nodesExpected:{ id: string,x?:number, y?:number, fx?:number, fy?:number }[]=[];
+
+            // TEST
+            const nodes=CalculateRelationCycle.getNodesPlacedInGroupCycle(subgraphNetwork,"groupCycle");
+
+            // EXPECT
+            expect(nodes).toEqual(nodesExpected);
+
+        });
+
+        it('should throw error because cycle group not defined in subgraphNetwork when trying to get node placed inside (as object) ', () => {
+            // EXPECT
+            expect(()=>{CalculateRelationCycle.getNodesPlacedInGroupCycleAsObject(subgraphNetwork,"groupCycle")}).toThrow();
+
+        });
+
+        it('should get nodes placed inside group cycle (as object) ', () => {
+            // DATA
+            const cycleGroup:Subgraph={
+                name: "groupCycle",
+                nodes: ["node2","node3","node4"],
+                precalculatedNodesPosition:  {
+                    node2: { x: 2, y: 3 },
+                    node3: { x: 3, y: 2 }
+                }
+            };
+
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]={};
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]["groupCycle"] = cycleGroup;
+
+            const nodesExpected={
+                node2: { x: 2, y: 3 },
+                node3: { x: 3, y: 2 }
+            };
+
+            // TEST
+            const nodes=CalculateRelationCycle.getNodesPlacedInGroupCycleAsObject(subgraphNetwork,"groupCycle");
+
+            // EXPECT
+            expect(nodes).toEqual(nodesExpected);
+
+        });
+
+        it('should get nodes placed inside group cycle (as object), but no precalculatedNodesPosition ', () => {
+            // DATA
+            const cycleGroup:Subgraph={
+                name: "groupCycle",
+                nodes: ["node2","node3","node4"],
+            };
+
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]={};
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]["groupCycle"] = cycleGroup;
+
+            const nodesExpected:{[key:string]:Coordinate}={};
+
+            // TEST
+            const nodes=CalculateRelationCycle.getNodesPlacedInGroupCycleAsObject(subgraphNetwork,"groupCycle");
+
+            // EXPECT
+            expect(nodes).toEqual(nodesExpected);
+
+        });
+
+        it('should return child of a groupcycle, that are not in a cycle ', () => {
+            // MOCK
+            const inCycleMock = jest.spyOn(GetSetAttributsNodes, 'inCycle');
+            inCycleMock.mockImplementation( (network,id)=>{
+                return id==="node2" || id==="node3" || id==="node0";
+            });
+
+            // DATA
+            const listNodes=["node2","node3"];
+
+            const childrenExpected=[
+                ["node1"],
+                ["node4"]
+            ];
+
+            // TEST
+            const children=CalculateRelationCycle.childNodeNotInCycle(subgraphNetwork,listNodes);
+
+            // EXPECT
+            expect(children).toEqual(childrenExpected);
+
+
+        });
+
+        it('should return parent of a groupcycle, that are not in a cycle ', () => {
+            // MOCK
+            const inCycleMock = jest.spyOn(GetSetAttributsNodes, 'inCycle');
+            inCycleMock.mockImplementation( (network,id)=>{
+                return id==="node2" || id==="node3" || id==="node0";
+            });
+
+            // DATA
+            const listNodes=["node2","node3"];
+
+            const parentExpected=[
+                [],
+                ["node4"]
+            ];
+
+            // TEST
+            const parent=CalculateRelationCycle.parentNodeNotInCycle(subgraphNetwork,listNodes);
+
+            // EXPECT
+            expect(parent).toEqual(parentExpected);
+
+
+        });
+
+        it('sould throw an error instead of returning parent/child of a group cycle , because no groupcycle', () => {
+            // EXPECT
+            expect(()=>{CalculateRelationCycle.neighborsGroupCycle(subgraphNetwork,"groupCycle","parent")}).toThrow();
+            expect(()=>{CalculateRelationCycle.neighborsGroupCycle(subgraphNetwork,"groupCycle","child")}).toThrow();
+        });
+
+        it('sould return parent/child of a group cycle , but no precalculatedPosition', () => {
+            // DATA
+            const cycleGroup:Subgraph={
+                name: "groupCycle",
+                nodes: ["node2","node3","node4"],
+            };
+
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]={};
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]["groupCycle"] = cycleGroup;
+
+            const resultExpected:string[]=[];
+
+            // TEST
+            const resultParent=CalculateRelationCycle.neighborsGroupCycle(subgraphNetwork,"groupCycle","parent");
+            const resultChildren=CalculateRelationCycle.neighborsGroupCycle(subgraphNetwork,"groupCycle","child");
+
+            // EXPECT
+            expect(resultParent).toEqual(resultExpected);
+            expect(resultChildren).toEqual(resultExpected);
+
+        });
+
+        it('sould return parent/child of a group cycle with neighborsGroupCycle, no sorting', () => {
+            // DATA
+            const cycleGroup:Subgraph={
+                name: "groupCycle",
+                nodes: ["node2","node3","node4"],
+            };
+
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]={};
+            subgraphNetwork[TypeSubgraph.CYCLEGROUP]["groupCycle"] = cycleGroup;
+
+            const resultExpected:string[]=[];// TO DO
+
+            // TEST
+            const resultParent=CalculateRelationCycle.neighborsGroupCycle(subgraphNetwork,"groupCycle","parent",false);
+            const resultChildren=CalculateRelationCycle.neighborsGroupCycle(subgraphNetwork,"groupCycle","child",false);
+
+            // EXPECT
+            expect(resultParent).toEqual(resultExpected);
+            expect(resultChildren).toEqual(resultExpected);
+
+        });
+
+
+
+// 1. Get (ordered) links *****************************************************************
+
+        it('should return the link with nodes as metanodes if it s the case', () => {
+            expect(true).toEqual(false);
+        });
+
+
+        it('should return the link with nodes as metanodes if it s the case', () => {
+
+            // DATA 
+            nodes.node1.metadataLayout={};
+            nodes.node2.metadataLayout={ [TypeSubgraph.CYCLEGROUP]: "groupCycle" };
+            nodes.node3.metadataLayout={ [TypeSubgraph.CYCLEGROUP]: "groupCycle" };
+            nodes.node4.metadataLayout={ [TypeSubgraph.CYCLEGROUP]: undefined};
+
+            // TEST
+            CalculateRelationCycle.cycleMetanodeLink(links[0],true);
+            
+            expect(true).toEqual(false);
+
+
+        });
+
+
+// getLinksForListNodes
+// sortLinksWithAllGroupCycle
+// cycleMetanodeLink
+
+
+// 2. Get graph *****************************************************************
+
+        //getListNodeLinksForCycleGroupAsObject
+        // getListNodeLinksForCycleGroup
+
+// 3. Get relation cycle *****************************************************************
+
+        // parentCycle
+
+
+    });
-- 
GitLab