/** * * Search for multiple elements on the page, starting from the document root. The located * elements will be returned as a WebElement JSON objects. The table below lists the * locator strategies that each server should support. Elements should be returned in * the order located in the DOM. * * The array of elements can be retrieved using the 'response.value' which is a * collection of element ID's and can be accessed in the subsequent commands * using the '.ELEMENT' method. * * @param {String} selector selector to query the elements * @return {Object[]} A list of WebElement JSON objects for the located elements. * * @see https://w3c.github.io/webdriver/webdriver-spec.html#find-elements * @type protocol * */ import q from 'q' import findStrategy from '../helpers/findElementStrategy' import hasElementResult from '../helpers/hasElementResultHelper' import { CommandError } from '../utils/ErrorHandler' let elements = function (selector) { let requestPath = '/session/:sessionId/elements' let lastPromise = this.lastResult ? q(this.lastResult).inspect() : this.lastPromise.inspect() let relative = false const elementResult = hasElementResult(lastPromise.value) if (lastPromise.state === 'fulfilled' && elementResult) { if (!selector) { let newSelector = Object.assign({}, lastPromise.value) /** * if last result was an element result transform result into an array */ newSelector.value = Array.isArray(newSelector.value) ? newSelector.value : newSelector.value !== null ? [newSelector.value] : [] /** * Only return new selector if existing otherwise fetch again for selector. * This is important in cases you do a waitForExist and use the same element * variable again after the element has appeared. */ if (newSelector.value.length === 0) { this.lastResult = null return elements.call(this, newSelector.selector) } return newSelector } /** * only run elementIdElement if lastPromise was an element command */ if (elementResult === 1) { if (lastPromise.value.value === null) { throw new CommandError(7, lastPromise.value.selector) } /** * format xpath selector (global -> relative) */ if (selector.slice(0, 2) === '//') { selector = '.' + selector.slice(1) } var elem = lastPromise.value.value.ELEMENT relative = true requestPath = `/session/:sessionId/element/${elem}/elements` } } let found = findStrategy(selector, relative) return this.requestHandler.create(requestPath, { using: found.using, value: found.value }).then((result) => { result.selector = selector /** * W3C webdriver protocol has changed element identifier from `ELEMENT` to * `element-6066-11e4-a52e-4f735466cecf`. Let's make sure both identifier * are supported. */ result.value = result.value.map((elem) => { const elemValue = elem.ELEMENT || elem['element-6066-11e4-a52e-4f735466cecf'] return { ELEMENT: elemValue, 'element-6066-11e4-a52e-4f735466cecf': elemValue } }) return result }, (err) => { if (err.message === 'no such element') { return [] } throw err }) } export default elements