From 6d5fc76fdef9960de3f3e746a538a63c300e0bae Mon Sep 17 00:00:00 2001 From: Li Zheng Date: Mon, 25 Sep 2017 14:43:21 +0800 Subject: [PATCH 1/3] increase considerable test speed of ~ locator in Appium by avoid xpathLocator() in WebDriverIO.js --- lib/helper/Appium.js | 5 ++++- lib/helper/WebDriverIO.js | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/helper/Appium.js b/lib/helper/Appium.js index 51d4e4356..4d5f8fa37 100644 --- a/lib/helper/Appium.js +++ b/lib/helper/Appium.js @@ -1235,7 +1235,10 @@ function parseLocator(locator) { if (!locator) return null; if (typeof locator === 'string') { if (locator.substr(0, 2) === '//') return locator; - if (locator[0] === '~') return locator; + if (locator[0] === '~' && !this.isWeb) { + // increase considerable test speed by avoid xpathLocator() in WebDriverIO.js + return { 'accessibility id': locator.slice(1) }; + } if (locator[0] === '#' && !this.isWeb) { // hook before webdriverio supports native # locators diff --git a/lib/helper/WebDriverIO.js b/lib/helper/WebDriverIO.js index a92796d76..79bf606dc 100644 --- a/lib/helper/WebDriverIO.js +++ b/lib/helper/WebDriverIO.js @@ -2142,6 +2142,8 @@ function withStrictLocator(locator) { return value; case 'css': return value; + case 'accessibility id': + return 'accessibility id:' + value; case 'id': return '#' + value; case 'name': From d2b5215a6df7641b57a3dce63bdcdc80567a0a9c Mon Sep 17 00:00:00 2001 From: Li Zheng Date: Mon, 25 Sep 2017 14:47:47 +0800 Subject: [PATCH 2/3] support ~ locator (to css selector with html attribute aria-label) in WebDriverIO --- lib/helper/WebDriverIO.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/helper/WebDriverIO.js b/lib/helper/WebDriverIO.js index 79bf606dc..ee00c1c22 100644 --- a/lib/helper/WebDriverIO.js +++ b/lib/helper/WebDriverIO.js @@ -1974,7 +1974,7 @@ function proceedSee(assertType, text, context, strict = false) { } function findClickable(locator, locateFn) { - if (typeof locator === 'object') return locateFn(withStrictLocator(locator), true); + if (typeof locator === 'object' || locator[0] === '~') return locateFn(withStrictLocator(locator), true); if (isCSSorXPathLocator(locator)) return locateFn(locator, true); let literal = xpathLocator.literal(locator); @@ -2019,7 +2019,7 @@ function toStrictLocator(locator) { } function findFields(locator) { - if (typeof locator === 'object') return this._locate(withStrictLocator(locator), true); + if (typeof locator === 'object' || locator[0] === '~') return this._locate(withStrictLocator(locator), true); if (isCSSorXPathLocator(locator)) return this._locate(locator, true); let literal = xpathLocator.literal(locator); @@ -2100,7 +2100,7 @@ function proceedSeeCheckbox(assertType, field) { } function findCheckable(locator, locateFn) { - if (typeof locator === 'object') return locateFn(withStrictLocator(locator), true); + if (typeof locator === 'object' || locator[0] === '~') return locateFn(withStrictLocator(locator), true); if (isCSSorXPathLocator(locator)) return locateFn(locator, true); let literal = xpathLocator.literal(locator); @@ -2130,6 +2130,13 @@ function isCSSorXPathLocator(locator) { function withStrictLocator(locator) { if (!locator) return null; + if (typeof locator === 'string') { + if (locator[0] === '~') { + // hook before webdriverio supports native ~ locators in web + return `[aria-label="${locator.slice(1)}"]`; + } + } + if (typeof locator !== 'object') return locator; let key = Object.keys(locator)[0]; let value = locator[key]; From 0e384c037f5643129ea80f7c3d285dfbe2774de1 Mon Sep 17 00:00:00 2001 From: Li Zheng Date: Thu, 23 Nov 2017 13:12:00 +0800 Subject: [PATCH 3/3] support ~ locator when Appium.js call method only in WebDriverIO.js e.g. waitForElement() --- lib/helper/Appium.js | 5 +- lib/helper/WebDriverIO.js | 98 ++++++++++++++++++++------------------- 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/lib/helper/Appium.js b/lib/helper/Appium.js index 4d5f8fa37..51d4e4356 100644 --- a/lib/helper/Appium.js +++ b/lib/helper/Appium.js @@ -1235,10 +1235,7 @@ function parseLocator(locator) { if (!locator) return null; if (typeof locator === 'string') { if (locator.substr(0, 2) === '//') return locator; - if (locator[0] === '~' && !this.isWeb) { - // increase considerable test speed by avoid xpathLocator() in WebDriverIO.js - return { 'accessibility id': locator.slice(1) }; - } + if (locator[0] === '~') return locator; if (locator[0] === '#' && !this.isWeb) { // hook before webdriverio supports native # locators diff --git a/lib/helper/WebDriverIO.js b/lib/helper/WebDriverIO.js index ee00c1c22..e71f83521 100644 --- a/lib/helper/WebDriverIO.js +++ b/lib/helper/WebDriverIO.js @@ -385,7 +385,7 @@ class WebDriverIO extends Helper { withinStore.elFn = this.browser.element; withinStore.elsFn = this.browser.elements; this.context = locator; - return client.element(withStrictLocator(locator)).then((res) => { + return client.element(withStrictLocator.call(this, locator)).then((res) => { this.browser.element = function (l) { return this.elementIdElement(res.value.ELEMENT, l); }; @@ -416,12 +416,12 @@ class WebDriverIO extends Helper { */ _locate(locator, smartWait = false) { - if (!this.options.smartWait || !smartWait) return this.browser.elements(withStrictLocator(locator)); + if (!this.options.smartWait || !smartWait) return this.browser.elements(withStrictLocator.call(this, locator)); let els; return this.defineTimeout({implicit: this.options.smartWait}) .then(() => this.debugSection('SmartWait', `Locating ${locator} in ${this.options.smartWait}`)) - .then(() => this.browser.elements(withStrictLocator(locator))); + .then(() => this.browser.elements(withStrictLocator.call(this, locator))); } /** @@ -432,7 +432,7 @@ class WebDriverIO extends Helper { * ``` */ _locateCheckable(locator) { - return findCheckable(locator, this.browser.elements.bind(this)).then((res) => res.value); + return findCheckable.call(this, locator, this.browser.elements.bind(this)).then((res) => res.value); } /** @@ -443,7 +443,7 @@ class WebDriverIO extends Helper { * ``` */ _locateClickable(locator) { - return findClickable(locator, this.browser.elements.bind(this)).then((res) => res.value); + return findClickable.call(this, locator, this.browser.elements.bind(this)).then((res) => res.value); } /** @@ -505,7 +505,7 @@ class WebDriverIO extends Helper { let clickMethod = this.browser.isMobile ? 'touchClick' : 'elementIdClick'; let locateFn = prepareLocateFn.call(this, context); - return findClickable(locator, locateFn).then((res) => { + return findClickable.call(this, locator, locateFn).then((res) => { if (!res.value || res.value.length === 0) { if (typeof locator === "object") locator = JSON.stringify(locator); if (context) locator += ` inside ${context}`; @@ -523,7 +523,7 @@ class WebDriverIO extends Helper { let clickMethod = this.browser.isMobile ? 'touchClick' : 'elementIdClick'; let locateFn = prepareLocateFn.call(this, context); - return findClickable(locator, locateFn).then((res) => { + return findClickable.call(this, locator, locateFn).then((res) => { if (!res.value || res.value.length === 0) { throw new ElementNotFound(locator, "Clickable element"); } @@ -667,7 +667,7 @@ class WebDriverIO extends Helper { let locateFn = prepareLocateFn.call(this, context); - return findCheckable(field, locateFn).then((res) => { + return findCheckable.call(this, field, locateFn).then((res) => { if (!res.value || res.value.length === 0) { throw new ElementNotFound(field, "Checkable"); } @@ -710,7 +710,7 @@ class WebDriverIO extends Helper { * ``` */ grabHTMLFrom(locator) { - return this.browser.getHTML(withStrictLocator(locator)).then(function (html) { + return this.browser.getHTML(withStrictLocator.call(this, locator)).then(function (html) { return html; }); } @@ -905,7 +905,7 @@ class WebDriverIO extends Helper { * Appium: support */ dontSeeElement(locator) { - return this.browser.elements(withStrictLocator(locator)).then((res) => { + return this.browser.elements(withStrictLocator.call(this, locator)).then((res) => { if (!res.value || res.value.length === 0) { return truth(`elements of ${locator}`, 'to be seen').negate(false); } @@ -924,7 +924,7 @@ class WebDriverIO extends Helper { * Appium: support */ seeElementInDOM(locator) { - return this.browser.elements(withStrictLocator(locator)).then(function (res) { + return this.browser.elements(withStrictLocator.call(this, locator)).then(function (res) { return empty('elements').negate(res.value); }); } @@ -934,7 +934,7 @@ class WebDriverIO extends Helper { * Appium: support */ dontSeeElementInDOM(locator) { - return this.browser.elements(withStrictLocator(locator)).then(function (res) { + return this.browser.elements(withStrictLocator.call(this, locator)).then(function (res) { return empty('elements').assert(res.value); }); } @@ -991,7 +991,7 @@ class WebDriverIO extends Helper { * ``` */ seeNumberOfElements(selector, num) { - return this._locate(withStrictLocator(selector)) + return this._locate(withStrictLocator.call(this, selector)) .then(function (res) { return assert.equal(res.value.length, num, `expected number of elements (${selector}) is ${num}, but found ${res.value.length}`); @@ -1101,7 +1101,7 @@ class WebDriverIO extends Helper { * ``` */ grabNumberOfVisibleElements(locator) { - return this.browser.elements(withStrictLocator(locator)).then((res) => { + return this.browser.elements(withStrictLocator.call(this, locator)).then((res) => { if (!res.value || res.value.length === 0) { return 0; } @@ -1195,7 +1195,7 @@ class WebDriverIO extends Helper { } if (locator) { - return this._locate(withStrictLocator(locator), true).then(function (res) { + return this._locate(withStrictLocator.call(this, locator), true).then(function (res) { if (!res.value || res.value.length === 0) { return truth(`elements of ${locator}`, 'to be seen').assert(false); } @@ -1229,7 +1229,7 @@ class WebDriverIO extends Helper { hasOffsetParams = false; } - return this._locate(withStrictLocator(locator), true).then((res) => { + return this._locate(withStrictLocator.call(this, locator), true).then((res) => { if (!res.value || res.value.length === 0) { return truth(`elements of ${locator}`, 'to be seen').assert(false); } @@ -1442,17 +1442,17 @@ class WebDriverIO extends Helper { if (client.isMobile) { - return client.element(withStrictLocator(srcElement)).then(function (res) { + return client.element(withStrictLocator.call(this, srcElement)).then((res) => { if (!res.value || res.value.length === 0) return truth(`elements of ${srcElement}`, 'to be seen').assert(false); let elem = res.value; - return this.elementIdLocation(elem.ELEMENT).then(function (location) { + return this.elementIdLocation(elem.ELEMENT).then((location) => { if (!location.value || location.value.length === 0) { throw new Error( `Failed to receive (${srcElement}) location`); } - return this.touchDown(location.value.x, location.value.y).then(function (res) { + return this.touchDown(location.value.x, location.value.y).then((res) => { if (res.state !== 'success') throw new Error(`Failed to touch button down on (${srcElement})`); - return client.element(withStrictLocator(destElement)).then(function (res) { + return client.element(withStrictLocator.call(this, destElement)).then(function (res) { if (!res.value || res.value.length === 0) { return truth(`elements of ${destElement}`, 'to be seen') .assert(false); @@ -1474,11 +1474,11 @@ class WebDriverIO extends Helper { }); } - return this2.moveCursorTo(withStrictLocator(srcElement)).then(function (res) { + return this2.moveCursorTo(withStrictLocator.call(this, srcElement)).then((res) => { if (res.state !== 'success') throw new Error(`Unable to move cursor to (${srcElement})`); - return this.buttonDown().then(function (res) { + return this.buttonDown().then((res) => { if (res.state !== 'success') throw new Error(`Failed to press button down on (${srcElement})`); - return this2.moveCursorTo(withStrictLocator(destElement)).then(function (res) { + return this2.moveCursorTo(withStrictLocator.call(this, destElement)).then(function (res) { if (res.state !== 'success') throw new Error(`Unable to move cursor to (${destElement})`); return this.buttonUp(); }); @@ -1525,8 +1525,8 @@ class WebDriverIO extends Helper { waitForEnabled(locator, sec = null) { let client = this.browser; let aSec = sec || this.options.waitForTimeout; - return client.waitUntil(function () { - return client.elements(withStrictLocator(locator)).then(function (res) { + return client.waitUntil(() => { + return client.elements(withStrictLocator.call(this, locator)).then(function (res) { if (!res.value || res.value.length === 0) { return false; } @@ -1551,8 +1551,8 @@ class WebDriverIO extends Helper { waitForElement(locator, sec = null) { let client = this.browser; let aSec = sec || this.options.waitForTimeout; - return client.waitUntil(function () { - return client.elements(withStrictLocator(locator)).then(function (res) { + return client.waitUntil(() => { + return client.elements(withStrictLocator.call(this, locator)).then(function (res) { if (!res.value || res.value.length === 0) { return false; } else return true; @@ -1567,8 +1567,8 @@ class WebDriverIO extends Helper { waitUntilExists(locator, sec = null) { let client = this.browser; sec = sec || this.options.waitForTimeout; - return client.waitUntil(function () { - return client.elements(withStrictLocator(locator)).then(function (res) { + return client.waitUntil(() => { + return client.elements(withStrictLocator.call(this, locator)).then(function (res) { if (!res.value || res.value.length === 0) { return true; } else return false; @@ -1642,8 +1642,8 @@ class WebDriverIO extends Helper { let client = this.browser; let aSec = sec || this.options.waitForTimeout; let context = aContext || this.root; - return client.waitUntil(function () { - return client.elements(withStrictLocator(context)).then(function (res) { + return client.waitUntil(() => { + return client.elements(withStrictLocator.call(this, context)).then(function (res) { if (!res.value || res.value.length === 0) { return false; } @@ -1703,8 +1703,8 @@ class WebDriverIO extends Helper { waitForVisible(locator, sec = null) { let client = this.browser; let aSec = sec || this.options.waitForTimeout; - return client.waitUntil(function () { - return client.elements(withStrictLocator(locator)).then(function (res) { + return client.waitUntil(() => { + return client.elements(withStrictLocator.call(this, locator)).then(function (res) { if (!res.value || res.value.length === 0) { return false; } @@ -1732,8 +1732,8 @@ class WebDriverIO extends Helper { waitNumberOfVisibleElements(locator, num, sec = null) { let client = this.browser; let aSec = sec || this.options.waitForTimeout; - return client.waitUntil(function () { - return client.elements(withStrictLocator(locator)).then(function (res) { + return client.waitUntil(() => { + return client.elements(withStrictLocator.call(this, locator)).then(function (res) { if (!res.value || res.value.length === 0) { return false; } @@ -1756,8 +1756,8 @@ class WebDriverIO extends Helper { waitForInvisible(locator, sec = null) { let client = this.browser; let aSec = sec || this.options.waitForTimeout; - return client.waitUntil(function () { - return client.elements(withStrictLocator(locator)).then(function (res) { + return client.waitUntil(() => { + return client.elements(withStrictLocator.call(this, locator)).then(function (res) { if (!res.value || res.value.length === 0) { return true; } @@ -1791,8 +1791,8 @@ class WebDriverIO extends Helper { waitForStalenessOf(locator, sec = null) { let client = this.browser; let aSec = sec || this.options.waitForTimeout; - return client.waitUntil(function () { - return client.elements(withStrictLocator(locator)).then(function (res) { + return client.waitUntil(() => { + return client.elements(withStrictLocator.call(this, locator)).then(function (res) { if (!res.value || res.value.length === 0) { return true; } else return false; @@ -1819,7 +1819,7 @@ class WebDriverIO extends Helper { } else if (Number.isInteger(locator)) { return this.browser.frame(locator); } - return this.browser.element(withStrictLocator(locator)).then((res) => { + return this.browser.element(withStrictLocator.call(this, locator)).then((res) => { if (!res.value || res.value.length === 0) { throw new ElementNotFound(locator); } @@ -1958,7 +1958,7 @@ function proceedSee(assertType, text, context, strict = false) { let smartWaitEnabled = assertType === 'assert'; - return this._locate(withStrictLocator(context), smartWaitEnabled).then((res) => { + return this._locate(withStrictLocator.call(this, context), smartWaitEnabled).then((res) => { if (!res.value || res.value.length === 0) { throw new ElementNotFound(context); } @@ -1974,7 +1974,7 @@ function proceedSee(assertType, text, context, strict = false) { } function findClickable(locator, locateFn) { - if (typeof locator === 'object' || locator[0] === '~') return locateFn(withStrictLocator(locator), true); + if (typeof locator === 'object' || locator[0] === '~') return locateFn(withStrictLocator.call(this, locator), true); if (isCSSorXPathLocator(locator)) return locateFn(locator, true); let literal = xpathLocator.literal(locator); @@ -2019,7 +2019,7 @@ function toStrictLocator(locator) { } function findFields(locator) { - if (typeof locator === 'object' || locator[0] === '~') return this._locate(withStrictLocator(locator), true); + if (typeof locator === 'object' || locator[0] === '~') return this._locate(withStrictLocator.call(this, locator), true); if (isCSSorXPathLocator(locator)) return this._locate(locator, true); let literal = xpathLocator.literal(locator); @@ -2100,7 +2100,7 @@ function proceedSeeCheckbox(assertType, field) { } function findCheckable(locator, locateFn) { - if (typeof locator === 'object' || locator[0] === '~') return locateFn(withStrictLocator(locator), true); + if (typeof locator === 'object' || locator[0] === '~') return locateFn(withStrictLocator.call(this, locator), true); if (isCSSorXPathLocator(locator)) return locateFn(locator, true); let literal = xpathLocator.literal(locator); @@ -2132,8 +2132,12 @@ function withStrictLocator(locator) { if (!locator) return null; if (typeof locator === 'string') { if (locator[0] === '~') { - // hook before webdriverio supports native ~ locators in web - return `[aria-label="${locator.slice(1)}"]`; + if (this.isWeb || this.isWeb === undefined) { + // hook before webdriverio supports native ~ locators in web + return `[aria-label="${locator.slice(1)}"]`; + } else { + return `accessibility id:${locator.slice(1)}`; + } } } @@ -2149,8 +2153,6 @@ function withStrictLocator(locator) { return value; case 'css': return value; - case 'accessibility id': - return 'accessibility id:' + value; case 'id': return '#' + value; case 'name':