From 097439eda32c1f40158a042313f775ecbfe038cf Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Fri, 2 Apr 2021 14:45:11 -0500 Subject: [PATCH] Add support for locators into driver abstraction (#10802) --- test/e2e/webdriver/driver.js | 50 +++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index f1da84a21..7787468ba 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -1,6 +1,6 @@ const { promises: fs } = require('fs'); const { strict: assert } = require('assert'); -const { until, error: webdriverError } = require('selenium-webdriver'); +const { until, error: webdriverError, By } = require('selenium-webdriver'); class Driver { /** @@ -15,6 +15,30 @@ class Driver { this.timeout = timeout; } + buildLocator(locator) { + if (typeof locator === 'string') { + // If locator is a string we assume its a css selector + return By.css(locator); + } else if (locator.value) { + // For backwards compatibility, checking if the locator has a value prop + // tells us this is a Selenium locator + return locator; + } else if (locator.xpath) { + // Providing an xpath prop to the object will consume the locator as an + // xpath locator. + return By.xpath(locator.xpath); + } else if (locator.text) { + // Providing a text prop, and optionally a tag, will use xpath to look + // for an element with the tag that has matching text. + return By.xpath( + `//${locator.tag ?? '*'}[contains(text(), '${locator.text}')]`, + ); + } + throw new Error( + `The locator '${locator}' is not supported by the E2E test driver`, + ); + } + async delay(time) { await new Promise((resolve) => setTimeout(resolve, time)); } @@ -29,17 +53,20 @@ class Driver { // Element interactions - async findElement(locator) { + async findElement(rawLocator) { + const locator = this.buildLocator(rawLocator); return await this.driver.wait(until.elementLocated(locator), this.timeout); } - async findVisibleElement(locator) { + async findVisibleElement(rawLocator) { + const locator = this.buildLocator(rawLocator); const element = await this.findElement(locator); await this.driver.wait(until.elementIsVisible(element), this.timeout); return element; } - async findClickableElement(locator) { + async findClickableElement(rawLocator) { + const locator = this.buildLocator(rawLocator); const element = await this.findElement(locator); await Promise.all([ this.driver.wait(until.elementIsVisible(element), this.timeout), @@ -48,11 +75,13 @@ class Driver { return element; } - async findElements(locator) { + async findElements(rawLocator) { + const locator = this.buildLocator(rawLocator); return await this.driver.wait(until.elementsLocated(locator), this.timeout); } - async findClickableElements(locator) { + async findClickableElements(rawLocator) { + const locator = this.buildLocator(rawLocator); const elements = await this.findElements(locator); await Promise.all( elements.reduce((acc, element) => { @@ -66,12 +95,14 @@ class Driver { return elements; } - async clickElement(locator) { + async clickElement(rawLocator) { + const locator = this.buildLocator(rawLocator); const element = await this.findClickableElement(locator); await element.click(); } - async clickPoint(locator, x, y) { + async clickPoint(rawLocator, x, y) { + const locator = this.buildLocator(rawLocator); const element = await this.findElement(locator); await this.driver .actions() @@ -87,7 +118,8 @@ class Driver { ); } - async assertElementNotPresent(locator) { + async assertElementNotPresent(rawLocator) { + const locator = this.buildLocator(rawLocator); let dataTab; try { dataTab = await this.findElement(locator);