diff --git a/e2e/calculator.po.ts b/e2e/calculator.po.ts
index be6a5eb4b40ffec0be06a15bb12c94d894d4d654..9d05454ed7dc9e1d90855850777fa2d4b79e76f6 100644
--- a/e2e/calculator.po.ts
+++ b/e2e/calculator.po.ts
@@ -1,4 +1,4 @@
-import { by, element, ElementFinder } from "protractor";
+import { by, element, ElementFinder, browser } from "protractor";
 
 export class CalculatorPage {
 
@@ -22,10 +22,21 @@ export class CalculatorPage {
     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(" ");
@@ -33,4 +44,31 @@ export class CalculatorPage {
     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/protractor.conf.js b/protractor.conf.js
index 8d5700529da6151ae8d94344f301a2e3e2c923e5..a4cc5bdbab60581670a5612667587e830a0aa818 100644
--- a/protractor.conf.js
+++ b/protractor.conf.js
@@ -33,5 +33,6 @@ exports.config = {
       project: 'e2e/tsconfig.e2e.json'
     });
     jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
+    browser.manage().window().setSize(1600, 1000);
   }
 };