blob: 49d23005f0c951442a477b6326246b8419fbcbee [file] [log] [blame] [edit]
/**
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_;