From 7e11eb1aaf91be2fff3b0ac5869fff57f8cb4be4 Mon Sep 17 00:00:00 2001 From: Aniket Singh Rawat Date: Sun, 1 Sep 2024 14:10:52 +0530 Subject: [PATCH 1/7] Add additional commands for new Element API stash --- .../web-element/commands/getComputedLabel.js | 3 ++ .../web-element/commands/getComputedRole.js | 3 ++ lib/api/web-element/commands/isActive.js | 3 ++ .../selenium-webdriver/method-mappings.js | 41 +++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 lib/api/web-element/commands/getComputedLabel.js create mode 100644 lib/api/web-element/commands/getComputedRole.js create mode 100644 lib/api/web-element/commands/isActive.js diff --git a/lib/api/web-element/commands/getComputedLabel.js b/lib/api/web-element/commands/getComputedLabel.js new file mode 100644 index 000000000..e274b2dce --- /dev/null +++ b/lib/api/web-element/commands/getComputedLabel.js @@ -0,0 +1,3 @@ +module.exports.command = function () { + return this.runQueuedCommand('getElementComputedLabel'); +}; diff --git a/lib/api/web-element/commands/getComputedRole.js b/lib/api/web-element/commands/getComputedRole.js new file mode 100644 index 000000000..e08f01ee6 --- /dev/null +++ b/lib/api/web-element/commands/getComputedRole.js @@ -0,0 +1,3 @@ +module.exports.command = function () { + return this.runQueuedCommand('getElementComputedRole'); +}; diff --git a/lib/api/web-element/commands/isActive.js b/lib/api/web-element/commands/isActive.js new file mode 100644 index 000000000..7df432c76 --- /dev/null +++ b/lib/api/web-element/commands/isActive.js @@ -0,0 +1,3 @@ +module.exports.command = function () { + return this.runQueuedCommandScoped('isElementActive'); +}; diff --git a/lib/transport/selenium-webdriver/method-mappings.js b/lib/transport/selenium-webdriver/method-mappings.js index cde1de0ef..12998f92b 100644 --- a/lib/transport/selenium-webdriver/method-mappings.js +++ b/lib/transport/selenium-webdriver/method-mappings.js @@ -493,6 +493,47 @@ module.exports = class MethodMappings { }; }, + async getElementComputedRole(webElementOrId) { + const element = this.getWebElement(webElementOrId); + + const role = await this.driver.executeScript(` + const el = arguments[0]; + let role = el.getAttribute('role'); + return role || 'unknown'; + `, element); + + return { + value: role + }; + }, + + async getElementComputedLabel(webElementOrId) { + const element = this.getWebElement(webElementOrId); + + const label = await this.driver.executeScript(` + const el = arguments[0]; + let label = el.getAttribute('aria-label') || + el.getAttribute('title') || + el.getAttribute('alt'); + return label || 'unknown'; + `, element); + + return { + value: label + }; + }, + + async isElementActive(webElementOrId) { + const element = this.getWebElement(webElementOrId); + + const isActive = await this.driver.executeScript(` + const el = arguments[0]; + return el === document.activeElement; + `, element); + + return isActive; + }, + async setElementProperty(webElementOrId, name, value) { const element = this.getWebElement(webElementOrId); From c755786dacb550d397d7f294d50d356bd4320a37 Mon Sep 17 00:00:00 2001 From: Aniket Singh Rawat Date: Sun, 1 Sep 2024 14:18:36 +0530 Subject: [PATCH 2/7] add types --- types/web-element.d.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/types/web-element.d.ts b/types/web-element.d.ts index 426778068..86ae5dc29 100644 --- a/types/web-element.d.ts +++ b/types/web-element.d.ts @@ -216,6 +216,12 @@ export interface ScopedElement extends Element, PromiseLike { isVisible(): ElementValue; isDisplayed(): ElementValue; + + isActive(): ElementValue; + + getComputedLabel(): ElementValue; + + getComputedRole(): ElementValue; } type WaitUntilOptions = { From 39f33159014bedd415276ab2ced739b5446b4f3d Mon Sep 17 00:00:00 2001 From: Aniket Singh Rawat Date: Tue, 15 Oct 2024 22:36:23 +0530 Subject: [PATCH 3/7] update get computed role and label command to use Webdriver endpoint --- lib/api/web-element/scoped-element.js | 4 +- lib/transport/selenium-webdriver/actions.js | 4 ++ .../selenium-webdriver/method-mappings.js | 37 ++++++++----------- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/lib/api/web-element/scoped-element.js b/lib/api/web-element/scoped-element.js index 35209164a..5c1f9a45f 100644 --- a/lib/api/web-element/scoped-element.js +++ b/lib/api/web-element/scoped-element.js @@ -265,9 +265,7 @@ class ScopedWebElement { this.webElement = promise; } else { this.webElement = new WebElementPromise(this.driver, this.then(async (element) => { - await promise; - - return element; + return await promise; })); } diff --git a/lib/transport/selenium-webdriver/actions.js b/lib/transport/selenium-webdriver/actions.js index e24a26c9a..87384057c 100644 --- a/lib/transport/selenium-webdriver/actions.js +++ b/lib/transport/selenium-webdriver/actions.js @@ -50,6 +50,10 @@ class TransportActions { promise = Array.isArray(args) ? mapping.apply(this.MethodMappings, args) : mapping.call(this.MethodMappings, args); } + if (promise.resolveEarly){ + promise = await promise; + } + if (!(promise instanceof Promise)) { const opts = {}; diff --git a/lib/transport/selenium-webdriver/method-mappings.js b/lib/transport/selenium-webdriver/method-mappings.js index 12998f92b..46f9d8f33 100644 --- a/lib/transport/selenium-webdriver/method-mappings.js +++ b/lib/transport/selenium-webdriver/method-mappings.js @@ -493,34 +493,27 @@ module.exports = class MethodMappings { }; }, - async getElementComputedRole(webElementOrId) { - const element = this.getWebElement(webElementOrId); - const role = await this.driver.executeScript(` - const el = arguments[0]; - let role = el.getAttribute('role'); - return role || 'unknown'; - `, element); + getElementComputedRole(webElementOrId) { + const promise = (async () => { + const id = await webElementOrId.getId(); - return { - value: role - }; + return `/element/${id}/computedrole`; + })(); + promise.resolveEarly = true; + + return promise; }, - async getElementComputedLabel(webElementOrId) { - const element = this.getWebElement(webElementOrId); + getElementComputedLabel(webElementOrId) { + const promise = (async () => { + const id = await webElementOrId.getId(); - const label = await this.driver.executeScript(` - const el = arguments[0]; - let label = el.getAttribute('aria-label') || - el.getAttribute('title') || - el.getAttribute('alt'); - return label || 'unknown'; - `, element); + return `/element/${id}/computedlabel`; + })(); + promise.resolveEarly = true; - return { - value: label - }; + return promise; }, async isElementActive(webElementOrId) { From aa568047bc7ac71608074b9ea63fca847caac254 Mon Sep 17 00:00:00 2001 From: Aniket Singh Rawat Date: Thu, 17 Oct 2024 13:37:10 +0530 Subject: [PATCH 4/7] fix: update command call fn --- lib/api/web-element/commands/getComputedLabel.js | 2 +- lib/api/web-element/commands/getComputedRole.js | 2 +- lib/api/web-element/scoped-element.js | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/api/web-element/commands/getComputedLabel.js b/lib/api/web-element/commands/getComputedLabel.js index e274b2dce..65d3bf579 100644 --- a/lib/api/web-element/commands/getComputedLabel.js +++ b/lib/api/web-element/commands/getComputedLabel.js @@ -1,3 +1,3 @@ module.exports.command = function () { - return this.runQueuedCommand('getElementComputedLabel'); + return this.runQueuedCommandScoped('getElementComputedLabel'); }; diff --git a/lib/api/web-element/commands/getComputedRole.js b/lib/api/web-element/commands/getComputedRole.js index e08f01ee6..7a51f5e4e 100644 --- a/lib/api/web-element/commands/getComputedRole.js +++ b/lib/api/web-element/commands/getComputedRole.js @@ -1,3 +1,3 @@ module.exports.command = function () { - return this.runQueuedCommand('getElementComputedRole'); + return this.runQueuedCommandScoped('getElementComputedRole'); }; diff --git a/lib/api/web-element/scoped-element.js b/lib/api/web-element/scoped-element.js index 5c1f9a45f..35209164a 100644 --- a/lib/api/web-element/scoped-element.js +++ b/lib/api/web-element/scoped-element.js @@ -265,7 +265,9 @@ class ScopedWebElement { this.webElement = promise; } else { this.webElement = new WebElementPromise(this.driver, this.then(async (element) => { - return await promise; + await promise; + + return element; })); } From 80a7a57905a3a4d3112b73f787b5bb28a947f290 Mon Sep 17 00:00:00 2001 From: Aniket Singh Rawat Date: Sat, 19 Oct 2024 16:50:32 +0530 Subject: [PATCH 5/7] add tests --- .../web-element/testGetComputedLabel.js | 61 +++++++++++++++++++ .../web-element/testGetComputedRole.js | 61 +++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 test/src/api/commands/web-element/testGetComputedLabel.js create mode 100644 test/src/api/commands/web-element/testGetComputedRole.js diff --git a/test/src/api/commands/web-element/testGetComputedLabel.js b/test/src/api/commands/web-element/testGetComputedLabel.js new file mode 100644 index 000000000..c8dbc74bc --- /dev/null +++ b/test/src/api/commands/web-element/testGetComputedLabel.js @@ -0,0 +1,61 @@ +const assert = require('assert'); +const {WebElement} = require('selenium-webdriver'); +const MockServer = require('../../../../lib/mockserver.js'); +const CommandGlobals = require('../../../../lib/globals/commands-w3c.js'); +const common = require('../../../../common.js'); +const Element = common.require('element/index.js'); + +describe('element().getComputedLabel() command', function() { + before(function (done) { + CommandGlobals.beforeEach.call(this, done); + + }); + + after(function (done) { + CommandGlobals.afterEach.call(this, done); + }); + + it('test .element().getComputedLabel() success', async function() { + MockServer.addMock({ + url: '/session/13521-10219-202/element/0/computedlabel', + method: 'GET', + response: JSON.stringify({ + value: 'signup' + }) + }); + + const resultPromise = this.client.api.element('#signupSection').getComputedLabel(); + assert.strictEqual(resultPromise instanceof Element, false); + assert.strictEqual(typeof resultPromise.find, 'undefined'); + + assert.strictEqual(resultPromise instanceof Promise, false); + assert.strictEqual(typeof resultPromise.then, 'function'); + + const result = await resultPromise; + assert.strictEqual(result instanceof WebElement, false); + assert.strictEqual(result, 'signup'); + + }); + + it('test .element().getComputedLabel() via find', async function() { + MockServer.addMock({ + url: '/session/13521-10219-202/element/1/computedlabel', + method: 'GET', + response: JSON.stringify({ + value: 'help' + }) + }); + + const resultPromise = this.client.api.element('#signupSection').find('#helpBtn').getComputedLabel(); + assert.strictEqual(resultPromise instanceof Element, false); + assert.strictEqual(typeof resultPromise.find, 'undefined'); + + assert.strictEqual(resultPromise instanceof Promise, false); + assert.strictEqual(typeof resultPromise.then, 'function'); + + const result = await resultPromise; + assert.strictEqual(result instanceof WebElement, false); + assert.strictEqual(result, 'help'); + + }); +}); \ No newline at end of file diff --git a/test/src/api/commands/web-element/testGetComputedRole.js b/test/src/api/commands/web-element/testGetComputedRole.js new file mode 100644 index 000000000..7fdb12c0e --- /dev/null +++ b/test/src/api/commands/web-element/testGetComputedRole.js @@ -0,0 +1,61 @@ +const assert = require('assert'); +const {WebElement} = require('selenium-webdriver'); +const MockServer = require('../../../../lib/mockserver.js'); +const CommandGlobals = require('../../../../lib/globals/commands-w3c.js'); +const common = require('../../../../common.js'); +const Element = common.require('element/index.js'); + +describe('element().getComputedRole() command', function() { + before(function (done) { + CommandGlobals.beforeEach.call(this, done); + + }); + + after(function (done) { + CommandGlobals.afterEach.call(this, done); + }); + + it('test .element().getComputedRole() success', async function() { + MockServer.addMock({ + url: '/session/13521-10219-202/element/0/computedrole', + method: 'GET', + response: JSON.stringify({ + value: 'signup-heading' + }) + }); + + const resultPromise = this.client.api.element('#signupSection').getComputedRole(); + assert.strictEqual(resultPromise instanceof Element, false); + assert.strictEqual(typeof resultPromise.find, 'undefined'); + + assert.strictEqual(resultPromise instanceof Promise, false); + assert.strictEqual(typeof resultPromise.then, 'function'); + + const result = await resultPromise; + assert.strictEqual(result instanceof WebElement, false); + assert.strictEqual(result, 'signup-heading'); + + }); + + it('test .element().getComputedRole() via find', async function() { + MockServer.addMock({ + url: '/session/13521-10219-202/element/1/computedrole', + method: 'GET', + response: JSON.stringify({ + value: 'help-button' + }) + }); + + const resultPromise = this.client.api.element('#signupSection').find('#helpBtn').getComputedRole(); + assert.strictEqual(resultPromise instanceof Element, false); + assert.strictEqual(typeof resultPromise.find, 'undefined'); + + assert.strictEqual(resultPromise instanceof Promise, false); + assert.strictEqual(typeof resultPromise.then, 'function'); + + const result = await resultPromise; + assert.strictEqual(result instanceof WebElement, false); + assert.strictEqual(result, 'help-button'); + + }); +}); \ No newline at end of file From 4f7f7ba09b7fa893693ddd6e0f26af48d78c9b0e Mon Sep 17 00:00:00 2001 From: Aniket Singh Rawat Date: Mon, 28 Oct 2024 21:37:06 +0530 Subject: [PATCH 6/7] update isActive command. --- lib/transport/selenium-webdriver/method-mappings.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/transport/selenium-webdriver/method-mappings.js b/lib/transport/selenium-webdriver/method-mappings.js index 46f9d8f33..fe01424cf 100644 --- a/lib/transport/selenium-webdriver/method-mappings.js +++ b/lib/transport/selenium-webdriver/method-mappings.js @@ -518,13 +518,12 @@ module.exports = class MethodMappings { async isElementActive(webElementOrId) { const element = this.getWebElement(webElementOrId); + const id = await element.getId(); - const isActive = await this.driver.executeScript(` - const el = arguments[0]; - return el === document.activeElement; - `, element); + const webElement = await this.driver.switchTo().activeElement(); + const currentActiveElementId = await webElement.getId(); - return isActive; + return id === currentActiveElementId; }, async setElementProperty(webElementOrId, name, value) { From 82b30b6256649bd306989ce2eb1d6f1c00084248 Mon Sep 17 00:00:00 2001 From: Aniket Singh Rawat Date: Mon, 28 Oct 2024 21:41:45 +0530 Subject: [PATCH 7/7] remove getcomputed role and label. --- .../web-element/commands/getComputedLabel.js | 3 - .../web-element/commands/getComputedRole.js | 3 - .../selenium-webdriver/method-mappings.js | 23 ------- .../web-element/testGetComputedLabel.js | 61 ------------------- .../web-element/testGetComputedRole.js | 61 ------------------- types/web-element.d.ts | 4 -- 6 files changed, 155 deletions(-) delete mode 100644 lib/api/web-element/commands/getComputedLabel.js delete mode 100644 lib/api/web-element/commands/getComputedRole.js delete mode 100644 test/src/api/commands/web-element/testGetComputedLabel.js delete mode 100644 test/src/api/commands/web-element/testGetComputedRole.js diff --git a/lib/api/web-element/commands/getComputedLabel.js b/lib/api/web-element/commands/getComputedLabel.js deleted file mode 100644 index 65d3bf579..000000000 --- a/lib/api/web-element/commands/getComputedLabel.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports.command = function () { - return this.runQueuedCommandScoped('getElementComputedLabel'); -}; diff --git a/lib/api/web-element/commands/getComputedRole.js b/lib/api/web-element/commands/getComputedRole.js deleted file mode 100644 index 7a51f5e4e..000000000 --- a/lib/api/web-element/commands/getComputedRole.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports.command = function () { - return this.runQueuedCommandScoped('getElementComputedRole'); -}; diff --git a/lib/transport/selenium-webdriver/method-mappings.js b/lib/transport/selenium-webdriver/method-mappings.js index fe01424cf..b62153c19 100644 --- a/lib/transport/selenium-webdriver/method-mappings.js +++ b/lib/transport/selenium-webdriver/method-mappings.js @@ -493,29 +493,6 @@ module.exports = class MethodMappings { }; }, - - getElementComputedRole(webElementOrId) { - const promise = (async () => { - const id = await webElementOrId.getId(); - - return `/element/${id}/computedrole`; - })(); - promise.resolveEarly = true; - - return promise; - }, - - getElementComputedLabel(webElementOrId) { - const promise = (async () => { - const id = await webElementOrId.getId(); - - return `/element/${id}/computedlabel`; - })(); - promise.resolveEarly = true; - - return promise; - }, - async isElementActive(webElementOrId) { const element = this.getWebElement(webElementOrId); const id = await element.getId(); diff --git a/test/src/api/commands/web-element/testGetComputedLabel.js b/test/src/api/commands/web-element/testGetComputedLabel.js deleted file mode 100644 index c8dbc74bc..000000000 --- a/test/src/api/commands/web-element/testGetComputedLabel.js +++ /dev/null @@ -1,61 +0,0 @@ -const assert = require('assert'); -const {WebElement} = require('selenium-webdriver'); -const MockServer = require('../../../../lib/mockserver.js'); -const CommandGlobals = require('../../../../lib/globals/commands-w3c.js'); -const common = require('../../../../common.js'); -const Element = common.require('element/index.js'); - -describe('element().getComputedLabel() command', function() { - before(function (done) { - CommandGlobals.beforeEach.call(this, done); - - }); - - after(function (done) { - CommandGlobals.afterEach.call(this, done); - }); - - it('test .element().getComputedLabel() success', async function() { - MockServer.addMock({ - url: '/session/13521-10219-202/element/0/computedlabel', - method: 'GET', - response: JSON.stringify({ - value: 'signup' - }) - }); - - const resultPromise = this.client.api.element('#signupSection').getComputedLabel(); - assert.strictEqual(resultPromise instanceof Element, false); - assert.strictEqual(typeof resultPromise.find, 'undefined'); - - assert.strictEqual(resultPromise instanceof Promise, false); - assert.strictEqual(typeof resultPromise.then, 'function'); - - const result = await resultPromise; - assert.strictEqual(result instanceof WebElement, false); - assert.strictEqual(result, 'signup'); - - }); - - it('test .element().getComputedLabel() via find', async function() { - MockServer.addMock({ - url: '/session/13521-10219-202/element/1/computedlabel', - method: 'GET', - response: JSON.stringify({ - value: 'help' - }) - }); - - const resultPromise = this.client.api.element('#signupSection').find('#helpBtn').getComputedLabel(); - assert.strictEqual(resultPromise instanceof Element, false); - assert.strictEqual(typeof resultPromise.find, 'undefined'); - - assert.strictEqual(resultPromise instanceof Promise, false); - assert.strictEqual(typeof resultPromise.then, 'function'); - - const result = await resultPromise; - assert.strictEqual(result instanceof WebElement, false); - assert.strictEqual(result, 'help'); - - }); -}); \ No newline at end of file diff --git a/test/src/api/commands/web-element/testGetComputedRole.js b/test/src/api/commands/web-element/testGetComputedRole.js deleted file mode 100644 index 7fdb12c0e..000000000 --- a/test/src/api/commands/web-element/testGetComputedRole.js +++ /dev/null @@ -1,61 +0,0 @@ -const assert = require('assert'); -const {WebElement} = require('selenium-webdriver'); -const MockServer = require('../../../../lib/mockserver.js'); -const CommandGlobals = require('../../../../lib/globals/commands-w3c.js'); -const common = require('../../../../common.js'); -const Element = common.require('element/index.js'); - -describe('element().getComputedRole() command', function() { - before(function (done) { - CommandGlobals.beforeEach.call(this, done); - - }); - - after(function (done) { - CommandGlobals.afterEach.call(this, done); - }); - - it('test .element().getComputedRole() success', async function() { - MockServer.addMock({ - url: '/session/13521-10219-202/element/0/computedrole', - method: 'GET', - response: JSON.stringify({ - value: 'signup-heading' - }) - }); - - const resultPromise = this.client.api.element('#signupSection').getComputedRole(); - assert.strictEqual(resultPromise instanceof Element, false); - assert.strictEqual(typeof resultPromise.find, 'undefined'); - - assert.strictEqual(resultPromise instanceof Promise, false); - assert.strictEqual(typeof resultPromise.then, 'function'); - - const result = await resultPromise; - assert.strictEqual(result instanceof WebElement, false); - assert.strictEqual(result, 'signup-heading'); - - }); - - it('test .element().getComputedRole() via find', async function() { - MockServer.addMock({ - url: '/session/13521-10219-202/element/1/computedrole', - method: 'GET', - response: JSON.stringify({ - value: 'help-button' - }) - }); - - const resultPromise = this.client.api.element('#signupSection').find('#helpBtn').getComputedRole(); - assert.strictEqual(resultPromise instanceof Element, false); - assert.strictEqual(typeof resultPromise.find, 'undefined'); - - assert.strictEqual(resultPromise instanceof Promise, false); - assert.strictEqual(typeof resultPromise.then, 'function'); - - const result = await resultPromise; - assert.strictEqual(result instanceof WebElement, false); - assert.strictEqual(result, 'help-button'); - - }); -}); \ No newline at end of file diff --git a/types/web-element.d.ts b/types/web-element.d.ts index 86ae5dc29..09df750c0 100644 --- a/types/web-element.d.ts +++ b/types/web-element.d.ts @@ -218,10 +218,6 @@ export interface ScopedElement extends Element, PromiseLike { isDisplayed(): ElementValue; isActive(): ElementValue; - - getComputedLabel(): ElementValue; - - getComputedRole(): ElementValue; } type WaitUntilOptions = {