selenium-webdriver 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
- data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
- data/chrome/src/extension/background.html +9 -0
- data/chrome/src/extension/background.js +933 -0
- data/chrome/src/extension/content_script.js +1286 -0
- data/chrome/src/extension/manifest-nonwin.json +15 -0
- data/chrome/src/extension/manifest-win.json +16 -0
- data/chrome/src/extension/toolstrip.html +28 -0
- data/chrome/src/extension/utils.js +196 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +8 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +324 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +70 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +119 -0
- data/common/src/js/abstractcommandprocessor.js +161 -0
- data/common/src/js/asserts.js +296 -0
- data/common/src/js/by.js +147 -0
- data/common/src/js/command.js +274 -0
- data/common/src/js/context.js +58 -0
- data/common/src/js/extension/README +2 -0
- data/common/src/js/extension/dommessenger.js +152 -0
- data/common/src/js/factory.js +55 -0
- data/common/src/js/future.js +118 -0
- data/common/src/js/key.js +117 -0
- data/common/src/js/localcommandprocessor.js +181 -0
- data/common/src/js/logging.js +249 -0
- data/common/src/js/testrunner.js +605 -0
- data/common/src/js/timing.js +89 -0
- data/common/src/js/wait.js +199 -0
- data/common/src/js/webdriver.js +853 -0
- data/common/src/js/webelement.js +683 -0
- data/common/src/rb/lib/selenium-webdriver.rb +1 -0
- data/common/src/rb/lib/selenium/webdriver.rb +52 -0
- data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +88 -0
- data/common/src/rb/lib/selenium/webdriver/child_process.rb +85 -0
- data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +41 -0
- data/common/src/rb/lib/selenium/webdriver/driver.rb +128 -0
- data/common/src/rb/lib/selenium/webdriver/element.rb +126 -0
- data/common/src/rb/lib/selenium/webdriver/error.rb +68 -0
- data/common/src/rb/lib/selenium/webdriver/find.rb +69 -0
- data/common/src/rb/lib/selenium/webdriver/navigation.rb +23 -0
- data/common/src/rb/lib/selenium/webdriver/options.rb +50 -0
- data/common/src/rb/lib/selenium/webdriver/platform.rb +82 -0
- data/common/src/rb/lib/selenium/webdriver/target_locator.rb +23 -0
- data/firefox/prebuilt/nsICommandProcessor.xpt +0 -0
- data/firefox/prebuilt/nsINativeEvents.xpt +0 -0
- data/firefox/prebuilt/nsIResponseHandler.xpt +0 -0
- data/firefox/src/extension/chrome.manifest +3 -0
- data/firefox/src/extension/components/context.js +37 -0
- data/firefox/src/extension/components/driver-component.js +127 -0
- data/firefox/src/extension/components/firefoxDriver.js +706 -0
- data/firefox/src/extension/components/json2.js +273 -0
- data/firefox/src/extension/components/keytest.html +554 -0
- data/firefox/src/extension/components/nsCommandProcessor.js +586 -0
- data/firefox/src/extension/components/screenshooter.js +70 -0
- data/firefox/src/extension/components/socketListener.js +185 -0
- data/firefox/src/extension/components/utils.js +1200 -0
- data/firefox/src/extension/components/webLoadingListener.js +57 -0
- data/firefox/src/extension/components/webdriverserver.js +101 -0
- data/firefox/src/extension/components/wrappedElement.js +609 -0
- data/firefox/src/extension/content/fxdriver.xul +30 -0
- data/firefox/src/extension/content/server.js +95 -0
- data/firefox/src/extension/idl/nsICommandProcessor.idl +38 -0
- data/firefox/src/extension/idl/nsIResponseHandler.idl +34 -0
- data/firefox/src/extension/install.rdf +29 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +21 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +86 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +426 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +82 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +132 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +174 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +60 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +23 -0
- data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
- data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +14 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +552 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +94 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +147 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +16 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +374 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/capabilities.rb +105 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +53 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +71 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +43 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +32 -0
- metadata +182 -0
|
@@ -0,0 +1,683 @@
|
|
|
1
|
+
/** @license
|
|
2
|
+
Copyright 2007-2009 WebDriver committers
|
|
3
|
+
Copyright 2007-2009 Google Inc.
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
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, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @fileoverview A class for working with elements on the page under test.
|
|
20
|
+
* @author jmleyba@gmail.com (Jason Leyba)
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
goog.provide('webdriver.WebElement');
|
|
24
|
+
|
|
25
|
+
goog.require('goog.array');
|
|
26
|
+
goog.require('goog.math.Coordinate');
|
|
27
|
+
goog.require('goog.math.Size');
|
|
28
|
+
goog.require('webdriver.By.Locator');
|
|
29
|
+
goog.require('webdriver.By.Strategy');
|
|
30
|
+
goog.require('webdriver.Command');
|
|
31
|
+
goog.require('webdriver.CommandName');
|
|
32
|
+
goog.require('webdriver.Future');
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Represents a DOM element. WebElements can be found by searching from the
|
|
37
|
+
* document root using a {@code webdriver.WebDriver}, or by searhcing under
|
|
38
|
+
* another {@code webdriver.WebElement}:
|
|
39
|
+
*
|
|
40
|
+
* driver.get('http://www.google.com');
|
|
41
|
+
* var searchForm = driver.findElement({tagName: 'form'});
|
|
42
|
+
* var searchBox = searchForm.findElement({name: 'q'});
|
|
43
|
+
* searchBox.sendKeys('webdriver');
|
|
44
|
+
*
|
|
45
|
+
* @param {webdriver.WebDriver} driver The WebDriver instance that will
|
|
46
|
+
* actually execute commands.
|
|
47
|
+
* @constructor
|
|
48
|
+
*/
|
|
49
|
+
webdriver.WebElement = function(driver) {
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The WebDriver instance to issue commands to.
|
|
53
|
+
* @type {webdriver.WebDriver}
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
56
|
+
this.driver_ = driver;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The UUID used by WebDriver to identify this element on the page. The ID is
|
|
60
|
+
* wrapped in a webdriver.Future instance so it can be determined
|
|
61
|
+
* asynchronously.
|
|
62
|
+
* @type {webdriver.Future}
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
this.elementId_ = new webdriver.Future(this.driver_);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Regular expression for a UUID.
|
|
71
|
+
* @type {RegExp}
|
|
72
|
+
* @static
|
|
73
|
+
*/
|
|
74
|
+
webdriver.WebElement.UUID_REGEX =
|
|
75
|
+
/^{[\da-z]{8}-[\da-z]{4}-[\da-z]{4}-[\da-z]{4}-[\da-z]{12}}$/i;
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Adds a command to the given {@code webdriver.WebDriver} instance to find an
|
|
80
|
+
* element on the page.
|
|
81
|
+
* @param {webdriver.WebDriver} driver The driver to perform the search with.
|
|
82
|
+
* @param {webdriver.By.Locator|{*: string}} locator The locator to use for
|
|
83
|
+
* finding the element, or a short-hand object that can be converted into a
|
|
84
|
+
* locator.
|
|
85
|
+
* @return {webdriver.WebElement} A WebElement that can be used to issue
|
|
86
|
+
* commands on the found element. The element's ID will be set
|
|
87
|
+
* asynchronously once the driver successfully finds the element.
|
|
88
|
+
* @see webdriver.By.Locator.createFromObj
|
|
89
|
+
*/
|
|
90
|
+
webdriver.WebElement.findElement = function(driver, locator) {
|
|
91
|
+
var webElement = new webdriver.WebElement(driver);
|
|
92
|
+
locator = webdriver.By.Locator.checkLocator(locator);
|
|
93
|
+
var command = new webdriver.Command(webdriver.CommandName.FIND_ELEMENT).
|
|
94
|
+
setParameters(locator.type, locator.target).
|
|
95
|
+
setSuccessCallback(function(response) {
|
|
96
|
+
webElement.getId().setValue(response.value);
|
|
97
|
+
});
|
|
98
|
+
driver.addCommand(command);
|
|
99
|
+
return webElement;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Adds a command to the given {@code webdriver.WebDriver} instance to test if
|
|
105
|
+
* an element is present on the page.
|
|
106
|
+
* @param {webdriver.WebDriver} driver The driver to perform the search with.
|
|
107
|
+
* @param {webdriver.By.Locator|{*: string}} locator The locator to use for
|
|
108
|
+
* finding the element, or a short-hand object that can be converted into a
|
|
109
|
+
* locator.
|
|
110
|
+
* @return {webdriver.Future} A future whose value will be set when the driver
|
|
111
|
+
* completes the search; value will be {@code true} if the element was
|
|
112
|
+
* found, false otherwise.
|
|
113
|
+
* @see webdriver.By.Locator.createFromObj
|
|
114
|
+
*/
|
|
115
|
+
webdriver.WebElement.isElementPresent = function(driver, locator) {
|
|
116
|
+
var isPresent = new webdriver.Future(driver);
|
|
117
|
+
var callback = function(response) {
|
|
118
|
+
// If returns without an error, element is present.
|
|
119
|
+
isPresent.setValue(response.value = !response.isFailure);
|
|
120
|
+
// Go ahead and clear the error.
|
|
121
|
+
response.isFailure = false;
|
|
122
|
+
};
|
|
123
|
+
locator = webdriver.By.Locator.checkLocator(locator);
|
|
124
|
+
var command = new webdriver.Command(webdriver.CommandName.FIND_ELEMENT).
|
|
125
|
+
setParameters(locator.type, locator.target).
|
|
126
|
+
setSuccessCallback(callback).
|
|
127
|
+
setFailureCallback(callback);
|
|
128
|
+
driver.addCommand(command);
|
|
129
|
+
return isPresent;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Adds a command to the given {@code webdriver.WebDriver} instance to find
|
|
135
|
+
* multiple elements on the page.
|
|
136
|
+
* @param {webdriver.WebDriver} driver The driver to perform the search with.
|
|
137
|
+
* @param {webdriver.By.Locator|{*: string}} locator The locator to use for
|
|
138
|
+
* finding the element, or a short-hand object that can be converted into a
|
|
139
|
+
* locator.
|
|
140
|
+
* @see webdriver.By.Locator.createFromObj
|
|
141
|
+
*/
|
|
142
|
+
webdriver.WebElement.findElements = function(driver, locator) {
|
|
143
|
+
locator = webdriver.By.Locator.checkLocator(locator);
|
|
144
|
+
var command = new webdriver.Command(webdriver.CommandName.FIND_ELEMENTS).
|
|
145
|
+
setParameters(locator.type, locator.target).
|
|
146
|
+
setSuccessCallback(function(response) {
|
|
147
|
+
var ids = response.value.split(',');
|
|
148
|
+
var elements = [];
|
|
149
|
+
for (var i = 0, id; id = ids[i]; i++) {
|
|
150
|
+
if (id) {
|
|
151
|
+
var element = new webdriver.WebElement(driver);
|
|
152
|
+
element.getId().setValue(id);
|
|
153
|
+
elements.push(element);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
response.value = elements;
|
|
157
|
+
});
|
|
158
|
+
driver.addCommand(command);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Adds a command to determine if an element is present under this element in
|
|
164
|
+
* the DOM tree.
|
|
165
|
+
* @param {webdriver.By.Locator|{*: string}} locator The locator to use for
|
|
166
|
+
* finding the element, or a short-hand object that can be converted into a
|
|
167
|
+
* locator.
|
|
168
|
+
* @return {webdriver.Future} A future whose value will be set when the driver
|
|
169
|
+
* completes the search; value will be {@code true} if the element was
|
|
170
|
+
* found, false otherwise.
|
|
171
|
+
* @see webdriver.By.Locator.createFromObj
|
|
172
|
+
*/
|
|
173
|
+
webdriver.WebElement.prototype.isElementPresent = function(locator) {
|
|
174
|
+
var isPresent = new webdriver.Future(this.driver_);
|
|
175
|
+
var callback = function(response) {
|
|
176
|
+
// If returns without an error, element is present.
|
|
177
|
+
isPresent.setValue(response.value = !response.isFailure);
|
|
178
|
+
// Go ahead and clear the error (if any).
|
|
179
|
+
response.isFailure = false;
|
|
180
|
+
};
|
|
181
|
+
locator = webdriver.By.Locator.checkLocator(locator);
|
|
182
|
+
var command = new webdriver.Command(webdriver.CommandName.FIND_CHILD_ELEMENT).
|
|
183
|
+
setParameters({
|
|
184
|
+
'id': this.getId(),
|
|
185
|
+
'using': locator.type,
|
|
186
|
+
'value': locator.target
|
|
187
|
+
}).
|
|
188
|
+
setSuccessCallback(callback).
|
|
189
|
+
setFailureCallback(callback);
|
|
190
|
+
this.driver_.addCommand(command);
|
|
191
|
+
return isPresent;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Adds a command to search for a single element on the page, restricting the
|
|
197
|
+
* search to the descendants of the element represented by this instance.
|
|
198
|
+
* @param {webdriver.By.Locator|{*: string}} locator The locator to use for
|
|
199
|
+
* finding the element, or a short-hand object that can be converted into a
|
|
200
|
+
* locator.
|
|
201
|
+
* @return {webdriver.WebElement} A WebElement that can be used to issue
|
|
202
|
+
* commands on the found element. The element's ID will be set
|
|
203
|
+
* asynchronously once the element is successfully located.
|
|
204
|
+
* @see webdriver.By.Locator.createFromObj
|
|
205
|
+
*/
|
|
206
|
+
webdriver.WebElement.prototype.findElement = function(locator) {
|
|
207
|
+
var webElement = new webdriver.WebElement(this.driver_);
|
|
208
|
+
locator = webdriver.By.Locator.checkLocator(locator);
|
|
209
|
+
var command = new webdriver.Command(webdriver.CommandName.FIND_CHILD_ELEMENT).
|
|
210
|
+
setParameters({
|
|
211
|
+
'id': this.getId(),
|
|
212
|
+
'using': locator.type,
|
|
213
|
+
'value': locator.target
|
|
214
|
+
}).
|
|
215
|
+
setSuccessCallback(function(response) {
|
|
216
|
+
webElement.getId().setValue(response.value);
|
|
217
|
+
});
|
|
218
|
+
this.driver_.addCommand(command);
|
|
219
|
+
return webElement;
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Adds a command to search for multiple elements on the page, restricting the
|
|
225
|
+
* search to the descendants of hte element represented by this instance.
|
|
226
|
+
* @param {webdriver.By.Locator|{*: string}} locator The locator to use for
|
|
227
|
+
* finding the element, or a short-hand object that can be converted into a
|
|
228
|
+
* locator.
|
|
229
|
+
* @see webdriver.By.Locator.createFromObj
|
|
230
|
+
*/
|
|
231
|
+
webdriver.WebElement.prototype.findElements = function(locator) {
|
|
232
|
+
locator = webdriver.By.Locator.checkLocator(locator);
|
|
233
|
+
var command =
|
|
234
|
+
new webdriver.Command(webdriver.CommandName.FIND_CHILD_ELEMENTS).
|
|
235
|
+
setParameters({
|
|
236
|
+
'id': this.getId(),
|
|
237
|
+
'using': locator.type,
|
|
238
|
+
'value': locator.target
|
|
239
|
+
}).
|
|
240
|
+
setSuccessCallback(function(response) {
|
|
241
|
+
var ids = response.value.split(',');
|
|
242
|
+
var elements = [];
|
|
243
|
+
for (var i = 0, id; id = ids[i]; i++) {
|
|
244
|
+
if (id) {
|
|
245
|
+
var element = new webdriver.WebElement(this.driver_);
|
|
246
|
+
element.getId().setValue(id);
|
|
247
|
+
elements.push(element);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
response.value = elements;
|
|
251
|
+
}, this);
|
|
252
|
+
this.driver_.addCommand(command);
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* @return {webdriver.WebDriver} The driver that this element delegates commands
|
|
258
|
+
* to.
|
|
259
|
+
*/
|
|
260
|
+
webdriver.WebElement.prototype.getDriver = function() {
|
|
261
|
+
return this.driver_;
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @return {webdriver.Futur} The UUID of this element wrapped in a Future.
|
|
267
|
+
*/
|
|
268
|
+
webdriver.WebElement.prototype.getId = function() {
|
|
269
|
+
return this.elementId_;
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Creates a new {@code webdriver.Command} against the element represented by
|
|
275
|
+
* this instance.
|
|
276
|
+
* @param {string} name The name of the command to create.
|
|
277
|
+
* @return {webdriver.Command} The new command.
|
|
278
|
+
* @private
|
|
279
|
+
*/
|
|
280
|
+
webdriver.WebElement.prototype.createCommand_ = function(name) {
|
|
281
|
+
return new webdriver.Command(name, this);
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Adds a command to click on this element.
|
|
287
|
+
*/
|
|
288
|
+
webdriver.WebElement.prototype.click = function() {
|
|
289
|
+
var command = this.createCommand_(webdriver.CommandName.CLICK);
|
|
290
|
+
this.driver_.addCommand(command);
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Types a sequence on the DOM element represented by this instance.
|
|
296
|
+
* <p/>
|
|
297
|
+
* Modifier keys (SHIFT, CONTROL, ALT, META) are stateful; once a modifier is
|
|
298
|
+
* processed in the keysequence, that key state is toggled until one of the
|
|
299
|
+
* following occurs:
|
|
300
|
+
* <ul>
|
|
301
|
+
* <li>The modifier key is encountered again in the sequence. At this point the
|
|
302
|
+
* state of the key is toggled (along with the appropriate keyup/down events).
|
|
303
|
+
* </li>
|
|
304
|
+
* <li>The {@code webdriver.Key.NULL} key is encountered in the sequence. When
|
|
305
|
+
* this key is encountered, all modifier keys current in the down state are
|
|
306
|
+
* released (with accompanying keyup events). The NULL key can be used to
|
|
307
|
+
* simulate common keyboard shortcuts:
|
|
308
|
+
* <code>
|
|
309
|
+
* element.sendKeys("text was",
|
|
310
|
+
* webdriver.Key.CONTROL, "a", webdriver.Key.NULL,
|
|
311
|
+
* "now text is");
|
|
312
|
+
* // Alternatively:
|
|
313
|
+
* element.sendKeys("text was",
|
|
314
|
+
* webdriver.Key.chord(webdriver.Key.CONTROL, "a"),
|
|
315
|
+
* "now text is");
|
|
316
|
+
* </code></li>
|
|
317
|
+
* <li>The end of the keysequence is encountered. When there are no more keys
|
|
318
|
+
* to type, all depressed modifier keys are released (with accompanying keyup
|
|
319
|
+
* events).
|
|
320
|
+
* </li>
|
|
321
|
+
* </ul>
|
|
322
|
+
* If a certain character can only be generated by using the shift key, such as
|
|
323
|
+
* uppercase characters or certain punctuation marks, the shift key will be
|
|
324
|
+
* applied for that individual key. If the shift key was not depressed before
|
|
325
|
+
* typing that key, it will be released after typing the key. If the shift key
|
|
326
|
+
* was already depressed, the extra event will not be generated. For example:
|
|
327
|
+
* <code>
|
|
328
|
+
* // Expect shift down/up for each character.
|
|
329
|
+
* element.sendKeys("ABC");
|
|
330
|
+
* // Shift is already depressed, so it will not be pushed again for each
|
|
331
|
+
* // character.
|
|
332
|
+
* element.sendKeys(webdriver.Key.SHIFT, "ABC");
|
|
333
|
+
* </code>
|
|
334
|
+
* <p/>
|
|
335
|
+
* <strong>Note:</strong> On browsers where native keyboard events are not yet
|
|
336
|
+
* supported (e.g. Firefox on OS X), key events will be synthesized. Special
|
|
337
|
+
* punctionation keys will be synthesized according to a standard QWERTY English
|
|
338
|
+
* keyboard layout.
|
|
339
|
+
* @param {string|webdriver.Future} var_args The strings to type. All arguments
|
|
340
|
+
* will be joined into a single sequence (var_args is permitted for
|
|
341
|
+
* convenience).
|
|
342
|
+
*/
|
|
343
|
+
webdriver.WebElement.prototype.sendKeys = function(var_args) {
|
|
344
|
+
var command = this.createCommand_(webdriver.CommandName.SEND_KEYS);
|
|
345
|
+
command.setParameters.apply(command, arguments);
|
|
346
|
+
this.driver_.addCommand(command);
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Queries for the tag/node name of this element.
|
|
351
|
+
*/
|
|
352
|
+
webdriver.WebElement.prototype.getTagName = function() {
|
|
353
|
+
var name = new webdriver.Future(this.driver_);
|
|
354
|
+
var command = this.createCommand_(webdriver.CommandName.GET_TAG_NAME).
|
|
355
|
+
setSuccessCallback(name.setValueFromResponse, name);
|
|
356
|
+
this.driver_.addCommand(command);
|
|
357
|
+
return name;
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Queries for the computed style of the element represented by this instance.
|
|
363
|
+
* If the element inherits the named style from its parent, the parent will be
|
|
364
|
+
* queried for its value. Where possible, color values will be converted to
|
|
365
|
+
* their hex representation (#00ff00 instead of rgb(0, 255, 0)).
|
|
366
|
+
* <em>Warning:</em> the value returned will be as the browser interprets it, so
|
|
367
|
+
* it may be tricky to form a proper assertion.
|
|
368
|
+
* @param {string} cssStyleProperty The name of the CSS style property to look
|
|
369
|
+
* up.
|
|
370
|
+
* @return {webdriver.Future<string>} The computed style property wrapped in a
|
|
371
|
+
* Future.
|
|
372
|
+
*/
|
|
373
|
+
webdriver.WebElement.prototype.getComputedStyle = function(cssStyleProperty) {
|
|
374
|
+
var value = new webdriver.Future(this.driver_);
|
|
375
|
+
var command = this.createCommand_(webdriver.CommandName.GET_VALUE_OF_CSS_PROPERTY).
|
|
376
|
+
setParameters(cssStyleProperty).
|
|
377
|
+
setSuccessCallback(value.setValueFromResponse, value);
|
|
378
|
+
this.driver_.addCommand(command);
|
|
379
|
+
return value;
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Queries for the specified attribute.
|
|
385
|
+
* @param {string} attributeName The name of the attribute to query.
|
|
386
|
+
*/
|
|
387
|
+
webdriver.WebElement.prototype.getAttribute = function(attributeName) {
|
|
388
|
+
var value = new webdriver.Future(this.driver_);
|
|
389
|
+
var command = this.createCommand_(webdriver.CommandName.GET_ATTRIBUTE).
|
|
390
|
+
setParameters(attributeName).
|
|
391
|
+
setSuccessCallback(value.setValueFromResponse, value).
|
|
392
|
+
// If there is an error b/c the attribute was not found, set value to null
|
|
393
|
+
setFailureCallback(function(response) {
|
|
394
|
+
// TODO(jmleyba): This error message needs to be consistent for all
|
|
395
|
+
// drivers.
|
|
396
|
+
if (response.value == 'No match') {
|
|
397
|
+
response.isFailure = false;
|
|
398
|
+
response.value = null;
|
|
399
|
+
value.setValue(null);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
this.driver_.addCommand(command);
|
|
403
|
+
return value;
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* @return {webdriver.Future} The value attribute for the element represented by
|
|
409
|
+
* this instance.
|
|
410
|
+
*/
|
|
411
|
+
webdriver.WebElement.prototype.getValue = function() {
|
|
412
|
+
var value = new webdriver.Future(this.driver_);
|
|
413
|
+
var command = this.createCommand_(webdriver.CommandName.GET_VALUE).
|
|
414
|
+
setSuccessCallback(value.setValueFromResponse, value);
|
|
415
|
+
this.driver_.addCommand(command);
|
|
416
|
+
return value;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* @return {webdriver.Future} The innerText of this element, without any leading
|
|
422
|
+
* or trailing whitespace.
|
|
423
|
+
*/
|
|
424
|
+
webdriver.WebElement.prototype.getText = function() {
|
|
425
|
+
var text = new webdriver.Future(this.driver_);
|
|
426
|
+
var command = this.createCommand_(webdriver.CommandName.GET_TEXT).
|
|
427
|
+
setSuccessCallback(text.setValueFromResponse, text);
|
|
428
|
+
this.driver_.addCommand(command);
|
|
429
|
+
return text;
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Selects this element.
|
|
435
|
+
*/
|
|
436
|
+
webdriver.WebElement.prototype.setSelected = function() {
|
|
437
|
+
var command = this.createCommand_(webdriver.CommandName.SET_SELECTED);
|
|
438
|
+
this.driver_.addCommand(command);
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @return {webdriver.Future} The size of this element.
|
|
444
|
+
*/
|
|
445
|
+
webdriver.WebElement.prototype.getSize = function() {
|
|
446
|
+
var size = new webdriver.Future(this.driver_);
|
|
447
|
+
var command = this.createCommand_(webdriver.CommandName.GET_SIZE).
|
|
448
|
+
setSuccessCallback(function(response) {
|
|
449
|
+
var wh = response.value.replace(/\s/g, '').split(',');
|
|
450
|
+
response.value = new goog.math.Size(wh[0], wh[1]);
|
|
451
|
+
size.setValue(response.value);
|
|
452
|
+
});
|
|
453
|
+
this.driver_.addCommand(command);
|
|
454
|
+
return size;
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Parses a response of the form "$x $y" into a {@code goog.math.Coordinate}
|
|
460
|
+
* object.
|
|
461
|
+
* @param {webdriver.Future} future The Future to store the parsed result in.
|
|
462
|
+
* @param {webdriver.Response} response The response to parse.
|
|
463
|
+
* @private
|
|
464
|
+
*/
|
|
465
|
+
webdriver.WebElement.createCoordinatesFromResponse_ = function(future,
|
|
466
|
+
response) {
|
|
467
|
+
var xy = response.value.replace(/\s/g, '').split(',');
|
|
468
|
+
response.value = new goog.math.Coordinate(xy[0], xy[1]);
|
|
469
|
+
future.setValue(response.value);
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* @return {webdriver.Future} The location of this element.
|
|
475
|
+
*/
|
|
476
|
+
webdriver.WebElement.prototype.getLocation = function() {
|
|
477
|
+
var currentLocation = new webdriver.Future(this.driver_);
|
|
478
|
+
var command = this.createCommand_(webdriver.CommandName.GET_LOCATION).
|
|
479
|
+
setSuccessCallback(
|
|
480
|
+
goog.bind(webdriver.WebElement.createCoordinatesFromResponse_, null,
|
|
481
|
+
currentLocation));
|
|
482
|
+
this.driver_.addCommand(command);
|
|
483
|
+
return currentLocation;
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* @param {webdriver.Future} newLocation Future to store the new location in
|
|
489
|
+
* when the command is complete.
|
|
490
|
+
* @param {number} x Horizontal distance to drag this element.
|
|
491
|
+
* @param {number} y Vertical distanct to drag this element.
|
|
492
|
+
* @param opt_addToFront
|
|
493
|
+
* @private
|
|
494
|
+
*/
|
|
495
|
+
webdriver.WebElement.prototype.addDragAndDropCommand_ = function(
|
|
496
|
+
newLocation, x, y, opt_addToFront) {
|
|
497
|
+
var command = this.createCommand_(webdriver.CommandName.DRAG_ELEMENT).
|
|
498
|
+
setParameters(x, y).
|
|
499
|
+
setSuccessCallback(
|
|
500
|
+
goog.bind(webdriver.WebElement.createCoordinatesFromResponse_, null,
|
|
501
|
+
newLocation));
|
|
502
|
+
this.driver_.addCommand(command, opt_addToFront);
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Drags this element by the given offset.
|
|
508
|
+
* @param {number} x The horizontal amount, in pixels, to drag this element.
|
|
509
|
+
* @param {number} y The vertical amount, in pixels, to drag this element.
|
|
510
|
+
* @return {webdriver.Future} The new location of the element.
|
|
511
|
+
*/
|
|
512
|
+
webdriver.WebElement.prototype.dragAndDropBy = function(x, y) {
|
|
513
|
+
var newLocation = new webdriver.Future(this.driver_);
|
|
514
|
+
this.addDragAndDropCommand_(newLocation, x, y);
|
|
515
|
+
return newLocation;
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Drags this element to the location of another {@code webElement}. After this
|
|
521
|
+
* command executes, this element's upper-left hand corner should be the same
|
|
522
|
+
* location as the upper-left hand corner of the given {@code webElement}.
|
|
523
|
+
* @param {webdriver.WebElement} webElement The element to drag this element to.
|
|
524
|
+
* @return {webdriver.Future} This element's new location.
|
|
525
|
+
*/
|
|
526
|
+
webdriver.WebElement.prototype.dragAndDropTo = function(webElement) {
|
|
527
|
+
if (this.driver_ != webElement.driver_) {
|
|
528
|
+
throw new Error(
|
|
529
|
+
'WebElements created by different drivers cannot coordinate');
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
var toLocation = webElement.getLocation();
|
|
533
|
+
var thisLocation = this.getLocation();
|
|
534
|
+
var newLocation = new webdriver.Future(this.driver_);
|
|
535
|
+
this.driver_.callFunction(goog.bind(function() {
|
|
536
|
+
var delta = goog.math.Coordinate.difference(
|
|
537
|
+
toLocation.getValue(), thisLocation.getValue());
|
|
538
|
+
this.addDragAndDropCommand_(newLocation, delta.x, delta.y, true);
|
|
539
|
+
}, this));
|
|
540
|
+
return newLocation;
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* @return {boolean} Whether the DOM element represented by this instance is
|
|
546
|
+
* enabled, as dictated by the {@code disabled} attribute.
|
|
547
|
+
*/
|
|
548
|
+
webdriver.WebElement.prototype.isEnabled = function() {
|
|
549
|
+
var futureValue = new webdriver.Future(this.driver_);
|
|
550
|
+
var command = this.createCommand_(webdriver.CommandName.GET_ATTRIBUTE).
|
|
551
|
+
setParameters('disabled').
|
|
552
|
+
setSuccessCallback(function(response) {
|
|
553
|
+
response.value = !!!response.value;
|
|
554
|
+
futureValue.setValue(response.value);
|
|
555
|
+
});
|
|
556
|
+
this.driver_.addCommand(command);
|
|
557
|
+
return futureValue;
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Determines if this element is checked or selected; will generate an error if
|
|
563
|
+
* the DOM element represented by this instance is not an OPTION or checkbox
|
|
564
|
+
* INPUT element.
|
|
565
|
+
* @return {webdriver.Future} Whether this instance is currently checked or
|
|
566
|
+
* selected.
|
|
567
|
+
* @private
|
|
568
|
+
*/
|
|
569
|
+
webdriver.WebElement.prototype.isCheckedOrSelected_ = function(opt_future,
|
|
570
|
+
opt_addToFront) {
|
|
571
|
+
var value = opt_future || new webdriver.Future(this.driver_);
|
|
572
|
+
var command = this.createCommand_(webdriver.CommandName.GET_TAG_NAME).
|
|
573
|
+
setSuccessCallback(function(response) {
|
|
574
|
+
var attribute = response.value == 'input' ? 'checked' : 'selected';
|
|
575
|
+
var getAttrCommand =
|
|
576
|
+
this.createCommand_(webdriver.CommandName.GET_ATTRIBUTE).
|
|
577
|
+
setParameters(attribute).
|
|
578
|
+
setSuccessCallback(function(response) {
|
|
579
|
+
response.value = !!response.value;
|
|
580
|
+
value.setValue(response.value);
|
|
581
|
+
});
|
|
582
|
+
this.driver_.addCommand(getAttrCommand, true);
|
|
583
|
+
}, this);
|
|
584
|
+
this.driver_.addCommand(command, opt_addToFront);
|
|
585
|
+
return value;
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* @return {webdriver.Future} Whether this element is selected.
|
|
591
|
+
*/
|
|
592
|
+
webdriver.WebElement.prototype.isSelected = function() {
|
|
593
|
+
return this.isCheckedOrSelected_();
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* @return {webdriver.Future} Whether this element is checked.
|
|
599
|
+
*/
|
|
600
|
+
webdriver.WebElement.prototype.isChecked = function() {
|
|
601
|
+
return this.isCheckedOrSelected_();
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Toggles the checked/selected state of this element; will generate an error if
|
|
607
|
+
* the DOM element represented by this instance is not an OPTION or checkbox
|
|
608
|
+
* input element.
|
|
609
|
+
* @return {webdriver.Future} The new checked/selected state of this element.
|
|
610
|
+
*/
|
|
611
|
+
webdriver.WebElement.prototype.toggle = function() {
|
|
612
|
+
var toggleResult = new webdriver.Future(this.driver_);
|
|
613
|
+
var command = this.createCommand_(webdriver.CommandName.TOGGLE).
|
|
614
|
+
setSuccessCallback(function() {
|
|
615
|
+
this.isCheckedOrSelected_(toggleResult, true);
|
|
616
|
+
}, this);
|
|
617
|
+
this.driver_.addCommand(command);
|
|
618
|
+
return toggleResult;
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* If this current element is a form, or an element within a form, then this
|
|
624
|
+
* will that form.
|
|
625
|
+
*/
|
|
626
|
+
webdriver.WebElement.prototype.submit = function() {
|
|
627
|
+
this.driver_.addCommand(
|
|
628
|
+
this.createCommand_(webdriver.CommandName.SUBMIT));
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* If this instance represents a text INPUT element, or a TEXTAREA element, this
|
|
634
|
+
* will clear its {@code value}.
|
|
635
|
+
*/
|
|
636
|
+
webdriver.WebElement.prototype.clear = function() {
|
|
637
|
+
this.driver_.addCommand(
|
|
638
|
+
this.createCommand_(webdriver.CommandName.CLEAR));
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* @return {webdriver.Future} Whether this element is currently displayed.
|
|
644
|
+
*/
|
|
645
|
+
webdriver.WebElement.prototype.isDisplayed = function() {
|
|
646
|
+
var futureValue = new webdriver.Future(this.driver_);
|
|
647
|
+
var command = this.createCommand_(webdriver.CommandName.IS_DISPLAYED).
|
|
648
|
+
setSuccessCallback(function(response) {
|
|
649
|
+
// TODO(jmleyba): FF extension should not be returning a string here...
|
|
650
|
+
if (goog.isString(response.value)) {
|
|
651
|
+
futureValue.setValue(response.value == 'true');
|
|
652
|
+
} else {
|
|
653
|
+
futureValue.setValue(response.value);
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
this.driver_.addCommand(command);
|
|
657
|
+
return futureValue;
|
|
658
|
+
};
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* @return {webdriver.Future} The outer HTML of this element.
|
|
663
|
+
*/
|
|
664
|
+
webdriver.WebElement.prototype.getOuterHtml = function() {
|
|
665
|
+
return this.driver_.executeScript(
|
|
666
|
+
['var element = arguments[0];',
|
|
667
|
+
'if ("outerHTML" in element) {',
|
|
668
|
+
' return element.outerHTML;',
|
|
669
|
+
'} else {',
|
|
670
|
+
' var div = document.createElement("div");',
|
|
671
|
+
' div.appendChild(element.cloneNode(true));',
|
|
672
|
+
' return div.innerHTML;',
|
|
673
|
+
'}'].join(''), this);
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* @return {webdriver.Future} The inner HTML of this element.
|
|
679
|
+
*/
|
|
680
|
+
webdriver.WebElement.prototype.getInnerHtml = function() {
|
|
681
|
+
return this.driver_.executeScript('return arguments[0].innerHTML', this);
|
|
682
|
+
};
|
|
683
|
+
|