Skip to content

Commit e5968b6

Browse files
[js] Add the ability to do Relative Locators with all By types
This also adds documentation for the new features. Fixes #9559
1 parent 8c217cf commit e5968b6

File tree

3 files changed

+53
-26
lines changed

3 files changed

+53
-26
lines changed

javascript/node/selenium-webdriver/lib/by.js

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,36 @@ class By {
258258
}
259259
}
260260

261+
/**
262+
* Start Searching for relative objects using the value returned from
263+
* `By.tagName()`.
264+
*
265+
* Note: this method will likely be removed in the future please use
266+
* `locateWith`.
267+
* @param {By} The value returned from calling By.tagName()
268+
* @returns
269+
*/
261270
function withTagName(tagName) {
262-
return new RelativeBy(tagName)
271+
return new RelativeBy({ 'css selector': tagName })
272+
}
273+
274+
/**
275+
* Start searching for relative objects using search criteria with By.
276+
* @param {string} A By map that shows how to find the initial element
277+
* @returns {RelativeBy}
278+
*/
279+
function locateWith(by) {
280+
return new RelativeBy(getLocator(by));
281+
}
282+
283+
function getLocator(locatorOrElement) {
284+
let toFind
285+
if (locatorOrElement instanceof By) {
286+
toFind = locatorOrElement.toObject()
287+
} else {
288+
toFind = locatorOrElement
289+
}
290+
return toFind
263291
}
264292

265293
/**
@@ -269,11 +297,11 @@ function withTagName(tagName) {
269297
*/
270298
class RelativeBy {
271299
/**
272-
* @param {string} tagName
300+
* @param {By} findDetails
273301
* @param {Array<Object>} filters
274302
*/
275-
constructor(tagName, filters = null) {
276-
this.root = tagName
303+
constructor(findDetails, filters = null) {
304+
this.root = findDetails
277305
this.filters = filters || []
278306
}
279307

@@ -285,7 +313,7 @@ class RelativeBy {
285313
above(locatorOrElement) {
286314
this.filters.push({
287315
kind: 'above',
288-
args: [this.getLocator(locatorOrElement)],
316+
args: [getLocator(locatorOrElement)],
289317
})
290318
return this
291319
}
@@ -298,7 +326,7 @@ class RelativeBy {
298326
below(locatorOrElement) {
299327
this.filters.push({
300328
kind: 'below',
301-
args: [this.getLocator(locatorOrElement)],
329+
args: [getLocator(locatorOrElement)],
302330
})
303331
return this
304332
}
@@ -311,7 +339,7 @@ class RelativeBy {
311339
toLeftOf(locatorOrElement) {
312340
this.filters.push({
313341
kind: 'left',
314-
args: [this.getLocator(locatorOrElement)],
342+
args: [getLocator(locatorOrElement)],
315343
})
316344
return this
317345
}
@@ -324,7 +352,7 @@ class RelativeBy {
324352
toRightOf(locatorOrElement) {
325353
this.filters.push({
326354
kind: 'right',
327-
args: [this.getLocator(locatorOrElement)],
355+
args: [getLocator(locatorOrElement)],
328356
})
329357
return this
330358
}
@@ -337,7 +365,7 @@ class RelativeBy {
337365
near(locatorOrElement) {
338366
this.filters.push({
339367
kind: 'near',
340-
args: [this.getLocator(locatorOrElement)],
368+
args: [getLocator(locatorOrElement)],
341369
})
342370
return this
343371
}
@@ -350,22 +378,12 @@ class RelativeBy {
350378
marshall() {
351379
return {
352380
relative: {
353-
root: { 'css selector': this.root },
381+
root: this.root,
354382
filters: this.filters,
355383
},
356384
}
357385
}
358386

359-
getLocator(locatorOrElement) {
360-
let toFind
361-
if (locatorOrElement instanceof By) {
362-
toFind = locatorOrElement.toObject()
363-
} else {
364-
toFind = locatorOrElement
365-
}
366-
return toFind
367-
}
368-
369387
/** @override */
370388
toString() {
371389
// The static By.name() overrides this.constructor.name. Shame...
@@ -411,5 +429,6 @@ module.exports = {
411429
By: By,
412430
RelativeBy: RelativeBy,
413431
withTagName: withTagName,
432+
locateWith: locateWith,
414433
checkedLocator: check,
415434
}

javascript/node/selenium-webdriver/test/element_finding_test.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const assert = require('assert')
2121
const promise = require('../lib/promise')
2222
const { Browser, By, error, withTagName, until } = require('..')
2323
const { Pages, ignore, suite, whereIs } = require('../lib/test')
24+
const { locateWith } = require('../lib/by')
2425

2526
suite(function (env) {
2627
const browsers = (...args) => env.browsers(...args)
@@ -61,7 +62,7 @@ suite(function (env) {
6162

6263
it(
6364
'should find multiple elements by ID even though that is ' +
64-
'malformed HTML',
65+
'malformed HTML',
6566
async function () {
6667
await driver.get(Pages.nestedPage)
6768

@@ -306,7 +307,7 @@ suite(function (env) {
306307

307308
it(
308309
'should find first matching element when searching by ' +
309-
'compound CSS selector',
310+
'compound CSS selector',
310311
async function () {
311312
await driver.get(Pages.xhtmlTestPage)
312313

@@ -349,7 +350,7 @@ suite(function (env) {
349350

350351
it(
351352
'should be able to find element with short ' +
352-
'boolean attribute selector',
353+
'boolean attribute selector',
353354
async function () {
354355
await driver.get(
355356
whereIs('locators_tests/boolean_attribute_selected.html')
@@ -362,7 +363,7 @@ suite(function (env) {
362363

363364
it(
364365
'should be able to find element with short boolean attribute ' +
365-
'selector on HTML4 page',
366+
'selector on HTML4 page',
366367
async function () {
367368
await driver.get(
368369
whereIs('locators_tests/boolean_attribute_selected_html4.html')
@@ -462,6 +463,12 @@ suite(function (env) {
462463
)
463464
assert.deepStrictEqual(await element.getAttribute('id'), `third`)
464465
})
466+
467+
it('should search by passing in a by object', async function () {
468+
await driver.get(Pages.relativeLocators)
469+
let element = await driver.findElement(locateWith(By.css('p')).above(await driver.findElement(By.id('below'))))
470+
assert.deepStrictEqual(await element.getAttribute('id'), 'mid')
471+
})
465472
})
466473

467474
describe('switchTo().activeElement()', function () {

javascript/node/selenium-webdriver/test/lib/by_test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ describe('by', function () {
8989

9090
describe('RelativeBy', function () {
9191
it('marshalls the RelativeBy object', function () {
92-
let relative = by.withTagName('p').above(by.By.name('foobar'))
92+
let relative = by.locateWith(by.By.tagName('p')).above(by.By.name('foobar'))
93+
9394
let expected = {
9495
relative: {
9596
root: { 'css selector': 'p' },
@@ -110,7 +111,7 @@ describe('by', function () {
110111
})
111112

112113
it('accepts custom locator functions', function () {
113-
let original = function () {}
114+
let original = function () { }
114115
let locator = by.checkedLocator(original)
115116
assert.strictEqual(locator, original)
116117
})

0 commit comments

Comments
 (0)