diff --git a/lib/testing/src/lib/protractor/core/pages/card-view/card-view-text-item.page.ts b/lib/testing/src/lib/protractor/core/pages/card-view/card-view-text-item.page.ts index 803f2a81e86..b49788af870 100644 --- a/lib/testing/src/lib/protractor/core/pages/card-view/card-view-text-item.page.ts +++ b/lib/testing/src/lib/protractor/core/pages/card-view/card-view-text-item.page.ts @@ -19,8 +19,8 @@ import { element, by, ElementFinder, Key } from 'protractor'; import { BrowserActions, BrowserVisibility } from '../../utils/public-api'; import { materialLocators } from '../public-api'; export class CardTextItemPage { - rootElement: ElementFinder; + label: string; textField = '[data-automation-id*="card-textitem-value"]'; saveButton = 'button[data-automation-id*="card-textitem-update"]'; clearButton = 'button[data-automation-id*="card-textitem-reset"]'; @@ -31,11 +31,16 @@ export class CardTextItemPage { readOnlyField = '.adf-property-read-only'; constructor(label: string = 'assignee') { - this.rootElement = element(by.xpath(`//${materialLocators.Label.root}[contains(@data-automation-id, "card-textitem-label-${label}")]//ancestor::adf-card-view-textitem`)); + this.rootElement = element( + by.xpath( + `//${materialLocators.Label.root}[contains(@data-automation-id, "card-textitem-label-${label}")]//ancestor::adf-card-view-textitem` + ) + ); + this.label = label; } async getFieldValue(): Promise { - const fieldElement = this.rootElement.$(this.field); + const fieldElement = element(by.css(`[data-automation-id="card-textitem-value-${this.label}"]`)); return BrowserActions.getInputValue(fieldElement); } diff --git a/lib/testing/src/lib/protractor/core/pages/data-table-component.page.ts b/lib/testing/src/lib/protractor/core/pages/data-table-component.page.ts index dcf1dc402f2..2d10886dca3 100644 --- a/lib/testing/src/lib/protractor/core/pages/data-table-component.page.ts +++ b/lib/testing/src/lib/protractor/core/pages/data-table-component.page.ts @@ -337,11 +337,7 @@ export class DataTableComponentPage { getRow(columnName: string, columnValue: string): ElementFinder { return this.rootElement - .all( - by.xpath( - `//div[starts-with(@title, '${columnName}')]//div[contains(@data-automation-id, '${columnValue}')]//ancestor::adf-datatable-row[contains(@class, 'adf-datatable-row')]` - ) - ) + .all(by.css(`adf-datatable-row:has(.adf-datatable-cell[title='${columnName}']):has(span[title*='${columnValue}'])`)) .first(); } diff --git a/lib/testing/src/lib/protractor/core/pages/header.page.ts b/lib/testing/src/lib/protractor/core/pages/header.page.ts index 0cb907bcbf1..f316333029d 100644 --- a/lib/testing/src/lib/protractor/core/pages/header.page.ts +++ b/lib/testing/src/lib/protractor/core/pages/header.page.ts @@ -21,7 +21,6 @@ import { BrowserActions } from '../utils/browser-actions'; import { materialLocators } from './public-api'; export class HeaderPage { - checkBox = element(by.cssContainingText(materialLocators.Checkbox.label.class, 'Show menu button')); headerColor = $('option[value="primary"]'); titleInput = $('input[name="title"]'); @@ -31,7 +30,9 @@ export class HeaderPage { logoTooltipInput = $('input[placeholder="Tooltip text"]'); positionStart = $$(`${materialLocators.Radio.button.root}[value="start"]`).first(); positionEnd = $$(`${materialLocators.Radio.button.root}[value="end"]`).first(); - sideBarPositionRight = $(`${materialLocators.Sidenav.root}${materialLocators.Drawer.class}${materialLocators.Sidenav.root}${materialLocators.Drawer.end}`); + sideBarPositionRight = $( + `${materialLocators.Sidenav.root}${materialLocators.Drawer.class}${materialLocators.Sidenav.root}${materialLocators.Drawer.end}` + ); sideBarPositionLeft = $(`${materialLocators.Sidenav.root}${materialLocators.Drawer.class}${materialLocators.Sidenav.root}`); async checkShowMenuCheckBoxIsDisplayed(): Promise { @@ -117,7 +118,7 @@ export class HeaderPage { } async sideBarPositionEnd(): Promise { - await browser.executeScript('arguments[0].scrollIntoView()', this.positionEnd); + await browser.executeScript(`document.querySelector('${this.positionEnd}').scrollIntoView()`); await BrowserActions.click(this.positionEnd); } @@ -128,5 +129,4 @@ export class HeaderPage { async checkSidebarPositionEnd(): Promise { await BrowserVisibility.waitUntilElementIsVisible(this.sideBarPositionRight); } - } diff --git a/lib/testing/src/lib/protractor/core/utils/browser-actions.ts b/lib/testing/src/lib/protractor/core/utils/browser-actions.ts index 132764b4947..cdd899ed53e 100644 --- a/lib/testing/src/lib/protractor/core/utils/browser-actions.ts +++ b/lib/testing/src/lib/protractor/core/utils/browser-actions.ts @@ -24,7 +24,6 @@ import * as fs from 'fs'; import { ApiUtil } from '../../../shared/api/api.util'; export class BrowserActions { - static async clickUntilIsNotVisible(elementToClick: ElementFinder, elementToFind: ElementFinder): Promise { Logger.info(`Click until element is not present: ${elementToClick.locator().toString()}`); const predicate = (isVisible: boolean) => isVisible; @@ -58,8 +57,26 @@ export class BrowserActions { static async clickScript(elementToClick: ElementFinder): Promise { Logger.info(`Click script ${elementToClick.locator().toString()}`); - await browser.executeScript(`arguments[0].scrollIntoView();`, elementToClick); - await browser.executeScript(`arguments[0].click();`, elementToClick); + if (elementToClick.locator().toString().includes('ContainingText')) { + await this.clickScriptByText(elementToClick); + } else { + await browser.executeScript(`document.querySelector('${elementToClick.locator().value}').click()`); + } + } + + private static async clickScriptByText(elementToClick: ElementFinder): Promise { + const locatorMatch = elementToClick + .locator() + .toString() + .match(new RegExp(/ContainingText\("(.+?)",."(.+?)"/)); + const locatorClass = locatorMatch[1]; + const locatorText = locatorMatch[2]; + await browser.executeScript(`function filterElementsByText(selector, text) { + const elements = document.querySelectorAll(selector); + return Array.from(elements).filter(element => element.textContent.includes(text)); + } + const filteredElements = filterElementsByText('${locatorClass}', '${locatorText}'); + filteredElements[0].click()`); } static async clickExecuteScript(elementCssSelector: string): Promise { @@ -90,8 +107,8 @@ export class BrowserActions { static async getAttribute(elementFinder: ElementFinder, attribute: string): Promise { await BrowserVisibility.waitUntilElementIsPresent(elementFinder); - const attributeValue: string = await browser.executeScript(`return arguments[0].getAttribute(arguments[1])`, elementFinder, attribute); - return attributeValue || ''; + const attributeValue: string = await elementFinder.getAttribute(`${attribute}`); + return attributeValue || 'BrowserActions.getAttribute() empty value'; } static async getText(elementFinder: ElementFinder): Promise { @@ -102,7 +119,8 @@ export class BrowserActions { if (present) { let text = await elementFinder.getText(); - if (text === '') { // DO NOT REMOVE BUG sometime wrongly return empty text for cdk elements + if (text === '') { + // DO NOT REMOVE BUG sometime wrongly return empty text for cdk elements Logger.info(`Use backup get text script`); text = await this.getTextScript(elementFinder); @@ -121,7 +139,7 @@ export class BrowserActions { const present = await BrowserVisibility.waitUntilElementIsVisible(elementFinder); if (present) { - return browser.executeScript(`return arguments[0].value`, elementFinder); + return elementFinder.getAttribute('value'); } else { Logger.error(`Get Input value ${elementFinder.locator().toString()} not present`); return ''; @@ -143,7 +161,7 @@ export class BrowserActions { await elementFinder.click(); await elementFinder.sendKeys(protractor.Key.END); - const value: string = await browser.executeScript(`return arguments[0].value`, elementFinder); + const value: string = await browser.executeScript(`return document.querySelector('${elementFinder.locator().value}').value`); if (value) { for (let i = value.length; i >= 0; i--) { await elementFinder.sendKeys(protractor.Key.BACK_SPACE); @@ -211,6 +229,6 @@ export class BrowserActions { // Don't make it pub,ic use getText private static async getTextScript(elementFinder: ElementFinder): Promise { - return browser.executeScript(`return arguments[0].textContent`, elementFinder); + return browser.executeScript(`return document.querySelector('${elementFinder.locator().value}').textContent`); } } diff --git a/lib/testing/src/lib/protractor/core/utils/browser-visibility.ts b/lib/testing/src/lib/protractor/core/utils/browser-visibility.ts index 17734513ae1..c7c565655a2 100644 --- a/lib/testing/src/lib/protractor/core/utils/browser-visibility.ts +++ b/lib/testing/src/lib/protractor/core/utils/browser-visibility.ts @@ -46,13 +46,21 @@ export class BrowserVisibility { static async waitUntilElementIsPresent(elementToCheck: ElementFinder, waitTimeout: number = BrowserVisibility.DEFAULT_TIMEOUT): Promise { Logger.info(`Wait Until Element Is Present ${elementToCheck.locator().toString()} for ${waitTimeout}`); - return browser.wait(protractor.ExpectedConditions.presenceOf(elementToCheck), waitTimeout, 'Element is not present ' + elementToCheck.locator()); + return browser.wait( + protractor.ExpectedConditions.presenceOf(elementToCheck), + waitTimeout, + 'Element is not present ' + elementToCheck.locator() + ); } /* * Wait for element to be visible */ - static async waitUntilElementIsVisible(elementToCheck: ElementFinder, waitTimeout: number = BrowserVisibility.DEFAULT_TIMEOUT, message: string = 'Element is not visible'): Promise { + static async waitUntilElementIsVisible( + elementToCheck: ElementFinder, + waitTimeout: number = BrowserVisibility.DEFAULT_TIMEOUT, + message: string = 'Element is not visible' + ): Promise { Logger.info(`Wait Until Element Is Visible ${elementToCheck.locator().toString()} for ${waitTimeout}`); return browser.wait(protractor.ExpectedConditions.visibilityOf(elementToCheck), waitTimeout, message + elementToCheck.locator()); @@ -64,34 +72,57 @@ export class BrowserVisibility { static async waitUntilElementIsClickable(elementToCheck: ElementFinder, waitTimeout: number = BrowserVisibility.DEFAULT_TIMEOUT): Promise { Logger.info(`Wait Until Element Is Clickable ${elementToCheck.locator().toString()} for ${waitTimeout}`); - return browser.wait(protractor.ExpectedConditions.elementToBeClickable(elementToCheck), waitTimeout, 'Element is not Clickable ' + elementToCheck.locator()); + return browser.wait( + protractor.ExpectedConditions.elementToBeClickable(elementToCheck), + waitTimeout, + 'Element is not Clickable ' + elementToCheck.locator() + ); } /* - * Wait for element to not be present on the page - */ + * Wait for element to not be present on the page + */ static async waitUntilElementIsStale(elementToCheck: ElementFinder, waitTimeout: number = BrowserVisibility.DEFAULT_TIMEOUT): Promise { Logger.info(`Wait Until Element Is Stale ${elementToCheck.locator().toString()} for ${waitTimeout}`); - return browser.wait(protractor.ExpectedConditions.stalenessOf(elementToCheck), waitTimeout, 'Element is not in stale ' + elementToCheck.locator()); + return browser.wait( + protractor.ExpectedConditions.stalenessOf(elementToCheck), + waitTimeout, + 'Element is not in stale ' + elementToCheck.locator() + ); } /* * Wait for element to not be visible */ - static async waitUntilElementIsNotVisible(elementToCheck: ElementFinder, waitTimeout: number = BrowserVisibility.NOT_VISIBLE_DEFAULT_TIMEOUT): Promise { + static async waitUntilElementIsNotVisible( + elementToCheck: ElementFinder, + waitTimeout: number = BrowserVisibility.NOT_VISIBLE_DEFAULT_TIMEOUT + ): Promise { Logger.info(`Wait Until Element Is Not Visible ${elementToCheck.locator().toString()} for ${waitTimeout}`); - return browser.wait(protractor.ExpectedConditions.invisibilityOf(elementToCheck), waitTimeout, 'Element is Visible and it should not' + elementToCheck.locator()); + return browser.wait( + protractor.ExpectedConditions.invisibilityOf(elementToCheck), + waitTimeout, + 'Element is Visible and it should not' + elementToCheck.locator() + ); } /* * Wait for element to have value */ - static async waitUntilElementHasValue(elementToCheck: ElementFinder, elementValue, waitTimeout: number = BrowserVisibility.DEFAULT_TIMEOUT): Promise { + static async waitUntilElementHasValue( + elementToCheck: ElementFinder, + elementValue, + waitTimeout: number = BrowserVisibility.DEFAULT_TIMEOUT + ): Promise { Logger.info(`Wait Until Element has value ${elementToCheck.locator().toString()} for ${waitTimeout}`); - return browser.wait(BrowserVisibility.textToBePresentInElementValue(elementToCheck, elementValue), waitTimeout, `Element doesn't have a value ${elementValue} ${elementToCheck.locator()}`); + return browser.wait( + BrowserVisibility.textToBePresentInElementValue(elementToCheck, elementValue), + waitTimeout, + `Element doesn't have a value ${elementValue} ${elementToCheck.locator()}` + ); } /* @@ -100,10 +131,17 @@ export class BrowserVisibility { static async waitUntilElementHasText(elementToCheck: ElementFinder, text, waitTimeout: number = BrowserVisibility.DEFAULT_TIMEOUT): Promise { Logger.info(`Wait Until Element has value ${elementToCheck.locator().toString()} for ${waitTimeout}`); - return browser.wait(protractor.ExpectedConditions.textToBePresentInElement(elementToCheck, text), waitTimeout, `Element doesn't have the text ${text} ${elementToCheck.locator()}`); + return browser.wait( + protractor.ExpectedConditions.textToBePresentInElement(elementToCheck, text), + waitTimeout, + `Element doesn't have the text ${text} ${elementToCheck.locator()}` + ); } - static async waitUntilElementIsNotPresent(elementToCheck: ElementFinder, waitTimeout: number = BrowserVisibility.NOT_VISIBLE_DEFAULT_TIMEOUT): Promise { + static async waitUntilElementIsNotPresent( + elementToCheck: ElementFinder, + waitTimeout: number = BrowserVisibility.NOT_VISIBLE_DEFAULT_TIMEOUT + ): Promise { Logger.info(`Wait Until Element is not present ${elementToCheck.locator().toString()} for ${waitTimeout}`); return browser.wait(protractor.ExpectedConditions.stalenessOf(elementToCheck), waitTimeout, 'Element is present ' + elementToCheck.locator()); @@ -117,9 +155,10 @@ export class BrowserVisibility { } private static textToBePresentInElementValue(elementFinder: ElementFinder, text: string) { - const hasText = async () => browser.executeScript(`return arguments[0].value`, elementFinder).then( - (actualText: string) => actualText.indexOf(text) > -1, falseIfMissing - ); + const hasText = async () => + browser + .executeScript(`return document.querySelector('${elementFinder.locator().value}').value`) + .then((actualText: string) => actualText.indexOf(text) > -1, falseIfMissing); return protractor.ExpectedConditions.and(protractor.ExpectedConditions.presenceOf(elementFinder), hasText); } }