diff --git a/e2e/diagramme-modules.e2e-spec.ts b/e2e/diagramme-modules.e2e-spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a7a1b6c41dff8f7e924220ae2c835fa40f97afb3
--- /dev/null
+++ b/e2e/diagramme-modules.e2e-spec.ts
@@ -0,0 +1,60 @@
+import { browser, by, element } from "protractor";
+import { Navbar } from "./navbar.po";
+import { ListPage } from "./list.po";
+import { SideNav } from "./sidenav.po";
+import { PreferencesPage } from "./preferences.po";
+
+/**
+ * convert Mermaid formatted id ("flowchat-id-xx") to id
+ * COPIED from Jalhyd since import is not possible.
+ */
+function removeMermaidIdFormat(id: string): string {
+    if (id.startsWith("flowchart-")) {
+        const i1 = id.indexOf("-");
+        const i2 = id.lastIndexOf("-");
+        id = id.substring(i1 + 1, i2);
+    }
+    return id;
+}
+
+describe("modules diagram", async () => {
+    let navBar: Navbar;
+    let listPage: ListPage;
+    let sideNav: SideNav;
+    let prefPage: PreferencesPage;
+
+    beforeEach(async () => {
+        listPage = new ListPage();
+        navBar = new Navbar();
+        sideNav = new SideNav();
+        prefPage = new PreferencesPage();
+
+        await prefPage.navigateTo();
+    });
+
+    it("- check click on a module opens matching calculator", async () => {
+        //browser.manage().window().setPosition(2000, 30);
+
+        // open predam calculator
+        await navBar.clickNewCalculatorButton();
+        await listPage.clickMenuEntryForCalcType(30);
+        await browser.sleep(200);
+
+        // open modules diagram
+        await navBar.clickMenuButton();
+        await browser.sleep(200);
+        await sideNav.clickDiagramButton();
+        await browser.sleep(200);
+
+        // click first module
+        const nodes = element.all(by.css("g.node.default"));
+        const node0 = nodes.get(0);
+        const n0id = removeMermaidIdFormat(await node0.getAttribute("id"));
+        await node0.click();
+        await browser.sleep(200);
+
+        // check calculator is open
+        const url = await browser.driver.getCurrentUrl();
+        expect(url).toContain("/#/calculator/" + n0id);
+    });
+});
diff --git a/e2e/sidenav.po.ts b/e2e/sidenav.po.ts
index 970a1e5b60834538c7c5d542e2c0f83eb26302ee..437aef64433dcdc305a5730733e1fa812bb9d581 100644
--- a/e2e/sidenav.po.ts
+++ b/e2e/sidenav.po.ts
@@ -11,6 +11,10 @@ export class SideNav {
         return element(by.css("#side-nav-empty-session"));
     }
 
+    getDiagramButton() {
+        return element(by.css("#side-nav-diagram"));
+    }
+
     getFileInput() {
         return element(by.css(`dialog-load-session input[type="file"]`));
     }
@@ -29,6 +33,12 @@ export class SideNav {
         await ncb.click();
     }
 
+    async clickDiagramButton() {
+        const ncb = this.getDiagramButton();
+        await browser.sleep(500);
+        await ncb.click();
+    }
+
     async clickNewSessionButton() {
         const ncb = this.getNewSessionButton();
         await browser.sleep(200);
diff --git a/src/app/components/modules-diagram/modules-diagram.component.ts b/src/app/components/modules-diagram/modules-diagram.component.ts
index 6dbd40924b19daf186202ca521eeeb85cf674b55..ac60e24efd94837630d25c74b6c3a8e4f6476ce9 100644
--- a/src/app/components/modules-diagram/modules-diagram.component.ts
+++ b/src/app/components/modules-diagram/modules-diagram.component.ts
@@ -20,8 +20,8 @@ import {
     Pab,
     Solveur,
     Verificateur,
-    Espece,
-    FishSpecies
+    FishSpecies,
+    MermaidUtil
 } from "jalhyd";
 
 import { I18nService } from "../../services/internationalisation.service";
@@ -255,8 +255,8 @@ export class ModulesDiagramComponent implements AfterContentInit, AfterViewCheck
         return this.graphDefinition();
     }
 
-    public openCalc(uid: string) {
-        this.router.navigate(["/calculator", uid]);
+    private openCalc(uid: string) {
+        this.router.navigate(["/calculator", MermaidUtil.removeMermaidIdFormat(uid)]);
     }
 
     /**
@@ -283,7 +283,7 @@ export class ModulesDiagramComponent implements AfterContentInit, AfterViewCheck
      */
     private formIsOpen(uid: string) {
         for (const f of this.formulaireService.formulaires) {
-            if (f.currentNub.uid === uid) {
+            if (MermaidUtil.isMermaidId(f.currentNub.uid, uid)) {
                 return true;
             }
         }
diff --git a/src/app/components/pb-schema/pb-schema.component.ts b/src/app/components/pb-schema/pb-schema.component.ts
index cc93dfab0accff583ca3e9dc07ad4f9b0c2d3c74..347e451a60ebbd931b9e74ea329cac8ae72a1685 100644
--- a/src/app/components/pb-schema/pb-schema.component.ts
+++ b/src/app/components/pb-schema/pb-schema.component.ts
@@ -4,7 +4,7 @@ import { MatDialog } from "@angular/material/dialog";
 import screenfull from "screenfull";
 
 import {
-    PreBarrage, PbBassin, PbBassinParams, PbCloison, Observer, IObservable, ParamDefinition, ParamValueMode
+    PreBarrage, PbBassin, PbBassinParams, PbCloison, Observer, IObservable, MermaidUtil
  } from "jalhyd";
 
 import mermaid from "mermaid";
@@ -307,7 +307,7 @@ export class PbSchemaComponent implements AfterViewInit, AfterContentInit, OnIni
      * @param itemId id to find
      */
     private matchMermaidIds(ids: string[], itemId: string): boolean {
-        return ids.find(id => PreBarrage.isMermaidId(id, itemId)) !== undefined;
+        return ids.find(id => MermaidUtil.isMermaidId(id, itemId)) !== undefined;
     }
 
     /**
@@ -415,7 +415,7 @@ export class PbSchemaComponent implements AfterViewInit, AfterContentInit, OnIni
      */
     private selectNodeOnSchema(element: PbBassin | PbCloison) {
         this.nativeElement.querySelectorAll("g.node").forEach(item => {
-            if (element !== undefined && PreBarrage.isMermaidId(element.uid, item.id)) {
+            if (element !== undefined && MermaidUtil.isMermaidId(element.uid, item.id)) {
                 this.selectNode(item);
             }
         });