selenium-webdriver 0.0.8 → 0.0.9
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/src/extension/background.js +975 -943
- data/chrome/src/extension/content_script.js +34 -5
- data/chrome/src/extension/utils.js +31 -10
- data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +10 -2
- data/common/src/js/abstractcommandprocessor.js +25 -19
- data/common/src/js/command.js +4 -68
- data/common/src/js/future.js +5 -1
- data/common/src/js/jsunit.js +40 -0
- data/common/src/js/localcommandprocessor.js +20 -15
- data/common/src/js/testcase.js +217 -0
- data/common/src/js/webdriver.js +146 -80
- data/common/src/js/webelement.js +49 -127
- data/common/src/rb/lib/selenium/webdriver/child_process.rb +12 -6
- data/firefox/src/extension/components/badCertListener.js +1 -1
- data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
- data/jobbie/prebuilt/Win32/Release/webdriver-ie-test.dll +0 -0
- data/jobbie/prebuilt/Win32/Release/webdriver-ie.dll +0 -0
- data/jobbie/prebuilt/x64/Release/webdriver-ie-test.dll +0 -0
- data/jobbie/prebuilt/x64/Release/webdriver-ie.dll +0 -0
- metadata +8 -4
- data/common/src/js/logging.js +0 -249
- data/common/src/js/testrunner.js +0 -598
|
@@ -0,0 +1,217 @@
|
|
|
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 test case that uses the WebDriver Javascript API. Each phase
|
|
20
|
+
* of a test (setUp, test function, and tearDown) will be called with an
|
|
21
|
+
* instance of a {@code webdriver.WebDriver} that can be used to schedule
|
|
22
|
+
* commands for controlling the browser (e.g. clicking or typing on an
|
|
23
|
+
* element).
|
|
24
|
+
* <p>
|
|
25
|
+
* Unlike pure JavaScript test frameworks like Selenium, WebDriver controls the
|
|
26
|
+
* browser directly, allowing for more accurate simulation of user actions in a
|
|
27
|
+
* web application.
|
|
28
|
+
* <p>
|
|
29
|
+
* See below for a basic example of using WebDriver to test cut and paste in
|
|
30
|
+
* a contentEditable document.
|
|
31
|
+
* <pre>
|
|
32
|
+
* goog.require('goog.dom');
|
|
33
|
+
* goog.require('webdriver.asserts');
|
|
34
|
+
* goog.require('webdriver.jsunit');
|
|
35
|
+
*
|
|
36
|
+
* var richTextFrame;
|
|
37
|
+
*
|
|
38
|
+
* function setUp() {
|
|
39
|
+
* richTextFrame = goog.dom.$('rtframe');
|
|
40
|
+
* richTextFrame.contentWindow.document.designMode = 'on';
|
|
41
|
+
* richTextFrame.contentWindow.document.body.innerHTML = '';
|
|
42
|
+
* }
|
|
43
|
+
*
|
|
44
|
+
* function testCutAndPaste(driver) {
|
|
45
|
+
* driver.switchToFrame('rtframe');
|
|
46
|
+
* var body = driver.findElement({xpath: '//body'});
|
|
47
|
+
* body.sendKeys('abc', webdriver.Key.CONTROL, 'axvv');
|
|
48
|
+
* driver.callFunction(function() {
|
|
49
|
+
* assertEquals('abcabc',
|
|
50
|
+
* richTextFrame.contentWindow.document.body.innerHTML);
|
|
51
|
+
* });
|
|
52
|
+
* }
|
|
53
|
+
* </pre>
|
|
54
|
+
*
|
|
55
|
+
* @author jmleyba@gmail.com (Jason Leyba)
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
goog.provide('webdriver.TestCase');
|
|
59
|
+
goog.provide('webdriver.TestCase.Test');
|
|
60
|
+
|
|
61
|
+
goog.require('goog.events');
|
|
62
|
+
goog.require('goog.testing.TestCase');
|
|
63
|
+
goog.require('goog.testing.TestCase.Test');
|
|
64
|
+
goog.require('goog.testing.asserts');
|
|
65
|
+
goog.require('webdriver.Command');
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A specialized test case for running jsunit tests with the WebDriver
|
|
71
|
+
* framework. Each phase of a test (setUp, test, and tearDown) will be given an
|
|
72
|
+
* instance of {@code webdriver.WebDriver} that can be used to schedule
|
|
73
|
+
* commands for controlling the browser.
|
|
74
|
+
* @param {string} name The name of the test case.
|
|
75
|
+
* @param {function(): webdriver.WebDriver} driverFactoryFn Factory function to
|
|
76
|
+
* use for creating {@code webdriver.WebDriver} instances for each test.
|
|
77
|
+
* @extends {goog.testing.TestCase}
|
|
78
|
+
* @constructor
|
|
79
|
+
*/
|
|
80
|
+
webdriver.TestCase = function(name, driverFactoryFn) {
|
|
81
|
+
goog.testing.TestCase.call(this, name);
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Factory function use for creating {@code webdriver.WebDriver}
|
|
85
|
+
* instances for each test.
|
|
86
|
+
* @type {function(): webdriver.WebDriver}
|
|
87
|
+
* @private
|
|
88
|
+
*/
|
|
89
|
+
this.driverFactoryFn_ = driverFactoryFn;
|
|
90
|
+
};
|
|
91
|
+
goog.inherits(webdriver.TestCase, goog.testing.TestCase);
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
/** @override */
|
|
95
|
+
webdriver.TestCase.prototype.cycleTests = function() {
|
|
96
|
+
this.saveMessage('Start');
|
|
97
|
+
this.batchTime_ = this.now_();
|
|
98
|
+
this.startTest_();
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Starts a test.
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
webdriver.TestCase.prototype.startTest_ = function() {
|
|
107
|
+
var test = this.next();
|
|
108
|
+
if (!test || !this.running) {
|
|
109
|
+
this.finalize(); // Tests are done.
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// TODO(jleyba): result_ should be exposed using a public accessor.
|
|
114
|
+
this.result_.runCount++;
|
|
115
|
+
this.log('Running test: ' + test.name);
|
|
116
|
+
goog.testing.TestCase.currentTestName = test.name;
|
|
117
|
+
|
|
118
|
+
var driver;
|
|
119
|
+
try {
|
|
120
|
+
driver = this.driverFactoryFn_();
|
|
121
|
+
|
|
122
|
+
// Attach an error handler to record each command failure as an error for
|
|
123
|
+
// the current test. After each error, the currently pending command and
|
|
124
|
+
// all of its subcommands so we can continue the test.
|
|
125
|
+
goog.events.listen(driver, webdriver.Command.ERROR_EVENT,
|
|
126
|
+
function(e) {
|
|
127
|
+
var failingCommand = (/** @type {webdriver.Command} */e.target);
|
|
128
|
+
if (!failingCommand.getResponse()) {
|
|
129
|
+
// This should never happen, but just in case.
|
|
130
|
+
test.errors.push('Unknown error');
|
|
131
|
+
} else {
|
|
132
|
+
test.errors.push(failingCommand.getResponse().getErrorMessage());
|
|
133
|
+
}
|
|
134
|
+
driver.abortCommand(null);
|
|
135
|
+
}, /*capture=*/false);
|
|
136
|
+
|
|
137
|
+
// TODO(jleyba): make this automatic upon creating an instance.
|
|
138
|
+
driver.newSession(true);
|
|
139
|
+
|
|
140
|
+
// If setup fails, we don't want to run the test function, so group setup
|
|
141
|
+
// and the test function together in a function command.
|
|
142
|
+
driver.callFunction(function() {
|
|
143
|
+
this.setUp(driver);
|
|
144
|
+
// Wrap the call to the actual test function in a function command. This
|
|
145
|
+
// will ensure all of the commands scheduled in setUp will executed before
|
|
146
|
+
// the test function is called.
|
|
147
|
+
driver.callFunction(function() {
|
|
148
|
+
test.ref.call(test.scope, driver);
|
|
149
|
+
});
|
|
150
|
+
}, this);
|
|
151
|
+
|
|
152
|
+
// Call tearDown once all setup and test commands have completed.
|
|
153
|
+
driver.callFunction(function() {
|
|
154
|
+
this.tearDown(driver);
|
|
155
|
+
}, this);
|
|
156
|
+
|
|
157
|
+
// Likewise, once tearDown is completely finished, finish the test.
|
|
158
|
+
driver.callFunction(function() {
|
|
159
|
+
this.finishTest_(test, driver);
|
|
160
|
+
}, this);
|
|
161
|
+
} catch (e) {
|
|
162
|
+
test.errors.push(e);
|
|
163
|
+
this.finishTest_(test, driver);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Completes a test.
|
|
169
|
+
* @param {webdriver.TestCase.Test} test The test to complete.
|
|
170
|
+
* @param {webdriver.WebDriver} driver The driver instance used by the test.
|
|
171
|
+
* @private
|
|
172
|
+
*/
|
|
173
|
+
webdriver.TestCase.prototype.finishTest_ = function(test, driver) {
|
|
174
|
+
if (driver) {
|
|
175
|
+
driver.dispose();
|
|
176
|
+
}
|
|
177
|
+
goog.testing.TestCase.currentTestName = null;
|
|
178
|
+
var numErrors = test.errors.length;
|
|
179
|
+
if (numErrors) {
|
|
180
|
+
for (var i = 0; i < numErrors; i++) {
|
|
181
|
+
this.doError(test, test.errors[i]);
|
|
182
|
+
}
|
|
183
|
+
} else {
|
|
184
|
+
this.doSuccess(test);
|
|
185
|
+
}
|
|
186
|
+
this.startTest_(); // Start the next test.
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
/** @override */
|
|
191
|
+
webdriver.TestCase.prototype.createTestFromAutoDiscoveredFunction =
|
|
192
|
+
function(name, ref) {
|
|
193
|
+
return new webdriver.TestCase.Test(name, ref, goog.global);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Represents a single test function that will be run by a
|
|
199
|
+
* {@code webdriver.TestCase}.
|
|
200
|
+
* @param {string} name The test name.
|
|
201
|
+
* @param {function} ref Reference to the test function.
|
|
202
|
+
* @param {Object} opt_scope Optional scope that the test function should be
|
|
203
|
+
* called in.
|
|
204
|
+
* @constructor
|
|
205
|
+
* @extends {goog.testing.TestCase.Test}
|
|
206
|
+
*/
|
|
207
|
+
webdriver.TestCase.Test = function(name, ref, opt_scope) {
|
|
208
|
+
goog.testing.TestCase.Test.call(this, name, ref, opt_scope);
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* The errors that occurred while running this test.
|
|
212
|
+
* @type {Array.<string|Error>}
|
|
213
|
+
*/
|
|
214
|
+
this.errors = [];
|
|
215
|
+
};
|
|
216
|
+
goog.inherits(webdriver.TestCase.Test, goog.testing.TestCase.Test);
|
|
217
|
+
|
data/common/src/js/webdriver.js
CHANGED
|
@@ -24,14 +24,15 @@ goog.provide('webdriver.WebDriver');
|
|
|
24
24
|
goog.provide('webdriver.WebDriver.EventType');
|
|
25
25
|
goog.provide('webdriver.WebDriver.Speed');
|
|
26
26
|
|
|
27
|
+
goog.require('goog.debug.Logger');
|
|
27
28
|
goog.require('goog.events');
|
|
28
29
|
goog.require('goog.events.EventTarget');
|
|
30
|
+
goog.require('webdriver.By.Locator');
|
|
29
31
|
goog.require('webdriver.Command');
|
|
30
32
|
goog.require('webdriver.CommandName');
|
|
31
33
|
goog.require('webdriver.Context');
|
|
32
34
|
goog.require('webdriver.Response');
|
|
33
35
|
goog.require('webdriver.WebElement');
|
|
34
|
-
goog.require('webdriver.logging');
|
|
35
36
|
goog.require('webdriver.timing');
|
|
36
37
|
|
|
37
38
|
|
|
@@ -68,6 +69,13 @@ goog.require('webdriver.timing');
|
|
|
68
69
|
webdriver.WebDriver = function(commandProcessor) {
|
|
69
70
|
goog.events.EventTarget.call(this);
|
|
70
71
|
|
|
72
|
+
/**
|
|
73
|
+
* The logger for this instance.
|
|
74
|
+
* @type {!goog.debug.Logger}
|
|
75
|
+
* @private
|
|
76
|
+
*/
|
|
77
|
+
this.logger_ = goog.debug.Logger.getLogger('webdriver.WebDriver');
|
|
78
|
+
|
|
71
79
|
/**
|
|
72
80
|
* The command processor to use for executing commands.
|
|
73
81
|
* @type {Object}
|
|
@@ -109,15 +117,6 @@ webdriver.WebDriver = function(commandProcessor) {
|
|
|
109
117
|
*/
|
|
110
118
|
this.context_ = new webdriver.Context();
|
|
111
119
|
|
|
112
|
-
/**
|
|
113
|
-
* Whether this instance is locked into its current session. Once locked in,
|
|
114
|
-
* any further calls to {@code webdriver.WebDriver.prototype.newSession} will
|
|
115
|
-
* be ignored.
|
|
116
|
-
* @type {boolean}
|
|
117
|
-
* @private
|
|
118
|
-
*/
|
|
119
|
-
this.sessionLocked_ = false;
|
|
120
|
-
|
|
121
120
|
/**
|
|
122
121
|
* This instance's current session ID. Set with the
|
|
123
122
|
* {@code webdriver.WebDriver.prototype.newSession} command.
|
|
@@ -221,6 +220,10 @@ webdriver.WebDriver.prototype.addCommand = function(name, opt_element) {
|
|
|
221
220
|
* commands).
|
|
222
221
|
*/
|
|
223
222
|
webdriver.WebDriver.prototype.isIdle = function() {
|
|
223
|
+
if (this.isDisposed()) {
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
|
|
224
227
|
// If there is a finished command on the pending command queue, but it
|
|
225
228
|
// failed, then the failure hasn't been dealt with yet and the driver will
|
|
226
229
|
// not process any more commands, so we consider this idle.
|
|
@@ -236,14 +239,15 @@ webdriver.WebDriver.prototype.isIdle = function() {
|
|
|
236
239
|
|
|
237
240
|
/**
|
|
238
241
|
* Aborts the specified command and all of its pending subcommands.
|
|
239
|
-
* @param {webdriver.Command} command The command to abort.
|
|
242
|
+
* @param {webdriver.Command|webdriver.WebDriver} command The command to abort.
|
|
240
243
|
* @return {number} The total number of commands aborted. A value of 0
|
|
241
244
|
* indicates that the given command was not a pending command.
|
|
242
245
|
*/
|
|
243
246
|
webdriver.WebDriver.prototype.abortCommand = function(command) {
|
|
244
|
-
var index =
|
|
245
|
-
|
|
246
|
-
|
|
247
|
+
var index = (null == command || this == command) ? 0 :
|
|
248
|
+
goog.array.findIndexRight(this.pendingCommands_, function(cmd) {
|
|
249
|
+
return cmd == command;
|
|
250
|
+
});
|
|
247
251
|
if (index >= 0) {
|
|
248
252
|
var numAborted = this.pendingCommands_.length - index;
|
|
249
253
|
var totalNumAborted = numAborted;
|
|
@@ -267,7 +271,7 @@ webdriver.WebDriver.prototype.abortCommand = function(command) {
|
|
|
267
271
|
*/
|
|
268
272
|
webdriver.WebDriver.prototype.pauseImmediately = function() {
|
|
269
273
|
this.isPaused_ = true;
|
|
270
|
-
|
|
274
|
+
this.logger_.fine('WebDriver paused');
|
|
271
275
|
this.dispatchEvent(webdriver.WebDriver.EventType.PAUSED);
|
|
272
276
|
};
|
|
273
277
|
|
|
@@ -278,7 +282,7 @@ webdriver.WebDriver.prototype.pauseImmediately = function() {
|
|
|
278
282
|
*/
|
|
279
283
|
webdriver.WebDriver.prototype.resume = function() {
|
|
280
284
|
this.isPaused_ = false;
|
|
281
|
-
|
|
285
|
+
this.logger_.fine('WebDriver resumed');
|
|
282
286
|
this.dispatchEvent(webdriver.WebDriver.EventType.RESUMED);
|
|
283
287
|
};
|
|
284
288
|
|
|
@@ -295,7 +299,7 @@ webdriver.WebDriver.prototype.processCommands_ = function() {
|
|
|
295
299
|
|
|
296
300
|
if (pendingCommand && pendingCommand.getResponse().isFailure) {
|
|
297
301
|
// Or should we be throwing this to be caught by window.onerror?
|
|
298
|
-
|
|
302
|
+
this.logger_.severe(
|
|
299
303
|
'Unhandled command failure; halting command processing:\n' +
|
|
300
304
|
pendingCommand.getResponse().getErrorMessage());
|
|
301
305
|
return;
|
|
@@ -315,7 +319,7 @@ webdriver.WebDriver.prototype.processCommands_ = function() {
|
|
|
315
319
|
nextCommand.setParentEventTarget(parentTarget);
|
|
316
320
|
this.pendingCommands_.push(nextCommand);
|
|
317
321
|
this.queuedCommands_.push([]);
|
|
318
|
-
this.commandProcessor_.execute(nextCommand
|
|
322
|
+
this.commandProcessor_.execute(nextCommand);
|
|
319
323
|
}
|
|
320
324
|
};
|
|
321
325
|
|
|
@@ -390,6 +394,40 @@ webdriver.WebDriver.prototype.catchExpectedError = function(opt_errorMsg,
|
|
|
390
394
|
};
|
|
391
395
|
|
|
392
396
|
|
|
397
|
+
/**
|
|
398
|
+
* Queueus a command to call the given function if and only if the previous
|
|
399
|
+
* command fails. Since failed commands do not have a result, the function
|
|
400
|
+
* called will not be given the return value of the previous command.
|
|
401
|
+
* @param {function} fn The function to call if the previous command fails.
|
|
402
|
+
* @param {Object} opt_selfObj The object in whose scope to call the function.
|
|
403
|
+
* @param {*} var_args Any arguments to pass to the function.
|
|
404
|
+
*/
|
|
405
|
+
webdriver.WebDriver.prototype.ifPreviousCommandFailsCall = function(
|
|
406
|
+
fn, opt_selfObj, var_args) {
|
|
407
|
+
var args = arguments;
|
|
408
|
+
var currentFrame = goog.array.peek(this.queuedCommands_);
|
|
409
|
+
var previousCommand = goog.array.peek(currentFrame);
|
|
410
|
+
if (!previousCommand) {
|
|
411
|
+
throw new Error('No commands in the queue to expect an error from');
|
|
412
|
+
}
|
|
413
|
+
var commandFailed = false;
|
|
414
|
+
var key = goog.events.listenOnce(previousCommand,
|
|
415
|
+
webdriver.Command.ERROR_EVENT, function(e) {
|
|
416
|
+
commandFailed = true;
|
|
417
|
+
this.abortCommand(e.currentTarget);
|
|
418
|
+
e.preventDefault();
|
|
419
|
+
e.stopPropagation();
|
|
420
|
+
return false;
|
|
421
|
+
}, /*capture phase*/true, this);
|
|
422
|
+
this.callFunction(function() {
|
|
423
|
+
goog.events.unlistenByKey(key);
|
|
424
|
+
if (commandFailed) {
|
|
425
|
+
return this.callFunction.apply(this, args);
|
|
426
|
+
}
|
|
427
|
+
}, this);
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
|
|
393
431
|
/**
|
|
394
432
|
* Adds a command to pause this driver so it will not execute anymore commands
|
|
395
433
|
* until {@code #resume()} is called. When this command executes, a
|
|
@@ -425,12 +463,9 @@ webdriver.WebDriver.prototype.callFunction = function(fn, opt_selfObj,
|
|
|
425
463
|
var args = goog.array.slice(arguments, 2);
|
|
426
464
|
var frame = goog.array.peek(this.queuedCommands_);
|
|
427
465
|
var previousCommand = goog.array.peek(frame);
|
|
428
|
-
|
|
429
|
-
args.push(previousCommand ? previousCommand.getResponse() : null);
|
|
430
|
-
return fn.apply(opt_selfObj, args);
|
|
431
|
-
}, this);
|
|
466
|
+
args.push(previousCommand ? previousCommand.getFutureResult() : null);
|
|
432
467
|
return this.addCommand(webdriver.CommandName.FUNCTION).
|
|
433
|
-
setParameters(
|
|
468
|
+
setParameters(fn, opt_selfObj, args).
|
|
434
469
|
getFutureResult();
|
|
435
470
|
};
|
|
436
471
|
|
|
@@ -478,7 +513,13 @@ webdriver.WebDriver.prototype.wait = function(conditionFn, timeout, opt_self,
|
|
|
478
513
|
if (ellapsed > timeout) {
|
|
479
514
|
throw Error('Wait timed out after ' + ellapsed + 'ms');
|
|
480
515
|
}
|
|
481
|
-
|
|
516
|
+
// If we pass the pending future in as is, the AbstractCommandProcessor
|
|
517
|
+
// will try to resolve it to its value. However, if we're scheduling
|
|
518
|
+
// this function, it's because the future has not been set yet, which
|
|
519
|
+
// will lead to an error. To avoid this, wrap up the pollFunction in an
|
|
520
|
+
// anonymous function so the AbstractCommandProcessor does not
|
|
521
|
+
// interfere.
|
|
522
|
+
callFunction(goog.bind(pollFunction, null, startTime, pendingFuture));
|
|
482
523
|
}
|
|
483
524
|
}
|
|
484
525
|
|
|
@@ -486,9 +527,8 @@ webdriver.WebDriver.prototype.wait = function(conditionFn, timeout, opt_self,
|
|
|
486
527
|
checkValue(result);
|
|
487
528
|
}
|
|
488
529
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
this.addCommand(webdriver.CommandName.WAIT).setParameters(initialPoll);
|
|
530
|
+
this.addCommand(webdriver.CommandName.WAIT).
|
|
531
|
+
setParameters(pollFunction, null, [0, null]);
|
|
492
532
|
};
|
|
493
533
|
|
|
494
534
|
|
|
@@ -513,24 +553,15 @@ webdriver.WebDriver.prototype.waitNot = function(conditionFn, timeout,
|
|
|
513
553
|
|
|
514
554
|
|
|
515
555
|
/**
|
|
516
|
-
* Request a new session ID.
|
|
517
|
-
* into a session.
|
|
518
|
-
* @param {boolean} lockSession Whether to lock this instance into the returned
|
|
519
|
-
* session. Once locked into a session, the driver cannot ask for a new
|
|
520
|
-
* session (a new instance must be created).
|
|
556
|
+
* Request a new session ID.
|
|
521
557
|
*/
|
|
522
|
-
webdriver.WebDriver.prototype.newSession = function(
|
|
523
|
-
|
|
524
|
-
this.addCommand(webdriver.CommandName.NEW_SESSION)
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
}, this);
|
|
530
|
-
} else {
|
|
531
|
-
webdriver.logging.warn(
|
|
532
|
-
'Cannot start new session; driver is locked into current session');
|
|
533
|
-
}
|
|
558
|
+
webdriver.WebDriver.prototype.newSession = function() {
|
|
559
|
+
this.callFunction(function() {
|
|
560
|
+
this.addCommand(webdriver.CommandName.NEW_SESSION);
|
|
561
|
+
this.callFunction(function(value) {
|
|
562
|
+
this.sessionId_ = value;
|
|
563
|
+
}, this);
|
|
564
|
+
}, this);
|
|
534
565
|
};
|
|
535
566
|
|
|
536
567
|
|
|
@@ -542,11 +573,11 @@ webdriver.WebDriver.prototype.newSession = function(lockSession) {
|
|
|
542
573
|
* {@code #getWindowHandle()} or {@code #getAllWindowHandles()}.
|
|
543
574
|
*/
|
|
544
575
|
webdriver.WebDriver.prototype.switchToWindow = function(name) {
|
|
545
|
-
this.
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
576
|
+
this.callFunction(function() {
|
|
577
|
+
this.addCommand(webdriver.CommandName.SWITCH_TO_WINDOW).
|
|
578
|
+
setParameters(name);
|
|
579
|
+
this.callFunction(this.setContext, this);
|
|
580
|
+
}, this);
|
|
550
581
|
};
|
|
551
582
|
|
|
552
583
|
|
|
@@ -561,15 +592,14 @@ webdriver.WebDriver.prototype.switchToWindow = function(name) {
|
|
|
561
592
|
* to transfer control to.
|
|
562
593
|
*/
|
|
563
594
|
webdriver.WebDriver.prototype.switchToFrame = function(frame) {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
this.context_ = response.context;
|
|
595
|
+
this.callFunction(function() {
|
|
596
|
+
var commandName = webdriver.CommandName.SWITCH_TO_FRAME;
|
|
597
|
+
var command;
|
|
598
|
+
if (goog.isString(frame) || goog.isNumber(frame)) {
|
|
599
|
+
command = this.addCommand(commandName).setParameters(frame);
|
|
600
|
+
} else {
|
|
601
|
+
command = this.addCommand(commandName, frame);
|
|
602
|
+
}
|
|
573
603
|
}, this);
|
|
574
604
|
};
|
|
575
605
|
|
|
@@ -579,11 +609,10 @@ webdriver.WebDriver.prototype.switchToFrame = function(frame) {
|
|
|
579
609
|
* contains iframes.
|
|
580
610
|
*/
|
|
581
611
|
webdriver.WebDriver.prototype.switchToDefaultContent = function() {
|
|
582
|
-
this.
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
}, this);
|
|
612
|
+
this.callFunction(function() {
|
|
613
|
+
this.addCommand(webdriver.CommandName.SWITCH_TO_DEFAULT_CONTENT).
|
|
614
|
+
setParameters(null);
|
|
615
|
+
}, this);
|
|
587
616
|
};
|
|
588
617
|
|
|
589
618
|
|
|
@@ -690,12 +719,13 @@ webdriver.WebDriver.prototype.executeScript = function(script, var_args) {
|
|
|
690
719
|
var args = goog.array.map(
|
|
691
720
|
goog.array.slice(arguments, 1),
|
|
692
721
|
webdriver.WebDriver.wrapScriptArgument_);
|
|
693
|
-
return this.
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
722
|
+
return this.callFunction(function() {
|
|
723
|
+
this.addCommand(webdriver.CommandName.EXECUTE_SCRIPT).
|
|
724
|
+
setParameters(script, args);
|
|
725
|
+
return this.callFunction(function(prevResult) {
|
|
726
|
+
return this.unwrapScriptResult_(prevResult);
|
|
727
|
+
}, this);
|
|
728
|
+
}, this);
|
|
699
729
|
};
|
|
700
730
|
|
|
701
731
|
|
|
@@ -704,11 +734,10 @@ webdriver.WebDriver.prototype.executeScript = function(script, var_args) {
|
|
|
704
734
|
* @param {goog.Uri|string} url The URL to fetch.
|
|
705
735
|
*/
|
|
706
736
|
webdriver.WebDriver.prototype.get = function(url) {
|
|
707
|
-
this.
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
}, this);
|
|
737
|
+
this.callFunction(function() {
|
|
738
|
+
this.addCommand(webdriver.CommandName.GET).
|
|
739
|
+
setParameters(url.toString());
|
|
740
|
+
}, this);
|
|
712
741
|
};
|
|
713
742
|
|
|
714
743
|
|
|
@@ -765,7 +794,12 @@ webdriver.WebDriver.prototype.getTitle = function() {
|
|
|
765
794
|
* issue commands against the located element.
|
|
766
795
|
*/
|
|
767
796
|
webdriver.WebDriver.prototype.findElement = function(by) {
|
|
768
|
-
|
|
797
|
+
var webElement = new webdriver.WebElement(this);
|
|
798
|
+
var locator = webdriver.By.Locator.checkLocator(by);
|
|
799
|
+
var command = this.addCommand(webdriver.CommandName.FIND_ELEMENT).
|
|
800
|
+
setParameters(locator.type, locator.target);
|
|
801
|
+
webElement.getId().setValue(command.getFutureResult());
|
|
802
|
+
return webElement;
|
|
769
803
|
};
|
|
770
804
|
|
|
771
805
|
|
|
@@ -779,7 +813,24 @@ webdriver.WebDriver.prototype.findElement = function(by) {
|
|
|
779
813
|
* @see webdriver.By.Locator.createFromObj
|
|
780
814
|
*/
|
|
781
815
|
webdriver.WebDriver.prototype.isElementPresent = function(by) {
|
|
782
|
-
|
|
816
|
+
var locator = webdriver.By.Locator.checkLocator(by);
|
|
817
|
+
return this.callFunction(function() {
|
|
818
|
+
var findCommand = this.addCommand(webdriver.CommandName.FIND_ELEMENT).
|
|
819
|
+
setParameters(locator.type, locator.target);
|
|
820
|
+
var commandFailed = false;
|
|
821
|
+
var key = goog.events.listenOnce(findCommand,
|
|
822
|
+
webdriver.Command.ERROR_EVENT, function(e) {
|
|
823
|
+
commandFailed = true;
|
|
824
|
+
this.abortCommand(e.currentTarget);
|
|
825
|
+
e.preventDefault();
|
|
826
|
+
e.stopPropagation();
|
|
827
|
+
return false;
|
|
828
|
+
}, /*capture phase*/true, this);
|
|
829
|
+
return this.callFunction(function() {
|
|
830
|
+
goog.events.unlistenByKey(key);
|
|
831
|
+
return !commandFailed;
|
|
832
|
+
});
|
|
833
|
+
}, this);
|
|
783
834
|
};
|
|
784
835
|
|
|
785
836
|
|
|
@@ -789,9 +840,9 @@ webdriver.WebDriver.prototype.isElementPresent = function(by) {
|
|
|
789
840
|
* operation can be accessed from the last saved {@code webdriver.Response}
|
|
790
841
|
* object:
|
|
791
842
|
* driver.findElements({xpath: '//div'});
|
|
792
|
-
* driver.callFunction(function(
|
|
793
|
-
*
|
|
794
|
-
*
|
|
843
|
+
* driver.callFunction(function(value) {
|
|
844
|
+
* value[0].click();
|
|
845
|
+
* value[1].click();
|
|
795
846
|
* // etc.
|
|
796
847
|
* });
|
|
797
848
|
* @param {webdriver.By.Locator|{*: string}} by The locator to use for finding
|
|
@@ -799,7 +850,22 @@ webdriver.WebDriver.prototype.isElementPresent = function(by) {
|
|
|
799
850
|
* @see webdriver.By.Locator.createFromObj
|
|
800
851
|
*/
|
|
801
852
|
webdriver.WebDriver.prototype.findElements = function(by) {
|
|
802
|
-
|
|
853
|
+
var locator = webdriver.By.Locator.checkLocator(by);
|
|
854
|
+
return this.callFunction(function() {
|
|
855
|
+
this.addCommand(webdriver.CommandName.FIND_ELEMENTS).
|
|
856
|
+
setParameters(locator.type, locator.target);
|
|
857
|
+
return this.callFunction(function(ids) {
|
|
858
|
+
var elements = [];
|
|
859
|
+
for (var i = 0; i < ids.length; i++) {
|
|
860
|
+
if (ids[i]) {
|
|
861
|
+
var element = new webdriver.WebElement(this);
|
|
862
|
+
element.getId().setValue(ids[i]);
|
|
863
|
+
elements.push(element);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
return elements;
|
|
867
|
+
}, this);
|
|
868
|
+
}, this);
|
|
803
869
|
};
|
|
804
870
|
|
|
805
871
|
|