From f635446d25eba4c6a4327d4cf9ace233767ba6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Wed, 13 Apr 2022 13:23:21 +0200 Subject: [PATCH 01/13] test: check field 'number of falls' of the 'generate fish ladder' dialog is empty with the 'enable empty fields on new calculators' option refs #516 --- e2e/pab-cloisons-empty-fields.e2e-spec.ts | 83 +++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 e2e/pab-cloisons-empty-fields.e2e-spec.ts diff --git a/e2e/pab-cloisons-empty-fields.e2e-spec.ts b/e2e/pab-cloisons-empty-fields.e2e-spec.ts new file mode 100644 index 000000000..1782869db --- /dev/null +++ b/e2e/pab-cloisons-empty-fields.e2e-spec.ts @@ -0,0 +1,83 @@ +import { ListPage } from "./list.po"; +import { PreferencesPage } from "./preferences.po"; +import { browser, by, element } from "protractor"; +import { CalculatorPage } from "./calculator.po"; +import { AppPage } from "./app.po"; +import { Navbar } from "./navbar.po"; + +/** + * Check that when "empty fields on calculator creation" is enabled + * fields are empty in the "generate fish ladder" dialog of the + * cross walls calculator + */ +describe("ngHyd - check the cross walls calculator has empty fields - ", () => { + let prefPage: PreferencesPage; + let listPage: ListPage; + let calcPage: CalculatorPage; + let navBar: Navbar; + + beforeAll(() => { + prefPage = new PreferencesPage(); + listPage = new ListPage(); + calcPage = new CalculatorPage(); + navBar = new Navbar(); + }); + + beforeEach(async () => { + // enable evil option "empty fields on module creation" + await prefPage.navigateTo(); + await browser.sleep(200); + await prefPage.enableEvilEmptyFields(); + await browser.sleep(200); + }); + + /** + * check that a input set is in a given (empty/filled) state + * @param inputIds id of the inputs to check + * @param emptys empty/not empty state array + */ + async function checkFields(inputIds: string[], emptys: boolean[]) { + let n = 0; + for (const id of inputIds) { + const inp = await calcPage.getInputById(id); + const txt = await inp.getAttribute("value"); + expect(txt === "").toEqual(emptys[n]); + n++; + } + } + + async function fillInput(symbol: string) { + const inp = calcPage.getInputById(symbol); + await inp.clear(); + await inp.sendKeys("1"); + } + + it("in the 'generate fish ladder' dialog", async () => { + // open cross walls calculator + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(10); + await browser.sleep(200); + + // fill inputs + await fillInput("Q"); + await fillInput("Z1"); + await fillInput("LB"); + await fillInput("BB"); + await fillInput("PB"); + await fillInput("0_h1"); + await fillInput("0_L"); + await fillInput("0_CdWSL"); + + // calculate + const calcButton = calcPage.getCalculateButton(); + await calcButton.click(); + await browser.sleep(200); + + // click "generate PAB" button + const genButton = calcPage.getGeneratePabButton(); + await genButton.click(); + await browser.sleep(200); + + await checkFields(["generatePabNbBassins"], [true]); + }); +}); -- GitLab From 0ef436f3d20d112bc46de51a781b3f03c5c3b67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Wed, 13 Apr 2022 13:26:33 +0200 Subject: [PATCH 02/13] fix: empty field 'number of falls" of 'generate fish ladder' dialog when 'enable empty fields on new calculator' option is set refs #516 --- .../dialog-generate-pab.component.ts | 13 +++++++------ .../generic-calculator/calculator.component.ts | 12 +++++++++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts b/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts index 9634a342b..65454306a 100644 --- a/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts +++ b/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts @@ -29,21 +29,22 @@ export class DialogGeneratePABComponent { @Inject(MAT_DIALOG_DATA) public data: any ) { const nDigits = this.appSetupService.displayPrecision; - this.coteAmont = round(data.coteAmont, nDigits); - this.debit = round(data.debit, nDigits); + this.coteAmont = data.coteAmont ? round(data.coteAmont, nDigits) : undefined; + this.debit = data.debit ? round(data.debit, nDigits) : undefined; this.chute = round(data.chute, nDigits); + this.nbBassins = data.nbBassins; } public generatePAB() { // calculate downstream elevation - const coteAval = this.coteAmont - (this.chute * this.nbBassins); + const coteAval = +this.coteAmont - (this.chute * +this.nbBassins); // create PAB this.dialogRef.close({ generate: true, - debit: this.debit, - coteAmont: this.coteAmont, + debit: +this.debit, + coteAmont: +this.coteAmont, coteAval: coteAval, - nbBassins: this.nbBassins + nbBassins: +this.nbBassins }); } diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 2608ce76e..195796210 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -58,6 +58,7 @@ import { MatomoTracker } from "ngx-matomo"; import { sprintf } from "sprintf-js"; import * as XLSX from "xlsx"; +import { ServiceFactory } from "app/services/service-factory"; @Component({ selector: "hydrocalc", @@ -731,13 +732,18 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe public generatePAB() { // création du dialogue de génération d'une passe à bassin const cloisons = (this._formulaire.currentNub as Cloisons); + const chute = cloisons.prms.DH.V; + const debit = cloisons.prms.Q.V; + const zAmont = cloisons.prms.Z1.V; + const nbBassins = ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit ? undefined : 6; const dialogRef = this.generatePABDialog.open( DialogGeneratePABComponent, { data: { - chute: cloisons.prms.DH.V, - debit: cloisons.prms.Q.V, - coteAmont: cloisons.prms.Z1.V + chute: chute, + debit: debit, + coteAmont: zAmont, + nbBassins: nbBassins }, disableClose: false } -- GitLab From 32e89a7a30f12fead5682a08ae115ce78df8b6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Wed, 13 Apr 2022 14:50:42 +0200 Subject: [PATCH 03/13] refactor: move downstream elevation calculation to GenericCalculatorComponent refs #516 --- .../dialog-generate-pab.component.ts | 6 - .../calculator.component.ts | 122 +++++++++--------- 2 files changed, 63 insertions(+), 65 deletions(-) diff --git a/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts b/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts index 65454306a..202aa1fd8 100644 --- a/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts +++ b/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts @@ -18,8 +18,6 @@ export class DialogGeneratePABComponent { public coteAmont = 102; - public chute: number; - public nbBassins = 6; constructor( @@ -31,19 +29,15 @@ export class DialogGeneratePABComponent { const nDigits = this.appSetupService.displayPrecision; this.coteAmont = data.coteAmont ? round(data.coteAmont, nDigits) : undefined; this.debit = data.debit ? round(data.debit, nDigits) : undefined; - this.chute = round(data.chute, nDigits); this.nbBassins = data.nbBassins; } public generatePAB() { - // calculate downstream elevation - const coteAval = +this.coteAmont - (this.chute * +this.nbBassins); // create PAB this.dialogRef.close({ generate: true, debit: +this.debit, coteAmont: +this.coteAmont, - coteAval: coteAval, nbBassins: +this.nbBassins }); } diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 195796210..9650543c6 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -1,5 +1,7 @@ -import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, - QueryList, AfterViewChecked, ElementRef, Inject, forwardRef, isDevMode } from "@angular/core"; +import { + Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, + QueryList, AfterViewChecked, ElementRef, Inject, forwardRef, isDevMode +} from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { @@ -308,7 +310,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public get quicknavItems() { - const elts = [ "input", "results" ]; + const elts = ["input", "results"]; if (this.isWide && this.hasResults) { elts.push("charts"); } @@ -329,7 +331,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe * the UI validity state) */ ngDoCheck() { - this.isCalculateDisabled = ! this._isUIValid; + this.isCalculateDisabled = !this._isUIValid; } ngOnDestroy() { @@ -363,7 +365,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public ngAfterViewChecked() { - if (! this.firstViewChecked) { + if (!this.firstViewChecked) { this.firstViewChecked = true; this.afterFirstViewChecked(); } @@ -394,7 +396,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public doCompute() { - if (! isDevMode()) { + if (!isDevMode()) { this.matomoTracker.trackEvent("userAction", "triggerCalculation", CalculatorType[this._formulaire.currentNub.calcType]); } this._formulaire.resetResults([]); @@ -445,7 +447,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe try { this.appComponent.scrollToQuicknav("results"); } catch (e) { - const element = document.getElementById ("fake-results-anchor"); + const element = document.getElementById("fake-results-anchor"); if (element) { element.scrollIntoView(); } @@ -472,7 +474,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe */ private updateUIValidity() { this._isUIValid = false; - if (! this._formulaire.calculateDisabled) { + if (!this._formulaire.calculateDisabled) { // all fieldsets must be valid this._isUIValid = true; if (this._fieldsetComponents !== undefined) { @@ -695,14 +697,14 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe private allParamsAreFixed(except: string[] = []) { let ret = true; for (const p of this._formulaire.currentNub.parameterIterator) { - if (! except.includes(p.symbol)) { + if (!except.includes(p.symbol)) { if (p.valueMode === ParamValueMode.LINK) { - ret = ret && (! p.hasMultipleValues); + ret = ret && (!p.hasMultipleValues); } else { // avoid calling hasMultipleValues here, because changing parameter mode in GUI // switches valueMode before setting min/max/step or valuesList, and iterator // checker fails to count values that do not exist yet - ret = ret && (! [ ParamValueMode.LISTE, ParamValueMode.MINMAX ].includes(p.valueMode)); + ret = ret && (![ParamValueMode.LISTE, ParamValueMode.MINMAX].includes(p.valueMode)); } } } @@ -717,10 +719,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public get uitextGeneratePabTitle() { - if (! this.hasResults) { + if (!this.hasResults) { return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } - if (! this.allParamsAreFixed()) { + if (!this.allParamsAreFixed()) { return this.intlService.localizeText("INFO_PARAMETRES_FIXES"); } return ""; @@ -737,41 +739,43 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe const zAmont = cloisons.prms.Z1.V; const nbBassins = ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit ? undefined : 6; const dialogRef = this.generatePABDialog.open( - DialogGeneratePABComponent, - { - data: { - chute: chute, - debit: debit, - coteAmont: zAmont, - nbBassins: nbBassins - }, - disableClose: false - } + DialogGeneratePABComponent, + { + data: { + debit: debit, + coteAmont: zAmont, + nbBassins: nbBassins + }, + disableClose: false + } ); dialogRef.afterClosed().subscribe(async result => { - if (result) { - if (result.generate) { - const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.Pab); - const pab = (f.currentNub as Pab); - const params = pab.prms; - // paramètres hydrauliques - params.Q.singleValue = result.debit; - params.Z1.singleValue = result.coteAmont; - params.Z2.singleValue = result.coteAval; - // création des bassins - pab.deleteChild(0); - pab.addCloisonsFromModel(this._formulaire.currentNub as Cloisons, result.nbBassins); - // go to new PAB - this.router.navigate(["/calculator", f.uid]); + if (result) { + if (result.generate) { + const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.Pab); + const pab = (f.currentNub as Pab); + const params = pab.prms; + // calculate downstream elevation + const chute = cloisons.prms.DH.V; + const coteAval = result.coteAmont - (chute * result.nbBassins); + // paramètres hydrauliques + params.Q.singleValue = result.debit; + params.Z1.singleValue = result.coteAmont; + params.Z2.singleValue = coteAval; + // création des bassins + pab.deleteChild(0); + pab.addCloisonsFromModel(this._formulaire.currentNub as Cloisons, result.nbBassins); + // go to new PAB + this.router.navigate(["/calculator", f.uid]); + } } - } }); } public get generateSPAmontEnabled(): boolean { const bief = (this._formulaire.currentNub as Bief); if (bief.prms.Z1 === bief.calculatedParam) { - return this.hasResults && ! bief.result.hasErrorMessages(); + return this.hasResults && !bief.result.hasErrorMessages(); } else { // check that linked values are available, if any return ( @@ -784,7 +788,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe public get generateSPAvalEnabled(): boolean { const bief = (this._formulaire.currentNub as Bief); if (bief.prms.Z2 === bief.calculatedParam) { - return this.hasResults && ! bief.result.hasErrorMessages(); + return this.hasResults && !bief.result.hasErrorMessages(); } else { // check that linked values are available, if any return ( @@ -795,7 +799,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public get uitextGenerateSPAmontTitle(): string { - if (! this.generateSPAmontEnabled) { + if (!this.generateSPAmontEnabled) { return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } else { return ""; @@ -803,7 +807,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public get uitextGenerateSPAvalTitle(): string { - if (! this.generateSPAvalEnabled) { + if (!this.generateSPAvalEnabled) { return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } else { return ""; @@ -841,7 +845,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe const bief = (this._formulaire.currentNub as Bief); return generateValuesCombination( bief, - [ Z, ZF ], + [Z, ZF], (nub: Nub, values: { [key: string]: number }): number => { return round(values[Z.symbol] - values[ZF.symbol], 3); } @@ -855,7 +859,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe const bief = (this._formulaire.currentNub as Bief); return generateValuesCombination( bief, - [ bief.prms.ZF1, bief.prms.ZF2, bief.prms.Long ], + [bief.prms.ZF1, bief.prms.ZF2, bief.prms.Long], (nub: Nub, values: { [key: string]: number }): number => { return round((values["ZF1"] - values["ZF2"]) / values["Long"], 5); } @@ -879,7 +883,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe // "If" is hidden in Bief, for ex. bief.section.getParameter(p.symbol).visible // do not link Y and If - && ! [ "If", "Y" ].includes(p.symbol) + && !["If", "Y"].includes(p.symbol) ) { const bP = bief.section.getParameter(p.symbol); if (bP.valueMode === ParamValueMode.LINK) { @@ -901,11 +905,11 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public get generateRuSpEnabled(): boolean { - return this.hasResults && ! this._formulaire.currentNub.result.hasErrorMessages(); + return this.hasResults && !this._formulaire.currentNub.result.hasErrorMessages(); } public get uitextGenerateRuSpTitle(): string { - if (! this.generateRuSpEnabled) { + if (!this.generateRuSpEnabled) { return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } else { return ""; @@ -941,7 +945,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe const parCalage = (this._formulaire.currentNub as Par); return ( this.hasResults - && ! parCalage.result.hasErrorMessages() + && !parCalage.result.hasErrorMessages() && parCalage.prms.Z1.isDefined && parCalage.prms.Z2.isDefined ); @@ -949,12 +953,12 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe public get uitextGenerateParSimulationTitle(): string { const parCalage = (this._formulaire.currentNub as Par); - if (! this.hasResults || parCalage.result.hasErrorMessages()) { + if (!this.hasResults || parCalage.result.hasErrorMessages()) { return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } if ( - ! parCalage.prms.Z1.isDefined - || ! parCalage.prms.Z2.isDefined + !parCalage.prms.Z1.isDefined + || !parCalage.prms.Z2.isDefined ) { return this.intlService.localizeText("INFO_Z1_Z2_MUST_BE_DEFINED"); } @@ -1031,7 +1035,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe public get exportAllPbResultsEnabled(): boolean { const pb = (this._formulaire as FormulairePrebarrage).currentNub as PreBarrage; - return (pb.result !== undefined && ! pb.result.hasOnlyErrors); + return (pb.result !== undefined && !pb.result.hasOnlyErrors); } /** @@ -1169,11 +1173,11 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe protected async doGenerateParSimWithValues(v: any) { const parCalage = (this._formulaire.currentNub as Par); const psim = new ParSimulationParams( - round(v.Q, 3), round(v.Z1, 3), round(v.Z2, 3), - round(v.S, 3), round(v.P, 3), round(v.Nb, 3), - round(v.ZR1, 3), round(v.ZD1, 3), round(v.ZR2, 3), - round(v.ZD2, 3), round(v.L, 3), round(v.a, 3), - round(v.N, 3), round(v.M, 3) + round(v.Q, 3), round(v.Z1, 3), round(v.Z2, 3), + round(v.S, 3), round(v.P, 3), round(v.Nb, 3), + round(v.ZR1, 3), round(v.ZD1, 3), round(v.ZR2, 3), + round(v.ZD2, 3), round(v.L, 3), round(v.a, 3), + round(v.N, 3), round(v.M, 3) ); const parSimulation = new ParSimulation(psim); parSimulation.parType = parCalage.parType; @@ -1194,7 +1198,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe const dialogRef = this.loadPredefinedEspeceDialog.open( DialogLoadPredefinedEspeceComponent, { - data: { }, + data: {}, disableClose: false } ); @@ -1217,7 +1221,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe DialogConfirmCloseCalcComponent, { data: { - uid: this._formulaire.currentNub.uid + uid: this._formulaire.currentNub.uid }, disableClose: true } -- GitLab From 16502913f57d7ff1060887441a9f60eaa4f99a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Tue, 26 Apr 2022 08:19:19 +0200 Subject: [PATCH 04/13] test: check cross walls calculator has no empty field after calculation refs #516 --- e2e/pab-cloisons-empty-fields.e2e-spec.ts | 122 +++++++++++++++------- 1 file changed, 87 insertions(+), 35 deletions(-) diff --git a/e2e/pab-cloisons-empty-fields.e2e-spec.ts b/e2e/pab-cloisons-empty-fields.e2e-spec.ts index 1782869db..c7305027a 100644 --- a/e2e/pab-cloisons-empty-fields.e2e-spec.ts +++ b/e2e/pab-cloisons-empty-fields.e2e-spec.ts @@ -5,6 +5,37 @@ import { CalculatorPage } from "./calculator.po"; import { AppPage } from "./app.po"; import { Navbar } from "./navbar.po"; +/** + * enable evil option "empty fields on module creation" + */ +async function enableEmptyFieldsOption(prefPage: PreferencesPage) { + await prefPage.navigateTo(); + await browser.sleep(200); + await prefPage.enableEvilEmptyFields(); + await browser.sleep(200); +} + +/** + * check that a input set is in a given (empty/filled) state + * @param inputIds id of the inputs to check + * @param emptys empty/not empty state array + */ +async function checkFields(calcPage: CalculatorPage, inputIds: string[], emptys: boolean[]) { + let n = 0; + for (const id of inputIds) { + const inp = await calcPage.getInputById(id); + const txt = await inp.getAttribute("value"); + expect(txt === "").toEqual(emptys[n]); + n++; + } +} + +async function fillInput(calcPage: CalculatorPage, symbol: string) { + const inp = calcPage.getInputById(symbol); + await inp.clear(); + await inp.sendKeys("1"); +} + /** * Check that when "empty fields on calculator creation" is enabled * fields are empty in the "generate fish ladder" dialog of the @@ -24,34 +55,9 @@ describe("ngHyd - check the cross walls calculator has empty fields - ", () => { }); beforeEach(async () => { - // enable evil option "empty fields on module creation" - await prefPage.navigateTo(); - await browser.sleep(200); - await prefPage.enableEvilEmptyFields(); - await browser.sleep(200); + await enableEmptyFieldsOption(prefPage); }); - /** - * check that a input set is in a given (empty/filled) state - * @param inputIds id of the inputs to check - * @param emptys empty/not empty state array - */ - async function checkFields(inputIds: string[], emptys: boolean[]) { - let n = 0; - for (const id of inputIds) { - const inp = await calcPage.getInputById(id); - const txt = await inp.getAttribute("value"); - expect(txt === "").toEqual(emptys[n]); - n++; - } - } - - async function fillInput(symbol: string) { - const inp = calcPage.getInputById(symbol); - await inp.clear(); - await inp.sendKeys("1"); - } - it("in the 'generate fish ladder' dialog", async () => { // open cross walls calculator await navBar.clickNewCalculatorButton(); @@ -59,14 +65,14 @@ describe("ngHyd - check the cross walls calculator has empty fields - ", () => { await browser.sleep(200); // fill inputs - await fillInput("Q"); - await fillInput("Z1"); - await fillInput("LB"); - await fillInput("BB"); - await fillInput("PB"); - await fillInput("0_h1"); - await fillInput("0_L"); - await fillInput("0_CdWSL"); + await fillInput(calcPage, "Q"); + await fillInput(calcPage, "Z1"); + await fillInput(calcPage, "LB"); + await fillInput(calcPage, "BB"); + await fillInput(calcPage, "PB"); + await fillInput(calcPage, "0_h1"); + await fillInput(calcPage, "0_L"); + await fillInput(calcPage, "0_CdWSL"); // calculate const calcButton = calcPage.getCalculateButton(); @@ -78,6 +84,52 @@ describe("ngHyd - check the cross walls calculator has empty fields - ", () => { await genButton.click(); await browser.sleep(200); - await checkFields(["generatePabNbBassins"], [true]); + await checkFields(calcPage, ["generatePabNbBassins"], [true]); + }); +}); + +/** + * Check that when "empty fields on calculator creation" is enabled + * fields are not empty after calculation + */ +describe("ngHyd - check the cross walls calculator has no empty field - ", () => { + let prefPage: PreferencesPage; + let listPage: ListPage; + let calcPage: CalculatorPage; + let navBar: Navbar; + + beforeAll(() => { + prefPage = new PreferencesPage(); + listPage = new ListPage(); + calcPage = new CalculatorPage(); + navBar = new Navbar(); + }); + + beforeEach(async () => { + await enableEmptyFieldsOption(prefPage); + }); + + it("after calculation", async () => { + // open cross walls calculator + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(10); + await browser.sleep(200); + + // fill inputs + await fillInput(calcPage, "Q"); + await fillInput(calcPage, "Z1"); + await fillInput(calcPage, "LB"); + await fillInput(calcPage, "BB"); + await fillInput(calcPage, "PB"); + await fillInput(calcPage, "0_h1"); + await fillInput(calcPage, "0_L"); + await fillInput(calcPage, "0_CdWSL"); + + // calculate + const calcButton = calcPage.getCalculateButton(); + await calcButton.click(); + await browser.sleep(200); + + await checkFields(calcPage, ["Q", "Z1", "LB", "BB", "PB", "0_h1", "0_L", "0_CdWSL"], [false, false, false, false, false, false, false, false]); }); }); -- GitLab From 4e39f6945f2c302271d32a6a054ff0b6d343c90b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Thu, 28 Apr 2022 15:01:35 +0200 Subject: [PATCH 05/13] refactor: move empty fields management to jalhyd refs #516 --- jalhyd_branch | 2 +- .../base-param-input.component.ts | 2 +- .../calculator-list.component.ts | 4 --- .../pb-schema/pb-schema.component.ts | 25 --------------- .../formulaire/definition/form-prebarrage.ts | 15 --------- src/app/formulaire/definition/form-section.ts | 5 --- src/app/formulaire/elements/fieldset.ts | 18 ++--------- .../formulaire/elements/formulaire-node.ts | 31 ------------------- src/app/services/app-setup.service.ts | 12 ++++++- 9 files changed, 15 insertions(+), 99 deletions(-) diff --git a/jalhyd_branch b/jalhyd_branch index 626e97d71..f6d80c358 100644 --- a/jalhyd_branch +++ b/jalhyd_branch @@ -1 +1 @@ -devel \ No newline at end of file +306-gerer-un-flag-modified-dans-paramdefinition \ No newline at end of file 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 25573571b..883fa0772 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 @@ -15,7 +15,7 @@ export class NgBaseParam extends Observable { constructor(symb: string, d: ParamDomain | ParamDomainValue, val: number, unit?: string) { super(); - this._param = new ParamDefinition(null, symb, d, unit, val); + this._param = new ParamDefinition(null, symb, d, unit, val, undefined, undefined, false); } public get param() { diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts index fcc96d90f..cd37dad30 100644 --- a/src/app/components/calculator-list/calculator-list.component.ts +++ b/src/app/components/calculator-list/calculator-list.component.ts @@ -181,10 +181,6 @@ export class CalculatorListComponent implements OnInit { } } } - - if (this.appSetupService.enableEmptyFieldsOnFormInit) { - f.emptyFields(); - } } public get nbOpenCalculators() { diff --git a/src/app/components/pb-schema/pb-schema.component.ts b/src/app/components/pb-schema/pb-schema.component.ts index e1e74c9e6..1862a8dcf 100644 --- a/src/app/components/pb-schema/pb-schema.component.ts +++ b/src/app/components/pb-schema/pb-schema.component.ts @@ -492,35 +492,10 @@ export class PbSchemaComponent implements AfterViewInit, AfterContentInit, OnIni return this.i18nService.localizeText("INFO_FIELDSET_COPY"); } - /** - * Set value of all single parameters to undefined, except for the given parameter ids - */ - private emptyFields(basin: PbBassin, except: string[] = FormulaireNode.NeverEmptyFields) { - // save current calculated param, as setting value on a CALC param will - // change its mode and choose another calculated param by default - let calcP: ParamDefinition; - for (const p of basin.parameterIterator) { - if ( - [ParamValueMode.SINGLE, ParamValueMode.CALCUL].includes(p.valueMode) - && !except.includes(p.symbol) - ) { - if (p.valueMode === ParamValueMode.CALCUL) { - calcP = p; - } - p.setValue(undefined); - } - } - // restore original calculated param - if (calcP !== undefined) { - calcP.setCalculated(); - } - } - /** Adds a new lone basin */ public onAddBasinClick() { const newBasin = new PbBassin(new PbBassinParams(20, 99)); this.model.addChild(newBasin); - this.emptyFields(newBasin); this.clearResults(); this.refreshWithSelection(newBasin.uid); this.calculatorComponent.showPBInputData = true; diff --git a/src/app/formulaire/definition/form-prebarrage.ts b/src/app/formulaire/definition/form-prebarrage.ts index ebe3ea8ff..811007d2c 100644 --- a/src/app/formulaire/definition/form-prebarrage.ts +++ b/src/app/formulaire/definition/form-prebarrage.ts @@ -322,21 +322,6 @@ export class FormulairePrebarrage extends FormulaireFixedVar { } } - /** - * Set value of all single parameters to undefined, except for the given parameter ids - */ - public emptyFields(except: string[] = FormulaireNode.NeverEmptyFields) { - // save current calculated param, as setting value on a CALC param will - // change its mode and choose another calculated param by default - const paramCalculated = this.currentNub.calculatedParam; - for (const p of this.currentNub.parameterIterator) { - if (! except.includes(p.symbol)) { - p.setValue(undefined); - } - } - this.currentNub.calculatedParam = paramCalculated; - } - /** * Check validity of all model parameters * @param withChildren check parameters of child nub as well diff --git a/src/app/formulaire/definition/form-section.ts b/src/app/formulaire/definition/form-section.ts index fd45ceb50..c408e572a 100644 --- a/src/app/formulaire/definition/form-section.ts +++ b/src/app/formulaire/definition/form-section.ts @@ -20,11 +20,6 @@ export class FormulaireSection extends FormulaireFixedVar { } // show / hide dependent fields this.refreshFieldsets(); - // empty fields ? only those belonging to the specific section type - if (ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit) { - // "LargeurBerge" is hackily used as LargeurFond in Rectangular and Trapez sections, omit it here - this.emptyFields([ "Ks", "Q", "If", "YB", "iPrec", "Y" ]); - } this.reset(); } } diff --git a/src/app/formulaire/elements/fieldset.ts b/src/app/formulaire/elements/fieldset.ts index e5a9ca15a..4081f8241 100644 --- a/src/app/formulaire/elements/fieldset.ts +++ b/src/app/formulaire/elements/fieldset.ts @@ -73,23 +73,13 @@ export class FieldSet extends FormulaireElement implements Observer { * @param backup list of NgParameter object representation * @see backupParameters */ - public restoreParameters(backup: any[], except: string[] = FormulaireNode.NeverEmptyFields) { + public restoreParameters(backup: any[]) { // for (const p of this.allFormElements) { for (const p of this._kids) { if (p instanceof NgParameter) { for (const bp of backup) { if (p.symbol === bp.prmDef.symbol) { - // if source parameter has been user modified, copy value - if (bp.modified) { - p.loadObjectRepresentation(bp); - } - else { - // can parameter be emptied ? - if (ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit && !except.includes(bp.prmDef.symbol)) { - p.resetValue(this, undefined); - } - // else let parameter to default value - } + p.loadObjectRepresentation(bp); break; } } @@ -421,10 +411,6 @@ export class FieldSet extends FormulaireElement implements Observer { } } - if (ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit) { - const f = this.parentForm; - f.emptyFields(); - } break; // switch (data.action) } } diff --git a/src/app/formulaire/elements/formulaire-node.ts b/src/app/formulaire/elements/formulaire-node.ts index 0ab8a88df..b57bec770 100644 --- a/src/app/formulaire/elements/formulaire-node.ts +++ b/src/app/formulaire/elements/formulaire-node.ts @@ -9,11 +9,6 @@ import { NgParameter } from "./ngparam"; */ export abstract class FormulaireNode implements IObservable { - /** - * fields in fieldset that must not be empty due to enableEmptyFieldsOnFormInit option - */ - public static readonly NeverEmptyFields = ["Cd0", "CdWS", "CdGR", "CdGRS", "CdCunge", "CdWR", "CdO", "CdT"]; - /** aide en ligne */ protected _helpLink: string; @@ -145,32 +140,6 @@ export abstract class FormulaireNode implements IObservable { return new DeepFormulaireElementIterator(this); } - /** - * Set value of all single parameters to undefined, except for the given parameter ids - */ - public emptyFields(except: string[] = FormulaireNode.NeverEmptyFields) { - // save current calculated param, as setting value on a CALC param will - // change its mode and choose another calculated param by default - let calcP: NgParameter; - for (const p of this.allFormElements) { - if (p instanceof NgParameter) { - if ( - [ParamValueMode.SINGLE, ParamValueMode.CALCUL].includes(p.valueMode) - && !except.includes(p.id) && !p.isValueModified - ) { - if (p.valueMode === ParamValueMode.CALCUL) { - calcP = p; - } - p.resetValue(this, undefined); - } - } - } - // restore original calculated param - if (calcP !== undefined) { - calcP.setCalculated(); - } - } - /** * notifie un événement aux observateurs */ diff --git a/src/app/services/app-setup.service.ts b/src/app/services/app-setup.service.ts index d1f01b2af..193b32aaf 100644 --- a/src/app/services/app-setup.service.ts +++ b/src/app/services/app-setup.service.ts @@ -24,7 +24,6 @@ export class ApplicationSetupService extends Observable { private _maxIterations = 100; // tied to model public enableNotifications = true; public enableHotkeys = false; - public enableEmptyFieldsOnFormInit = true; public set computePrecision(p: number) { this._computePrecision = p; @@ -46,6 +45,14 @@ export class ApplicationSetupService extends Observable { return this._maxIterations; } + public get enableEmptyFieldsOnFormInit() { + return !SessionSettings.useDefaultParamValue; + } + + public set enableEmptyFieldsOnFormInit(b: boolean) { + SessionSettings.useDefaultParamValue = !b; + } + /** * just stores the current language preference, does not transmit it to I18nService, that is * not available here. @@ -71,6 +78,9 @@ export class ApplicationSetupService extends Observable { // related to @HostListener("window:beforeunload") in AppComponent this.warnBeforeTabClose = true; + // by default, create empty fields for new calculators + this.enableEmptyFieldsOnFormInit = true; + // load JSON config this.readValuesFromConfig().then((data) => { const configLanguage = this.language; -- GitLab From c04b030825e18123377a1a5c2b8c1c2cd9e4e89b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Thu, 28 Apr 2022 15:03:52 +0200 Subject: [PATCH 06/13] refactor: remove unused NgParam "modified" flag refs #516 --- .../generic-input/generic-input.component.ts | 7 +--- src/app/formulaire/elements/ngparam.ts | 33 ------------------- 2 files changed, 1 insertion(+), 39 deletions(-) diff --git a/src/app/components/generic-input/generic-input.component.ts b/src/app/components/generic-input/generic-input.component.ts index 5b31ee4e8..3dc390d50 100644 --- a/src/app/components/generic-input/generic-input.component.ts +++ b/src/app/components/generic-input/generic-input.component.ts @@ -263,12 +263,7 @@ export abstract class GenericInputComponentDirective implements OnChanges { if (valid && this._uiValue !== "") { val = +this._uiValue; // cast UI value to Number } - if (this.setAndValidateModel(this, val)) { - // set parameter "modified" flag - if (this._model instanceof NgParameter) { - this._model.isValueModified = true; - } - } + this.setAndValidateModel(this, val); } } diff --git a/src/app/formulaire/elements/ngparam.ts b/src/app/formulaire/elements/ngparam.ts index 59c4e188f..43d7cb298 100644 --- a/src/app/formulaire/elements/ngparam.ts +++ b/src/app/formulaire/elements/ngparam.ts @@ -38,9 +38,6 @@ export class NgParameter extends InputField implements Observer { public disabled: boolean; - /** true if value has been modified by user */ - private _isValueModified = false; - constructor(private _paramDef: ParamDefinition, parent: FormulaireNode) { super(parent); this.radioConfig = this.radioState; @@ -284,14 +281,6 @@ export class NgParameter extends InputField implements Observer { return this._paramDef.valuesIterator; } - public get isValueModified(): boolean { - return this._isValueModified; - } - - public set isValueModified(b: boolean) { - this._isValueModified = b; - } - /** * Reads radio config from parameter calculability */ @@ -404,18 +393,6 @@ export class NgParameter extends InputField implements Observer { ); } - /** - * fixe la valeur du paramètre en tant que valeur par défaut - */ - public resetValue(sender: any, val: number) { - const changed = (this._paramDef.getValue() !== val); - this._isValueModified = false; - if (changed) { - this._paramDef.setValue(val, sender); - this.notifyValueModified(sender); - } - } - /** * fixe la valeur du paramètre. * une notification préalable est envoyée pour laisser l'occasion aux objets liés de préciser le contexte @@ -433,7 +410,6 @@ export class NgParameter extends InputField implements Observer { public resetMinValue(sender: any, v: number) { const changed = (this._paramDef.min !== v); - this._isValueModified = false; if (changed) { this._paramDef.min = v; this.notifyMinValueModified(sender); @@ -444,14 +420,12 @@ export class NgParameter extends InputField implements Observer { const changed = (this._paramDef.min !== v); if (changed) { this._paramDef.min = v; - this._isValueModified = true; this.notifyMinValueModified(sender); } } public resetMaxValue(sender: any, v: number) { const changed = (this._paramDef.max !== v); - this._isValueModified = false; if (changed) { this._paramDef.max = v; this.notifyMaxValueModified(sender); @@ -462,14 +436,12 @@ export class NgParameter extends InputField implements Observer { const changed = (this._paramDef.max !== v); if (changed) { this._paramDef.max = v; - this._isValueModified = true; this.notifyMaxValueModified(sender); } } public resetStepValue(sender: any, v: number) { const changed = (this._paramDef.step !== v); - this._isValueModified = false; if (changed) { this._paramDef.step = v; this.notifyStepValueModified(sender); @@ -480,14 +452,12 @@ export class NgParameter extends InputField implements Observer { const changed = (this._paramDef.step !== v); if (changed) { this._paramDef.step = v; - this._isValueModified = true; this.notifyStepValueModified(sender); } } public resetValueList(sender: any, l: number[]) { const changed = (JSON.stringify(this._paramDef.valueList) !== JSON.stringify(l)); - this._isValueModified = false; if (changed) { this._paramDef.valueList = l; this.notifyListValueModified(sender); @@ -498,7 +468,6 @@ export class NgParameter extends InputField implements Observer { const changed = (JSON.stringify(this._paramDef.valueList) !== JSON.stringify(l)); if (changed) { this._paramDef.valueList = l; - this._isValueModified = true; this.notifyListValueModified(sender); } } @@ -520,7 +489,6 @@ export class NgParameter extends InputField implements Observer { allowEmpty: this._allowEmpty, unit: this.unit, radioConfig: this.radioConfig, - modified: this._isValueModified } } @@ -530,7 +498,6 @@ export class NgParameter extends InputField implements Observer { this._allowEmpty = rep.allowEmpty; this.unit = rep.unit; this.radioConfig = rep.radioConfig; - this._isValueModified = rep._isValueModified; } } -- GitLab From e99d3bf6fccda221882cf5e140b57fdc0a54a5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Thu, 28 Apr 2022 15:04:21 +0200 Subject: [PATCH 07/13] test(e2e): add a test to check empty fields on a copy of modified structure refs #516 --- e2e/ouvrages-empty-fields.e2e-spec.ts | 68 +++++++++++++++++------ e2e/pab-cloisons-empty-fields.e2e-spec.ts | 6 +- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/e2e/ouvrages-empty-fields.e2e-spec.ts b/e2e/ouvrages-empty-fields.e2e-spec.ts index 096393e60..6eac089d5 100644 --- a/e2e/ouvrages-empty-fields.e2e-spec.ts +++ b/e2e/ouvrages-empty-fields.e2e-spec.ts @@ -2,40 +2,44 @@ import { ListPage } from "./list.po"; import { browser, by, element } from "protractor"; import { CalculatorPage } from "./calculator.po"; import { AppPage } from "./app.po"; +import { PreferencesPage } from "./preferences.po"; +import { Navbar } from "./navbar.po"; /** * Check that created/cloned structures have empty fields when * "empty fields on calculator creation" is enabled */ describe("ngHyd - check that created/cloned structures have empty fields - ", () => { - //let prefPage: PreferencesPage; - let startPage: AppPage; + let prefPage: PreferencesPage; let listPage: ListPage; let calcPage: CalculatorPage; + let navBar: Navbar; beforeAll(() => { - //prefPage = new PreferencesPage(); - startPage = new AppPage(); + prefPage = new PreferencesPage(); listPage = new ListPage(); calcPage = new CalculatorPage(); + navBar = new Navbar(); + browser.manage().window().setPosition(2000, 30); }); beforeEach(async () => { // enable evil option "empty fields on module creation" - // await prefPage.navigateTo(); - // await prefPage.enableEvilEmptyFields(); // message "stale element reference: element is not attached to the page document" - // await browser.sleep(200); - - // assume that "empty fields on module creation" is true by default + await prefPage.navigateTo(); + await browser.sleep(200); + await prefPage.enableEvilEmptyFields(); + await browser.sleep(200); + }); + async function setup() { // start page - await startPage.navigateTo(); + await navBar.clickNewCalculatorButton(); await browser.sleep(200); // open structures calculator await listPage.clickMenuEntryForCalcType(8); await browser.sleep(200); - }); + } /** * check that a input set is in a given (empty/filled) state @@ -53,9 +57,11 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () } it("when a structure calculator is created", async () => { + await setup(); + // check 1st structure empty fields - const inputIds = ["Q", "calc_Z1", "Z2", "0_ZDV", "0_L", "0_W", "0_CdGR"]; - const emptys = [true, false, true, true, true, true, false]; + const inputIds = ["Q", "Z1", "Z2", "0_ZDV", "0_L", "0_W", "0_CdGR"]; + const emptys = [true, true, true, true, true, true, false]; await checkFields(inputIds, emptys); // change 1st structure type to rectangular weir @@ -64,12 +70,14 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () await browser.sleep(200); // check 1st structure empty fields - const inputIds2 = ["Q", "calc_Z1", "Z2", "0_ZDV", "0_L", "0_CdWR"]; - const emptys2 = [true, false, true, true, true, false]; + const inputIds2 = ["Q", "Z1", "Z2", "0_ZDV", "0_L", "0_CdWR"]; + const emptys2 = [true, true, true, true, true, false]; await checkFields(inputIds2, emptys2); }); it("when a structure is added", async () => { + await setup(); + // add structure const addStruct = calcPage.getAddStructureButton(); await addStruct.click(); @@ -81,6 +89,8 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () }); it("when a structure is copied", async () => { + await setup(); + // copy structure const addStruct = calcPage.getCopyStructureButton(); await addStruct.click(); @@ -91,7 +101,9 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () await checkFields(inputIds, emptys); }); - it("when a modified structure is copied", async () => { + it("when a modified structure is copied (type)", async () => { + await setup(); + // change 1st structure type to rectangular weir const structSelect = calcPage.getSelectById("select_structure"); await calcPage.changeSelectValue(structSelect, 1); @@ -103,7 +115,8 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () await browser.sleep(200); // change 2nd structure type to rectangular gate - const structSelect2 = element(by.className("ng-tns-c3-47")); + const selects = await element.all(by.css("mat-select#select_structure")); + const structSelect2 = selects[1]; await calcPage.changeSelectValue(structSelect2, 4); await browser.sleep(200); @@ -113,7 +126,28 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () await checkFields(inputIds, emptys); }); + it("when a modified structure is copied (input)", async () => { + await setup(); + + // fill + const inp = calcPage.getInputById("0_ZDV"); + await inp.clear(); + await inp.sendKeys("1"); + + // copy structure + const addStruct = calcPage.getCopyStructureButton(); + await addStruct.click(); + await browser.sleep(200); + + // check empty fields + const inputIds = ["1_ZDV", "1_L", "1_W", "1_CdGR"]; + const emptys = [false, true, true, false]; + await checkFields(inputIds, emptys); + }); + it("except for discharge coefficient when a Larinier weir is used", async () => { + await setup(); + // change 1st structure type to rectangular weir const structSelect = calcPage.getSelectById("select_structure"); await calcPage.changeSelectValue(structSelect, 1); diff --git a/e2e/pab-cloisons-empty-fields.e2e-spec.ts b/e2e/pab-cloisons-empty-fields.e2e-spec.ts index c7305027a..7e99a7de4 100644 --- a/e2e/pab-cloisons-empty-fields.e2e-spec.ts +++ b/e2e/pab-cloisons-empty-fields.e2e-spec.ts @@ -65,11 +65,11 @@ describe("ngHyd - check the cross walls calculator has empty fields - ", () => { await browser.sleep(200); // fill inputs - await fillInput(calcPage, "Q"); await fillInput(calcPage, "Z1"); await fillInput(calcPage, "LB"); await fillInput(calcPage, "BB"); await fillInput(calcPage, "PB"); + await fillInput(calcPage, "DH"); await fillInput(calcPage, "0_h1"); await fillInput(calcPage, "0_L"); await fillInput(calcPage, "0_CdWSL"); @@ -116,11 +116,11 @@ describe("ngHyd - check the cross walls calculator has no empty field - ", () => await browser.sleep(200); // fill inputs - await fillInput(calcPage, "Q"); await fillInput(calcPage, "Z1"); await fillInput(calcPage, "LB"); await fillInput(calcPage, "BB"); await fillInput(calcPage, "PB"); + await fillInput(calcPage, "DH"); await fillInput(calcPage, "0_h1"); await fillInput(calcPage, "0_L"); await fillInput(calcPage, "0_CdWSL"); @@ -130,6 +130,6 @@ describe("ngHyd - check the cross walls calculator has no empty field - ", () => await calcButton.click(); await browser.sleep(200); - await checkFields(calcPage, ["Q", "Z1", "LB", "BB", "PB", "0_h1", "0_L", "0_CdWSL"], [false, false, false, false, false, false, false, false]); + await checkFields(calcPage, ["Z1", "LB", "BB", "PB", "DH", "0_h1", "0_L", "0_CdWSL"], [false, false, false, false, false, false, false, false]); }); }); -- GitLab From b5e2fef235cec8b8e12ecd133eec552c30fa957a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Mon, 2 May 2022 10:26:15 +0200 Subject: [PATCH 08/13] fix(e2e): fix broken "all calculator examples" test refs #516 --- e2e/calc-all-examples.e2e-spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/e2e/calc-all-examples.e2e-spec.ts b/e2e/calc-all-examples.e2e-spec.ts index 4dae4b1dd..34d4a63f1 100644 --- a/e2e/calc-all-examples.e2e-spec.ts +++ b/e2e/calc-all-examples.e2e-spec.ts @@ -49,12 +49,14 @@ describe("ngHyd − example sessions −", async () => { } const examples = await element.all(by.css("#examples-list .load-example")); + await browser.sleep(200); if (examples.length > i) { // click example #i await examples[i].click(); - await browser.sleep(50); + await browser.sleep(200); const nbModules = await navbar.getCalculatorEntriesCount(); + await browser.sleep(200); for (let j = 0; j < nbModules; j++) { // select module await navbar.openNthCalculator(j); -- GitLab From db23cc50b8f7e8de14bd80acc1c46a96090c9f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Mon, 2 May 2022 14:44:30 +0200 Subject: [PATCH 09/13] test(e2e): check computed parameter initial value is not null with "empty fields on calculator creation" option refs #516 --- e2e/examples-empty-fields.e2e-spec.ts | 31 +++++++++++++++++++ .../dialog-edit-param-computed.component.html | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/e2e/examples-empty-fields.e2e-spec.ts b/e2e/examples-empty-fields.e2e-spec.ts index 573012930..590ac5b47 100644 --- a/e2e/examples-empty-fields.e2e-spec.ts +++ b/e2e/examples-empty-fields.e2e-spec.ts @@ -58,4 +58,35 @@ describe("ngHyd - Check that examples fields are not empty with 'empty fields on const emptys = [false, false, false, false, false]; await checkFields(inputIds, emptys); }); + + it("calculated parameter initial value when discharge law is modified", async () => { + // start page + await navBar.clickNewCalculatorButton(); + await browser.sleep(200); + + // open 1st example + const examples = await element.all(by.css("#examples-list .load-example")); + await examples[0].click(); + await browser.sleep(50); + + // select wall module + await navBar.openNthCalculator(4); + await browser.sleep(50); + + // modify 1st structure discharge law + const dischargeSelect = calcPage.getSelectById("select_loidebit"); + await calcPage.changeSelectValue(dischargeSelect, 1); + await browser.sleep(200); + + // open initial dialog + const initDlgButton = element(by.className("param-computed-more")); + await initDlgButton.click(); + await browser.sleep(200); + + // check input value is not null + const input = calcPage.getInputById("initval-input"); + const underlyingInput = input.element(by.id("0_h1")); + const txt = await underlyingInput.getAttribute("value"); + expect(txt === "").toEqual(false); + }); }); diff --git a/src/app/components/dialog-edit-param-computed/dialog-edit-param-computed.component.html b/src/app/components/dialog-edit-param-computed/dialog-edit-param-computed.component.html index 38bcc40fb..9037cd52b 100644 --- a/src/app/components/dialog-edit-param-computed/dialog-edit-param-computed.component.html +++ b/src/app/components/dialog-edit-param-computed/dialog-edit-param-computed.component.html @@ -3,7 +3,7 @@ <form> <div mat-dialog-content> - <ngparam-input [title]="param.title"></ngparam-input> + <ngparam-input id="initval-input" [title]="param.title"></ngparam-input> </div> <div mat-dialog-actions [attr.align]="'end'"> -- GitLab From b97738ebea992090fbba64d75a86fcc38e0463bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Wed, 4 May 2022 07:43:15 +0200 Subject: [PATCH 10/13] test(e2e): check calculation works in generated PAB from 'standard fish ladder' example (walls calculator) refs #516 --- e2e/examples-empty-fields.e2e-spec.ts | 62 +++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/e2e/examples-empty-fields.e2e-spec.ts b/e2e/examples-empty-fields.e2e-spec.ts index 590ac5b47..a9df5a682 100644 --- a/e2e/examples-empty-fields.e2e-spec.ts +++ b/e2e/examples-empty-fields.e2e-spec.ts @@ -90,3 +90,65 @@ describe("ngHyd - Check that examples fields are not empty with 'empty fields on expect(txt === "").toEqual(false); }); }); + +describe("ngHyd - Check that examples work with 'empty fields on calculator creation' enabled - ", () => { + let prefPage: PreferencesPage; + let navBar: Navbar; + let calcPage: CalculatorPage; + + beforeEach(async () => { + prefPage = new PreferencesPage(); + navBar = new Navbar(); + calcPage = new CalculatorPage(); + + // enable evil option "empty fields on module creation" + await prefPage.navigateTo(); + await browser.sleep(200); + await prefPage.enableEvilEmptyFields(); + await browser.sleep(200); + }); + + fit("when calculation is run on a generated fish ladder calculator", async () => { + debugger + // start page + await navBar.clickNewCalculatorButton(); + await browser.sleep(200); + + // open 1st example + const examples = await element.all(by.css("#examples-list .load-example")); + await examples[0].click(); + await browser.sleep(50); + + // select wall module + await navBar.openNthCalculator(4); + await browser.sleep(50); + + // run calculation + const calcButton = calcPage.getCalculateButton(); + await calcButton.click(); + await browser.sleep(200); + + // click "generate PAB" button + const genButton = calcPage.getGeneratePabButton(); + await genButton.click(); + await browser.sleep(200); + + // write "6" in basin count input + const nbBassins = calcPage.getInputById("generatePabNbBassins"); + await nbBassins.sendKeys("6"); + await browser.sleep(50); + + // click "Generate PAB" + await element(by.css("dialog-generate-pab button#do-generate")).click(); + await browser.sleep(1000); + + // calculate PAB + const calcButtonPAB = calcPage.getCalculateButton(); + await calcButtonPAB.click(); + await browser.sleep(200); + + // check that result is not empty + const hasResults = await calcPage.hasResults(); + expect(hasResults).toBe(true); + }); +}); -- GitLab From c9008f3b151d54a7ad17b6465fcade932b453460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr> Date: Wed, 4 May 2022 07:44:48 +0200 Subject: [PATCH 11/13] fix: adapt to useDefaultParamValue flag removal in jalhyd refs #516 --- src/app/components/pb-schema/pb-schema.component.ts | 3 ++- src/app/formulaire/definition/form-definition.ts | 4 +++- src/app/formulaire/definition/form-parallel-structures.ts | 4 +++- src/app/services/app-setup.service.ts | 5 +++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/app/components/pb-schema/pb-schema.component.ts b/src/app/components/pb-schema/pb-schema.component.ts index 1862a8dcf..7ea4ba81d 100644 --- a/src/app/components/pb-schema/pb-schema.component.ts +++ b/src/app/components/pb-schema/pb-schema.component.ts @@ -21,6 +21,7 @@ import { AppComponent } from "../../app.component"; import { fv } from "app/util"; import { FormulaireNode } from "app/formulaire/elements/formulaire-node"; +import { ServiceFactory } from "app/services/service-factory"; /** * The interactive schema for calculator type "PreBarrage" (component) @@ -494,7 +495,7 @@ export class PbSchemaComponent implements AfterViewInit, AfterContentInit, OnIni /** Adds a new lone basin */ public onAddBasinClick() { - const newBasin = new PbBassin(new PbBassinParams(20, 99)); + const newBasin = new PbBassin(new PbBassinParams(20, 99, ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit)); this.model.addChild(newBasin); this.clearResults(); this.refreshWithSelection(newBasin.uid); diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 442a96ef6..3fd3ee3a2 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -9,7 +9,8 @@ import { acSection, ParamDefinition, Result, - VariatedDetails + VariatedDetails, + Prop_NullParameters } from "jalhyd"; import { FormulaireElement } from "../elements/formulaire-element"; @@ -110,6 +111,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs */ public initNub(props?: Props) { const p = props ? props : new Props(this.defaultProperties); + p.setPropValue(Prop_NullParameters, ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit); // transmit "empty fields" flag this.currentNub = Session.getInstance().createSessionNub(p); if (this.currentNub instanceof SectionNub) { diff --git a/src/app/formulaire/definition/form-parallel-structures.ts b/src/app/formulaire/definition/form-parallel-structures.ts index 5e35710f9..9e4dd86d6 100644 --- a/src/app/formulaire/definition/form-parallel-structures.ts +++ b/src/app/formulaire/definition/form-parallel-structures.ts @@ -1,4 +1,4 @@ -import { Structure, Nub, ParallelStructure, StructureProperties, Props, Session, ParamDefinition } from "jalhyd"; +import { Structure, Nub, ParallelStructure, StructureProperties, Props, Session, ParamDefinition, Prop_NullParameters } from "jalhyd"; import { FieldsetContainer } from "../elements/fieldset-container"; import { FieldSet } from "../elements/fieldset"; @@ -7,6 +7,7 @@ import { NgParameter } from "../elements/ngparam"; import { FieldsetTemplate } from "../elements/fieldset-template"; import { FormulaireNode } from "../elements/formulaire-node"; import { FormulaireRepeatableFieldset } from "./form-repeatable-fieldset"; +import { ServiceFactory } from "app/services/service-factory"; export class FormulaireParallelStructure extends FormulaireRepeatableFieldset { @@ -66,6 +67,7 @@ export class FormulaireParallelStructure extends FormulaireRepeatableFieldset { params["nodeType"] = templ.defaultNodeTypeFromConfig; params["structureType"] = templ.defaultStructTypeFromConfig; params["loiDebit"] = templ.defaultLoiDebitFromConfig; + params[Prop_NullParameters] = ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit; return this.createStructure(new Props(params)); } diff --git a/src/app/services/app-setup.service.ts b/src/app/services/app-setup.service.ts index 193b32aaf..32b9f517d 100644 --- a/src/app/services/app-setup.service.ts +++ b/src/app/services/app-setup.service.ts @@ -24,6 +24,7 @@ export class ApplicationSetupService extends Observable { private _maxIterations = 100; // tied to model public enableNotifications = true; public enableHotkeys = false; + private _enableEmptyFieldsOnFormInit = true; public set computePrecision(p: number) { this._computePrecision = p; @@ -46,11 +47,11 @@ export class ApplicationSetupService extends Observable { } public get enableEmptyFieldsOnFormInit() { - return !SessionSettings.useDefaultParamValue; + return this._enableEmptyFieldsOnFormInit; } public set enableEmptyFieldsOnFormInit(b: boolean) { - SessionSettings.useDefaultParamValue = !b; + this._enableEmptyFieldsOnFormInit = b; } /** -- GitLab From 9c37bd28cc18821019e6c9a4f4aebf1a88251c4f Mon Sep 17 00:00:00 2001 From: David Dorchies <david.dorchies@inrae.fr> Date: Wed, 4 May 2022 08:13:10 +0000 Subject: [PATCH 12/13] refactor: change jalhyd_branch to devel after merge of jalhyd Refs #516 --- jalhyd_branch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jalhyd_branch b/jalhyd_branch index f6d80c358..626e97d71 100644 --- a/jalhyd_branch +++ b/jalhyd_branch @@ -1 +1 @@ -306-gerer-un-flag-modified-dans-paramdefinition \ No newline at end of file +devel \ No newline at end of file -- GitLab From 2d2f00d03eaa45392b72af85ce67a5784dd524cb Mon Sep 17 00:00:00 2001 From: David Dorchies <david.dorchies@inrae.fr> Date: Wed, 4 May 2022 08:13:28 +0000 Subject: [PATCH 13/13] test: forgottent fix Refs #516 --- e2e/examples-empty-fields.e2e-spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/examples-empty-fields.e2e-spec.ts b/e2e/examples-empty-fields.e2e-spec.ts index a9df5a682..491ef77c6 100644 --- a/e2e/examples-empty-fields.e2e-spec.ts +++ b/e2e/examples-empty-fields.e2e-spec.ts @@ -108,7 +108,7 @@ describe("ngHyd - Check that examples work with 'empty fields on calculator crea await browser.sleep(200); }); - fit("when calculation is run on a generated fish ladder calculator", async () => { + it("when calculation is run on a generated fish ladder calculator", async () => { debugger // start page await navBar.clickNewCalculatorButton(); -- GitLab