From 089260924ee35678e05519ee60a12b7099c76a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Wed, 15 Feb 2023 09:12:24 +0100 Subject: [PATCH 1/8] refactor(e2e): add changeSelectValue() as a util function refs #586 --- e2e/calculate-linked-params.e2e-spec.ts | 13 +++++++------ e2e/calculator.po.ts | 7 ------- e2e/cloisons.e2e-spec.ts | 3 ++- e2e/clone-calc.e2e-spec.ts | 6 +++--- e2e/examples-empty-fields.e2e-spec.ts | 3 ++- e2e/lechapt-calmon.e2e-spec.ts | 5 +++-- e2e/linked-parameter-section-type.e2e-spec.ts | 3 ++- e2e/load-save-session.e2e-spec.ts | 6 +++--- e2e/ouvrages-empty-fields.e2e-spec.ts | 11 ++++++----- e2e/pab.e2e-spec.ts | 4 ++-- e2e/preferences.po.ts | 6 ++---- e2e/pressure-loss-empty-fields.e2e-spec.ts | 3 ++- e2e/remous.e2e-spec.ts | 3 ++- e2e/solveur.e2e-spec.ts | 10 +++++----- e2e/util.po.ts | 10 +++++++++- 15 files changed, 50 insertions(+), 43 deletions(-) diff --git a/e2e/calculate-linked-params.e2e-spec.ts b/e2e/calculate-linked-params.e2e-spec.ts index 12e68d423..7c54f5af4 100644 --- a/e2e/calculate-linked-params.e2e-spec.ts +++ b/e2e/calculate-linked-params.e2e-spec.ts @@ -5,6 +5,7 @@ import { Navbar } from "./navbar.po"; import { SideNav } from "./sidenav.po"; import { browser, by } from "protractor"; import { PreferencesPage } from "./preferences.po"; +import { changeSelectValue } from "./util.po"; /** * Uses an example configuration to calculate : @@ -62,7 +63,7 @@ describe("ngHyd − calculate with linked parameters", () => { const Y = calcPage.getInputById("Y"); await calcPage.setParamMode(Y, "link"); const sel = await calcPage.getLinkedValueSelect(Y); - await calcPage.changeSelectValue(sel, 0); + await changeSelectValue(sel, 0); await computeAndCheckPresenceOfResults(); }); @@ -79,7 +80,7 @@ describe("ngHyd − calculate with linked parameters", () => { const Y = calcPage.getInputById("Y"); await calcPage.setParamMode(Y, "link"); const sel = await calcPage.getLinkedValueSelect(Y); - await calcPage.changeSelectValue(sel, 0); + await changeSelectValue(sel, 0); // vary W const W = calcPage.getInputById("W"); await calcPage.setParamMode(W, "var"); @@ -102,7 +103,7 @@ describe("ngHyd − calculate with linked parameters", () => { const Y2 = calcPage.getInputById("Y"); await calcPage.setParamMode(Y2, "link"); const sel = await calcPage.getLinkedValueSelect(Y2); - await calcPage.changeSelectValue(sel, 0); + await changeSelectValue(sel, 0); await computeAndCheckPresenceOfResults(); }); @@ -122,7 +123,7 @@ describe("ngHyd − calculate with linked parameters", () => { const Y2 = calcPage.getInputById("Y"); await calcPage.setParamMode(Y2, "link"); const sel = await calcPage.getLinkedValueSelect(Y2); - await calcPage.changeSelectValue(sel, 0); + await changeSelectValue(sel, 0); await computeAndCheckPresenceOfResults(); }); @@ -142,7 +143,7 @@ describe("ngHyd − calculate with linked parameters", () => { const Y2 = calcPage.getInputById("Y"); await calcPage.setParamMode(Y2, "link"); const sel = await calcPage.getLinkedValueSelect(Y2); - await calcPage.changeSelectValue(sel, 0); + await changeSelectValue(sel, 0); // vary W const W = calcPage.getInputById("W"); await calcPage.setParamMode(W, "var"); @@ -168,7 +169,7 @@ describe("ngHyd − calculate with linked parameters", () => { const Y2 = calcPage.getInputById("Y"); await calcPage.setParamMode(Y2, "link"); const sel = await calcPage.getLinkedValueSelect(Y2); - await calcPage.changeSelectValue(sel, 0); + await changeSelectValue(sel, 0); await computeAndCheckPresenceOfResults(); }); diff --git a/e2e/calculator.po.ts b/e2e/calculator.po.ts index af1e1803c..12c5a8de4 100644 --- a/e2e/calculator.po.ts +++ b/e2e/calculator.po.ts @@ -331,13 +331,6 @@ export class CalculatorPage { return calcButton; } - async changeSelectValue(elt: ElementFinder, index: number) { - await elt.click(); - const optionId = ".cdk-overlay-container mat-option:nth-of-type(" + (index + 1) + ")"; - const option = element(by.css(optionId)); - await option.click(); - } - // find parent element of elt having class "container" async findParentContainer(elt: ElementFinder): Promise<ElementFinder> { let i = 8; // garde fous diff --git a/e2e/cloisons.e2e-spec.ts b/e2e/cloisons.e2e-spec.ts index 2febdc57e..f251afabc 100644 --- a/e2e/cloisons.e2e-spec.ts +++ b/e2e/cloisons.e2e-spec.ts @@ -3,6 +3,7 @@ import { CalculatorPage } from "./calculator.po"; import { browser } from "protractor"; import { Navbar } from "./navbar.po"; import { PreferencesPage } from "./preferences.po"; +import { changeSelectValue } from "./util.po"; /** * Cloisons - différents tests qui n'ont pas tant de rapport que ça avec les cloisons :) @@ -44,7 +45,7 @@ describe("ngHyd − cloisons", () => { await browser.sleep(300); // 4. change LoiDebit - await calcPage.changeSelectValue(calcPage.getSelectById("select_loidebit"), 1); + await changeSelectValue(calcPage.getSelectById("select_loidebit"), 1); await browser.sleep(300); // 5. check number of inputs in CALC mode diff --git a/e2e/clone-calc.e2e-spec.ts b/e2e/clone-calc.e2e-spec.ts index 038a90e66..a63f565b0 100644 --- a/e2e/clone-calc.e2e-spec.ts +++ b/e2e/clone-calc.e2e-spec.ts @@ -4,7 +4,7 @@ import { CalculatorPage } from "./calculator.po"; import { Navbar } from "./navbar.po"; import { browser } from "protractor"; import { PreferencesPage } from "./preferences.po"; -import { scrollPageToTop } from "./util.po"; +import { changeSelectValue, scrollPageToTop } from "./util.po"; /** * Clone calculators @@ -54,7 +54,7 @@ describe("ngHyd − clone a calculator", () => { k: 0.6, Ks: 42 }; - await calcPage.changeSelectValue(calcPage.getSelectById("select_section"), 3); // mode "parabolique" + await 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(); @@ -63,7 +63,7 @@ describe("ngHyd − clone a calculator", () => { 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 changeSelectValue(calcPage.getSelectById("linked_Q"), 1); // "Courbe de remous" await browser.sleep(500); // otherwise clickCloneCalcButton() fails with "Element is not clickable at point" diff --git a/e2e/examples-empty-fields.e2e-spec.ts b/e2e/examples-empty-fields.e2e-spec.ts index 08f40c467..3a8d3942c 100644 --- a/e2e/examples-empty-fields.e2e-spec.ts +++ b/e2e/examples-empty-fields.e2e-spec.ts @@ -3,6 +3,7 @@ import { CalculatorPage } from "./calculator.po"; import { ListPage } from "./list.po"; import { Navbar } from "./navbar.po"; import { PreferencesPage } from "./preferences.po" +import { changeSelectValue } from "./util.po"; /** * check that fields are empty on creation @@ -60,7 +61,7 @@ describe("ngHyd - Check that examples fields are not empty with 'empty fields on // modify 1st structure discharge law const dischargeSelect = calcPage.getSelectById("select_loidebit"); - await calcPage.changeSelectValue(dischargeSelect, 1); + await changeSelectValue(dischargeSelect, 1); await browser.sleep(200); // open initial dialog diff --git a/e2e/lechapt-calmon.e2e-spec.ts b/e2e/lechapt-calmon.e2e-spec.ts index 91dea3194..f3be14a59 100644 --- a/e2e/lechapt-calmon.e2e-spec.ts +++ b/e2e/lechapt-calmon.e2e-spec.ts @@ -3,6 +3,7 @@ import { browser, by } from "protractor"; import { CalculatorPage } from "./calculator.po"; import { PreferencesPage } from "./preferences.po"; import { Navbar } from "./navbar.po"; +import { changeSelectValue } from "./util.po"; /** * Check that created/cloned structures have empty fields when @@ -45,7 +46,7 @@ describe("Lechapt&Calmon - ", () => { // select last material type const materialSelect = calcPage.getSelectById("select_material"); - await calcPage.changeSelectValue(materialSelect, 8); + await changeSelectValue(materialSelect, 8); await browser.sleep(200); // run calculation @@ -58,7 +59,7 @@ describe("Lechapt&Calmon - ", () => { const pl1 = await res1.all(by.css("td")).get(1).getText(); // select first material type - await calcPage.changeSelectValue(materialSelect, 0); + await changeSelectValue(materialSelect, 0); await browser.sleep(200); // run calculation diff --git a/e2e/linked-parameter-section-type.e2e-spec.ts b/e2e/linked-parameter-section-type.e2e-spec.ts index b42c13d0f..a863f273e 100644 --- a/e2e/linked-parameter-section-type.e2e-spec.ts +++ b/e2e/linked-parameter-section-type.e2e-spec.ts @@ -3,6 +3,7 @@ import { ListPage } from "./list.po"; import { Navbar } from "./navbar.po"; import { PreferencesPage } from "./preferences.po"; import { CalculatorPage } from "./calculator.po"; +import { changeSelectValue } from "./util.po"; describe("linked parameter in calculator with section - ", () => { let listPage: ListPage; @@ -42,7 +43,7 @@ describe("linked parameter in calculator with section - ", () => { await calcPage.setParamMode(inputQ, "link"); // change section type - await calcPage.changeSelectValue(calcPage.getSelectById("select_section"), 3); // mode "parabolique" + await changeSelectValue(calcPage.getSelectById("select_section"), 3); // mode "parabolique" // check Q is still in linked mode expect(await calcPage.inputIsInLinkedMode(inputQ)).toBe(true); diff --git a/e2e/load-save-session.e2e-spec.ts b/e2e/load-save-session.e2e-spec.ts index 436058e6f..8689c6f13 100644 --- a/e2e/load-save-session.e2e-spec.ts +++ b/e2e/load-save-session.e2e-spec.ts @@ -5,7 +5,7 @@ import { Navbar } from "./navbar.po"; import { SideNav } from "./sidenav.po"; import { browser, by, element } from "protractor"; import { PreferencesPage } from "./preferences.po"; -import { expectNumber } from "./util.po"; +import { changeSelectValue, expectNumber } from "./util.po"; const fs = require("fs"); const path = require("path"); @@ -122,7 +122,7 @@ describe("ngHyd − save and load sessions", () => { await listPage.clickMenuEntryForCalcType(2); // Section paramétrée await browser.sleep(500); - await calcPage.changeSelectValue(calcPage.getSelectById("select_section"), 2); // mode "trapezoidal" + await changeSelectValue(calcPage.getSelectById("select_section"), 2); // mode "trapezoidal" await calcPage.getInputById("Ks").clear(); // coefficient de Strickler await browser.sleep(1000); @@ -190,7 +190,7 @@ describe("ngHyd − save and load sessions", () => { // select next select option (optionally looping) const nextInd = (ind + 1) % optionCount; - await calcPage.changeSelectValue(sel, nextInd); + await changeSelectValue(sel, nextInd); await browser.sleep(200); // save session diff --git a/e2e/ouvrages-empty-fields.e2e-spec.ts b/e2e/ouvrages-empty-fields.e2e-spec.ts index 4a28316f8..918107e2c 100644 --- a/e2e/ouvrages-empty-fields.e2e-spec.ts +++ b/e2e/ouvrages-empty-fields.e2e-spec.ts @@ -4,6 +4,7 @@ import { CalculatorPage } from "./calculator.po"; import { AppPage } from "./app.po"; import { PreferencesPage } from "./preferences.po"; import { Navbar } from "./navbar.po"; +import { changeSelectValue } from "./util.po"; /** * Check that created/cloned structures have empty fields when @@ -51,7 +52,7 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () // change 1st structure type to rectangular weir const structSelect = calcPage.getSelectById("select_structure"); - await calcPage.changeSelectValue(structSelect, 1); + await changeSelectValue(structSelect, 1); await browser.sleep(200); // check 1st structure empty fields @@ -91,7 +92,7 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () // change 1st structure type to rectangular weir const structSelect = calcPage.getSelectById("select_structure"); - await calcPage.changeSelectValue(structSelect, 1); + await changeSelectValue(structSelect, 1); await browser.sleep(200); // copy structure @@ -102,7 +103,7 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () // change 2nd structure type to rectangular gate const selects = await element.all(by.css("mat-select#select_structure")); const structSelect2 = selects[1]; - await calcPage.changeSelectValue(structSelect2, 5); + await changeSelectValue(structSelect2, 5); await browser.sleep(200); // check empty fields @@ -135,12 +136,12 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () // change 1st structure type to rectangular weir const structSelect = calcPage.getSelectById("select_structure"); - await calcPage.changeSelectValue(structSelect, 1); + await changeSelectValue(structSelect, 1); await browser.sleep(200); // change discharge law to Larinier const dischargeSelect = calcPage.getSelectById("select_loidebit"); - await calcPage.changeSelectValue(dischargeSelect, 3); + await changeSelectValue(dischargeSelect, 3); await browser.sleep(200); // check empty fields diff --git a/e2e/pab.e2e-spec.ts b/e2e/pab.e2e-spec.ts index 866f67fb5..edcdd9750 100644 --- a/e2e/pab.e2e-spec.ts +++ b/e2e/pab.e2e-spec.ts @@ -5,7 +5,7 @@ import { browser, by, element } from "protractor"; import { AppPage } from "./app.po"; import { SideNav } from "./sidenav.po"; import { PreferencesPage } from "./preferences.po"; -import { scrollPageToTop } from "./util.po"; +import { changeSelectValue, scrollPageToTop } from "./util.po"; /** * Clone calculators @@ -297,7 +297,7 @@ describe("ngHyd − Passe à Bassins", () => { // change iteration const pve = calcPage.getSelectById("pab-variating-element"); - calcPage.changeSelectValue(pve, 3); + await changeSelectValue(pve, 3); await browser.sleep(300); // check absence of logs expect(await calcPage.nbLogEntries()).toBe(2); diff --git a/e2e/preferences.po.ts b/e2e/preferences.po.ts index 264ebb84f..51c1fc8de 100644 --- a/e2e/preferences.po.ts +++ b/e2e/preferences.po.ts @@ -1,4 +1,5 @@ import { browser, by, element, ElementFinder } from "protractor"; +import { changeSelectValue } from "./util.po"; export class PreferencesPage { navigateTo() { @@ -43,10 +44,7 @@ export class PreferencesPage { async changeLanguage(index: number) { const select = this.getLanguageSelect(); - await select.click(); - const optionId = ".cdk-overlay-container mat-option#mat-option-" + index; - const option = element(by.css(optionId)); - await option.click(); + await changeSelectValue(select, index); } async enableEvilEmptyFields() { diff --git a/e2e/pressure-loss-empty-fields.e2e-spec.ts b/e2e/pressure-loss-empty-fields.e2e-spec.ts index c4516a88b..59eb87c64 100644 --- a/e2e/pressure-loss-empty-fields.e2e-spec.ts +++ b/e2e/pressure-loss-empty-fields.e2e-spec.ts @@ -3,6 +3,7 @@ import { Navbar } from "./navbar.po"; import { browser } from "protractor"; import { CalculatorPage } from "./calculator.po"; import { PreferencesPage } from "./preferences.po"; +import { changeSelectValue } from "./util.po"; describe("Check fields are empty in 'pressure loss' calculator when created with 'empty fields' option -", () => { let listPage: ListPage; @@ -32,7 +33,7 @@ describe("Check fields are empty in 'pressure loss' calculator when created with // select Lechapt-Calmon pressure loss law const materialSelect = calcPage.getSelectById("select_pressurelosstype"); - await calcPage.changeSelectValue(materialSelect, 0); + await changeSelectValue(materialSelect, 0); await browser.sleep(200); expect(calcPage.checkEmptyOrFilledFields(["Q", "D", "Lg", "Kloc"], [true, true, true, true])); diff --git a/e2e/remous.e2e-spec.ts b/e2e/remous.e2e-spec.ts index d13ccd48b..342d35edb 100644 --- a/e2e/remous.e2e-spec.ts +++ b/e2e/remous.e2e-spec.ts @@ -4,6 +4,7 @@ import { browser } from "protractor"; import { Navbar } from "./navbar.po"; import { PreferencesPage } from "./preferences.po"; import { SideNav } from "./sidenav.po"; +import { changeSelectValue } from "./util.po"; /** * Remous @@ -59,7 +60,7 @@ describe("ngHyd − remous", () => { await browser.sleep(300); // 2. Set to trapezoidal section with bank slope of 2m/m and 20 meter width bed - await calcPage.changeSelectValue(calcPage.getSelectById("select_section"), 2); + await changeSelectValue(calcPage.getSelectById("select_section"), 2); await browser.sleep(300); await calcPage.getInputById("LargeurFond").clear(); await browser.sleep(300); diff --git a/e2e/solveur.e2e-spec.ts b/e2e/solveur.e2e-spec.ts index 89ca70d6e..afe88721e 100644 --- a/e2e/solveur.e2e-spec.ts +++ b/e2e/solveur.e2e-spec.ts @@ -5,7 +5,7 @@ import { Navbar } from "./navbar.po"; import { browser, by, element } from "protractor"; import { SideNav } from "./sidenav.po"; import { PreferencesPage } from "./preferences.po"; -import { scrollPageToTop } from "./util.po"; +import { changeSelectValue, scrollPageToTop } from "./util.po"; /** * Clone calculators @@ -76,7 +76,7 @@ describe("Solveur - ", () => { expect(hasResults).toBe(true); // change targetted Nub, check that targetted result changes too - await calcPage.changeSelectValue(ntc, 0); + await changeSelectValue(ntc, 0); const nttV2 = await calcPage.getSelectValueText(ntt); expect(nttV2).not.toContain("Puissance dissipée (PV)"); }); @@ -111,9 +111,9 @@ describe("Solveur - ", () => { // Go back to Solveur await navbar.clickCalculatorTab(0); - await calcPage.changeSelectValue(calcPage.getSelectById("select_target_nub"), 1); // "Puissance / PV" + await changeSelectValue(calcPage.getSelectById("select_target_nub"), 1); // "Puissance / PV" await browser.sleep(500); - await calcPage.changeSelectValue(calcPage.getSelectById("select_searched_param"), 2); // "Chute / Z2" + await changeSelectValue(calcPage.getSelectById("select_searched_param"), 2); // "Chute / Z2" await browser.sleep(500); await calcPage.getInputById("Ytarget").sendKeys("318"); @@ -159,7 +159,7 @@ describe("Solveur - ", () => { // modify searched parameter const sel = calcPage.getSelectById("select_searched_param"); - await calcPage.changeSelectValue(sel, 11); + await changeSelectValue(sel, 11); await browser.sleep(300); const selText = await calcPage.getSelectValueText(sel); diff --git a/e2e/util.po.ts b/e2e/util.po.ts index e772a28ce..aded71c16 100644 --- a/e2e/util.po.ts +++ b/e2e/util.po.ts @@ -1,4 +1,4 @@ -import { ElementFinder, browser } from "protractor"; +import { ElementFinder, browser, by, element } from "protractor"; /** * scroll page to make element visible @@ -27,3 +27,11 @@ export function expectNumber(msg: string, val: number, expected: number) { } expect(val).toEqual(expected); } + +export async function changeSelectValue(elt: ElementFinder, index: number) { + await elt.click(); + const optionId = ".cdk-overlay-container mat-option:nth-of-type(" + (index + 1) + ")"; + const option = element(by.css(optionId)); + await option.click(); + await browser.sleep(200); +} -- GitLab From e7bec0d51002da010c36047bfdd0ac919cd6ba9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Wed, 15 Feb 2023 09:39:11 +0100 Subject: [PATCH 2/8] test(e2e): check that changing language setting changes labels in results refs #586 --- e2e/preferences.po.ts | 17 +++++++ e2e/translation.e2e-spec.ts | 97 +++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 e2e/translation.e2e-spec.ts diff --git a/e2e/preferences.po.ts b/e2e/preferences.po.ts index 51c1fc8de..39604b8cb 100644 --- a/e2e/preferences.po.ts +++ b/e2e/preferences.po.ts @@ -63,6 +63,23 @@ export class PreferencesPage { } } + /** + * enable/disable option "empty fields on module creation" + * @param b true to enable "empty fields on module creation" option, false to disable it (fill fields with default values) + */ + async setEmptyFields(b: boolean) { + await this.navigateTo(); + await browser.sleep(200); + + if (b) { + await this.enableEvilEmptyFields(); + } + else { + await this.disableEvilEmptyFields(); + } + await browser.sleep(200); + } + async setIterationCount(n: number) { const input = this.getInputFromName("nmi"); input.clear(); diff --git a/e2e/translation.e2e-spec.ts b/e2e/translation.e2e-spec.ts new file mode 100644 index 000000000..b0118eac9 --- /dev/null +++ b/e2e/translation.e2e-spec.ts @@ -0,0 +1,97 @@ +import { ListPage } from "./list.po"; +import { Navbar } from "./navbar.po"; +import { browser, by } from "protractor"; +import { CalculatorPage } from "./calculator.po"; +import { PreferencesPage } from "./preferences.po"; +import { SideNav } from "./sidenav.po"; + +describe("Check translation", () => { + let listPage: ListPage; + let navBar: Navbar; + let calcPage: CalculatorPage; + let prefPage: PreferencesPage; + let sideNav: SideNav; + + beforeAll(async () => { + listPage = new ListPage(); + navBar = new Navbar(); + calcPage = new CalculatorPage(); + prefPage = new PreferencesPage(); + sideNav = new SideNav(); + }); + + beforeEach(async () => { + prefPage.setEmptyFields(false); + }); + + it("variables in results", async () => { + // *** results in french *** + + prefPage.changeLanguage(1); // fr + await browser.sleep(200); + + // open "fish ladder: fall" calculator + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(12); + await browser.sleep(200); + + // set Z2 to variated mode + const inpZ2 = calcPage.getInputById("Z2"); + await calcPage.setParamMode(inpZ2, "var"); + + // run calculation + await calcPage.getCalculateButton().click(); + await browser.sleep(500); + + // "variable for X axis" select label + const selXaxis = calcPage.getSelectById("selectX"); + expect(await calcPage.getMatselectCurrentOptionText(selXaxis)).toEqual("Cote aval"); + + // "variable for Y axis" select label + const selYaxis = calcPage.getSelectById("selectY"); + expect(await calcPage.getMatselectCurrentOptionText(selYaxis)).toEqual("DH : Chute (m)"); + + // fixed results variables + const frr = calcPage.getAllFixedResultsRows(); + let lbl1 = await frr.all(by.css("td")).get(0).getText(); + expect(lbl1).toEqual("Cote amont (m)"); + + // variated results headers + const vrh = calcPage.getAllVariatedResultsTableHeaders(); + let lbl2 = await vrh.get(0).getText(); + expect(lbl2).toEqual("Cote aval"); + let lbl3 = await vrh.get(1).getText(); + expect(lbl3).toEqual("Chute (m)"); + + // *** results in english *** + + // setup -> english + await navBar.clickMenuButton(); + await browser.sleep(200); + const setupBtn = await sideNav.getSetupButton(); + await setupBtn.click(); + await browser.sleep(200); + await prefPage.changeLanguage(0); // en + await browser.sleep(200); + + // back to calculator + await navBar.clickCalculatorTab(0); + await browser.sleep(200); + + // "variable for X axis" select label + expect(await calcPage.getMatselectCurrentOptionText(selXaxis)).toEqual("Downstream elevation"); + + // "variable for Y axis" select label + expect(await calcPage.getMatselectCurrentOptionText(selYaxis)).toEqual("DH : Fall (m)"); + + // fixed results variables + lbl1 = await frr.all(by.css("td")).get(0).getText(); + expect(lbl1).toEqual("Upstream elevation (m)"); + + // variated results headers + lbl2 = await vrh.get(0).getText(); + expect(lbl2).toEqual("Downstream elevation"); + lbl3 = await vrh.get(1).getText(); + expect(lbl3).toEqual("Fall (m)"); + }); +}); -- GitLab From 3d5312616777b5333d9f8eb8908c086ea999c418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Wed, 15 Feb 2023 16:40:45 +0100 Subject: [PATCH 3/8] refactor: remove useless code refs #586 --- .../definition/form-section-parametree.ts | 4 --- src/app/formulaire/definition/form-section.ts | 5 ---- src/app/formulaire/elements/fieldset.ts | 30 ------------------- 3 files changed, 39 deletions(-) diff --git a/src/app/formulaire/definition/form-section-parametree.ts b/src/app/formulaire/definition/form-section-parametree.ts index 7f91f2fca..7ddfdefaf 100644 --- a/src/app/formulaire/definition/form-section-parametree.ts +++ b/src/app/formulaire/definition/form-section-parametree.ts @@ -23,10 +23,6 @@ export class FormulaireSectionParametree extends FormulaireSection { this.reaffectResultComponents(); } - protected runNubCalc(nub: Nub, computedParam?: ParamDefinition): Result { - return nub.CalcSerie(); - } - protected reaffectResultComponents() { this.resetFormResults(); // to avoid adding fixed parameters more than once (see below) const sectNub: SectionParametree = this.currentNub as SectionParametree; diff --git a/src/app/formulaire/definition/form-section.ts b/src/app/formulaire/definition/form-section.ts index bf06c16b2..3a6906d1a 100644 --- a/src/app/formulaire/definition/form-section.ts +++ b/src/app/formulaire/definition/form-section.ts @@ -47,11 +47,6 @@ export class FormulaireSection extends FormulaireFixedVar { const newSect = Session.getInstance().createSection(data.value); (this._currentNub as SectionNub).setSection(newSect); // reflect changes in GUI - for (const fs of this.allFieldsets) { - // show / hide dependent fields - fs.updateFields(); - } - // show / hide dependent fields this.refreshFieldsets(); this.reset(); } diff --git a/src/app/formulaire/elements/fieldset.ts b/src/app/formulaire/elements/fieldset.ts index c1678a93b..a705ab392 100644 --- a/src/app/formulaire/elements/fieldset.ts +++ b/src/app/formulaire/elements/fieldset.ts @@ -38,7 +38,6 @@ export class FieldSet extends FormulaireElement implements IProperties { public setNub(sn: Nub, update: boolean = true) { this._nub = sn; - this.setParentNubForAllFields(); if (update) { this.updateFields(); } @@ -135,9 +134,6 @@ export class FieldSet extends FormulaireElement implements IProperties { return this._jsonConfig; } - private setParentNubForAllFields() { - } - /** * crée un input * @param json definition de l'input, extrait du fichier de conf du module de calcul @@ -280,32 +276,6 @@ export class FieldSet extends FormulaireElement implements IProperties { } } - public getNodeParameter(symbol: string): NgParameter { - for (const p of this.kids) { - if (p instanceof NgParameter) { - if (p.isDisplayed && p.symbol === symbol) { - return p; - } - } - } - } - - public getNodeParameterValue(symbol: string): number { - const p = this.getNodeParameter(symbol); - if (!p) { - throw new Error(`FieldSet.getNodeParameterValue() : pas de paramètre ${symbol} trouvé`); - } - - switch (p.radioState) { - case ParamRadioConfig.FIX: - return p.getValue(); - - case ParamRadioConfig.VAR: - case ParamRadioConfig.CAL: - return undefined; - } - } - /** * retourne la valeur actuellement sélectionnée d'un SelectField (qui doit être affiché) * @param selectFieldId id du SelectField -- GitLab From 90ff0a177a315b514d447eb27ca0384c71cc896a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Wed, 15 Feb 2023 16:44:56 +0100 Subject: [PATCH 4/8] refactor: rename FormulaireDefinition.getParamFromSymbol() to getNgparamFromNubParam() refs #586 --- src/app/formulaire/definition/form-definition.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 9acb17e78..eec033312 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -346,11 +346,10 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs } /** - * Trouve le Ngparameter correspondant au symbole "symbol", parmi tous les - * éléments du formulaire - * @param symbol string + * Trouve le NgParameter correspondant au paramètre Nub parmi tous les éléments du formulaire + * @param param paramètre critère de recherche */ - public getParamFromSymbol(param: ParamDefinition): NgParameter { + private getNgparamFromNubParam(param: ParamDefinition): NgParameter { for (const p of this.allFormElements) { if (p instanceof NgParameter) { if (p.symbol === param.symbol && p.paramDefinition.parentNub.uid === param.parentNub.uid) { @@ -552,7 +551,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs const fixedParams: ParamDefinition[] = this._currentNub.findFixedParams(); let fnp: NgParameter[] = []; for (const fp of fixedParams) { - fnp.push(this.getParamFromSymbol(fp)); + fnp.push(this.getNgparamFromNubParam(fp)); } fnp = fnp.filter((e) => e !== undefined); return fnp; -- GitLab From 32ae1dfce014403b9fff84935c58905c9e646d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Wed, 15 Feb 2023 16:48:29 +0100 Subject: [PATCH 5/8] refactor: avoid NgParameter duplication refs #586 --- .../calculator.component.ts | 2 +- .../formulaire/definition/form-definition.ts | 16 ++++++---- .../formulaire/definition/form-fixedvar.ts | 9 +++--- .../definition/form-macrorugo-compound.ts | 2 +- .../formulaire/definition/form-prebarrage.ts | 2 +- .../definition/form-pressureloss.ts | 27 ++++++++++------- src/app/formulaire/definition/form-section.ts | 2 +- src/app/formulaire/definition/form-solveur.ts | 2 +- src/app/formulaire/elements/fieldset.ts | 29 ++++++++++++++----- 9 files changed, 57 insertions(+), 34 deletions(-) diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 49e81d946..46a03da75 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -1259,7 +1259,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe const form = this._formulaire as FormulaireFixedVar; const nub = (form.currentNub as Espece); nub.loadPredefinedSpecies(result.selected); - form.refreshFieldsets(); + form.refreshFieldsets(false); } }); } diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index eec033312..c6b05ea1b 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -359,6 +359,14 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs } } + public getOrCreateParam(nubParam: ParamDefinition, parent: FormulaireNode): NgParameter { + const res = this.getNgparamFromNubParam(nubParam); + if (res === undefined) { + return new NgParameter(nubParam, parent); + } + return res; + } + public getFieldById(id: string): Field { const res = this.getFormulaireNodeById(id); if (res instanceof Field) { @@ -531,14 +539,10 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs protected getComputedParameter(): NgParameter { const cpd = this.currentNub.calculatedParam; - let ngparam: NgParameter; if (cpd !== undefined) { - ngparam = this.getParamFromSymbol(cpd); - if (ngparam === undefined) { // calculated parameter is not displayed on screen - ngparam = new NgParameter(cpd, this); - } + return this.getOrCreateParam(cpd, this); } - return ngparam; + return undefined; } /** find variated (possibly linked) parameters from model, and get their values at the same time */ diff --git a/src/app/formulaire/definition/form-fixedvar.ts b/src/app/formulaire/definition/form-fixedvar.ts index 8eb6917e7..f20ce41fe 100644 --- a/src/app/formulaire/definition/form-fixedvar.ts +++ b/src/app/formulaire/definition/form-fixedvar.ts @@ -82,8 +82,7 @@ export class FormulaireFixedVar extends FormulaireDefinition { protected compute() { this.runNubCalc(this.currentNub); - this.refreshFieldsets(); // important: before reaffectResultComponents() or it will break results components localization - // this.reaffectResultComponents(); // seems useless since called from runNubCalc() + this.reaffectResultComponents(); } protected reaffectResultComponents() { @@ -115,9 +114,9 @@ export class FormulaireFixedVar extends FormulaireDefinition { /** * Forces all fieldsets to update all their fields */ - public refreshFieldsets() { + public refreshFieldsets(forceClear: boolean) { for (const fs of this.allFieldsets) { - fs.updateFields(); + fs.updateFields(forceClear); } this.completeParse(false); // re-add observers that were destroyed by updateFields() } @@ -130,7 +129,7 @@ export class FormulaireFixedVar extends FormulaireDefinition { if (data.action === "propertyChange") { this.reset(); // reflect changes in GUI (who knows ?), for ex. show / hide dependent fields - this.refreshFieldsets(); + this.refreshFieldsets(true); } } } diff --git a/src/app/formulaire/definition/form-macrorugo-compound.ts b/src/app/formulaire/definition/form-macrorugo-compound.ts index 306332cb5..5dd33e865 100644 --- a/src/app/formulaire/definition/form-macrorugo-compound.ts +++ b/src/app/formulaire/definition/form-macrorugo-compound.ts @@ -84,7 +84,7 @@ export class FormulaireMacrorugoCompound extends FormulaireRepeatableFieldset { */ public updateApronState(inclined: MRCInclination) { // show / hide dependent fields (read from model) - this.refreshFieldsets(); + this.refreshFieldsets(false); // show / hide children list (GUI only) for (const elt of this.allFormElements) { if (elt instanceof FieldsetContainer) { diff --git a/src/app/formulaire/definition/form-prebarrage.ts b/src/app/formulaire/definition/form-prebarrage.ts index c9a0d9e0d..09a2b1570 100644 --- a/src/app/formulaire/definition/form-prebarrage.ts +++ b/src/app/formulaire/definition/form-prebarrage.ts @@ -239,7 +239,7 @@ export class FormulairePrebarrage extends FormulaireFixedVar { protected compute() { this.runNubCalc(this.currentNub); - this.refreshFieldsets(); // important: before reaffectResultComponents() or it will break results components localization + this.refreshFieldsets(false); // important: before reaffectResultComponents() or it will break results components localization // reset variable index to avoid trying to access an index > 0 when nothing varies this._pbResults.variableIndex = 0; diff --git a/src/app/formulaire/definition/form-pressureloss.ts b/src/app/formulaire/definition/form-pressureloss.ts index 26c862355..9260bc79a 100644 --- a/src/app/formulaire/definition/form-pressureloss.ts +++ b/src/app/formulaire/definition/form-pressureloss.ts @@ -36,16 +36,23 @@ export class FormulairePressureLoss extends FormulaireFixedVar { } public update(sender: IObservable, data: any) { - // changement de propriété du FieldSet contenant le select de choix du type de perte de charge - if (sender instanceof FieldSet && sender.id === "fs_pressureloss_law" && data.action === "propertyChange") { - // replace underlying pressure loss law without replacing whole Nub - const newPLL = Session.getInstance().createPressureLossLaw(data.value, undefined, this.currentNub.getPropValue(Prop_NullParameters)); - (this._currentNub as PressureLoss).setLaw(newPLL); - // show / hide dependent fields - this.refreshFieldsets(); - this.reset(); + // if (sender instanceof FieldSet && sender.id === "fs_pressureloss_law" && data.action === "propertyChange") { + if (data.action === "propertyChange") { + if (data.name === "pressurelosstype") { + // changement de propriété du FieldSet contenant le select de choix du type de perte de charge + + // replace underlying pressure loss law without replacing whole Nub + const newPLL = Session.getInstance().createPressureLossLaw(data.value, undefined, this.currentNub.getPropValue(Prop_NullParameters)); + (this._currentNub as PressureLoss).setLaw(newPLL); + // show / hide dependent fields + this.refreshFieldsets(true); + this.reset(); + } + else if (data.name === "material") { + // changement de propriété du FieldSet contenant le select de choix du type de matériau + this.refreshFieldsets(false); + this.reset(); + } } - else - super.update(sender, data); } } diff --git a/src/app/formulaire/definition/form-section.ts b/src/app/formulaire/definition/form-section.ts index 3a6906d1a..d2aa08b33 100644 --- a/src/app/formulaire/definition/form-section.ts +++ b/src/app/formulaire/definition/form-section.ts @@ -47,7 +47,7 @@ export class FormulaireSection extends FormulaireFixedVar { const newSect = Session.getInstance().createSection(data.value); (this._currentNub as SectionNub).setSection(newSect); // reflect changes in GUI - this.refreshFieldsets(); + this.refreshFieldsets(true); this.reset(); } } diff --git a/src/app/formulaire/definition/form-solveur.ts b/src/app/formulaire/definition/form-solveur.ts index 0a3d446ef..ce7be1797 100644 --- a/src/app/formulaire/definition/form-solveur.ts +++ b/src/app/formulaire/definition/form-solveur.ts @@ -63,7 +63,7 @@ export class FormulaireSolveur extends FormulaireFixedVar { // refresh targetted result selector const trSel = this.getFormulaireNodeById(this._targettedResultSelectId) as SelectField; if (trSel) { - (trSel.parent as FieldSet).updateFields(); + (trSel.parent as FieldSet).updateFields(true); // trick to re-set observers this.completeParse(false); } diff --git a/src/app/formulaire/elements/fieldset.ts b/src/app/formulaire/elements/fieldset.ts index a705ab392..7b709eb76 100644 --- a/src/app/formulaire/elements/fieldset.ts +++ b/src/app/formulaire/elements/fieldset.ts @@ -10,7 +10,7 @@ import { import { FormulaireElement } from "./formulaire-element"; import { Field } from "./field"; import { SelectField } from "./select/select-field"; -import { NgParameter, ParamRadioConfig } from "./ngparam"; +import { NgParameter } from "./ngparam"; import { FieldsetContainer } from "./fieldset-container"; import { SelectFieldFactory } from "./select/select-field-factory"; import { FormulaireFixedVar } from "../definition/form-fixedvar"; @@ -39,7 +39,7 @@ export class FieldSet extends FormulaireElement implements IProperties { public setNub(sn: Nub, update: boolean = true) { this._nub = sn; if (update) { - this.updateFields(); + this.updateFields(true); } } @@ -47,7 +47,9 @@ export class FieldSet extends FormulaireElement implements IProperties { if (!f) { throw new Error("FieldSet.addField() : argument incorrect (undefined)"); } - this.kids.push(f); + if (this.kids.indexOf(f) === -1) { + this.kids.push(f); + } } /** @@ -105,6 +107,15 @@ export class FieldSet extends FormulaireElement implements IProperties { } } + private getOrCreateSelect(json: {}): SelectField { + const id: string = json["id"]; + const res = this.getFormulaireNodeById(id); + if (res === undefined || !(res instanceof SelectField)) { + return SelectFieldFactory.newSelectField(json, this); + } + return res; + } + private parse_select(json: {}): SelectField { let ok: boolean = true; // in case select is associated to a property, check nub has the property @@ -113,7 +124,7 @@ export class FieldSet extends FormulaireElement implements IProperties { ok = this.parentForm.getPropValue(p) !== undefined; } if (ok) { - const res: SelectField = SelectFieldFactory.newSelectField(json, this); + const res: SelectField = this.getOrCreateSelect(json); res.parseConfig(json); res.afterParseConfig(); res.addObserver(this); @@ -147,7 +158,7 @@ export class FieldSet extends FormulaireElement implements IProperties { try { nubParam = this.getNubParamFromSymbol(input_id); if (nubParam.visible) { - res = new NgParameter(nubParam, this); + res = this.parentForm.getOrCreateParam(nubParam, this); res.parseConfig(json); } } catch (e) { @@ -157,8 +168,6 @@ export class FieldSet extends FormulaireElement implements IProperties { } private parseFields() { - // clear everything so that parseFields() is idempotent - this.clearFields(); // parse children fields from config const fields = this._jsonConfig["fields"]; for (const field_index in fields) { @@ -203,7 +212,10 @@ export class FieldSet extends FormulaireElement implements IProperties { /** * Reloads the model values and properties, and reloads localisation strings */ - public updateFields() { + public updateFields(forceClear: boolean) { + if (forceClear) { + this.clearFields(); + } this.parseFields(); this.updateLocalisation(); @@ -257,6 +269,7 @@ export class FieldSet extends FormulaireElement implements IProperties { // parse fields once, so that SelectField elements are present // when setting default properties below + this.clearFields(); this.parseFields(); // for all select fields known by the form, apply default value -- GitLab From 73dedf3ef575ce008678aaa04be30f0acf4dbac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Wed, 15 Feb 2023 17:22:06 +0100 Subject: [PATCH 6/8] fix: variated results headers translation update after langage setting modification refs #586 --- .../fixedvar-results/var-results.component.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/app/components/fixedvar-results/var-results.component.ts b/src/app/components/fixedvar-results/var-results.component.ts index 7493401d2..3ba2053f5 100644 --- a/src/app/components/fixedvar-results/var-results.component.ts +++ b/src/app/components/fixedvar-results/var-results.component.ts @@ -3,7 +3,7 @@ import { Component, ViewChild, ElementRef, Input } from "@angular/core"; import { MatDialog } from "@angular/material/dialog"; import { VarResults } from "../../results/var-results"; -import { ResultElement, Message, MessageSeverity } from "jalhyd"; +import { ResultElement, Message, MessageSeverity, Observer } from "jalhyd"; import { I18nService } from "../../services/internationalisation.service"; import { ResultsComponentDirective } from "./results.component"; import { DialogLogEntriesDetailsComponent } from "../dialog-log-entries-details/dialog-log-entries-details.component"; @@ -17,7 +17,7 @@ import { longestVarParam } from "../../../app/util"; "./var-results.component.scss" ] }) -export class VarResultsComponent extends ResultsComponentDirective { +export class VarResultsComponent extends ResultsComponentDirective implements Observer { /** size of the longest variated parameter */ public size: number; @@ -42,12 +42,17 @@ export class VarResultsComponent extends ResultsComponentDirective { protected logEntriesDetailsDialog: MatDialog ) { super(); + this.intlService.addObserver(this); } /** Refreshes results and builds the dataset */ @Input() public set results(r: VarResults) { this._varResults = r; + this.updateResults(); + } + + private updateResults() { this._results = []; this._headers = []; this._messages = []; @@ -190,4 +195,12 @@ export class VarResultsComponent extends ResultsComponentDirective { } ); } + + // Observer interface + + update(sender: any, data: any): void { + if (sender instanceof I18nService) { + this._varResults.update(); + } + } } -- GitLab From 50b72f15f8fc9404455855fb3b8a218f77f3f405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Thu, 16 Feb 2023 09:48:32 +0100 Subject: [PATCH 7/8] fix: variable results graph: select entries not translated when modifying langage setting refs #586 --- .../fixedvar-results/var-results.component.ts | 8 ++++++-- src/app/results/param-calc-results.ts | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/app/components/fixedvar-results/var-results.component.ts b/src/app/components/fixedvar-results/var-results.component.ts index 3ba2053f5..f6204377d 100644 --- a/src/app/components/fixedvar-results/var-results.component.ts +++ b/src/app/components/fixedvar-results/var-results.component.ts @@ -1,4 +1,4 @@ -import { Component, ViewChild, ElementRef, Input } from "@angular/core"; +import { Component, ViewChild, ElementRef, Input, OnInit } from "@angular/core"; import { MatDialog } from "@angular/material/dialog"; @@ -17,7 +17,7 @@ import { longestVarParam } from "../../../app/util"; "./var-results.component.scss" ] }) -export class VarResultsComponent extends ResultsComponentDirective implements Observer { +export class VarResultsComponent extends ResultsComponentDirective implements Observer, OnInit { /** size of the longest variated parameter */ public size: number; @@ -196,6 +196,10 @@ export class VarResultsComponent extends ResultsComponentDirective implements Ob ); } + ngOnInit(): void { + this._varResults.updateCalculatedParameterHeader(); + } + // Observer interface update(sender: any, data: any): void { diff --git a/src/app/results/param-calc-results.ts b/src/app/results/param-calc-results.ts index eaca087d3..9e22d98b4 100644 --- a/src/app/results/param-calc-results.ts +++ b/src/app/results/param-calc-results.ts @@ -12,7 +12,7 @@ export abstract class CalculatedParamResults extends CalculatorResults { protected _calculatedParam: NgParameter; /** titre de la colonne du paramètre calculé */ - public calculatedParameterHeader: string; + private _calculatedParameterHeader: string; /** résultat du calcul sur le paramètre calculé */ public result: Result; @@ -22,7 +22,7 @@ export abstract class CalculatedParamResults extends CalculatorResults { public reset() { this._calculatedParam = undefined; - this.calculatedParameterHeader = undefined; + this._calculatedParameterHeader = undefined; this.result = undefined; } @@ -32,7 +32,17 @@ export abstract class CalculatedParamResults extends CalculatorResults { public set calculatedParameter(p: NgParameter) { this._calculatedParam = p; - this.calculatedParameterHeader = CalculatorResults.paramLabel(this._calculatedParam, true); + this.updateCalculatedParameterHeader(); + } + + public updateCalculatedParameterHeader() { + if (this._calculatedParam !== undefined) { + this._calculatedParameterHeader = CalculatorResults.paramLabel(this._calculatedParam, true); + } + } + + public get calculatedParameterHeader(): string { + return this._calculatedParameterHeader; } public get hasResults(): boolean { -- GitLab From 0ab34d388e87c56b9f3005877f4deea6275c6ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Thu, 16 Feb 2023 10:29:00 +0100 Subject: [PATCH 8/8] fix: variated results graph: axis Y label not translated when changing langage setting refs #586 --- src/app/components/results-chart/results-chart.component.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/components/results-chart/results-chart.component.ts b/src/app/components/results-chart/results-chart.component.ts index 0b33967f3..0bb985913 100644 --- a/src/app/components/results-chart/results-chart.component.ts +++ b/src/app/components/results-chart/results-chart.component.ts @@ -182,6 +182,10 @@ export class ResultsChartComponent extends ResultsComponentDirective implements } public ngOnChanges() { + if (this._results instanceof VarResults) { + this._results.updateCalculatedParameterHeader(); + } + // redessiner le graphique chaque fois qu'une entrée change this.drawChart(); } -- GitLab