diff --git a/src/composables/LayoutManageSideCompounds.ts b/src/composables/LayoutManageSideCompounds.ts
index 34416e9897899500b434cf1dca9b89d95bc66f2d..4593c9ea45f4a25b0ff8248225c4bbedcafd95c3 100644
--- a/src/composables/LayoutManageSideCompounds.ts
+++ b/src/composables/LayoutManageSideCompounds.ts
@@ -8,7 +8,7 @@ import { Coordinate } from "../types/CoordinatesSize";
 import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties";
 
 // Composable imports
-import { removeAllSelectedNodes , duplicateAllNodesByAttribut} from "@metabohub/viz-core";
+import { removeAllSelectedNodes , duplicateAllNodesByAttribut} from "./VizCoreFunctions";
 import { getMeanNodesSizePixel, inchesToPixels, minEdgeLength as minEdgeLength, pixelsToInches } from "./CalculateSize";
 import { sideCompoundAttribute,isDuplicate, isReaction, isSideCompound, setAsSideCompound } from "./GetSetAttributsNodes";
 
@@ -142,74 +142,74 @@ import { error } from "console";
 
 
 
-/**
- * Add attribute of side compound to all nodes in network from a list 
- * @param network 
- * @param pathListSideCompounds path to the list of id of side compounds
- */
-export async function addSideCompoundAttributeFromList(subgraphNetwork:SubgraphNetwork, pathListSideCompounds:string):Promise<void>{
-    const listIDSideCompounds = await getIDSideCompoundsInNetworkFromFile(subgraphNetwork,pathListSideCompounds);
-    listIDSideCompounds.forEach((sideCompoundID) => {
-        setAsSideCompound(subgraphNetwork.network,sideCompoundID);
-    });
-}
-
-/**
- * Return the list of id of side compounds in the network
- * @param subgraphNetwork 
- * @param pathListSideCompounds path to the list of id of side compounds
- * @returns list of id of side compounds in the network
- */
-async function getIDSideCompoundsInNetworkFromFile(subgraphNetwork:SubgraphNetwork,pathListSideCompounds:string):Promise<string[]>{
-    let listIDSideCompounds:string[];
-    const network = subgraphNetwork.network;
-    try {
-        listIDSideCompounds = await getIDSideCompoundsFromFile(pathListSideCompounds);
-        const sideCompoundInNetwork = Object.keys(network.nodes).filter(id => listIDSideCompounds.includes(id));
-        return sideCompoundInNetwork;
-    } catch (error) {
-        throw error;
-    }   
-}
-
-/**
- * Return the list of id of side compounds from a file
- * @param pathListSideCompounds path to the list of id of side compounds
- * @returns list of id of side compounds
- */
-async function getIDSideCompoundsFromFile(pathListSideCompounds:string):Promise<string[]>{
-    try {
-        const sideCompoundsFile=pathListSideCompounds;
-        const sideCompoundsString = await getContentFromURL(sideCompoundsFile);
-        const lines = sideCompoundsString.split('\n');
-        const listId: Array<string> = [];
-        lines.forEach((line: string) => {
-        listId.push(line.split('\t')[0]);
-        })
-        return listId;
-    }catch (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;
-	}
-  }
+// /**
+//  * Add attribute of side compound to all nodes in network from a list 
+//  * @param network 
+//  * @param pathListSideCompounds path to the list of id of side compounds
+//  */
+// export async function addSideCompoundAttributeFromList(subgraphNetwork:SubgraphNetwork, pathListSideCompounds:string):Promise<void>{
+//     const listIDSideCompounds = await getIDSideCompoundsInNetworkFromFile(subgraphNetwork,pathListSideCompounds);
+//     listIDSideCompounds.forEach((sideCompoundID) => {
+//         setAsSideCompound(subgraphNetwork.network,sideCompoundID);
+//     });
+// }
+
+// /**
+//  * Return the list of id of side compounds in the network
+//  * @param subgraphNetwork 
+//  * @param pathListSideCompounds path to the list of id of side compounds
+//  * @returns list of id of side compounds in the network
+//  */
+// async function getIDSideCompoundsInNetworkFromFile(subgraphNetwork:SubgraphNetwork,pathListSideCompounds:string):Promise<string[]>{
+//     let listIDSideCompounds:string[];
+//     const network = subgraphNetwork.network;
+//     try {
+//         listIDSideCompounds = await getIDSideCompoundsFromFile(pathListSideCompounds);
+//         const sideCompoundInNetwork = Object.keys(network.nodes).filter(id => listIDSideCompounds.includes(id));
+//         return sideCompoundInNetwork;
+//     } catch (error) {
+//         throw error;
+//     }   
+// }
+
+// /**
+//  * Return the list of id of side compounds from a file
+//  * @param pathListSideCompounds path to the list of id of side compounds
+//  * @returns list of id of side compounds
+//  */
+// async function getIDSideCompoundsFromFile(pathListSideCompounds:string):Promise<string[]>{
+//     try {
+//         const sideCompoundsFile=pathListSideCompounds;
+//         const sideCompoundsString = await getContentFromURL(sideCompoundsFile);
+//         const lines = sideCompoundsString.split('\n');
+//         const listId: Array<string> = [];
+//         lines.forEach((line: string) => {
+//         listId.push(line.split('\t')[0]);
+//         })
+//         return listId;
+//     }catch (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;
+// 	}
+//   }
   
 
 
@@ -227,16 +227,17 @@ export async function getContentFromURL(url: string): Promise<string> {
  * @param pathListSideCompounds path to the list of id of side compounds
  * @returns subgraphNetwork with updated network and sideCompounds
  */
-export async function putDuplicatedSideCompoundAside(subgraphNetwork:SubgraphNetwork, doDuplicateSideCompounds:boolean,doPutAsideSideCompounds:boolean, addSideCompoundAttribute:boolean=true, pathListSideCompounds:string):Promise<SubgraphNetwork>{
+export async function putDuplicatedSideCompoundAside(subgraphNetwork:SubgraphNetwork, doDuplicateSideCompounds:boolean,doPutAsideSideCompounds:boolean):Promise<SubgraphNetwork>{
     try {
         // finding side compounds in network
-        if (addSideCompoundAttribute){
-            await addSideCompoundAttributeFromList(subgraphNetwork,pathListSideCompounds);
-        }
+        // if (addSideCompoundAttribute){
+        //     await addSideCompoundAttributeFromList(subgraphNetwork,pathListSideCompounds);
+        // }
         // duplication of side compounds
         if (doDuplicateSideCompounds){
             await duplicateSideCompound(subgraphNetwork);
         }
+
         // remove side compounds from network, they are keeped aside in subgraphNetwork.sideCompounds
         if (doPutAsideSideCompounds){
             return removeSideCompoundsFromNetwork(subgraphNetwork);
@@ -255,7 +256,7 @@ export async function putDuplicatedSideCompoundAside(subgraphNetwork:SubgraphNet
  * @param subgraphNetwork - The subgraph network containing the side compounds to be duplicated.
  * @returns void
  */
-export async function duplicateSideCompound(subgraphNetwork:SubgraphNetwork):Promise<void>{
+async function duplicateSideCompound(subgraphNetwork:SubgraphNetwork):Promise<void>{
     const network = subgraphNetwork.network;
     const networkStyle = subgraphNetwork.networkStyle;
     // duplication of side compounds
@@ -332,7 +333,9 @@ function removeSideCompoundsFromNetwork(subgraphNetwork:SubgraphNetwork): Subgra
  * @returns subgraphNetwork with updated network and sideCompounds
  */
 export async function reinsertionSideCompounds(subgraphNetwork:SubgraphNetwork,factorMinEdgeLength:number=1/2,doReactionReversible:boolean):Promise<SubgraphNetwork>{
-    if(subgraphNetwork.sideCompounds){
+    if(!subgraphNetwork.sideCompounds){
+        return subgraphNetwork;
+    }else {
         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)
@@ -352,12 +355,13 @@ export async function reinsertionSideCompounds(subgraphNetwork:SubgraphNetwork,f
         }
 
         // for each reaction, apply motif stamp
-        Object.keys(sideCompounds).forEach( async (reactionID)=>{
-            subgraphNetwork= await motifStampSideCompound(subgraphNetwork,reactionID,factorMinEdgeLength);
-        });       
-    }
-    return subgraphNetwork;
+        for (const reactionID of Object.keys(sideCompounds)) {
+            subgraphNetwork = await motifStampSideCompound(subgraphNetwork, reactionID, factorMinEdgeLength);
+        }   
 
+        return subgraphNetwork;   
+    }
+    
 }
 
 /**
@@ -391,7 +395,7 @@ async function updateSideCompoundsReversibleReaction(subgraphNetwork:SubgraphNet
     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 (!(reactionID in network.nodes)) throw new Error("Reaction in side compounds but not in network")
             // if reaction has been reversed : exchange products and reactants
             if(network.nodes[reactionID].metadataLayout && network.nodes[reactionID].metadataLayout.isReversedVersion){
                 const products=sideCompounds[reactionID].products;
@@ -414,7 +418,7 @@ async function updateSideCompoundsReversibleReaction(subgraphNetwork:SubgraphNet
  * @returns The subgraphNetwork with the motif stamp applied for the reaction.
  */
 async function motifStampSideCompound(subgraphNetwork:SubgraphNetwork,reactionID:string,factorMinEdgeLength:number=1/2):Promise<SubgraphNetwork>{
-    //try {
+    try {
         // initialize reaction stamp
         let reaction= await initializeReactionSideCompounds(subgraphNetwork,reactionID);
         // find intervals between reactants and products
@@ -430,10 +434,10 @@ async function motifStampSideCompound(subgraphNetwork:SubgraphNetwork,reactionID
         subgraphNetwork= await giveCoordAllSideCompounds(subgraphNetwork,reaction,factorMinEdgeLength);
         // insert side compounds in network
         insertAllSideCompoundsInNetwork(subgraphNetwork,reaction);
-    // } catch (error) {
-    //     throw new Error("Error in motifStampSideCompound, reaction : "+ reactionID+ "\n"+error);
-    // }
-    return subgraphNetwork;
+        return subgraphNetwork;
+    } catch (error) {
+        throw new Error("Error in motifStampSideCompound, reaction : "+ reactionID+ "\n"+error);
+    }
 }
 
 
@@ -514,7 +518,6 @@ async function getMetaboliteFromReaction(subgraphNetwork: SubgraphNetwork, idRea
  */
 function angleRadianSegment(x1:number,y1:number,x2:number,y2:number,clockwise:boolean=true):number{
     if (!isFinite(x1) || !isFinite(y1) || !isFinite(x2) || !isFinite(y2)) {
-        //console.error("Invalid coordinates for angle : one or more coordinates are not finite numbers.");
         throw new Error("Invalid coordinates for angle : one or more coordinates are not finite numbers."); 
     }
 
@@ -548,6 +551,16 @@ function angleRadianSegment(x1:number,y1:number,x2:number,y2:number,clockwise:bo
 async function addSideCompoundsIntervals(reaction: Reaction):Promise<Reaction> {
 
     try {
+        // if no reactant or product
+        if (Object.keys(reaction.metabolitesAngles).length===0) {
+            reaction.intervalsAvailables =[{
+                typeInterval: 0, 
+                reactant: undefined,
+                product: undefined,
+            }];
+            return reaction;
+        }
+
         // Sort metabolites by angle
         const sortedMetabolites = Object.entries(reaction.metabolitesAngles)
         .map(([id, {angle, type}]) => ({id, angle, type}))
@@ -582,7 +595,6 @@ async function addSideCompoundsIntervals(reaction: Reaction):Promise<Reaction> {
                 product: undefined,
             }];
         }
-
         return reaction;
     } catch(error){
         throw error;
@@ -709,9 +721,10 @@ function sizeInterval(reaction:Reaction,intervalIndex:number):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;
+    if (reactantNumber<0 && productNumber<0) throw new Error("Number of side compounds negative");
     return {
-        reactant: reactantNumber === 0 ? undefined : sizeInterval / (2 * (reactantNumber+1)),
-        product: productNumber === 0 ? undefined : sizeInterval / (2 * (productNumber+1))
+        reactant: reactantNumber === 0 ? undefined :  Number((sizeInterval / (2 * (reactantNumber+1))).toFixed(3)),
+        product: productNumber === 0 ? undefined : Number((sizeInterval / (2 * (productNumber+1))).toFixed(3))
     };
 }
 
@@ -780,15 +793,14 @@ async function placeSideCompounds(sideCompounds: Array<Node>, reaction: Reaction
     }
     const interval = reaction.intervalsAvailables[0];
     const startSideCompound = placeReactants ? interval.reactant : interval.product;
-    if (!startSideCompound) {
-        console.error("No start side compound found");
-        return;
+    let startAngle:number=0;
+    if (startSideCompound) {
+        startAngle = startSideCompound ? reaction.metabolitesAngles[startSideCompound].angle : 0;
     }
-    let startAngle = startSideCompound ? reaction.metabolitesAngles[startSideCompound].angle : 0;
+   
     const angleSpacing = placeReactants ? reaction.angleSpacingReactant : reaction.angleSpacingProduct;
-    if (! angleSpacing! || isFinite(angleSpacing)) {
-        console.error("No angle spacing found");
-        return;
+    if (angleSpacing===undefined || isNaN(angleSpacing) || angleSpacing===null){ 
+        throw new Error("No angle spacing found");
     }
 
     sideCompounds.forEach((sideCompoundNode, i) => {
@@ -826,8 +838,8 @@ function determineDirection(typeInterval: number, placeReactants: boolean): numb
  * @returns The side compound node with updated coordinates.
  */
 function giveCoordSideCompound(sideCompound:Node,angle:number,center:{x:number,y:number},distance:number):Node{
-    sideCompound.x = center.x + distance * Math.cos(angle);
-    sideCompound.y = center.y + distance * Math.sin(angle);
+    sideCompound.x = Number((center.x + distance * Math.cos(angle)).toFixed(3));
+    sideCompound.y = Number((center.y + distance * Math.sin(angle)).toFixed(3));
     return sideCompound;
 }
 
diff --git a/src/composables/VizCoreFunctions.ts b/src/composables/VizCoreFunctions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..610a47b518deab012095453f90657c16cfdcd82e
--- /dev/null
+++ b/src/composables/VizCoreFunctions.ts
@@ -0,0 +1,124 @@
+// Type imports
+import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties";
+import { Network } from "@metabohub/viz-core/src/types/Network";
+import { Node } from "@metabohub/viz-core/src/types/Node";
+
+
+
+/*******************************************************************************************************************************************************/
+//___________________________________________________0.  Node duplication _________________________________________________________________________
+
+
+/**
+ * Duplicate all nodes according to a specific metadata attribut
+ * @param network Network object that contains all nodes
+ * @param attribut Metadata attribut of node. Must be a boolean
+ */
+export function duplicateAllNodesByAttribut(network: Network, networkStyle: GraphStyleProperties, attribut: string): void {
+    Object.keys(network.nodes).forEach((nodeID: string) => {
+      const node = network.nodes[nodeID] as Node;
+      if (node.metadata && node.metadata[attribut]) {
+        const checkAtt = node.metadata[attribut] as boolean;
+        if (checkAtt) {
+          duplicateNode(nodeID, network, networkStyle);
+        }
+      }
+    });
+  }
+
+
+  /**
+ * Duplicate specific node in network object
+ * @param nodeId Node id
+ * @param network Network object
+ * @param networkStyle Style object
+ */
+export function duplicateNode(nodeId: string, network: Network, networkStyle: GraphStyleProperties): void {
+    if (network.nodes[nodeId]) {
+      const linksIndex = [] as Array<number>;
+      const originalNode = network.nodes[nodeId];
+  
+      if (networkStyle.nodeStyles) {
+        networkStyle.nodeStyles['duplicate'] = {
+          fill: '#FFFFFF',
+          height: 10,
+          width: 10,
+          shape: 'circle',
+        }
+      } else {
+        networkStyle['nodeStyles'] = {
+          duplicate: {
+            fill: '#FFFFFF',
+            height: 10,
+            width: 10,
+            shape: 'circle',
+          }
+        }
+      }
+  
+      network.links.forEach((link) => {
+        if (link.source.id === nodeId || link.target.id === nodeId) {
+          const index = network.links.indexOf(link);
+          linksIndex.push(index);
+        }
+      });
+  
+      for (let i = 0; i < linksIndex.length; i++) {
+        
+        const newNode: Node = {
+          id: nodeId + i,
+          classes: ['duplicate'],
+          label: originalNode.label,
+          x: 0,
+          y: 0
+        };
+  
+        const index = linksIndex[i];
+  
+        if (network.links[index].source.id === nodeId) {
+          newNode.x = originalNode.x - ((originalNode.x - network.links[index].target.x) / 2);
+          newNode.y = originalNode.y - ((originalNode.y - network.links[index].target.y) / 2);
+          network.links[index].source = newNode;
+        }
+  
+        if (network.links[index].target.id === nodeId) {
+          newNode.x = originalNode.x - ((originalNode.x - network.links[index].source.x) / 2);
+          newNode.y = originalNode.y - ((originalNode.y - network.links[index].source.y) / 2);
+          network.links[index].target = newNode
+        }
+  
+        network.nodes[nodeId+i] = newNode;
+      }
+  
+      delete network.nodes[nodeId];
+    }
+  }
+  
+
+
+/*******************************************************************************************************************************************************/
+//___________________________________________________1.  Node suppresion _________________________________________________________________________
+
+
+/**
+ * Remove a list of nodes from network object
+ * @param listId Array of nodes id
+ * @param network Network object
+ */
+export function removeAllSelectedNodes(listId: Array<string>, network: Network): void {
+    listId.forEach((nodeId: string) => {
+      if (Object.keys(network.nodes).includes(nodeId)) {
+        delete network.nodes[nodeId];
+  
+        const links = network.links.filter((link) => {
+          if (link.source.id !== nodeId && link.target.id !== nodeId) {
+            return link;
+          }
+        });
+    
+        network.links = links;
+      }
+    });
+}
+  
+  
\ No newline at end of file
diff --git a/src/composables/__tests__/LayoutManageSideCompounds.test.ts b/src/composables/__tests__/LayoutManageSideCompounds.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2fc6785b5c947684eb229085d365c871d1f1e37d
--- /dev/null
+++ b/src/composables/__tests__/LayoutManageSideCompounds.test.ts
@@ -0,0 +1,765 @@
+// Type imports
+import { SubgraphNetwork } from "../../types/SubgraphNetwork";
+import { Network } from "@metabohub/viz-core/src/types/Network";
+import { Node } from "@metabohub/viz-core/src/types/Node";
+import { Link } from "@metabohub/viz-core/src/types/Link";
+import { MetaboliteType, Reaction, ReactionInterval } from "../../types/Reaction";
+import { VizArgs } from "../../types/EnumArgs";
+import { Coordinate } from "../../types/CoordinatesSize";
+import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties";
+import { NetworkLayout, NodeLayout } from "../../types/NetworkLayout";
+
+
+// Composable imports
+import * as LayoutManageSideCompounds from "../LayoutManageSideCompounds";
+import {sideCompoundAttribute} from "../GetSetAttributsNodes";
+import * as VizCoreFunctions from "../VizCoreFunctions";
+import * as CalculateSize from "../CalculateSize";
+import * as GetSetAttributsNodes from "../GetSetAttributsNodes";
+
+
+
+describe("LayoutManageSideCompounds", () => {
+
+    describe('putDuplicatedSideCompoundAside', () => {
+
+        let network: Network;
+        let subgraphNetwork: SubgraphNetwork;
+        let nodes: {[key: string]: Node};
+        let links:Link[];
+
+        let duplicateAllNodesByAttributMock: jest.SpyInstance;
+        let removeAllSelectedNodesMock: jest.SpyInstance;
+        let isSideCompoundMock: jest.SpyInstance;
+        let setAsSideCompoundMock: jest.SpyInstance;
+        let isDuplicateMock: jest.SpyInstance;
+
+        beforeEach(() => {
+
+            nodes={
+                nodeA:{id: 'nodeA',x: 0, y: 0},
+                nodeC:{id: 'nodeC',x: 2, y: 2,metadata:{[sideCompoundAttribute]:true}},
+                nodeD:{id: 'nodeD',x: 3, y: 3},
+                nodeE:{id: 'nodeE',x: 4, y: 4,metadata:{[sideCompoundAttribute]:true}},
+                nodeF:{id: 'nodeF',x: 5, y: 5},
+                nodeG:{id: 'nodeG',x: 6, y: 6},
+            };
+
+            links=[
+                {id:"link", source: nodes.nodeA, target: nodes.nodeF},
+                {id:"link", source: nodes.nodeC, target: nodes.nodeF},
+                {id:"link", source: nodes.nodeF, target: nodes.nodeD},
+                {id:"link", source: nodes.nodeF, target: nodes.nodeE},
+                {id:"link", source: nodes.nodeC, target: nodes.nodeG},
+            ]
+
+            network={
+                id: 'network',
+                nodes: nodes,
+                links: links,
+            };
+
+            subgraphNetwork={
+                network: network,
+                networkStyle: {}
+            };
+
+            // MOCK
+            duplicateAllNodesByAttributMock = jest.spyOn(VizCoreFunctions, 'duplicateAllNodesByAttribut');
+            duplicateAllNodesByAttributMock.mockImplementation(() => {
+                network.nodes['nodeC0'] = {id: 'nodeC0',x: 2, y: 2,classes: ['duplicate']};
+                network.nodes['nodeC1'] = {id: 'nodeC1',x: 2, y: 2,classes: ['duplicate']};
+                delete network.nodes['nodeC'];
+                network.nodes['nodeE0'] = {id: 'nodeE0',x: 4, y: 4,classes: ['duplicate']};
+                delete network.nodes['nodeE'];
+                network.links[1].source = network.nodes['nodeC0'];
+                network.links[4].source = network.nodes['nodeC1'];
+                network.links[3].target = network.nodes['nodeE0'];
+            });
+
+            removeAllSelectedNodesMock = jest.spyOn(VizCoreFunctions, 'removeAllSelectedNodes');
+            isSideCompoundMock = jest.spyOn(GetSetAttributsNodes, 'isSideCompound');
+            isSideCompoundMock.mockImplementation((node: NodeLayout) => {
+                return node.id === 'nodeC' || node.id === 'nodeC0'|| node.id === 'nodeC1' ||
+                 node.id === 'nodeE' || node.id === 'nodeE0';
+            });
+
+            setAsSideCompoundMock = jest.spyOn(GetSetAttributsNodes, 'setAsSideCompound');
+            setAsSideCompoundMock.mockImplementation((network:Network,nodeID: string) => {
+                if (network.nodes[nodeID].metadata){
+                network.nodes[nodeID].metadata[sideCompoundAttribute]=true;
+                }else{
+                    network.nodes[nodeID].metadata={[sideCompoundAttribute]:true};
+                }
+            });
+
+            isDuplicateMock = jest.spyOn(GetSetAttributsNodes, 'isDuplicate');
+            isDuplicateMock.mockImplementation((network:Network,nodeID: string) => {
+                return  nodeID === 'nodeC0'|| nodeID === 'nodeC1' || nodeID=== 'nodeE0';
+            });
+
+        });
+
+        afterEach(() => {
+            jest.clearAllMocks();
+        });
+
+        it('should only duplicate side compound', async () => {
+            
+            // DATA
+            const resultExpected = {
+                "network": {
+                  "id": "network",
+                  "nodes": {
+                    "nodeA": {"id": "nodeA", "x": 0, "y": 0},
+                    "nodeD": {"id": "nodeD", "x": 3, "y": 3},
+                    "nodeF": {"id": "nodeF", "x": 5, "y": 5},
+                    "nodeG": {"id": "nodeG", "x": 6, "y": 6},
+                    "nodeC0": {"id": "nodeC0", "x": 2, "y": 2, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                    "nodeC1": {"id": "nodeC1", "x": 2, "y": 2, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                    "nodeE0": {"id": "nodeE0", "x": 4, "y": 4, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                  },
+                  "links": [
+                    {"id": "link", "source": {"id": "nodeA", "x": 0, "y": 0}, "target": {"id": "nodeF", "x": 5, "y": 5}},
+                    {"id": "link", "source": {"id": "nodeC0", "x": 2, "y": 2, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}, "target": {"id": "nodeF", "x": 5, "y": 5}},
+                    {"id": "link", "source": {"id": "nodeF", "x": 5, "y": 5}, "target": {"id": "nodeD", "x": 3, "y": 3}},
+                    {"id": "link", "source": {"id": "nodeF", "x": 5, "y": 5}, "target": {"id": "nodeE0", "x": 4, "y": 4, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}},
+                    {"id": "link", "source": {"id": "nodeC1", "x": 2, "y": 2, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}, "target": {"id": "nodeG", "x": 6, "y": 6}}
+                  ]
+                },
+                "networkStyle": {}
+              }
+              
+
+            // TEST
+            const result = await LayoutManageSideCompounds.putDuplicatedSideCompoundAside(subgraphNetwork,true,false);
+
+            // EXPECT
+            expect(result).toEqual(resultExpected);
+
+        });
+
+        it('should put side compound aside', async () => {
+
+            // MOCK 
+            removeAllSelectedNodesMock.mockImplementation(() => {
+                delete network.nodes.nodeC;
+                 delete network.nodes.nodeE;
+                 const links = network.links.filter((link) => {
+                 if (link.source.id !== "nodeC" && link.target.id !== "nodeC" &&
+                     link.source.id !== "nodeE" && link.target.id !== "nodeE" 
+                 ) {
+                     return link;
+                 }
+                 });
+                 network.links = links;
+             });
+
+            // DATA
+             const resultExpected :SubgraphNetwork= {
+                "network": {
+                  "id": "network",
+                  "nodes": {
+                    "nodeA": {"id": "nodeA", "x": 0, "y": 0},
+                    "nodeD": {"id": "nodeD", "x": 3, "y": 3},
+                    "nodeF": {"id": "nodeF", "x": 5, "y": 5},
+                    "nodeG": {"id": "nodeG", "x": 6, "y": 6}
+                  },
+                  "links": [
+                    {"id": "link", "source": {"id": "nodeA", "x": 0, "y": 0}, "target": {"id": "nodeF", "x": 5, "y": 5}},
+                    {"id": "link", "source": {"id": "nodeF", "x": 5, "y": 5}, "target": {"id": "nodeD", "x": 3, "y": 3}}
+                  ]
+                },
+                "networkStyle": {},
+                "sideCompounds": {
+                  "nodeF": {
+                    "reactants": [
+                      {"id": "nodeC", "x": 2, "y": 2, "metadata": {"isSideCompound": true}}
+                    ],
+                    "products": [
+                      {"id": "nodeE", "x": 4, "y": 4, "metadata": {"isSideCompound": true}}
+                    ]
+                  },
+                  "nodeG": {
+                    "reactants": [
+                      {"id": "nodeC", "x": 2, "y": 2, "metadata": {"isSideCompound": true}}
+                    ],
+                    "products": []
+                  }
+                }
+              };
+              
+
+            // TEST
+            const result = await LayoutManageSideCompounds.putDuplicatedSideCompoundAside(subgraphNetwork,false,true);
+
+            // EXPECT
+            expect(result).toEqual(resultExpected);
+
+        });
+
+        it('should duplicate side compound and put them aside', async() => {
+            // MOCK
+            removeAllSelectedNodesMock.mockImplementation(() => {
+               delete network.nodes.nodeC0;
+                delete network.nodes.nodeC1;
+                delete network.nodes.nodeE0;
+                const links = network.links.filter((link) => {
+                if (link.source.id !== "nodeC0" && link.target.id !== "nodeC0" &&
+                    link.source.id !== "nodeC1" && link.target.id !== "nodeC1" &&
+                    link.source.id !== "nodeE0" && link.target.id !== "nodeE0" 
+                ) {
+                    return link;
+                }
+                });
+                network.links = links;
+            });
+
+            // DATA
+            const resultExpected :SubgraphNetwork= {
+                "network": {
+                  "id": "network",
+                  "nodes": {
+                    "nodeA": {"id": "nodeA", "x": 0, "y": 0},
+                    "nodeD": {"id": "nodeD", "x": 3, "y": 3},
+                    "nodeF": {"id": "nodeF", "x": 5, "y": 5},
+                    "nodeG": {"id": "nodeG", "x": 6, "y": 6}
+                  },
+                  "links": [
+                    {"id": "link", "source": {"id": "nodeA", "x": 0, "y": 0}, "target": {"id": "nodeF", "x": 5, "y": 5}},
+                    {"id": "link", "source": {"id": "nodeF", "x": 5, "y": 5}, "target": {"id": "nodeD", "x": 3, "y": 3}}
+                  ]
+                },
+                "networkStyle": {},
+                "sideCompounds": {
+                  "nodeF": {
+                    "reactants": [
+                      {"id": "nodeC0", "x": 2, "y": 2, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                    ],
+                    "products": [
+                      {"id": "nodeE0", "x": 4, "y": 4, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                    ]
+                  },
+                  "nodeG": {
+                    "reactants": [
+                      {"id": "nodeC1", "x": 2, "y": 2, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                    ],
+                    "products": []
+                  }
+                }
+              };
+              
+
+            // TEST
+            const result = await LayoutManageSideCompounds.putDuplicatedSideCompoundAside(subgraphNetwork,true,true);
+
+            // EXPECT
+            expect(result).toEqual(resultExpected);
+
+        });
+
+    });
+
+
+    describe('reinsertionSideCompounds', () => {
+
+        let subgraphNetworkDupliAside: SubgraphNetwork;
+        let minEdgeLengthMock: jest.SpyInstance;
+        let getMeanNodesSizePixelMock: jest.SpyInstance;
+        let inchesToPixelsMock: jest.SpyInstance;
+
+        beforeEach(() => {
+
+            const nodes:{[key:string]:NodeLayout}= {
+                    "nodeA": {"id": "nodeA", "x": 0, "y": 0},
+                    "nodeD": {"id": "nodeD", "x": 7, "y": 6},
+                    "nodeF": {"id": "nodeF", "x": 5, "y": 5, metadataLayout:{isReversedVersion:true}},
+                };
+            subgraphNetworkDupliAside = {
+                "network": {
+                  "id": "network",
+                  nodes:nodes,
+                  "links": [
+                    {"id": "link",source: nodes.nodeA, "target": nodes.nodeF},
+                    {"id": "link", source: nodes.nodeF, "target": nodes.nodeD}
+                  ]
+                },
+                "networkStyle": {},
+                "sideCompounds": {
+                  "nodeF": {
+                    "reactants": [
+                      {"id": "nodeC0", "x": 2, "y": 2, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                    ],
+                    "products": [
+                      {"id": "nodeE0", "x": 4, "y": 4, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                    ]
+                  }
+                }
+              };
+
+              // MOCK
+              minEdgeLengthMock = jest.spyOn(CalculateSize, 'minEdgeLength');
+              minEdgeLengthMock.mockReturnValue(3);
+
+              getMeanNodesSizePixelMock = jest.spyOn(CalculateSize, 'getMeanNodesSizePixel');
+              getMeanNodesSizePixelMock.mockReturnValue(Promise.resolve({height:2,width:2}));
+
+              inchesToPixelsMock = jest.spyOn(CalculateSize, 'inchesToPixels');
+              inchesToPixelsMock.mockReturnValue(2);
+           
+        });
+
+        afterEach(() => {
+            jest.clearAllMocks();
+        });
+
+
+        it('should throw error because reaction node in sideCompound but not in netwotk for update when reversed version', async () => {
+            // DATA
+            delete subgraphNetworkDupliAside.network.nodes.nodeF;
+
+            // TEST & EXPECT
+            await expect(LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true)).rejects.toThrow("Reaction in side compounds but not in network");
+        
+        });
+
+        it('should throw error because reaction node in sideCompound but not in network for initializeReactionSideCompounds (no update rev)', async () => {
+            // DATA
+            delete subgraphNetworkDupliAside.network.nodes.nodeF;
+
+            // TEST & EXPECT
+            await expect(LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,false)).rejects.toThrow();
+        
+        });
+
+
+        it('should t change network because no product or reactant in reaction in side compounds', async () => {
+            // DATA
+            if (subgraphNetworkDupliAside.sideCompounds && subgraphNetworkDupliAside.sideCompounds.nodeF){
+                subgraphNetworkDupliAside.sideCompounds.nodeF.products=[];
+                subgraphNetworkDupliAside.sideCompounds.nodeF.reactants=[];
+            }
+            
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+
+            // EXPECT 
+            expect(result.network).toEqual(subgraphNetworkDupliAside.network);
+        
+        });
+
+        it('should t change because no side compounds', async () => {
+            // DATA
+            delete subgraphNetworkDupliAside.sideCompounds;
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+
+            // EXPECT 
+            expect(result).toEqual(subgraphNetworkDupliAside);
+        
+        });
+
+        it('should t change because side compounds empty', async () => {
+            // DATA
+            subgraphNetworkDupliAside.sideCompounds={};
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+
+            // EXPECT 
+            expect(result).toEqual(subgraphNetworkDupliAside);
+        
+        });
+
+         it('should use min edge length by default, when no rank and node sep', async () => {
+            // MOCK
+            minEdgeLengthMock.mockReturnValue(NaN);
+
+            // DATA
+            const networkExpected:NetworkLayout  = {
+                "id": "network",
+                "nodes": {
+                  "nodeA": {"id": "nodeA", "x": 0, "y": 0},
+                  "nodeD": {"id": "nodeD", "x": 7, "y": 6},
+                  "nodeF": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                  "nodeE0": {
+                    "id": "nodeE0",
+                    "x": 3.006,
+                    "y": 5.161,
+                    "classes": ["duplicate"],
+                    "metadata": {"isSideCompound": true}
+                  },
+                  "nodeC0": {
+                    "id": "nodeC0",
+                    "x": 5.478,
+                    "y": 6.942,
+                    "classes": ["duplicate"],
+                    "metadata": {"isSideCompound": true}
+                  }
+                },
+                "links": [
+                  {
+                    "id": "link",
+                    "source": {"id": "nodeA", "x": 0, "y": 0},
+                    "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}
+                  },
+                  {
+                    "id": "link",
+                    "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                    "target": {"id": "nodeD", "x": 7, "y": 6}
+                  },
+                  {
+                    "id": "nodeE0--nodeF",
+                    "source": {
+                      "id": "nodeE0",
+                      "x": 3.006,
+                      "y": 5.161,
+                      "classes": ["duplicate"],
+                      "metadata": {"isSideCompound": true}
+                    },
+                    "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}
+                  },
+                  {
+                    "id": "nodeF--nodeC0",
+                    "source": {
+                      "id": "nodeF",
+                      "x": 5,
+                      "y": 5,
+                      "metadataLayout": {"isReversedVersion": true}
+                    },
+                    "target": {
+                      "id": "nodeC0",
+                      "x": 5.478,
+                      "y": 6.942,
+                      "classes": ["duplicate"],
+                      "metadata": {"isSideCompound": true}
+                    }
+                  }
+                ]
+              };
+              
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+            // => type interval : 0
+
+            // EXPECT
+            expect(result.network).toEqual(networkExpected);
+
+        });
+
+        it('should use min edge length by default, when rank and node sep', async () => {
+            // MOCK
+            minEdgeLengthMock.mockReturnValue(NaN);
+
+            // DATA
+            subgraphNetworkDupliAside.attributs={};
+            subgraphNetworkDupliAside.attributs[VizArgs.RANKSEP]=2;
+            subgraphNetworkDupliAside.attributs[VizArgs.NODESEP]=1;
+
+            const networkExpected:NetworkLayout= {
+                "id": "network",
+                "nodes": {
+                  "nodeA": {"id": "nodeA", "x": 0, "y": 0},
+                  "nodeD": {"id": "nodeD", "x": 7, "y": 6},
+                  "nodeF": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                  "nodeE0": {"id": "nodeE0", "x": 3.006, "y": 5.161, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                  "nodeC0": {"id": "nodeC0", "x": 5.478, "y": 6.942, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                },
+                "links": [
+                  {"id": "link", "source": {"id": "nodeA", "x": 0, "y": 0}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "link", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeD", "x": 7, "y": 6}},
+                  {"id": "nodeE0--nodeF", "source": {"id": "nodeE0", "x": 3.006, "y": 5.161, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "nodeF--nodeC0", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeC0", "x": 5.478, "y": 6.942, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}}
+                ]
+              }
+              
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+
+            // EXPECT
+            expect(result.network).toEqual(networkExpected);
+
+        });
+        
+
+
+        it('should reinsert side compounds when case of biggest interval includes angle 0 (test 1)', async () => {
+            // DATA
+            subgraphNetworkDupliAside.network.nodes.nodeD.x=6;
+            subgraphNetworkDupliAside.network.nodes.nodeD.y=7;
+
+            const networkExpected:NetworkLayout= {
+                "id": "network",
+                "nodes": {
+                  "nodeA": {"id": "nodeA", "x": 0, "y": 0},
+                  "nodeD": {"id": "nodeD", "x": 6, "y": 7},
+                  "nodeF": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                  "nodeE0": {"id": "nodeE0", "x": 5.242, "y": 2.01, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                  "nodeC0": {"id": "nodeC0", "x": 7.913, "y": 5.716, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                },
+                "links": [
+                  {
+                    "id": "link",
+                    "source": {"id": "nodeA", "x": 0, "y": 0},
+                    "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}
+                  },
+                  {
+                    "id": "link",
+                    "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                    "target": {"id": "nodeD", "x": 6, "y": 7}
+                  },
+                  {
+                    "id": "nodeE0--nodeF",
+                    "source": {"id": "nodeE0", "x": 5.242, "y": 2.01, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                    "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}
+                  },
+                  {
+                    "id": "nodeF--nodeC0",
+                    "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                    "target": {"id": "nodeC0", "x": 7.913, "y": 5.716, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                  }
+                ]
+              };
+              
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+            // => type interval : 2
+
+            // EXPECT
+            expect(result.network).toEqual(networkExpected);
+
+        
+        });
+
+        it('should reinsert side compounds but position of reactant and product is the other way', async () => {
+            // DATA 
+            subgraphNetworkDupliAside.network.nodes.nodeD.x=0;
+            subgraphNetworkDupliAside.network.nodes.nodeD.y=0;
+            subgraphNetworkDupliAside.network.nodes.nodeA.x=7;
+            subgraphNetworkDupliAside.network.nodes.nodeA.y=6;
+
+            const networkExpected:NetworkLayout= {
+                "id": "network",
+                "nodes": {
+                  "nodeA": {"id": "nodeA", "x": 7, "y": 6},
+                  "nodeD": {"id": "nodeD", "x": 0, "y": 0},
+                  "nodeF": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                  "nodeE0": {"id": "nodeE0", "x": 5.716, "y": 7.913, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                  "nodeC0": {"id": "nodeC0", "x": 2.01, "y": 5.242, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                },
+                "links": [
+                  {"id": "link", "source": {"id": "nodeA", "x": 7, "y": 6}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "link", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeD", "x": 0, "y": 0}},
+                  {"id": "nodeE0--nodeF", "source": {"id": "nodeE0", "x": 5.716, "y": 7.913, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "nodeF--nodeC0", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeC0", "x": 2.01, "y": 5.242, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}}
+                ]
+              }
+              
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+            // => type interval : 1
+
+            // EXPECT
+            expect(result.network).toEqual(networkExpected);
+        
+        });
+
+        it('should reinsert side compounds when case of biggest interval includes angle 0 (test 2)', async () => {
+
+            // DATA 
+            subgraphNetworkDupliAside.network.nodes.nodeD.x=0;
+            subgraphNetworkDupliAside.network.nodes.nodeD.y=0;
+            subgraphNetworkDupliAside.network.nodes.nodeA.x=6;
+            subgraphNetworkDupliAside.network.nodes.nodeA.y=7;
+
+            const networkExpected:NetworkLayout= {
+                "id": "network",
+                "nodes": {
+                  "nodeA": {"id": "nodeA", "x": 6, "y": 7},
+                  "nodeD": {"id": "nodeD", "x": 0, "y": 0},
+                  "nodeF": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                  "nodeE0": {"id": "nodeE0", "x": 7.913, "y": 5.716, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                  "nodeC0": {"id": "nodeC0", "x": 5.242, "y": 2.01, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                },
+                "links": [
+                  {"id": "link", "source": {"id": "nodeA", "x": 6, "y": 7}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "link", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeD", "x": 0, "y": 0}},
+                  {"id": "nodeE0--nodeF", "source": {"id": "nodeE0", "x": 7.913, "y": 5.716, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "nodeF--nodeC0", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeC0", "x": 5.242, "y": 2.01, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}}
+                ]
+              };
+            
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+            // => type interval : 3
+            
+            // EXPECT
+            expect(result.network).toEqual(networkExpected);
+        
+        });
+
+
+        it('should reinsert side compounds when only product in reaction', async () => {
+            // DATA
+            delete subgraphNetworkDupliAside.network.nodes.nodeA;
+            const newLinks=subgraphNetworkDupliAside.network.links.filter(link => link.source.id !== "nodeA");
+            subgraphNetworkDupliAside.network.links=newLinks;
+            const networkExpected:NetworkLayout= {
+                "id": "network",
+                "nodes": {
+                  "nodeD": {"id": "nodeD", "x": 7, "y": 6},
+                  "nodeF": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                  "nodeE0": {"id": "nodeE0", "x": 3.658, "y": 7.683, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                  "nodeC0": {"id": "nodeC0", "x": 6.341, "y": 2.316, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                },
+                "links": [
+                  {"id": "link", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeD", "x": 7, "y": 6}},
+                  {"id": "nodeE0--nodeF", "source": {"id": "nodeE0", "x": 3.658, "y": 7.683, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "nodeF--nodeC0", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeC0", "x": 6.341, "y": 2.316, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}}
+                ]
+              };
+              
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+            
+            // EXPECT
+            expect(result.network).toEqual(networkExpected);
+
+        });
+
+        it('should reinsert side compounds when only reactant in reaction', async () => {
+            // DATA
+            delete subgraphNetworkDupliAside.network.nodes.nodeD;
+            const newLinks=subgraphNetworkDupliAside.network.links.filter(link => link.target.id !== "nodeD");
+            subgraphNetworkDupliAside.network.links=newLinks;
+
+            const networkExpected:NetworkLayout= {
+                "id": "network",
+                "nodes": {
+                  "nodeA": {"id": "nodeA", "x": 0, "y": 0},
+                  "nodeF": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                  "nodeE0": {"id": "nodeE0", "x": 7.122, "y": 2.879, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                  "nodeC0": {"id": "nodeC0", "x": 2.879, "y": 7.122, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                },
+                "links": [
+                  {"id": "link", "source": {"id": "nodeA", "x": 0, "y": 0}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "nodeE0--nodeF", "source": {"id": "nodeE0", "x": 7.122, "y": 2.879, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "nodeF--nodeC0", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeC0", "x": 2.879, "y": 7.122, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}}
+                ]
+              };
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+
+            // EXPECT
+            expect(result.network).toEqual(networkExpected);
+
+        });
+
+        it('should reinsert side compounds when no reactant or product in reaction', async () => {
+            // DATA
+            delete subgraphNetworkDupliAside.network.nodes.nodeD;
+            delete subgraphNetworkDupliAside.network.nodes.nodeA;
+            subgraphNetworkDupliAside.network.links=[];
+
+            const networkExpected:NetworkLayout= {
+                "id": "network",
+                "nodes": {
+                  "nodeF": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                  "nodeE0": {"id": "nodeE0", "x": 4.999, "y": 2, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                  "nodeC0": {"id": "nodeC0", "x": 4.999, "y": 8, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                },
+                "links": [
+                  {"id": "nodeE0--nodeF", "source": {"id": "nodeE0", "x": 4.999, "y": 2, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "nodeF--nodeC0", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeC0", "x": 4.999, "y": 8, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}}
+                ]
+              };
+                 
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+
+            // EXPECT
+            expect(result.network).toEqual(networkExpected);
+        
+        });
+
+        
+
+        it('should reinsert side compounds with several side compound of same type (reactant or product)', async () => {
+            
+            // DATA
+            const nodeB0:NodeLayout={"id": "nodeB0", "x": 1, "y": 2, "classes": ["duplicate"], "metadata": {"isSideCompound": true}};
+            if (subgraphNetworkDupliAside.sideCompounds){
+                subgraphNetworkDupliAside.sideCompounds.nodeF.reactants.push(nodeB0);
+            }
+            const networkExpected:NetworkLayout= {
+                "id": "network",
+                "nodes": {
+                  "nodeA": {"id": "nodeA", "x": 0, "y": 0},
+                  "nodeD": {"id": "nodeD", "x": 7, "y": 6},
+                  "nodeF": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                  "nodeE0": {"id": "nodeE0", "x": 2.01, "y": 5.242, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                  "nodeC0": {"id": "nodeC0", "x": 6.517, "y": 7.588, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                  "nodeB0": {"id": "nodeB0", "x": 4.859, "y": 7.997, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                },
+                "links": [
+                  {"id": "link", "source": {"id": "nodeA", "x": 0, "y": 0}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "link", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeD", "x": 7, "y": 6}},
+                  {"id": "nodeE0--nodeF", "source": {"id": "nodeE0", "x": 2.01, "y": 5.242, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "nodeF--nodeC0", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeC0", "x": 6.517, "y": 7.588, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}},
+                  {"id": "nodeF--nodeB0", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeB0", "x": 4.859, "y": 7.997, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}}
+                ]
+              };
+              
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,true);
+
+            // EXPECT
+            expect(result.network).toEqual(networkExpected);
+
+        
+        });
+
+        it('should reinsert side compounds but no update of reaction reversible', async () => {
+            // DATA
+            const networkExpected:NetworkLayout= {
+                "id": "network",
+                "nodes": {
+                  "nodeA": {"id": "nodeA", "x": 0, "y": 0},
+                  "nodeD": {"id": "nodeD", "x": 7, "y": 6},
+                  "nodeF": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}},
+                  "nodeC0": {"id": "nodeC0", "x": 2.01, "y": 5.242, "classes": ["duplicate"], "metadata": {"isSideCompound": true}},
+                  "nodeE0": {"id": "nodeE0", "x": 5.716, "y": 7.913, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}
+                },
+                "links": [
+                  {"id": "link", "source": {"id": "nodeA", "x": 0, "y": 0}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "link", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeD", "x": 7, "y": 6}},
+                  {"id": "nodeC0--nodeF", "source": {"id": "nodeC0", "x": 2.01, "y": 5.242, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}, "target": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}},
+                  {"id": "nodeF--nodeE0", "source": {"id": "nodeF", "x": 5, "y": 5, "metadataLayout": {"isReversedVersion": true}}, "target": {"id": "nodeE0", "x": 5.716, "y": 7.913, "classes": ["duplicate"], "metadata": {"isSideCompound": true}}}
+                ]
+              };
+              
+
+            // TEST
+            const result = await LayoutManageSideCompounds.reinsertionSideCompounds(subgraphNetworkDupliAside,1,false);
+
+            // EXPECT
+            expect(result.network).toEqual(networkExpected);
+
+        });
+
+
+
+    });
+
+});
\ No newline at end of file