blob: 172c79e1c33e40a37848e8850a915a15e813ca00 [file] [log] [blame]
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you 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.filters');
goog.require('core.text');
goog.require('goog.dom');
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['link'] = core.text.linkLocator;
core.LocatorStrategies['name'] = core.LocatorStrategies.name_;
core.LocatorStrategies['stored'] = core.LocatorStrategies.stored_;
core.LocatorStrategies['xpath'] = core.LocatorStrategies.xpath_;