| /** |
| Copyright 2010 WebDriver committers |
| Copyright 2010 Google Inc. |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /** |
| * @fileoverview The selenium element locators. |
| */ |
| |
| goog.provide('core.LocatorStrategies'); |
| |
| goog.require('bot.inject.cache'); |
| goog.require('bot.locators'); |
| goog.require('core.Error'); |
| goog.require('core.filters'); |
| goog.require('goog.string'); |
| |
| |
| |
| /** |
| * The implicit locator, that is used when no prefix is supplied. |
| * |
| * @param {string} locator The value of the locator to use. |
| * @param {Document=} opt_doc The document to start the search from. |
| * @return {Element} The located element. |
| * @private |
| */ |
| core.LocatorStrategies.implicit_ = function(locator, opt_doc) { |
| if (goog.string.startsWith(locator, ('//'))) { |
| return core.LocatorStrategies.xpath_(locator, opt_doc); |
| } |
| if (goog.string.startsWith(locator, 'document.')) { |
| return core.LocatorStrategies.dom_(locator, opt_doc); |
| } |
| return core.LocatorStrategies.identifier_(locator, opt_doc); |
| }; |
| |
| |
| /** |
| * Find an element by the value of the 'alt' attribute. |
| * |
| * @param {string} locator The value of the locator to use. |
| * @param {Document=} opt_doc The document to start the search from. |
| * @return {Element} The located element. |
| * @private |
| */ |
| core.LocatorStrategies.alt_ = function(locator, opt_doc) { |
| var doc = opt_doc || goog.dom.getOwnerDocument(bot.getWindow()); |
| |
| return core.locators.elementFindFirstMatchingChild(doc, |
| function(element) { |
| return element['alt'] == locator; |
| }); |
| }; |
| |
| |
| /** |
| * Find an element by the value of the 'class' attribute. |
| * |
| * @param {string} locator The value of the locator to use. |
| * @param {Document=} opt_doc The document to start the search from.. |
| * @return {Element} The located element. |
| * @private |
| */ |
| core.LocatorStrategies.class_ = function(locator, opt_doc) { |
| var doc = opt_doc || goog.dom.getOwnerDocument(bot.getWindow()); |
| |
| return core.locators.elementFindFirstMatchingChild(doc, |
| function(element) { |
| return element.className == locator; |
| }); |
| }; |
| |
| |
| /** |
| * Find an element by evaluating a Javascript expression. |
| * |
| * @param {string} locator The value of the locator to use. |
| * @param {Document=} opt_doc The document to start the search from. |
| * @return {Element} The located element. |
| * @private |
| */ |
| core.LocatorStrategies.dom_ = function(locator, opt_doc) { |
| var element = null; |
| try { |
| element = eval(locator); |
| } catch (e) { |
| return null; |
| } |
| |
| return element ? (/**@type{Element}*/ element) : null; |
| }; |
| |
| |
| /** |
| * Find an element using by the value of its "id" attribute. |
| * |
| * @param {string} locator The value of the locator to use. |
| * @param {Document=} opt_doc The document to start the search from. |
| * @return {Element} The located element. |
| * @private |
| */ |
| core.LocatorStrategies.id_ = function(locator, opt_doc) { |
| return bot.locators.findElement({'id': locator}, opt_doc); |
| }; |
| |
| |
| /** |
| * Find an element by the value of its "id" or "name" attribute. |
| * |
| * @param {string} locator The value of the locator to use. |
| * @param {Document=} opt_doc The document to start the search from. |
| * @return {Element} The located element. |
| * @private |
| */ |
| core.LocatorStrategies.identifier_ = function(locator, opt_doc) { |
| return core.LocatorStrategies['id'](locator, opt_doc) || |
| core.LocatorStrategies['name'](locator, opt_doc); |
| }; |
| |
| |
| /** |
| * Find an element by the value of its "name" attribute. |
| * |
| * @param {string} locator The value of the locator to use. |
| * @param {Document=} opt_doc The document to start the search from. |
| * @return {Element} The located element. |
| * @private |
| */ |
| core.LocatorStrategies.name_ = function(locator, opt_doc) { |
| var doc = opt_doc || goog.dom.getOwnerDocument(bot.getWindow()); |
| var dom = goog.dom.getDomHelper(doc); |
| |
| var elements = goog.dom.getElementsByTagNameAndClass('*', null, doc); |
| |
| var filters = locator.split(' '); |
| filters[0] = 'name=' + filters[0]; |
| |
| while (filters.length) { |
| var filter = filters.shift(); |
| elements = core.filters.selectElements(filter, elements, 'value'); |
| } |
| |
| return elements.length > 0 ? elements[0] : null; |
| }; |
| |
| |
| /** |
| * Find an element by the value of an opaque key. |
| * |
| * @param {string} locator The value of the locator to use. |
| * @param {Document=} opt_doc The document to start the search from. |
| * @return {Element} The located element. |
| * @private |
| */ |
| core.LocatorStrategies.stored_ = function(locator, opt_doc) { |
| try { |
| return /** @type {!Element}*/bot.inject.cache.getElement(locator, opt_doc); |
| } catch (e) { |
| return null; |
| } |
| }; |
| |
| |
| /** |
| * Find an element using xpath. |
| * |
| * @param {string} locator The value of the locator to use. |
| * @param {Document=} opt_doc The document to start the search from. |
| * @return {Element} The located element. |
| * @private |
| */ |
| core.LocatorStrategies.xpath_ = function(locator, opt_doc) { |
| var trailingSlash = goog.string.endsWith(locator, '/'); |
| var selector = {'xpath': locator}; |
| |
| try { |
| var element = bot.locators.findElement(selector, opt_doc); |
| if (element || !trailingSlash) { |
| return element; |
| } |
| } catch (e) { |
| if (!trailingSlash) { |
| throw e; |
| } |
| |
| // The exception from the xpath engine *may* have been because of |
| // the trailing slash. If there was a trailing slash, fall through. |
| } |
| |
| selector = {'xpath': locator.substring(0, locator.length - 1)}; |
| return bot.locators.findElement(selector, opt_doc); |
| }; |
| |
| |
| /** |
| * Selenium Core location strategies. |
| * |
| * @const |
| * @type {Object.<string, function(string):function(string, Document=):Element>} |
| */ |
| core.LocatorStrategies['alt'] = core.LocatorStrategies.alt_; |
| core.LocatorStrategies['class'] = core.LocatorStrategies.class_; |
| core.LocatorStrategies['dom'] = core.LocatorStrategies.dom_; |
| core.LocatorStrategies['id'] = core.LocatorStrategies.id_; |
| core.LocatorStrategies['identifier'] = core.LocatorStrategies.identifier_; |
| core.LocatorStrategies['implicit'] = core.LocatorStrategies.implicit_; |
| core.LocatorStrategies['name'] = core.LocatorStrategies.name_; |
| core.LocatorStrategies['stored'] = core.LocatorStrategies.stored_; |
| core.LocatorStrategies['xpath'] = core.LocatorStrategies.xpath_; |