diff --git a/e2e/calc-all-examples.e2e-spec.ts b/e2e/calc-all-examples.e2e-spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..31a63bbabd460eb3642394a59963e16ac00ee999 --- /dev/null +++ b/e2e/calc-all-examples.e2e-spec.ts @@ -0,0 +1,57 @@ +import { ListPage } from "./list.po"; +import { CalculatorPage } from "./calculator.po"; +import { Navbar } from "./navbar.po"; +import { browser, by, element } from "protractor"; + +/** + * Calculate all modules of all examples + */ +describe("ngHyd − calculate all modules of all examples −", async () => { + + let listPage: ListPage; + let calcPage: CalculatorPage; + let navbar: Navbar; + + beforeAll(() => { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; + }); + + it("calcul de tous les modules de tous les exemples −", async () => { + listPage = new ListPage(); + calcPage = new CalculatorPage(); + navbar = new Navbar(); + listPage = new ListPage(); + + // for each calculator + let lastExampleFound = true; + let i = 0; + while (lastExampleFound) { + await listPage.navigateTo(); + + const examples = await element.all(by.css("#examples-list .load-example")); + if (examples.length > i) { + // click example #i + await examples[i].click(); + await browser.sleep(50); + + const nbModules = await navbar.getCalculatorEntriesCount(); + for (let j = 0; j < nbModules; j++) { + // select module + await navbar.openNthCalculator(j); + await browser.sleep(50); + // calculate module + await calcPage.getCalculateButton().click(); + // check results + const hasResults = await calcPage.hasValidResults(); + expect(hasResults).toBe(true, `example ${i + 1}, module ${j + 1} (starting at 1)`); + } + } else { + // no more examples + lastExampleFound = false; + } + i++; + } + + }); + +}); diff --git a/e2e/calculator.po.ts b/e2e/calculator.po.ts index 0e6f9f322c5c18d0698058e68032838b87b42793..3dda3f42d72b7d0ecfb0a98879602d15212072c2 100644 --- a/e2e/calculator.po.ts +++ b/e2e/calculator.po.ts @@ -71,6 +71,14 @@ export class CalculatorPage { return element.all(by.css("mat-button-toggle.radio_link")); } + getPabResultsTable() { + return element(by.css(".pab-results-table-inner-container table")); + } + + getVariatedResultsTable() { + return element(by.css(".var-results-inner-container table")); + } + getAllVariatedResultsTableHeaders() { return element.all(by.css("var-results table thead th")); } @@ -89,6 +97,10 @@ export class CalculatorPage { return element(by.css(".fixed-results-inner-container table")); } + getAllFixedResultsRows() { + return element.all(by.css("fixed-results table tbody tr")); + } + /** return nth <tr> of given <table>, starting at 1 */ getNthRow(table: ElementFinder, n: number) { return table.element(by.css("tbody > tr:nth-of-type(" + n + ")")); @@ -123,6 +135,65 @@ export class CalculatorPage { ); } + /** + * For a given <table> element, check that values of all cells of all rows in <tbody> are + * different from "NaN", "ERR" and optionally "" + * @param table a <table> ElementFinder + * @param allowEmpty if true, empty "" values will be considered valid + */ + async allRowsHaveValidResults(table: ElementFinder, allowEmpty: boolean = false): Promise<boolean> { + let n = 0; + let ok = true; + const invalidValues = [ "ERR", "NaN" ]; + if (! allowEmpty) { + invalidValues.push(""); + } + + const nbCols = await table.all(by.css("thead th")).count(); + const rows = await table.all(by.css("tbody tr")); + + for (const row of rows) { + for (let i = 0; i < nbCols; i++) { + // get i_th column of n_th row + const val = await row.element(by.css("td:nth-of-type(" + (i + 1) + ")")).getText(); + // console.log(`TABLE VAL ${n}/${i}=>`, val); + ok = ok && ! invalidValues.includes(val); + } + n++; + } + return ok; + } + + /** + * Returns true if this.hasResults() is true, and if results table are + * not empty and contain only valid values (no "NaN", no "", no "ERR") + */ + async hasValidResults(): Promise<boolean> { + let ok = false; + if (await this.hasResults()) { + ok = true; + // check fixed results + const frt = this.getFixedResultsTable(); + if (await frt.isPresent() && await frt.isDisplayed()) { + console.log("==============> Fixed found !"); + ok = ok && await this.allRowsHaveValidResults(frt); + } + // check variated results + const vrt = this.getVariatedResultsTable(); + if (await vrt.isPresent() && await vrt.isDisplayed()) { + console.log("==============> Var found !"); + ok = ok && await this.allRowsHaveValidResults(vrt); + } + // check PAB results + const prt = this.getPabResultsTable(); + if (await prt.isPresent() && await prt.isDisplayed()) { + console.log("==============> Pab found !"); + ok = ok && await this.allRowsHaveValidResults(prt, true); + } + } + return ok; + } + async hasLog() { return await this.nbLogEntries() > 0; } diff --git a/e2e/navbar.po.ts b/e2e/navbar.po.ts index 13b1efc1f8c5c828ed9a99b903536f817804b69c..05273efdee188484ce85ba4ebb3054287095000f 100644 --- a/e2e/navbar.po.ts +++ b/e2e/navbar.po.ts @@ -1,10 +1,46 @@ -import { by, element } from "protractor"; +import { by, element, protractor } from "protractor"; export class Navbar { getAllCalculatorTabs() { return element.all(by.css("#tabs-container button.calculator-button")); } + /** + * Robust method that returns number of calculator entries, + * whether they are buttons or dropdown select options + */ + async getCalculatorEntriesCount() { + // if dropDown calculators select is visible + const dropDown = element(by.css("mat-select#selectCalculator")); + if (await dropDown.isPresent() && await dropDown.isDisplayed()) { + await dropDown.click(); + const options = (await dropDown.getAttribute("aria-owns")).split(" "); + await dropDown.sendKeys(protractor.Key.ESCAPE); // close dropdown + return options.length; + } else { + return (await element.all(by.css("#tabs-container button.calculator-button"))).length; + } + } + + /** + * Robust method that opens the nth calculator, whether the + * calculator selector is a list of buttons or a dropdown select + */ + async openNthCalculator(n: number) { + // if dropDown calculators select is visible + const dropDown = element(by.css("mat-select#selectCalculator")); + if (await dropDown.isPresent() && await dropDown.isDisplayed()) { + await dropDown.click(); + const options = (await dropDown.getAttribute("aria-owns")).split(" "); + const optId = options[n]; + const option = element(by.id(optId)); + await option.click(); + } else { + const tabs = this.getAllCalculatorTabs(); + await tabs.get(n).click(); + } + } + getCalculatorTabForUid(uid: string) { return element(by.css("#tabs-container button.calculator-button.calculator-uid-" + uid)); }