Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/javascript/atoms/locators/locators.js
2884 views
1
// Licensed to the Software Freedom Conservancy (SFC) under one
2
// or more contributor license agreements. See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership. The SFC licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License. You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied. See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
/**
19
* @fileoverview Element locator functions.
20
*/
21
22
23
goog.provide('bot.locators');
24
25
goog.require('bot');
26
goog.require('bot.locators.className');
27
goog.require('bot.locators.css');
28
goog.require('bot.locators.id');
29
goog.require('bot.locators.linkText');
30
goog.require('bot.locators.name');
31
goog.require('bot.locators.partialLinkText');
32
goog.require('bot.locators.relative');
33
goog.require('bot.locators.tagName');
34
goog.require('bot.locators.xpath');
35
36
37
/**
38
* @typedef {{single:function(string,!(Document|Element)):Element,
39
* many:function(string,!(Document|Element)):!IArrayLike}}
40
*/
41
bot.locators.strategy;
42
43
44
/**
45
* Known element location strategies. The returned objects have two
46
* methods on them, "single" and "many", for locating a single element
47
* or multiple elements, respectively.
48
*
49
* Note that the versions with spaces are synonyms for those without spaces,
50
* and are specified at:
51
* https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol
52
* @private {Object.<string,bot.locators.strategy>}
53
* @const
54
*/
55
bot.locators.STRATEGIES_ = {
56
'className': bot.locators.className,
57
'class name': bot.locators.className,
58
59
'css': bot.locators.css,
60
'css selector': bot.locators.css,
61
62
'relative': bot.locators.relative,
63
64
'id': bot.locators.id,
65
66
'linkText': bot.locators.linkText,
67
'link text': bot.locators.linkText,
68
69
'name': bot.locators.name,
70
71
'partialLinkText': bot.locators.partialLinkText,
72
'partial link text': bot.locators.partialLinkText,
73
74
'tagName': bot.locators.tagName,
75
'tag name': bot.locators.tagName,
76
77
'xpath': bot.locators.xpath
78
};
79
80
81
/**
82
* Add or override an existing strategy for locating elements.
83
*
84
* @param {string} name The name of the strategy.
85
* @param {!bot.locators.strategy} strategy The strategy to use.
86
*/
87
bot.locators.add = function (name, strategy) {
88
bot.locators.STRATEGIES_[name] = strategy;
89
};
90
91
92
/**
93
* Returns one key from the object map that is not present in the
94
* Object.prototype, if any exists.
95
*
96
* @param {Object} target The object to pick a key from.
97
* @return {?string} The key or null if the object is empty.
98
*/
99
bot.locators.getOnlyKey = function (target) {
100
for (var k in target) {
101
if (target.hasOwnProperty(k)) {
102
return k;
103
}
104
}
105
return null;
106
};
107
108
109
/**
110
* Find the first element in the DOM matching the target. The target
111
* object should have a single key, the name of which determines the
112
* locator strategy and the value of which gives the value to be
113
* searched for. For example {id: 'foo'} indicates that the first
114
* element on the DOM with the ID 'foo' should be returned.
115
*
116
* @param {!Object} target The selector to search for.
117
* @param {(Document|Element)=} opt_root The node from which to start the
118
* search. If not specified, will use `document` as the root.
119
* @return {Element} The first matching element found in the DOM, or null if no
120
* such element could be found.
121
*/
122
bot.locators.findElement = function (target, opt_root) {
123
var key = bot.locators.getOnlyKey(target);
124
125
if (key) {
126
var strategy = bot.locators.STRATEGIES_[key];
127
if (strategy && goog.isFunction(strategy.single)) {
128
var root = opt_root || bot.getDocument();
129
return strategy.single(target[key], root);
130
}
131
}
132
throw new bot.Error(bot.ErrorCode.INVALID_ARGUMENT,
133
'Unsupported locator strategy: ' + key);
134
};
135
136
137
/**
138
* Find all elements in the DOM matching the target. The target object
139
* should have a single key, the name of which determines the locator
140
* strategy and the value of which gives the value to be searched
141
* for. For example {name: 'foo'} indicates that all elements with the
142
* 'name' attribute equal to 'foo' should be returned.
143
*
144
* @param {!Object} target The selector to search for.
145
* @param {(Document|Element)=} opt_root The node from which to start the
146
* search. If not specified, will use `document` as the root.
147
* @return {!IArrayLike.<Element>} All matching elements found in the
148
* DOM.
149
*/
150
bot.locators.findElements = function (target, opt_root) {
151
var key = bot.locators.getOnlyKey(target);
152
153
if (key) {
154
var strategy = bot.locators.STRATEGIES_[key];
155
if (strategy && goog.isFunction(strategy.many)) {
156
var root = opt_root || bot.getDocument();
157
return strategy.many(target[key], root);
158
}
159
}
160
throw new bot.Error(bot.ErrorCode.INVALID_ARGUMENT,
161
'Unsupported locator strategy: ' + key);
162
};
163
164