diff --git a/e2e/calculator.po.ts b/e2e/calculator.po.ts
index d4b7a51d5adc0649cc0a73b1fdb2a04ce2ff1a7b..9d05454ed7dc9e1d90855850777fa2d4b79e76f6 100644
--- a/e2e/calculator.po.ts
+++ b/e2e/calculator.po.ts
@@ -1,4 +1,4 @@
-import { browser, by, element } from "protractor";
+import { by, element, ElementFinder, browser } from "protractor";
 
 export class CalculatorPage {
 
@@ -9,4 +9,66 @@ export class CalculatorPage {
   getHeader1() {
     return element(by.css("h1"));
   }
+
+  getSelectById(id: string) {
+    return element(by.css("mat-select#" + id));
+  }
+
+  getInputById(id: string) {
+    return element(by.css("input#" + id));
+  }
+
+  getSaveSessionButton() {
+    return element(by.css("dialog-save-session button[type=submit]"));
+  }
+
+  scrollTo(elt: ElementFinder) {
+    browser.controlFlow().execute(function() {
+      browser.executeScript("arguments[0].scrollIntoView(true)", elt.getWebElement());
+    });
+  }
+
+  async clickSaveCalcButton() {
+    return await element(by.css("#save-calc")).click();
+  }
+
+  async clickCloneCalcButton() {
+    const cloneButton = element(by.css("#clone-calc"));
+    return await cloneButton.click();
+  }
+
+  async changeSelectValue(elt: ElementFinder, index: number) {
+    await elt.click();
+    const options = (await elt.getAttribute("aria-owns")).split(" ");
+    const optId = options[index];
+    const option = element(by.id(optId));
+    await option.click();
+  }
+
+  // find parent element of elt having class "container"
+  async findParentContainer(elt: ElementFinder): Promise<ElementFinder> {
+    let i = 8; // garde fous
+    while ((await elt.getAttribute("class") !== "container") && (i >= 0)) {
+      elt = elt.element(by.xpath(".."));
+      i--;
+    }
+    return elt;
+  }
+
+  /**
+   * @param elt an <input> element
+   * @param mode "fix", "var", "cal" or "link"
+   */
+  async setParamMode(elt: ElementFinder, mode: string) {
+    // get parent (div.container)
+    const container = await this.findParentContainer(elt);
+    // find radio buttons
+    const button = container.element(by.css("button#radio_" + mode + "-button"));
+    await button.click();
+    // for "var" mode, close the modal
+    if (mode === "var") {
+      await browser.sleep(500);
+      await element(by.css("dialog-edit-param-values .mat-dialog-actions button")).click();
+    }
+  }
 }
diff --git a/e2e/clone-calc.e2e-spec.ts b/e2e/clone-calc.e2e-spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..21b6206f784d2e219f8ab845a1437a26c73a3570
--- /dev/null
+++ b/e2e/clone-calc.e2e-spec.ts
@@ -0,0 +1,68 @@
+import { AppPage } from "./app.po";
+import { ListPage } from "./list.po";
+import { CalculatorPage } from "./calculator.po";
+import { Navbar } from "./navbar.po";
+import { SideNav } from "./sidenav.po";
+import { browser } from "protractor";
+
+describe("ngHyd − clone a calculator", () => {
+  let startPage: AppPage;
+  let listPage: ListPage;
+  let calcPage: CalculatorPage;
+  let navbar: Navbar;
+  let sidenav: SideNav;
+
+  beforeEach(() => {
+    startPage = new AppPage();
+    listPage = new ListPage();
+    calcPage = new CalculatorPage();
+    navbar = new Navbar();
+    sidenav = new SideNav();
+  });
+
+  it("when cloning a calculator, the clone should have the same values for all parameters", async () => {
+    await startPage.navigateTo();
+
+    // 1. create target modules for linked parameter
+    await listPage.clickMenuEntryForCalcType(3); // Régime uniforme
+    await browser.sleep(500);
+    const debitRU = calcPage.getInputById("calc_Q"); // "Débit" is calculated by default
+    await calcPage.setParamMode(debitRU, "fix");
+    await browser.sleep(500);
+
+    await navbar.clickNewCalculatorButton();
+    await listPage.clickMenuEntryForCalcType(4); // Courbe de remous
+    await browser.sleep(500);
+
+    // 2. create source module to clone
+    await navbar.clickNewCalculatorButton();
+    await listPage.clickMenuEntryForCalcType(2); // Section paramétrée
+    await browser.sleep(500);
+
+    // 3. change and store source parameter values
+    const sourceValues = {
+      k: 0.6,
+      Ks: 42
+    };
+    // await calcPage.changeSelectValue(calcPage.getSelectById("select_section"), 3); // mode "parabolique"
+    // await calcPage.getInputById("k").clear();
+    // await calcPage.getInputById("k").sendKeys(sourceValues["k"]);
+    await calcPage.getInputById("Ks").clear();
+    await calcPage.getInputById("Ks").sendKeys(sourceValues["Ks"]);
+    // link "Débit" to "Courbe de remous"
+    const debitSP = calcPage.getInputById("Q");
+    await calcPage.setParamMode(debitSP, "link");
+    await browser.sleep(500);
+    await calcPage.changeSelectValue(calcPage.getSelectById("linked_Q"), 1); // "Courbe de remous"
+    await browser.sleep(500);
+
+    // otherwise clickCloneCalcButton() fails with "Element is not clickable at point"
+    await browser.executeScript("window.scrollTo(0, 0);");
+    await calcPage.clickCloneCalcButton();
+    await browser.sleep(500);
+    // 4. check the cloned module
+    expect(await navbar.getAllCalculatorTabs().count()).toBe(4);
+    await navbar.clickCalculatorTab(3); // n°3 should be the latest
+
+  });
+});
diff --git a/e2e/list.po.ts b/e2e/list.po.ts
index 2f06248a15933ff12b610e0870991d8d4cfe39dc..4e32624df6e5941c5b92c91bcf08d71044e4bf24 100644
--- a/e2e/list.po.ts
+++ b/e2e/list.po.ts
@@ -27,4 +27,9 @@ export class ListPage {
     const r = Math.min((Math.floor(Math.random() * l)), (l - 1));
     return menuEntries.get(r).click();
   }
+
+  async clickMenuEntryForCalcType(type: number) {
+    const but = element(by.css("#create-calc-" + type));
+    return but.click();
+  }
 }
diff --git a/e2e/load-save-session.e2e-spec.ts b/e2e/load-save-session.e2e-spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b288a375f9e67fb0f83f6f2a90386fae3d058624
--- /dev/null
+++ b/e2e/load-save-session.e2e-spec.ts
@@ -0,0 +1,86 @@
+import { AppPage } from "./app.po";
+import { ListPage } from "./list.po";
+import { CalculatorPage } from "./calculator.po";
+import { Navbar } from "./navbar.po";
+import { SideNav } from "./sidenav.po";
+import { browser } from "protractor";
+
+describe("ngHyd − save and load sessions", () => {
+  let startPage: AppPage;
+  let listPage: ListPage;
+  let calcPage: CalculatorPage;
+  let navbar: Navbar;
+  let sidenav: SideNav;
+
+  beforeEach(() => {
+    startPage = new AppPage();
+    listPage = new ListPage();
+    calcPage = new CalculatorPage();
+    navbar = new Navbar();
+    sidenav = new SideNav();
+  });
+
+  it("when loading session-6-calc.test.json file from home page, 6 calculators should be loaded", async () => {
+    await startPage.navigateTo();
+
+    await navbar.clickMenuButton();
+    await browser.sleep(200);
+
+    await sidenav.clickLoadSessionButton();
+    await browser.sleep(200);
+
+    await sidenav.loadSessionFile("./session-6-calc.test.json");
+    await browser.sleep(200);
+
+    expect(await navbar.getAllCalculatorTabs().count()).toBe(6);
+  });
+
+  it("when loading session-optional-params.test.json file from home page, the calculator should be loaded", async () => {
+    await startPage.navigateTo();
+
+    await navbar.clickMenuButton();
+    await browser.sleep(200);
+
+    await sidenav.clickLoadSessionButton();
+    await browser.sleep(200);
+
+    await sidenav.loadSessionFile("./session-optional-params.test.json");
+    await browser.sleep(200);
+
+    expect(await navbar.getAllCalculatorTabs().count()).toBe(1);
+  });
+
+  it("when saving a calculator, the current parameter values should be found in the file", async () => {
+    await startPage.navigateTo();
+
+    await listPage.clickMenuEntryForCalcType(2); // Section paramétrée
+    await browser.sleep(500);
+
+    await calcPage.changeSelectValue(calcPage.getSelectById("select_section"), 2); // mode "circulaire"
+
+    await calcPage.getInputById("Ks").clear(); // coefficient de Strickler
+    await calcPage.getInputById("Ks").sendKeys("42");
+
+    await calcPage.clickSaveCalcButton();
+
+    // see: https://stackoverflow.com/questions/21935696/protractor-e2e-test-case-for-downloading-pdf-file
+    const fs = require("fs");
+    const path = require("path");
+    const os = require("os");
+    const filename = path.resolve(os.homedir(), "Téléchargements/session.json");
+    if (fs.existsSync(filename)) {
+        // Make sure the browser doesn't have to rename the download.
+        fs.unlinkSync(filename);
+    }
+
+    await calcPage.getSaveSessionButton().click();
+    await browser.sleep(1000);
+    const fileContent = fs.readFileSync(filename, { encoding: "utf8" });
+
+    // tslint:disable-next-line:quotemark
+    expect(fileContent).toContain('{"id":"select_section","selected_id":"select_section_circ"}');
+    // tslint:disable-next-line:quotemark
+    expect(fileContent).toContain('{"param":{"id":"Ks","values":{"mode":"SINGLE","value":42}}}');
+  });
+
+});
diff --git a/e2e/load-sesssion.e2e-spec.ts b/e2e/load-sesssion.e2e-spec.ts
deleted file mode 100644
index 39f919a41a020378ddc0b05f33fc0d179d3c6cbd..0000000000000000000000000000000000000000
--- a/e2e/load-sesssion.e2e-spec.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { AppPage } from "./app.po";
-import { Navbar } from "./navbar.po";
-import { SideNav } from "./sidenav.po";
-import { browser } from "protractor";
-
-describe("ngHyd − start page", () => {
-  let page: AppPage;
-  let navbar: Navbar;
-  let sidenav: SideNav;
-
-  beforeEach(() => {
-    page = new AppPage();
-    navbar = new Navbar();
-    sidenav = new SideNav();
-  });
-
-  it("when loading session-6-calc.test.json file from home page, 6 calculators should be loaded", async () => {
-    await page.navigateTo();
-
-    await navbar.clickMenuButton();
-    await browser.sleep(200);
-
-    await sidenav.clickLoadSessionButton();
-    await browser.sleep(200);
-
-    await sidenav.loadSessionFile("./session-6-calc.test.json");
-    await browser.sleep(200);
-
-    expect(await navbar.getAllCalculatorTabs().count()).toBe(6);
-  });
-
-  /*it("when app starts, user should see the list of available compute nodes", () => {
-    page.navigateTo();
-    expect(page.getListLength()).toBeGreaterThan(8);
-  });*/
-});
diff --git a/e2e/session-6-calc.test.json b/e2e/session-6-calc.test.json
index 070c2019ffbbcf04af8916c80df6de9adf073391..4dab5ec3d21e82dee47b8e81bc24a04328e71317 100644
--- a/e2e/session-6-calc.test.json
+++ b/e2e/session-6-calc.test.json
@@ -1 +1,811 @@
-{"session":{"elements":[{"form":{"id":"Conduite distributrice (MTJmNH)","uid":"MTJmNH","props":{"calcType":0,"nodeType":0},"elements":[{"fieldset":{"id":"fs_hydraulique","props":{"calcType":0,"nodeType":0},"elements":[{"param":{"id":"Q","values":{"mode":"SINGLE","value":3}}},{"param":{"id":"D","values":{"mode":"SINGLE","value":1.2}}},{"param":{"id":"J","values":{"mode":"CALCUL"}}},{"param":{"id":"Lg","values":{"mode":"SINGLE","value":100}}},{"param":{"id":"Nu","values":{"mode":"SINGLE","value":0.000001}}}]}},{"fieldset":{"id":"fs_param_calc","props":{"calcType":0,"nodeType":0},"elements":[{"param":{"id":"Pr","values":{"mode":"SINGLE","value":0.0001}}}]}}]}},{"form":{"id":"Lechapt-Calmon (NHdtdT)","uid":"NHdtdT","props":{"calcType":1,"nodeType":0},"elements":[{"fieldset":{"id":"fs_materiau","props":{"calcType":1,"nodeType":0},"elements":[{"select":{"id":"select_material","selected_id":"select_material_1"}},{"param":{"id":"L","values":{"mode":"SINGLE","value":1.863}}},{"param":{"id":"M","values":{"mode":"SINGLE","value":2}}},{"param":{"id":"N","values":{"mode":"SINGLE","value":5.33}}}]}},{"fieldset":{"id":"fs_hydraulique","props":{"calcType":1,"nodeType":0},"elements":[{"param":{"id":"Q","values":{"mode":"SINGLE","value":3}}},{"param":{"id":"D","values":{"mode":"SINGLE","value":1.2}}},{"param":{"id":"J","values":{"mode":"CALCUL"}}},{"param":{"id":"Lg","values":{"mode":"SINGLE","value":100}}}]}},{"fieldset":{"id":"fs_param_calc","props":{"calcType":1,"nodeType":0},"elements":[{"param":{"id":"Pr","values":{"mode":"SINGLE","value":0.0001}}}]}}]}},{"form":{"id":"Section paramétrée (YjZxc2)","uid":"YjZxc2","props":{"calcType":2,"nodeType":2},"elements":[{"fieldset":{"id":"fs_section","props":{"calcType":2,"nodeType":2},"elements":[{"select":{"id":"select_section","selected_id":"select_section_rect"}},{"param":{"id":"LargeurBerge","values":{"mode":"SINGLE","value":2.5}}}]}},{"fieldset":{"id":"fs_bief","props":{"calcType":2,"nodeType":2},"elements":[{"param":{"id":"Ks","values":{"mode":"SINGLE","value":40}}},{"param":{"id":"If","values":{"mode":"SINGLE","value":0.001}}},{"param":{"id":"YB","values":{"mode":"SINGLE","value":1}}}]}},{"fieldset":{"id":"fs_hydraulique","props":{"calcType":2,"nodeType":2},"elements":[{"param":{"id":"Q","values":{"mode":"SINGLE","value":1.2}}},{"param":{"id":"Y","values":{"mode":"SINGLE","value":0.8}}}]}},{"fieldset":{"id":"fs_param_calc","props":{"calcType":2,"nodeType":2},"elements":[{"param":{"id":"Pr","values":{"mode":"SINGLE","value":0.0001}}}]}},{"fieldset":{"id":"fs_computed_var","props":{"calcType":2,"nodeType":2},"elements":[{"select":{"id":"select_target","selected_id":"select_target_Hs"}}]}}]}},{"form":{"id":"Régime uniforme (ZmEwcX)","uid":"ZmEwcX","props":{"calcType":3,"nodeType":2},"elements":[{"fieldset":{"id":"fs_section","props":{"calcType":3,"nodeType":2},"elements":[{"select":{"id":"select_section","selected_id":"select_section_rect"}},{"param":{"id":"LargeurBerge","values":{"mode":"SINGLE","value":2.5}}}]}},{"fieldset":{"id":"fs_bief","props":{"calcType":3,"nodeType":2},"elements":[{"param":{"id":"Ks","values":{"mode":"SINGLE","value":40}}},{"param":{"id":"If","values":{"mode":"SINGLE","value":0.001}}},{"param":{"id":"YB","values":{"mode":"SINGLE","value":1}}}]}},{"fieldset":{"id":"fs_hydraulique","props":{"calcType":3,"nodeType":2},"elements":[{"param":{"id":"Q","values":{"mode":"CALCUL"}}},{"param":{"id":"Y","values":{"mode":"SINGLE","value":0.8}}}]}},{"fieldset":{"id":"fs_param_calc","props":{"calcType":3,"nodeType":2},"elements":[{"param":{"id":"Pr","values":{"mode":"SINGLE","value":0.0001}}}]}}]}},{"form":{"id":"Courbes de remous (NHdmeG)","uid":"NHdmeG","props":{"calcType":4,"nodeType":2},"elements":[{"fieldset":{"id":"fs_section","props":{"calcType":4,"nodeType":2},"elements":[{"select":{"id":"select_section","selected_id":"select_section_rect"}},{"param":{"id":"LargeurBerge","values":{"mode":"SINGLE","value":2.5}}}]}},{"fieldset":{"id":"fs_bief","props":{"calcType":4,"nodeType":2},"elements":[{"param":{"id":"Ks","values":{"mode":"SINGLE","value":40}}},{"param":{"id":"Long","values":{"mode":"SINGLE","value":100}}},{"param":{"id":"If","values":{"mode":"SINGLE","value":0.001}}},{"param":{"id":"YB","values":{"mode":"SINGLE","value":1}}}]}},{"fieldset":{"id":"fs_condlim","props":{"calcType":4,"nodeType":2},"elements":[{"param":{"id":"Q","values":{"mode":"SINGLE","value":1.2}}},{"param":{"id":"Yaval","values":{"mode":"SINGLE","value":0.4}}},{"param":{"id":"Yamont","values":{"mode":"SINGLE","value":0.15}}}]}},{"fieldset":{"id":"fs_param_calc","props":{"calcType":4,"nodeType":2},"elements":[{"param":{"id":"Dx","values":{"mode":"SINGLE","value":5}}},{"param":{"id":"Pr","values":{"mode":"SINGLE","value":0.0001}}},{"select":{"id":"select_resolution","selected_id":"select_resolution_trap"}}]}},{"fieldset":{"id":"fs_target_data","props":{"calcType":4,"nodeType":2},"elements":[{"select":{"id":"select_target","selected_id":"select_target_none"}}]}}]}},{"form":{"id":"Lois d'ouvrages (Yzgxan)","uid":"Yzgxan","props":{"calcType":8,"nodeType":0},"elements":[{"fieldset":{"id":"fs_param_hydro","props":{"calcType":8,"nodeType":0},"elements":[{"param":{"id":"Q","values":{"mode":"CALCUL"}}},{"param":{"id":"Z1","values":{"mode":"SINGLE","value":102}}},{"param":{"id":"Z2","values":{"mode":"SINGLE","value":101.5}}}]}},{"fieldset_container":{"id":"struct_container","elements":[{"fieldset":{"id":"fs_ouvrage","props":{"calcType":7,"nodeType":5,"structureType":1,"loiDebit":1},"elements":[{"select":{"id":"select_ouvrage","selected_id":"select_ouvrage_vanne_rect"}},{"select":{"id":"select_loidebit1","selected_id":"select_loidebit1_cem88d"}},{"select":{"id":"select_loidebit2","selected_id":"select_loidebit2_cem88v"}},{"select":{"id":"select_loidebit3","selected_id":"select_loidebit3_seuiltriang"}},{"select":{"id":"select_loidebit4","selected_id":"select_loidebit4_seuiltriangtrunc"}},{"param":{"id":"ZDV","values":{"mode":"SINGLE","value":100}}},{"param":{"id":"L","values":{"mode":"SINGLE","value":2}}},{"param":{"id":"W","values":{"mode":"SINGLE","value":null}}},{"param":{"id":"Cd","values":{"mode":"SINGLE","value":0.4}}}]}}]}},{"fieldset":{"id":"fs_param_calc","props":{"calcType":8,"nodeType":0},"elements":[{"param":{"id":"Pr","values":{"mode":"SINGLE","value":0.0001}}}]}}]}}]}}
\ No newline at end of file
+{
+    "session": {
+        "elements": [
+            {
+                "form": {
+                    "id": "Conduite distributrice (MTJmNH)",
+                    "uid": "MTJmNH",
+                    "props": {
+                        "calcType": 0,
+                        "nodeType": 0
+                    },
+                    "elements": [
+                        {
+                            "fieldset": {
+                                "id": "fs_hydraulique",
+                                "props": {
+                                    "calcType": 0,
+                                    "nodeType": 0
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Q",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 3
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "D",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 1.2
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "J",
+                                            "values": {
+                                                "mode": "CALCUL"
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Lg",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 100
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Nu",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.000001
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_param_calc",
+                                "props": {
+                                    "calcType": 0,
+                                    "nodeType": 0
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Pr",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.0001
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    ]
+                }
+            },
+            {
+                "form": {
+                    "id": "Lechapt-Calmon (NHdtdT)",
+                    "uid": "NHdtdT",
+                    "props": {
+                        "calcType": 1,
+                        "nodeType": 0
+                    },
+                    "elements": [
+                        {
+                            "fieldset": {
+                                "id": "fs_materiau",
+                                "props": {
+                                    "calcType": 1,
+                                    "nodeType": 0
+                                },
+                                "elements": [
+                                    {
+                                        "select": {
+                                            "id": "select_material",
+                                            "selected_id": "select_material_1"
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "L",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 1.863
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "M",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 2
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "N",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 5.33
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_hydraulique",
+                                "props": {
+                                    "calcType": 1,
+                                    "nodeType": 0
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Q",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 3
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "D",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 1.2
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "J",
+                                            "values": {
+                                                "mode": "CALCUL"
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Lg",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 100
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_param_calc",
+                                "props": {
+                                    "calcType": 1,
+                                    "nodeType": 0
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Pr",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.0001
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    ]
+                }
+            },
+            {
+                "form": {
+                    "id": "Section paramétrée (YjZxc2)",
+                    "uid": "YjZxc2",
+                    "props": {
+                        "calcType": 2,
+                        "nodeType": 2
+                    },
+                    "elements": [
+                        {
+                            "fieldset": {
+                                "id": "fs_section",
+                                "props": {
+                                    "calcType": 2,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "select": {
+                                            "id": "select_section",
+                                            "selected_id": "select_section_rect"
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "LargeurBerge",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 2.5
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_bief",
+                                "props": {
+                                    "calcType": 2,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Ks",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 40
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "If",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.001
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "YB",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 1
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_hydraulique",
+                                "props": {
+                                    "calcType": 2,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Q",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 1.2
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Y",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.8
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_param_calc",
+                                "props": {
+                                    "calcType": 2,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Pr",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.0001
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_computed_var",
+                                "props": {
+                                    "calcType": 2,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "select": {
+                                            "id": "select_target",
+                                            "selected_id": "select_target_Hs"
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    ]
+                }
+            },
+            {
+                "form": {
+                    "id": "Régime uniforme (ZmEwcX)",
+                    "uid": "ZmEwcX",
+                    "props": {
+                        "calcType": 3,
+                        "nodeType": 2
+                    },
+                    "elements": [
+                        {
+                            "fieldset": {
+                                "id": "fs_section",
+                                "props": {
+                                    "calcType": 3,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "select": {
+                                            "id": "select_section",
+                                            "selected_id": "select_section_rect"
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "LargeurBerge",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 2.5
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_bief",
+                                "props": {
+                                    "calcType": 3,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Ks",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 40
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "If",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.001
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "YB",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 1
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_hydraulique",
+                                "props": {
+                                    "calcType": 3,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Q",
+                                            "values": {
+                                                "mode": "CALCUL"
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Y",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.8
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_param_calc",
+                                "props": {
+                                    "calcType": 3,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Pr",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.0001
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    ]
+                }
+            },
+            {
+                "form": {
+                    "id": "Courbes de remous (NHdmeG)",
+                    "uid": "NHdmeG",
+                    "props": {
+                        "calcType": 4,
+                        "nodeType": 2
+                    },
+                    "elements": [
+                        {
+                            "fieldset": {
+                                "id": "fs_section",
+                                "props": {
+                                    "calcType": 4,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "select": {
+                                            "id": "select_section",
+                                            "selected_id": "select_section_rect"
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "LargeurBerge",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 2.5
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_bief",
+                                "props": {
+                                    "calcType": 4,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Ks",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 40
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Long",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 100
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "If",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.001
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "YB",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 1
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_condlim",
+                                "props": {
+                                    "calcType": 4,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Q",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 1.2
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Yaval",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.4
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Yamont",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.15
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_param_calc",
+                                "props": {
+                                    "calcType": 4,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Dx",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 5
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Pr",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.0001
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "select": {
+                                            "id": "select_resolution",
+                                            "selected_id": "select_resolution_trap"
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_target_data",
+                                "props": {
+                                    "calcType": 4,
+                                    "nodeType": 2
+                                },
+                                "elements": [
+                                    {
+                                        "select": {
+                                            "id": "select_target",
+                                            "selected_id": "select_target_none"
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    ]
+                }
+            },
+            {
+                "form": {
+                    "id": "Lois d'ouvrages (Yzgxan)",
+                    "uid": "Yzgxan",
+                    "props": {
+                        "calcType": 8,
+                        "nodeType": 0
+                    },
+                    "elements": [
+                        {
+                            "fieldset": {
+                                "id": "fs_param_hydro",
+                                "props": {
+                                    "calcType": 8,
+                                    "nodeType": 0
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Q",
+                                            "values": {
+                                                "mode": "CALCUL"
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Z1",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 102
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Z2",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 101.5
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset_container": {
+                                "id": "struct_container",
+                                "elements": [
+                                    {
+                                        "fieldset": {
+                                            "id": "fs_ouvrage",
+                                            "props": {
+                                                "calcType": 7,
+                                                "nodeType": 5,
+                                                "structureType": 1,
+                                                "loiDebit": 1
+                                            },
+                                            "elements": [
+                                                {
+                                                    "select": {
+                                                        "id": "select_ouvrage",
+                                                        "selected_id": "select_ouvrage_vanne_rect"
+                                                    }
+                                                },
+                                                {
+                                                    "select": {
+                                                        "id": "select_loidebit1",
+                                                        "selected_id": "select_loidebit1_cem88d"
+                                                    }
+                                                },
+                                                {
+                                                    "select": {
+                                                        "id": "select_loidebit2",
+                                                        "selected_id": "select_loidebit2_cem88v"
+                                                    }
+                                                },
+                                                {
+                                                    "select": {
+                                                        "id": "select_loidebit3",
+                                                        "selected_id": "select_loidebit3_seuiltriang"
+                                                    }
+                                                },
+                                                {
+                                                    "select": {
+                                                        "id": "select_loidebit4",
+                                                        "selected_id": "select_loidebit4_seuiltriangtrunc"
+                                                    }
+                                                },
+                                                {
+                                                    "param": {
+                                                        "id": "ZDV",
+                                                        "values": {
+                                                            "mode": "SINGLE",
+                                                            "value": 100
+                                                        }
+                                                    }
+                                                },
+                                                {
+                                                    "param": {
+                                                        "id": "L",
+                                                        "values": {
+                                                            "mode": "SINGLE",
+                                                            "value": 2
+                                                        }
+                                                    }
+                                                },
+                                                {
+                                                    "param": {
+                                                        "id": "W",
+                                                        "values": {
+                                                            "mode": "SINGLE",
+                                                            "value": null
+                                                        }
+                                                    }
+                                                },
+                                                {
+                                                    "param": {
+                                                        "id": "Cd",
+                                                        "values": {
+                                                            "mode": "SINGLE",
+                                                            "value": 0.4
+                                                        }
+                                                    }
+                                                }
+                                            ]
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_param_calc",
+                                "props": {
+                                    "calcType": 8,
+                                    "nodeType": 0
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Pr",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.0001
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    ]
+                }
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/e2e/session-optional-params.test.json b/e2e/session-optional-params.test.json
new file mode 100644
index 0000000000000000000000000000000000000000..0d5cea59ec6fed688895456e8abe90f0e8a53188
--- /dev/null
+++ b/e2e/session-optional-params.test.json
@@ -0,0 +1,160 @@
+{
+    "session": {
+        "elements": [
+            {
+                "form": {
+                    "id": "Section paramétrée",
+                    "uid": "ZDZ1Yn",
+                    "props": {
+                        "calcType": 2,
+                        "nodeType": 4
+                    },
+                    "elements": [
+                        {
+                            "fieldset": {
+                                "id": "fs_section",
+                                "props": {
+                                    "calcType": 2,
+                                    "nodeType": 4
+                                },
+                                "elements": [
+                                    {
+                                        "select": {
+                                            "id": "select_section",
+                                            "selected_id": "select_section_puiss"
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "k",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.5
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "LargeurBerge",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 4
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_bief",
+                                "props": {
+                                    "calcType": 2,
+                                    "nodeType": 4
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Ks",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 40
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "If",
+                                            "values": {
+                                                "mode": "MINMAX",
+                                                "min": 0.0005,
+                                                "max": 0.002,
+                                                "step": 0.00007500000000000001
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "YB",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 1
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_hydraulique",
+                                "props": {
+                                    "calcType": 2,
+                                    "nodeType": 4
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Q",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 1.2
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "param": {
+                                            "id": "Y",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.8
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_param_calc",
+                                "props": {
+                                    "calcType": 2,
+                                    "nodeType": 4
+                                },
+                                "elements": [
+                                    {
+                                        "param": {
+                                            "id": "Pr",
+                                            "values": {
+                                                "mode": "SINGLE",
+                                                "value": 0.0001
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        },
+                        {
+                            "fieldset": {
+                                "id": "fs_computed_var",
+                                "props": {
+                                    "calcType": 2,
+                                    "nodeType": 4,
+                                    "varCalc": "B"
+                                },
+                                "elements": [
+                                    {
+                                        "select": {
+                                            "id": "select_target",
+                                            "selected_id": "select_target_B"
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    ]
+                }
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 5a2713b26c5e5a1165ba32394037b4d218277c0b..bead599e1f868212b954745b7ec76f9f61afa37a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "nghyd",
-  "version": "1.2.0",
+  "version": "4.1.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/package.json b/package.json
index bb1875351a7cd2f95737651be8ae0fd92da0f459..0ffdf2dc9269207bebb79a330a8348ed899f51a5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "nghyd",
-  "version": "4.0.0",
+  "version": "4.1.0",
   "license": "MIT",
   "scripts": {
     "ng": "ng",
@@ -10,6 +10,7 @@
     "test": "ng test",
     "lint": "ng lint",
     "e2e": "ng e2e",
+    "e2equick": "ng e2e --dev-server-target= --baseUrl=http://localhost:4200",
     "jalhyd": "rm node_modules/jalhyd; cd ../jalhyd; npm run build; cd ../nghyd; npm install ../jalhyd;",
     "mathjax": "rsync -az --delete node_modules/mathjax docs-fr/javascripts;",
     "mkdocs": "npm run mathjax; find docs-fr/javascripts/ -name '*.md' -type f -delete; python3 -m mkdocs build",
diff --git a/protractor.conf.js b/protractor.conf.js
index a2584537bfd8d7b18361bfb3ace681021ba2d824..a4cc5bdbab60581670a5612667587e830a0aa818 100644
--- a/protractor.conf.js
+++ b/protractor.conf.js
@@ -9,7 +9,16 @@ exports.config = {
     './e2e/**/*.e2e-spec.ts'
   ],
   capabilities: {
-    'browserName': 'chrome'
+    browserName: 'chrome',
+    chromeOoptions: {
+      prefs: {
+        download: {
+            prompt_for_download: false, 
+            directory_upgrade: true,
+            default_directory: '/tmp/e2e-downloads' // @WARNING marche pas !?
+        },
+      },
+    },
   },
   directConnect: true,
   baseUrl: 'http://localhost:4201/',
@@ -24,5 +33,6 @@ exports.config = {
       project: 'e2e/tsconfig.e2e.json'
     });
     jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
+    browser.manage().window().setSize(1600, 1000);
   }
 };
diff --git a/src/app/components/base-param-input/base-param-input.component.ts b/src/app/components/base-param-input/base-param-input.component.ts
index f89955f565aacae16b9f9cf676fb607bf8a5c2ed..e04b0a4607e2d3632eab3e07700c7a8b2c0bb888 100644
--- a/src/app/components/base-param-input/base-param-input.component.ts
+++ b/src/app/components/base-param-input/base-param-input.component.ts
@@ -2,11 +2,12 @@
 
 import { Component, ChangeDetectorRef } from "@angular/core";
 
-import { Message, ParamDefinition, ParamDomain, ParamDomainValue, Observable, isNumeric } from "jalhyd";
+import { Message, ParamDefinition, ParamDomain, ParamDomainValue, Observable } from "jalhyd";
 
 import { I18nService } from "../../services/internationalisation/internationalisation.service";
 import { GenericInputComponent } from "../generic-input/generic-input.component";
 import { ServiceFactory } from "../../services/service-factory";
+import { NgParameter } from "../../formulaire/ngparam";
 
 export class NgBaseParam extends Observable {
     private _param: ParamDefinition;
@@ -98,8 +99,8 @@ export class BaseParamInputComponent extends GenericInputComponent {
     /**
      * paramètre géré
      */
-    private get _paramDef(): NgBaseParam {
-        return this._model;
+    private get _paramDef(): NgParameter {
+        return this._model as NgParameter;
     }
 
     /**
@@ -119,13 +120,15 @@ export class BaseParamInputComponent extends GenericInputComponent {
     protected setModelValue(sender: any, v: any) {
         this._tmp = v;
         try {
-            this._paramDef.setValue(v);
+            this._paramDef.setValue(null, v);
         } catch (e) {
             // géré par validateModelValue()
         }
     }
 
     protected validateModelValue(v: any): { isValid: boolean, message: string } {
-        return this._model.validateModelValue(v);
+        if (this._model instanceof NgBaseParam) {
+            return this._model.validateModelValue(v);
+        }
     }
 }
diff --git a/src/app/components/calculator-list/calculator-list.component.html b/src/app/components/calculator-list/calculator-list.component.html
index 925ebed1196278810f8b7be0598805d63c2730b2..25c88f0250120f157df3e2ea882db154a79ebfe2 100644
--- a/src/app/components/calculator-list/calculator-list.component.html
+++ b/src/app/components/calculator-list/calculator-list.component.html
@@ -24,7 +24,7 @@
         <mat-card-actions>
             <div class="container" fxLayout="column" fxLayoutAlign="left" fxLayoutGap="10px">
                 <button mat-raised-button color="accent" *ngFor="let calc of theme.calculators" class="theme-calculator"
-                    (click)="create(calc.type)" [innerHTML]="calc.label"></button>
+                    (click)="create(calc.type)" [innerHTML]="calc.label" [id]="calc.buttonId"></button>
             </div>
         </mat-card-actions>
     
diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts
index aef92e3e136016e8bc40b94cc47ae1f8ee66c474..4a084aa81a7fe2c3b0b96d48a04cb393cd6e75a6 100644
--- a/src/app/components/calculator-list/calculator-list.component.ts
+++ b/src/app/components/calculator-list/calculator-list.component.ts
@@ -50,7 +50,8 @@ export class CalculatorListComponent implements OnInit {
                     for (const calcType of theme.calculators) {
                         item.calculators.push({
                             type: calcType,
-                            label: ServiceFactory.instance.formulaireService.getLocalisedTitleFromCalculatorType(calcType)
+                            label: ServiceFactory.instance.formulaireService.getLocalisedTitleFromCalculatorType(calcType),
+                            buttonId: "create-calc-" + calcType
                         });
                         // mark as used
                         const index = unusedCalculators.indexOf(calcType);
@@ -77,7 +78,8 @@ export class CalculatorListComponent implements OnInit {
                     if (t !== CalculatorType.Structure) {
                         unusedTheme.calculators.push({
                             type: t,
-                            label: ServiceFactory.instance.formulaireService.getLocalisedTitleFromCalculatorType(t)
+                            label: ServiceFactory.instance.formulaireService.getLocalisedTitleFromCalculatorType(t),
+                            buttonId: "create-calc-" + t
                         });
                     }
                 }
diff --git a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html
index 9ce4c7853638fdcd3f2aa185b1d549f5bfb9dcd7..2720065f10a449408185a2f1e3d125a2495e1347 100644
--- a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html
+++ b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html
@@ -88,7 +88,7 @@
 
                 <div fxHide.xs fxFlex.gt-xs="0 0 16px"></div>
 
-                <mat-form-field class="values-file" fxFlex.gt-xs="1 0 auto" fxFlex.lt-sm="1 0 100%">
+                <mat-form-field class="values-file file-input-field" fxFlex.gt-xs="1 0 auto" fxFlex.lt-sm="1 0 100%">
                     <ngx-mat-file-input #valuesFile [placeholder]="uitextImportFile"
                         (change)="onFileSelected($event)" formControlName="file">
                     </ngx-mat-file-input>
diff --git a/src/app/components/dialog-load-session/dialog-load-session.component.html b/src/app/components/dialog-load-session/dialog-load-session.component.html
index b9f411fb767fdff20042560145f24d00edfef737..0473b4cdeb95ad579bf3a19d62aeb8fda50f2427 100644
--- a/src/app/components/dialog-load-session/dialog-load-session.component.html
+++ b/src/app/components/dialog-load-session/dialog-load-session.component.html
@@ -4,7 +4,7 @@
 
   <div mat-dialog-content>
 
-    <mat-form-field>
+    <mat-form-field class="file-input-field">
       <ngx-mat-file-input id="session-file-input" #sessionFile formControlName="file"[placeholder]="uitextLoadSessionFilename"
         (change)="onFileSelected($event)"></ngx-mat-file-input>
       <button mat-icon-button matSuffix *ngIf="!sessionFile.empty" (click)="sessionFile.clear($event)">
diff --git a/src/app/components/fixedvar-results/fixed-results.component.ts b/src/app/components/fixedvar-results/fixed-results.component.ts
index cf23921d8e5e41b06fc6c2346245b324a70e171d..8207c30c1d9c35a2cf293fad04cbf52afcaa65d2 100644
--- a/src/app/components/fixedvar-results/fixed-results.component.ts
+++ b/src/app/components/fixedvar-results/fixed-results.component.ts
@@ -81,7 +81,7 @@ export class FixedResultsComponent {
             && res.extraResults
         ) {
             // 2.1. main result (sometimes empty, for ex. in "Section paramétrée")
-            if (res.name && res.resultElement.vCalc) {
+            if (res.name && res.resultElement.vCalc !== undefined) {
                 data.push({
                     label: this._fixedResults.calculatedParameterHeader,
                     value: this.intlService.formatResult(res.name, res.resultElement.vCalc),
diff --git a/src/app/components/generic-calculator/calc-name.component.html b/src/app/components/generic-calculator/calc-name.component.html
index 3866997a9293167d49281314dc156818649c9b17..85c1f9c069760458e4f52acd8d78e5ccc78d514c 100644
--- a/src/app/components/generic-calculator/calc-name.component.html
+++ b/src/app/components/generic-calculator/calc-name.component.html
@@ -1,5 +1,5 @@
 <mat-form-field>
     <input matInput #inputControl="ngModel" class="form-control" type="text"
-        [id]="inputId" [(ngModel)]="uiValue" [placeholder]="title" required>
+        id="calc-name-input" [(ngModel)]="uiValue" [placeholder]="title" required>
     <mat-error>{{ errorMessage }}</mat-error>
 </mat-form-field>
diff --git a/src/app/components/generic-calculator/calc-name.component.ts b/src/app/components/generic-calculator/calc-name.component.ts
index 70c236305fa3c4f667eb8fc1b8b95fb8914d65dc..208d11e9737a1484ac513de75271a67efc88c7fe 100644
--- a/src/app/components/generic-calculator/calc-name.component.ts
+++ b/src/app/components/generic-calculator/calc-name.component.ts
@@ -19,7 +19,7 @@ export class CalculatorNameComponent extends GenericInputComponent {
      * formulaire géré
      */
     private get _form(): FormulaireDefinition {
-        return this._model;
+        return this._model as FormulaireDefinition;
     }
 
     /**
diff --git a/src/app/components/generic-calculator/calculator.component.html b/src/app/components/generic-calculator/calculator.component.html
index 7874908f369790519d73e029d0819a560c0fb714..4c2623ff5d94eb7fc43befc6dd660c8dc4efcafc 100644
--- a/src/app/components/generic-calculator/calculator.component.html
+++ b/src/app/components/generic-calculator/calculator.component.html
@@ -1,14 +1,16 @@
-<mat-card id="calculator-card">
+<mat-card class="calculator-card" [id]="ID">
 
     <mat-card-header>
 
         <div class="hyd-window-btns">
             <!-- bouton d'aide -->
             <mat-icon *ngIf="enableHelpButton" (click)="openHelp()" color="accent">help</mat-icon>
+            <!-- bouton de duplication -->
+            <mat-icon id="clone-calc" (click)="cloneCalculator()">file_copy</mat-icon>
             <!-- bouton de sauvegarde -->
-            <mat-icon (click)="saveCalculator()">save_alt</mat-icon>
+            <mat-icon id="save-calc" (click)="saveCalculator()">save_alt</mat-icon>
             <!-- bouton de fermeture -->
-            <mat-icon (click)="closeCalculator()">close</mat-icon>
+            <mat-icon id="close-calc" (click)="closeCalculator()">close</mat-icon>
         </div>
 
         <!-- titre -->
diff --git a/src/app/components/generic-calculator/calculator.component.scss b/src/app/components/generic-calculator/calculator.component.scss
index 2346a487428bcb44594db9221dc7e84c2e6fd3ab..68df692b88e3ab7eeff62572d0de073c0db48587 100644
--- a/src/app/components/generic-calculator/calculator.component.scss
+++ b/src/app/components/generic-calculator/calculator.component.scss
@@ -24,7 +24,7 @@ mat-card {
     margin-bottom: 2em;
 
     // main card
-    &#calculator-card {
+    &.calculator-card {
 
         > mat-card-header {
             margin-bottom: .5em;
diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts
index 3496192aabb2636a334ae6753ef68c73ea743936..e8c97032324028131f9dda6cb21bf7938681d244 100644
--- a/src/app/components/generic-calculator/calculator.component.ts
+++ b/src/app/components/generic-calculator/calculator.component.ts
@@ -87,6 +87,14 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
     private intlService: I18nService;
     private formulaireService: FormulaireService;
 
+    public get ID() {
+        if (this._formulaire) {
+            return this._formulaire.uid;
+        } else {
+            return "calculator_1";
+        }
+    }
+
     constructor(
         private route: ActivatedRoute,
         private confirmCloseCalcDialog: MatDialog
@@ -399,4 +407,9 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
             }
         });
     }
+
+    public cloneCalculator() {
+        const serializedForm = this._formulaire.JSONserialise()["form"];
+        this.formulaireService.deserialiseForm(serializedForm);
+    }
 }
diff --git a/src/app/components/generic-input/generic-input.component.ts b/src/app/components/generic-input/generic-input.component.ts
index a7cd9064ce906ff59382e4dc0382751f45fd1073..4b34c81133b49c704c6fdb00f2427f0f1f47c1e4 100644
--- a/src/app/components/generic-input/generic-input.component.ts
+++ b/src/app/components/generic-input/generic-input.component.ts
@@ -2,6 +2,8 @@ import { Input, Output, EventEmitter, ChangeDetectorRef, OnChanges, ViewChild }
 import { NgModel } from "@angular/forms";
 import { BaseComponent } from "../base/base.component";
 import { isNumeric } from "jalhyd";
+import { FormulaireDefinition } from "../../formulaire/definition/form-definition";
+import { NgParameter } from "../../formulaire/ngparam";
 
 /**
  * classe de gestion générique d'un champ de saisie avec titre, validation et message d'erreur
@@ -17,7 +19,7 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC
     /**
      * entité mémoire gérée
      */
-    protected _model: any; // NgBaseParam mais aussi FormDefinition parfois (!?)
+    protected _model: NgParameter | FormulaireDefinition; // CalcName utilise un FormDefinition ici !?
 
     /**
      * flag de désactivation de l'input
@@ -31,9 +33,18 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC
     public showError = true;
 
     /**
-     * id de l'input, pour accorder <label> et <input> sans ambiguïté
+     * id de l'input, utilisé notamment pour les tests
      */
-    public inputId = "input1";
+    public get inputId() {
+        let id = "input-1";
+        if (this._model) {
+            // unique input id based on parameter symbol
+            if (this._model instanceof NgParameter) {
+                id = (this._model as NgParameter).symbol;
+            }
+        }
+        return id;
+    }
 
     /**
      * chaîne affichée dans l'input quand aucune valeur n'est saisie
@@ -79,8 +90,6 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC
 
     constructor(private cdRef: ChangeDetectorRef) {
         super();
-        // generate "unique" input id
-        this.inputId = "form-" + btoa(String(Math.random())).substring(2, 10);
     }
 
     public get isDisabled(): boolean {
diff --git a/src/app/components/generic-select/generic-select.component.html b/src/app/components/generic-select/generic-select.component.html
index da7a82515f0406dfc56beb7a36b4e61fc37ac7ac..005ac94275da7445a5a27dbeb24435e2060e82fd 100644
--- a/src/app/components/generic-select/generic-select.component.html
+++ b/src/app/components/generic-select/generic-select.component.html
@@ -1,5 +1,5 @@
 <mat-form-field>
-    <mat-select [placeholder]="label" [(value)]="selectedValue">
+    <mat-select [id]="selectId" [placeholder]="label" [(value)]="selectedValue">
         <mat-option *ngFor="let e of entries" [value]="e">
             {{ entryLabel(e) }}
         </mat-option>
diff --git a/src/app/components/param-computed/param-computed.component.html b/src/app/components/param-computed/param-computed.component.html
index 0751e36bf1dc93de19a451f8aefd886085dc6130..eb582f98d402700628c2885a1ea772e7fa60e078 100644
--- a/src/app/components/param-computed/param-computed.component.html
+++ b/src/app/components/param-computed/param-computed.component.html
@@ -1,6 +1,6 @@
 <!-- a fake input bound to nothing, for the sake of UI consistency -->
 <mat-form-field>
-    <input matInput disabled class="form-control" type="text" [ngModel]="infoText" [placeholder]="param.title">
+    <input matInput disabled [id]="inputId" class="form-control" type="text" [ngModel]="infoText" [placeholder]="param.title">
     <button *ngIf="isDicho" mat-icon-button class="param-computed-more" (click)="openDialog()">
         <mat-icon>more_horiz</mat-icon>
     </button>
diff --git a/src/app/components/param-computed/param-computed.component.ts b/src/app/components/param-computed/param-computed.component.ts
index 6bfced00bab90372af36a4d7946a5aee44dae579..889c3f10bd038dd6fda007d7290ad3c8e2f16981 100644
--- a/src/app/components/param-computed/param-computed.component.ts
+++ b/src/app/components/param-computed/param-computed.component.ts
@@ -20,6 +20,17 @@ export class ParamComputedComponent {
     @Input()
     public title: string;
 
+    /**
+     * id de l'input, utilisé notamment pour les tests
+     */
+    public get inputId() {
+        let id = "calc_input-1";
+        if (this.param) {
+            id = "calc_" + this.param.symbol;
+        }
+        return id;
+    }
+
     constructor(
         private editInitialValueDialog: MatDialog,
         private intlService: I18nService
diff --git a/src/app/components/param-link/param-link.component.html b/src/app/components/param-link/param-link.component.html
index 5b198816bf96e4b7b3df1aec2f428f7e681d1ec2..b493734349abc13a15f7b14a946fffc78b12eabf 100644
--- a/src/app/components/param-link/param-link.component.html
+++ b/src/app/components/param-link/param-link.component.html
@@ -1,5 +1,6 @@
 <mat-form-field>
-    <mat-select [name]='"linked-param_" + param.uid' required [placeholder]="param.title" [(ngModel)]="currentLinkedParam">
+    <mat-select [id]="selectId" [name]="selectId" [placeholder]="param.title"
+        [(ngModel)]="currentLinkedParam" required>
         <mat-option *ngFor="let e of linkableParams" [value]="e">
             {{ selectItemLabel(e) }}
         </mat-option>
diff --git a/src/app/components/param-link/param-link.component.ts b/src/app/components/param-link/param-link.component.ts
index 9e28788f706eecf48a47c5836360e400ac127a98..bbc231d26787ae7f477592eab92ca90f68c9365b 100644
--- a/src/app/components/param-link/param-link.component.ts
+++ b/src/app/components/param-link/param-link.component.ts
@@ -54,6 +54,10 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy {
 
     private _formService: FormulaireService;
 
+    public get selectId() {
+        return  "linked_" + this.param.symbol;
+    }
+
     constructor(
         private intlService: I18nService
     ) {
@@ -76,11 +80,9 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy {
 
     public set currentLinkedParam(p: any) {
         for (let i = 0; i < this._linkableParams.length; i++) {
-            if (this._linkableParams[i].value.uid === p.uid) {
+            if (this._linkableParams[i].nub.uid === p.nub.uid) {
                 this.linkTo(i);
                 break;
-            } else {
-                i++;
             }
         }
     }
diff --git a/src/app/components/results-graph/graph-type.component.ts b/src/app/components/results-graph/graph-type.component.ts
index c96f6c53257d276a45ee07e3a7d8f936d861af85..3ed06955a72693dace890a5bc59c9464524617d4 100644
--- a/src/app/components/results-graph/graph-type.component.ts
+++ b/src/app/components/results-graph/graph-type.component.ts
@@ -17,6 +17,10 @@ export class GraphTypeSelectComponent implements IObservable {
 
     private _observable: Observable;
 
+    public get selectId() {
+        return "graph-type"; // for generic select component
+    }
+
     constructor(private intlService: I18nService) {
         this._observable = new Observable();
         this._entriesLabels = [
diff --git a/src/app/components/select-field-line/select-field-line.component.ts b/src/app/components/select-field-line/select-field-line.component.ts
index a7840110a5aec8492dcacf86f4fd16775fc2c8b0..61c4cc62a6d7ee0bca2eef3d3236b35bd33a2434 100644
--- a/src/app/components/select-field-line/select-field-line.component.ts
+++ b/src/app/components/select-field-line/select-field-line.component.ts
@@ -5,7 +5,6 @@ import { SelectEntry } from "../../formulaire/select-entry";
 
 @Component({
     selector: "select-field-line",
-    // templateUrl: "./select-field-line.component.html",
     templateUrl: "../generic-select/generic-select.component.html",
     styleUrls: [
         "./select-field-line.component.scss"
@@ -15,6 +14,10 @@ export class SelectFieldLineComponent {
     @Input()
     private _select: SelectField;
 
+    public get selectId() {
+        return this._select.id;
+    }
+
     public get entries(): SelectEntry[] {
         if (! this._select) {
             return [];
diff --git a/src/app/formulaire/definition/form-def-section.ts b/src/app/formulaire/definition/form-def-section.ts
index f4fe312ca445de92751bd3f3db6fa3ea73b42120..9ad2dbf71baf45b31384f8558417fe3a583b559c 100644
--- a/src/app/formulaire/definition/form-def-section.ts
+++ b/src/app/formulaire/definition/form-def-section.ts
@@ -1,10 +1,3 @@
-import {
-    ComputeNodeType, ParamsSectionTrapez, cSnTrapez, ParamsSectionRectang, cSnRectang,
-    ParamsSectionCirc, cSnCirc, ParamsSectionPuiss, cSnPuiss, acSection, ParamsEquation
-} from "jalhyd";
-
-import { SelectField } from "../select-field";
-import { Field } from "../field";
 import { NgParameter, ParamRadioConfig } from "../ngparam";
 import { FormulaireDefinition } from "./form-definition";
 import { FieldSet } from "../fieldset";
diff --git a/src/app/formulaire/formulaire-node.ts b/src/app/formulaire/formulaire-node.ts
index 627e38f7d9225419a966d63c0d0d96801dede6c0..128f39a675a5501b93bc4bb4692c411e4c910f1d 100644
--- a/src/app/formulaire/formulaire-node.ts
+++ b/src/app/formulaire/formulaire-node.ts
@@ -56,6 +56,11 @@ export abstract class FormulaireNode implements IObservable {
         return this._uid;
     }
 
+    /** utiliser uniquement pour charger des sessions (désérialisation JSON) */
+    public setUid(uid: string) {
+        this._uid = uid;
+    }
+
     /**
      * cherche un FormulaireNode par son id de conf
      */
diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts
index 82cca313a78d8406fadd269a9385505202866da5..1c82a275adb49d278b97f3ed65f4fe198f67fe51 100644
--- a/src/app/formulaire/ngparam.ts
+++ b/src/app/formulaire/ngparam.ts
@@ -304,7 +304,6 @@ export class NgParameter extends InputField implements Observer {
         if (super.verifiesDependency(d)) {
             return true;
         }
-
         switch (d.masterCondition.type) {
             case DependencyConditionType.HasValue: {
                     const mc: ValueDependencyCondition = <ValueDependencyCondition>d.masterCondition;
@@ -326,21 +325,20 @@ export class NgParameter extends InputField implements Observer {
         res["mode"] = ParamValueMode[vm];
         switch (vm) {
             case ParamValueMode.SINGLE:
-                res["value"] = this._paramValues.singleValue;
+                res["value"] = this.getValue();
                 break;
 
             case ParamValueMode.MINMAX:
-                res["min"] = this._paramValues.min;
-                res["max"] = this._paramValues.max;
-                res["step"] = this._paramValues.step;
+                res["min"] = this.minValue;
+                res["max"] = this.maxValue;
+                res["step"] = this.stepValue;
                 break;
 
             case ParamValueMode.LISTE:
-                res["values"] = this._paramValues.valueList;
+                res["values"] = this.valueList;
                 break;
 
             case ParamValueMode.LINK:
-                // @TODO copié à l'arrache, vérifier que ça marche
                 res["form_uid"] = ServiceFactory.instance.formulaireService.getFormulaireFromNubId(this._paramDef.referencedNub["uid"]).uid;
                 res["ref"] = this.paramDefinition.referenceDefinition;
                 break;
@@ -378,7 +376,19 @@ export class NgParameter extends InputField implements Observer {
                 break;
 
             case ParamValueMode.LINK:
-                break;  // cf FormulaireService.updateParamsLinks()
+                const uid: string = json["form_uid"];
+                const ref: string = json["ref"];
+                this._paramValues.valueMode = ParamValueMode.LINK;
+                // formulaire dont le Nub est la cible du lien
+                const destForm = ServiceFactory.instance.formulaireService.getFormulaireFromId(uid);
+                if (destForm) {
+                    this._paramValues.defineReference(destForm.currentNub, ref);
+                } else {
+                    // @TODO et si la cible du lien n'existe pas ??
+                    // cf FormulaireService.updateParamsLinks()
+                    console.log("LA CIBLE DU LIEN N'EXISTE PAS !!");
+                }
+                break;
 
             default:
                 throw new Error(`session file : invalid value mode '${json["mode"]}' in param object`);
diff --git a/src/app/formulaire/select-field.ts b/src/app/formulaire/select-field.ts
index 3bfadc6cf957cd3df97395df4cb7344aafd4ee75..a8162bac46fbaf3563160d4ae82548ed13faacac 100644
--- a/src/app/formulaire/select-field.ts
+++ b/src/app/formulaire/select-field.ts
@@ -43,6 +43,7 @@ export class SelectField extends Field {
 
     public setValue(v: SelectEntry) {
         if (this._selectedEntry !== v) {
+            console.log("++++ select field : notify observers", v);
             this._selectedEntry = v;
             this.notifyObservers({
                 "action": "select",
@@ -145,7 +146,7 @@ export class SelectField extends Field {
                     const sel = elements[k];
                     for (const e of this._entries) {
                         if (e.id === sel) {
-                            this._selectedEntry = e;
+                            this.setValue(e);
                             break;
                         }
                     }
diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts
index dda5ad7a3f3d766173caec498ca3309bfdd1fcc6..8be740fa20060504a1e71e02822e473b9664318d 100644
--- a/src/app/services/formulaire/formulaire.service.ts
+++ b/src/app/services/formulaire/formulaire.service.ts
@@ -81,6 +81,20 @@ export class FormulaireService extends Observable {
             });
     }
 
+    /**
+     * retourne true si l'uid passé en paramètre est déjà utilisé par un formulaire
+     * @param uid uid à tester
+     */
+    private formUIDAlreadyUsed(uid: string): boolean {
+        let alreadyUsed = false;
+        for (const f of this._formulaires) {
+            if (f.uid === uid) {
+                alreadyUsed = true;
+            }
+        }
+        return alreadyUsed;
+    }
+
     public updateLocalisation() {
         for (const c of EnumEx.getValues(CalculatorType)) {
             const prom: Promise<StringMap> = this.loadLocalisation(c);
@@ -149,10 +163,17 @@ export class FormulaireService extends Observable {
     /**
      * crée un formulaire d'un type donné
      * @param ct type de formulaire
-     * @param jsonState
+     * @param jsonState descripteur sérialisé du formulaire, le cal échéant
      */
     public createFormulaire(ct: CalculatorType, jsonState?: {}): Promise<FormulaireDefinition> {
         const f: FormulaireDefinition = this.newFormulaire(ct);
+        // conserver l'UID d'origine, sauf en cas de collision
+        if (jsonState !== undefined) {
+            const originalUID = jsonState["uid"];
+            if (originalUID !== undefined && ! this.formUIDAlreadyUsed(originalUID)) {
+                f.setUid(originalUID);
+            }
+        }
         this._formulaires.push(f);
 
         const prom: Promise<any> = this.loadConfig(ct);
@@ -424,7 +445,7 @@ export class FormulaireService extends Observable {
         });
     }
 
-    private deserialiseForm(elements: {}): Promise<FormulaireDefinition> {
+    public deserialiseForm(elements: {}): Promise<FormulaireDefinition> {
         const props = elements["props"];
         const ct: CalculatorType = props["calcType"];
         return this.createFormulaire(ct, elements);
@@ -441,6 +462,7 @@ export class FormulaireService extends Observable {
                 const form = element[keys[0]];
 
                 for (const i of formInfos) {
+                    // on the loadSession dialog, was the checkbox checked for this calculator ?
                     if (i["uid"] === form["uid"] && i["selected"]) {
                         return this.deserialiseForm(form);
                     }
diff --git a/src/styles.scss b/src/styles.scss
index 013d064f64343a703326db51277fd2409092bfa2..ae70c285c30da9d28cefe7c73a789f2c1069048a 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -6,7 +6,11 @@
 
 html, body { height: 100%; }
 
-body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
+body {
+    margin: 0;
+    font-family: Roboto, "Helvetica Neue", sans-serif;
+    background-color: #FAFAFA; // harmonize with app-content
+}
 
 button {
     &:focus {
@@ -40,6 +44,10 @@ mat-form-field {
     }
 }
 
+.file-input-field {
+    cursor: pointer;
+}
+
 .eight-em-bottom-padding {
     padding-bottom: 8em;
 }