selenium-webdriver 0.0.7 → 0.0.8
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 +19 -14
- data/chrome/src/extension/manifest-nonwin.json +1 -2
- data/chrome/src/extension/manifest-win.json +1 -2
- data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +5 -1
- data/common/src/js/abstractcommandprocessor.js +0 -33
- data/common/src/js/asserts.js +2 -2
- data/common/src/js/by.js +2 -0
- data/common/src/js/command.js +130 -36
- data/common/src/js/future.js +42 -23
- data/common/src/js/localcommandprocessor.js +0 -1
- data/common/src/js/testrunner.js +9 -16
- data/common/src/js/webdriver.js +225 -254
- data/common/src/js/webelement.js +76 -197
- data/common/src/rb/lib/selenium/webdriver/driver.rb +4 -0
- data/common/src/rb/lib/selenium/webdriver/element.rb +4 -0
- data/firefox/src/extension/components/badCertListener.js +186 -0
- data/firefox/src/extension/components/firefoxDriver.js +7 -16
- data/firefox/src/extension/components/nsCommandProcessor.js +10 -9
- data/firefox/src/extension/components/utils.js +5 -5
- data/firefox/src/extension/components/webdriverserver.js +5 -0
- data/firefox/src/extension/components/wrappedElement.js +10 -6
- data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +11 -12
- data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +2 -2
- data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +2 -1
- metadata +3 -4
- data/chrome/src/extension/toolstrip.html +0 -28
- data/common/src/js/wait.js +0 -199
@@ -131,7 +131,6 @@ webdriver.LocalCommandProcessor.onResponse_ = function(command, e) {
|
|
131
131
|
rawResponse['isError'],
|
132
132
|
webdriver.Context.fromString(rawResponse['context']),
|
133
133
|
rawResponse['response']);
|
134
|
-
response.extraData['resultType'] = rawResponse['resultType'];
|
135
134
|
|
136
135
|
// Only code in this file should be dispatching command events and listening
|
137
136
|
// for response events, so this is safe. If someone else decided to attach a
|
data/common/src/js/testrunner.js
CHANGED
@@ -230,12 +230,13 @@ webdriver.TestRunner.SINGLETON = null;
|
|
230
230
|
|
231
231
|
|
232
232
|
webdriver.TestRunner.start = function(factoryFn) {
|
233
|
-
if (webdriver.TestRunner.SINGLETON) {
|
234
|
-
|
233
|
+
if (!webdriver.TestRunner.SINGLETON) {
|
234
|
+
webdriver.TestRunner.SINGLETON = new webdriver.TestRunner(factoryFn);
|
235
|
+
webdriver.TestRunner.SINGLETON.go();
|
235
236
|
}
|
236
|
-
webdriver.TestRunner.SINGLETON
|
237
|
-
webdriver.TestRunner.SINGLETON.go();
|
237
|
+
return webdriver.TestRunner.SINGLETON;
|
238
238
|
};
|
239
|
+
goog.exportSymbol('WD_getTestRunner', webdriver.TestRunner.start);
|
239
240
|
|
240
241
|
|
241
242
|
/**
|
@@ -585,21 +586,13 @@ webdriver.TestRunner.prototype.tearDown_ = function(result, driver) {
|
|
585
586
|
*/
|
586
587
|
webdriver.TestRunner.prototype.handleDriverError_ = function(result, e) {
|
587
588
|
result.passed = false;
|
588
|
-
var failingCommand = e.target
|
589
|
-
var response = failingCommand
|
589
|
+
var failingCommand = e.target;
|
590
|
+
var response = failingCommand.getResponse();
|
590
591
|
if (response) {
|
591
|
-
result.errMsg =
|
592
|
-
if (response.value) {
|
593
|
-
result.errMsg.push(' ' + response.value);
|
594
|
-
}
|
595
|
-
goog.array.extend(
|
596
|
-
result.errMsg, goog.array.map(response.errors, function(error) {
|
597
|
-
return error.message + (error.stack ? ('\n' + error.stack) : '');
|
598
|
-
}));
|
599
|
-
result.errMsg = result.errMsg.join('\n');
|
592
|
+
result.errMsg = response.getErrorMessage();
|
600
593
|
} else {
|
601
594
|
// Should never happen, but just in case.
|
602
595
|
result.errMsg = 'Unknown error!';
|
603
596
|
}
|
604
|
-
this.reportResult_(result,
|
597
|
+
this.reportResult_(result, failingCommand.getDriver());
|
605
598
|
};
|
data/common/src/js/webdriver.js
CHANGED
@@ -22,15 +22,14 @@ limitations under the License.
|
|
22
22
|
|
23
23
|
goog.provide('webdriver.WebDriver');
|
24
24
|
goog.provide('webdriver.WebDriver.EventType');
|
25
|
+
goog.provide('webdriver.WebDriver.Speed');
|
25
26
|
|
26
27
|
goog.require('goog.events');
|
27
28
|
goog.require('goog.events.EventTarget');
|
28
29
|
goog.require('webdriver.Command');
|
29
30
|
goog.require('webdriver.CommandName');
|
30
31
|
goog.require('webdriver.Context');
|
31
|
-
goog.require('webdriver.Future');
|
32
32
|
goog.require('webdriver.Response');
|
33
|
-
goog.require('webdriver.Wait');
|
34
33
|
goog.require('webdriver.WebElement');
|
35
34
|
goog.require('webdriver.logging');
|
36
35
|
goog.require('webdriver.timing');
|
@@ -77,31 +76,23 @@ webdriver.WebDriver = function(commandProcessor) {
|
|
77
76
|
this.commandProcessor_ = commandProcessor;
|
78
77
|
|
79
78
|
/**
|
80
|
-
*
|
81
|
-
*
|
82
|
-
*
|
83
|
-
*
|
84
|
-
* 2: a command within a wait condition is pending with the command
|
85
|
-
* processor
|
86
|
-
* @type {Array.<webdriver.Command>}
|
87
|
-
* @private
|
88
|
-
*/
|
89
|
-
this.pendingCommands_ = [];
|
90
|
-
|
91
|
-
/**
|
92
|
-
* A stack of frames for managing batched command execution order.
|
79
|
+
* A stack of frames for queued commands. The list of commands at index 0
|
80
|
+
* are global commands. When the stack has more than 1 frame, the commands
|
81
|
+
* in the list at the top of the stack are the remaining subcommands for the
|
82
|
+
* command at the top of the {@code pendingCommands_} stack.
|
93
83
|
* @type {Array.<Array.<webdriver.Command>>}
|
94
84
|
* @private
|
95
85
|
*/
|
96
|
-
this.
|
86
|
+
this.queuedCommands_ = [[]];
|
97
87
|
|
98
88
|
/**
|
99
|
-
* A list of commands that
|
100
|
-
*
|
89
|
+
* A list of commands that are currently being executed. The command at index
|
90
|
+
* N+1 is a subcommand to the command at index N. It will always be the case
|
91
|
+
* that {@code queuedCommands_.length == pendingCommands_.length + 1;}.
|
101
92
|
* @type {Array.<webdriver.Command>}
|
102
|
-
* @
|
93
|
+
* @private
|
103
94
|
*/
|
104
|
-
this.
|
95
|
+
this.pendingCommands_ = [];
|
105
96
|
|
106
97
|
/**
|
107
98
|
* Whether this instance is paused. When paused, commands can still be issued,
|
@@ -188,10 +179,18 @@ webdriver.WebDriver.prototype.disposeInternal = function() {
|
|
188
179
|
this.commandProcessor_.dispose();
|
189
180
|
webdriver.timing.clearInterval(this.commandInterval_);
|
190
181
|
|
182
|
+
goog.array.forEach(this.pendingCommands_, function(command) {
|
183
|
+
command.dispose();
|
184
|
+
});
|
185
|
+
goog.array.forEach(this.queuedCommands_, function(frame) {
|
186
|
+
goog.array.forEach(frame, function(command) {
|
187
|
+
command.dispose();
|
188
|
+
});
|
189
|
+
});
|
190
|
+
|
191
191
|
delete this.commandProcessor_;
|
192
192
|
delete this.pendingCommands_;
|
193
|
-
delete this.
|
194
|
-
delete this.commandHistory_;
|
193
|
+
delete this.queuedCommands_;
|
195
194
|
delete this.isPaused_;
|
196
195
|
delete this.context_;
|
197
196
|
delete this.sessionLocked_;
|
@@ -204,44 +203,60 @@ webdriver.WebDriver.prototype.disposeInternal = function() {
|
|
204
203
|
|
205
204
|
/**
|
206
205
|
* Queues a command to execute.
|
207
|
-
* @param {webdriver.
|
208
|
-
* @param {
|
209
|
-
*
|
206
|
+
* @param {webdriver.CommandName} name The name of the command to execute.
|
207
|
+
* @param {webdriver.WebElement} opt_element The element that is the target
|
208
|
+
* of the new command.
|
209
|
+
* @return {webdriver.Command} The new command.
|
210
210
|
* @protected
|
211
211
|
*/
|
212
|
-
webdriver.WebDriver.prototype.addCommand = function(
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
}
|
217
|
-
var frame = goog.array.peek(this.frames_);
|
218
|
-
if (opt_addToFront) {
|
219
|
-
goog.array.insertAt(frame, command, 0);
|
220
|
-
} else {
|
221
|
-
frame.push(command);
|
222
|
-
}
|
212
|
+
webdriver.WebDriver.prototype.addCommand = function(name, opt_element) {
|
213
|
+
var command = new webdriver.Command(this, name, opt_element);
|
214
|
+
goog.array.peek(this.queuedCommands_).push(command);
|
215
|
+
return command;
|
223
216
|
};
|
224
217
|
|
225
218
|
|
226
219
|
/**
|
227
|
-
* @return {
|
228
|
-
*
|
220
|
+
* @return {boolean} Whether this driver is idle (there are no pending
|
221
|
+
* commands).
|
229
222
|
*/
|
230
|
-
webdriver.WebDriver.prototype.
|
231
|
-
|
223
|
+
webdriver.WebDriver.prototype.isIdle = function() {
|
224
|
+
// If there is a finished command on the pending command queue, but it
|
225
|
+
// failed, then the failure hasn't been dealt with yet and the driver will
|
226
|
+
// not process any more commands, so we consider this idle.
|
227
|
+
var pendingCommand = goog.array.peek(this.pendingCommands_);
|
228
|
+
if (pendingCommand && pendingCommand.isFinished() &&
|
229
|
+
pendingCommand.getResponse().isFailure) {
|
230
|
+
return true;
|
231
|
+
}
|
232
|
+
return !pendingCommand && this.queuedCommands_.length == 1 &&
|
233
|
+
!this.queuedCommands_[0].length;
|
232
234
|
};
|
233
235
|
|
234
236
|
|
235
237
|
/**
|
236
|
-
* Aborts the
|
237
|
-
*
|
238
|
+
* Aborts the specified command and all of its pending subcommands.
|
239
|
+
* @param {webdriver.Command} command The command to abort.
|
240
|
+
* @return {number} The total number of commands aborted. A value of 0
|
241
|
+
* indicates that the given command was not a pending command.
|
238
242
|
*/
|
239
|
-
webdriver.WebDriver.prototype.
|
240
|
-
goog.array.
|
241
|
-
|
243
|
+
webdriver.WebDriver.prototype.abortCommand = function(command) {
|
244
|
+
var index = goog.array.findIndexRight(this.pendingCommands_, function(cmd) {
|
245
|
+
return cmd == command;
|
242
246
|
});
|
243
|
-
|
244
|
-
|
247
|
+
if (index >= 0) {
|
248
|
+
var numAborted = this.pendingCommands_.length - index;
|
249
|
+
var totalNumAborted = numAborted;
|
250
|
+
for (var i = 0; i < numAborted; i++) {
|
251
|
+
this.pendingCommands_.pop().dispose();
|
252
|
+
goog.array.forEach(this.queuedCommands_.pop(), function(subCommand) {
|
253
|
+
totalNumAborted += 1;
|
254
|
+
subCommand.dispose();
|
255
|
+
});
|
256
|
+
}
|
257
|
+
return totalNumAborted;
|
258
|
+
}
|
259
|
+
return 0;
|
245
260
|
};
|
246
261
|
|
247
262
|
|
@@ -273,62 +288,38 @@ webdriver.WebDriver.prototype.resume = function() {
|
|
273
288
|
* @private
|
274
289
|
*/
|
275
290
|
webdriver.WebDriver.prototype.processCommands_ = function() {
|
276
|
-
|
291
|
+
var pendingCommand = goog.array.peek(this.pendingCommands_);
|
292
|
+
if (this.isPaused_ || (pendingCommand && !pendingCommand.isFinished())) {
|
277
293
|
return;
|
278
294
|
}
|
279
295
|
|
280
|
-
|
281
|
-
|
296
|
+
if (pendingCommand && pendingCommand.getResponse().isFailure) {
|
297
|
+
// Or should we be throwing this to be caught by window.onerror?
|
298
|
+
webdriver.logging.error(
|
299
|
+
'Unhandled command failure; halting command processing:\n' +
|
300
|
+
pendingCommand.getResponse().getErrorMessage());
|
282
301
|
return;
|
283
302
|
}
|
284
303
|
|
285
|
-
var currentFrame = goog.array.peek(this.
|
304
|
+
var currentFrame = goog.array.peek(this.queuedCommands_);
|
286
305
|
var nextCommand = currentFrame.shift();
|
306
|
+
while (!nextCommand && this.queuedCommands_.length > 1) {
|
307
|
+
this.queuedCommands_.pop();
|
308
|
+
this.pendingCommands_.pop();
|
309
|
+
currentFrame = goog.array.peek(this.queuedCommands_);
|
310
|
+
nextCommand = currentFrame.shift();
|
311
|
+
}
|
312
|
+
|
287
313
|
if (nextCommand) {
|
314
|
+
var parentTarget = goog.array.peek(this.pendingCommands_) || this;
|
315
|
+
nextCommand.setParentEventTarget(parentTarget);
|
288
316
|
this.pendingCommands_.push(nextCommand);
|
289
|
-
|
290
|
-
this.frames_.push([]);
|
291
|
-
} else if (nextCommand.name == webdriver.CommandName.WAIT) {
|
292
|
-
this.waitFrame_ = [];
|
293
|
-
this.frames_.push(this.waitFrame_);
|
294
|
-
}
|
295
|
-
|
296
|
-
nextCommand.setCompleteCallback(this.onCommandComplete_, this);
|
317
|
+
this.queuedCommands_.push([]);
|
297
318
|
this.commandProcessor_.execute(nextCommand, this.sessionId_, this.context_);
|
298
|
-
} else if (this.frames_.length > 1) {
|
299
|
-
if (currentFrame !== this.waitFrame_) {
|
300
|
-
this.frames_.pop();
|
301
|
-
}
|
302
|
-
}
|
303
|
-
};
|
304
|
-
|
305
|
-
|
306
|
-
/**
|
307
|
-
* Callback for when a pending {@code webdriver.Command} is finished.
|
308
|
-
* @private
|
309
|
-
*/
|
310
|
-
webdriver.WebDriver.prototype.onCommandComplete_ = function(command) {
|
311
|
-
this.commandHistory_.push(command);
|
312
|
-
if (command.response.isFailure || command.response.errors.length) {
|
313
|
-
if (webdriver.CommandName.WAIT == command.name) {
|
314
|
-
// The wait terminated early. Abort all other commands issued inside the
|
315
|
-
// wait condition.
|
316
|
-
for (var i = 1; i < this.pendingCommands_.length; i++) {
|
317
|
-
this.pendingCommands_[i].abort = true;
|
318
|
-
}
|
319
|
-
this.pendingCommands_ = [this.pendingCommands_[0]];
|
320
|
-
}
|
321
|
-
this.dispatchEvent(webdriver.WebDriver.EventType.ERROR);
|
322
|
-
} else {
|
323
|
-
this.pendingCommands_.pop();
|
324
|
-
if (webdriver.CommandName.WAIT == command.name) {
|
325
|
-
this.waitFrame_ = null;
|
326
|
-
}
|
327
319
|
}
|
328
320
|
};
|
329
321
|
|
330
322
|
|
331
|
-
|
332
323
|
/**
|
333
324
|
* @return {?string} This instance's current session ID or {@code null} if it
|
334
325
|
* does not have one yet.
|
@@ -346,6 +337,15 @@ webdriver.WebDriver.prototype.getContext = function() {
|
|
346
337
|
};
|
347
338
|
|
348
339
|
|
340
|
+
/**
|
341
|
+
* Sets this driver's context.
|
342
|
+
* @param {webdriver.Context} context The new context.
|
343
|
+
*/
|
344
|
+
webdriver.WebDriver.prototype.setContext = function(context) {
|
345
|
+
return this.context_ = context;
|
346
|
+
};
|
347
|
+
|
348
|
+
|
349
349
|
// ----------------------------------------------------------------------------
|
350
350
|
// Client command functions:
|
351
351
|
// ----------------------------------------------------------------------------
|
@@ -361,66 +361,32 @@ webdriver.WebDriver.prototype.getContext = function() {
|
|
361
361
|
*/
|
362
362
|
webdriver.WebDriver.prototype.catchExpectedError = function(opt_errorMsg,
|
363
363
|
opt_handlerFn) {
|
364
|
-
var currentFrame = goog.array.peek(this.
|
365
|
-
var previousCommand =
|
364
|
+
var currentFrame = goog.array.peek(this.queuedCommands_);
|
365
|
+
var previousCommand = goog.array.peek(currentFrame);
|
366
366
|
if (!previousCommand) {
|
367
367
|
throw new Error('No commands in the queue to expect an error from');
|
368
368
|
}
|
369
369
|
|
370
|
-
var
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
// Errors cause the pending command to hang. Go ahead and abort that command
|
389
|
-
// so we can proceed.
|
390
|
-
this.abortPendingCommand();
|
391
|
-
var frame = goog.array.peek(this.frames_);
|
392
|
-
while (frame !== currentFrame) {
|
393
|
-
this.frames_.pop();
|
394
|
-
frame = goog.array.peek(this.frames_);
|
370
|
+
var failedCommand = null;
|
371
|
+
var key = goog.events.listenOnce(previousCommand,
|
372
|
+
webdriver.Command.ERROR_EVENT, function(e) {
|
373
|
+
failedCommand = e.target;
|
374
|
+
this.abortCommand(e.currentTarget);
|
375
|
+
e.preventDefault();
|
376
|
+
e.stopPropagation();
|
377
|
+
return false;
|
378
|
+
}, /*capture phase*/true, this);
|
379
|
+
|
380
|
+
this.callFunction(function() {
|
381
|
+
if (null == failedCommand) {
|
382
|
+
goog.events.unlistenByKey(key);
|
383
|
+
throw new Error(
|
384
|
+
(opt_errorMsg ? (opt_errorMsg + '\n') : '') +
|
385
|
+
'Expected an error but none were raised.');
|
386
|
+
} else if (goog.isFunction(opt_handlerFn)) {
|
387
|
+
opt_handlerFn(failedCommand);
|
395
388
|
}
|
396
|
-
|
397
|
-
};
|
398
|
-
|
399
|
-
// Surround the last command with two new commands. The first enables our
|
400
|
-
// error listener which cancels any errors. The second verifies that we
|
401
|
-
// caught an error. If not, it fails the test.
|
402
|
-
var catchExpected = new webdriver.Command(webdriver.CommandName.FUNCTION).
|
403
|
-
setParameters(goog.bind(function() {
|
404
|
-
goog.events.listenOnce(this, webdriver.WebDriver.EventType.ERROR,
|
405
|
-
handleError, /*capture=*/true);
|
406
|
-
}, this));
|
407
|
-
|
408
|
-
var cleanupCatch = new webdriver.Command(webdriver.CommandName.FUNCTION).
|
409
|
-
setParameters(goog.bind(function() {
|
410
|
-
// Need to unlisten for error events so the error below doesn't get
|
411
|
-
// blocked.
|
412
|
-
goog.events.unlisten(this, webdriver.WebDriver.EventType.ERROR,
|
413
|
-
handleError, /*capture=*/true);
|
414
|
-
if (!caughtError) {
|
415
|
-
throw new Error(
|
416
|
-
(opt_errorMsg ? (opt_errorMsg + '\n') : '') +
|
417
|
-
'Expected an error but none were raised.');
|
418
|
-
}
|
419
|
-
}, this));
|
420
|
-
|
421
|
-
currentFrame.push(catchExpected);
|
422
|
-
currentFrame.push(previousCommand);
|
423
|
-
currentFrame.push(cleanupCatch);
|
389
|
+
});
|
424
390
|
};
|
425
391
|
|
426
392
|
|
@@ -441,8 +407,7 @@ webdriver.WebDriver.prototype.pause = function() {
|
|
441
407
|
* sleep.
|
442
408
|
*/
|
443
409
|
webdriver.WebDriver.prototype.sleep = function(ms) {
|
444
|
-
this.addCommand(
|
445
|
-
setParameters(ms));
|
410
|
+
this.addCommand(webdriver.CommandName.SLEEP).setParameters(ms);
|
446
411
|
};
|
447
412
|
|
448
413
|
|
@@ -453,24 +418,27 @@ webdriver.WebDriver.prototype.sleep = function(ms) {
|
|
453
418
|
* {@code webdriver.Response} and passed to any subsequent function commands.
|
454
419
|
* @param {function} fn The function to call; should take a single
|
455
420
|
* {@code webdriver.Response} object.
|
421
|
+
* @return {webdriver.Future} The result of the function wrapped in a future.
|
456
422
|
*/
|
457
423
|
webdriver.WebDriver.prototype.callFunction = function(fn, opt_selfObj,
|
458
424
|
var_args) {
|
459
425
|
var args = goog.array.slice(arguments, 2);
|
426
|
+
var frame = goog.array.peek(this.queuedCommands_);
|
427
|
+
var previousCommand = goog.array.peek(frame);
|
460
428
|
var wrappedFunction = goog.bind(function() {
|
461
|
-
|
462
|
-
|
463
|
-
fn.apply(opt_selfObj, args);
|
429
|
+
args.push(previousCommand ? previousCommand.getResponse() : null);
|
430
|
+
return fn.apply(opt_selfObj, args);
|
464
431
|
}, this);
|
465
|
-
this.addCommand(
|
466
|
-
setParameters(wrappedFunction)
|
432
|
+
return this.addCommand(webdriver.CommandName.FUNCTION).
|
433
|
+
setParameters(wrappedFunction).
|
434
|
+
getFutureResult();
|
467
435
|
};
|
468
436
|
|
469
437
|
|
470
438
|
/**
|
471
439
|
* Waits for a condition to be true before executing the next command. If the
|
472
440
|
* condition does not hold after the given {@code timeout}, an error will be
|
473
|
-
* raised.
|
441
|
+
* raised.
|
474
442
|
* Example:
|
475
443
|
* <code>
|
476
444
|
* driver.get('http://www.google.com');
|
@@ -481,23 +449,46 @@ webdriver.WebDriver.prototype.callFunction = function(fn, opt_selfObj,
|
|
481
449
|
* @param {number} timeout The maximum amount of time to wait, in milliseconds.
|
482
450
|
* @param {Object} opt_self (Optional) The object in whose context to execute
|
483
451
|
* the {@code conditionFn}.
|
484
|
-
* @
|
485
|
-
* @
|
486
|
-
*/
|
487
|
-
webdriver.WebDriver.prototype.wait = function(conditionFn, timeout, opt_self
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
452
|
+
* @param {boolean} opt_waitNot (Optional) Whether to wait for the inverse of
|
453
|
+
* the {@code conditionFn}.
|
454
|
+
*/
|
455
|
+
webdriver.WebDriver.prototype.wait = function(conditionFn, timeout, opt_self,
|
456
|
+
opt_waitNot) {
|
457
|
+
conditionFn = goog.bind(conditionFn, opt_self);
|
458
|
+
var waitOnInverse = !!opt_waitNot;
|
459
|
+
var callFunction = goog.bind(this.callFunction, this);
|
460
|
+
|
461
|
+
function pollFunction(opt_startTime, opt_future) {
|
462
|
+
var startTime = opt_startTime || goog.now();
|
463
|
+
|
464
|
+
function checkValue(value) {
|
465
|
+
var pendingFuture = null;
|
466
|
+
if (value instanceof webdriver.Future) {
|
467
|
+
if (value.isSet()) {
|
468
|
+
value = value.getValue();
|
469
|
+
} else {
|
470
|
+
pendingFuture = value;
|
471
|
+
value = null;
|
472
|
+
}
|
473
|
+
}
|
474
|
+
|
475
|
+
var done = !pendingFuture && (waitOnInverse != !!value);
|
476
|
+
if (!done) {
|
477
|
+
var ellapsed = goog.now() - startTime;
|
478
|
+
if (ellapsed > timeout) {
|
479
|
+
throw Error('Wait timed out after ' + ellapsed + 'ms');
|
480
|
+
}
|
481
|
+
callFunction(pollFunction, null, startTime, pendingFuture);
|
482
|
+
}
|
492
483
|
}
|
493
|
-
}
|
494
484
|
|
495
|
-
|
496
|
-
|
485
|
+
var result = opt_future || conditionFn();
|
486
|
+
checkValue(result);
|
497
487
|
}
|
498
|
-
|
499
|
-
|
500
|
-
|
488
|
+
|
489
|
+
// Binding pollFunction for our initial values.
|
490
|
+
var initialPoll = goog.bind(pollFunction, null, 0, null);
|
491
|
+
this.addCommand(webdriver.CommandName.WAIT).setParameters(initialPoll);
|
501
492
|
};
|
502
493
|
|
503
494
|
|
@@ -514,17 +505,10 @@ webdriver.WebDriver.prototype.wait = function(conditionFn, timeout, opt_self) {
|
|
514
505
|
* @param {number} timeout The maximum amount of time to wait, in milliseconds.
|
515
506
|
* @param {Object} opt_self (Optional) The object in whose context to execute
|
516
507
|
* the {@code conditionFn}.
|
517
|
-
* @see webdriver.Wait
|
518
508
|
*/
|
519
|
-
webdriver.WebDriver.prototype.waitNot = function(conditionFn, timeout,
|
520
|
-
|
521
|
-
|
522
|
-
conditionFn = goog.bind(conditionFn, opt_self);
|
523
|
-
}
|
524
|
-
var waitOp = new webdriver.Wait(conditionFn, timeout);
|
525
|
-
waitOp.waitOnInverse(true);
|
526
|
-
this.addCommand(new webdriver.Command(webdriver.CommandName.WAIT).
|
527
|
-
setParameters(waitOp));
|
509
|
+
webdriver.WebDriver.prototype.waitNot = function(conditionFn, timeout,
|
510
|
+
opt_self) {
|
511
|
+
this.wait(conditionFn, timeout, opt_self, true);
|
528
512
|
};
|
529
513
|
|
530
514
|
|
@@ -537,12 +521,12 @@ webdriver.WebDriver.prototype.waitNot = function(conditionFn, timeout, opt_self,
|
|
537
521
|
*/
|
538
522
|
webdriver.WebDriver.prototype.newSession = function(lockSession) {
|
539
523
|
if (lockSession) {
|
540
|
-
this.addCommand(
|
524
|
+
this.addCommand(webdriver.CommandName.NEW_SESSION).
|
541
525
|
setSuccessCallback(function(response) {
|
542
526
|
this.sessionLocked_ = lockSession;
|
543
527
|
this.sessionId_ = response.value;
|
544
528
|
this.context_ = response.context;
|
545
|
-
}, this)
|
529
|
+
}, this);
|
546
530
|
} else {
|
547
531
|
webdriver.logging.warn(
|
548
532
|
'Cannot start new session; driver is locked into current session');
|
@@ -558,11 +542,11 @@ webdriver.WebDriver.prototype.newSession = function(lockSession) {
|
|
558
542
|
* {@code #getWindowHandle()} or {@code #getAllWindowHandles()}.
|
559
543
|
*/
|
560
544
|
webdriver.WebDriver.prototype.switchToWindow = function(name) {
|
561
|
-
this.addCommand(
|
545
|
+
this.addCommand(webdriver.CommandName.SWITCH_TO_WINDOW).
|
562
546
|
setParameters(name).
|
563
547
|
setSuccessCallback(function(response) {
|
564
548
|
this.context_ = response.value;
|
565
|
-
}, this)
|
549
|
+
}, this);
|
566
550
|
};
|
567
551
|
|
568
552
|
|
@@ -580,13 +564,13 @@ webdriver.WebDriver.prototype.switchToFrame = function(frame) {
|
|
580
564
|
var commandName = webdriver.CommandName.SWITCH_TO_FRAME;
|
581
565
|
var command;
|
582
566
|
if (goog.isString(frame) || goog.isNumber(frame)) {
|
583
|
-
command =
|
567
|
+
command = this.addCommand(commandName).setParameters(frame);
|
584
568
|
} else {
|
585
|
-
command =
|
569
|
+
command = this.addCommand(commandName, frame);
|
586
570
|
}
|
587
|
-
|
571
|
+
command.setSuccessCallback(function(response) {
|
588
572
|
this.context_ = response.context;
|
589
|
-
}, this)
|
573
|
+
}, this);
|
590
574
|
};
|
591
575
|
|
592
576
|
|
@@ -595,13 +579,11 @@ webdriver.WebDriver.prototype.switchToFrame = function(frame) {
|
|
595
579
|
* contains iframes.
|
596
580
|
*/
|
597
581
|
webdriver.WebDriver.prototype.switchToDefaultContent = function() {
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
}, this);
|
604
|
-
this.addCommand(command);
|
582
|
+
this.addCommand(webdriver.CommandName.SWITCH_TO_DEFAULT_CONTENT).
|
583
|
+
setParameters(null).
|
584
|
+
setSuccessCallback(function(response) {
|
585
|
+
this.context_ = response.context;
|
586
|
+
}, this);
|
605
587
|
};
|
606
588
|
|
607
589
|
|
@@ -610,12 +592,8 @@ webdriver.WebDriver.prototype.switchToDefaultContent = function() {
|
|
610
592
|
* @return {webdriver.Future} The current handle wrapped in a Future.
|
611
593
|
*/
|
612
594
|
webdriver.WebDriver.prototype.getWindowHandle = function() {
|
613
|
-
|
614
|
-
|
615
|
-
new webdriver.Command(webdriver.CommandName.GET_CURRENT_WINDOW_HANDLE).
|
616
|
-
setSuccessCallback(handle.setValueFromResponse, handle);
|
617
|
-
this.addCommand(command);
|
618
|
-
return handle;
|
595
|
+
return this.addCommand(webdriver.CommandName.GET_CURRENT_WINDOW_HANDLE).
|
596
|
+
getFutureResult();
|
619
597
|
};
|
620
598
|
|
621
599
|
|
@@ -623,12 +601,7 @@ webdriver.WebDriver.prototype.getWindowHandle = function() {
|
|
623
601
|
* Retrieves the handles for all known windows.
|
624
602
|
*/
|
625
603
|
webdriver.WebDriver.prototype.getAllWindowHandles = function() {
|
626
|
-
|
627
|
-
new webdriver.Command(webdriver.CommandName.GET_WINDOW_HANDLES).
|
628
|
-
setSuccessCallback(function(response) {
|
629
|
-
response.value = response.value.split(',');
|
630
|
-
});
|
631
|
-
this.addCommand(command);
|
604
|
+
this.addCommand(webdriver.CommandName.GET_WINDOW_HANDLES);
|
632
605
|
};
|
633
606
|
|
634
607
|
|
@@ -637,11 +610,8 @@ webdriver.WebDriver.prototype.getAllWindowHandles = function() {
|
|
637
610
|
* @return {webdriver.Future} The page source wrapped in a Future.
|
638
611
|
*/
|
639
612
|
webdriver.WebDriver.prototype.getPageSource = function() {
|
640
|
-
|
641
|
-
|
642
|
-
setSuccessCallback(source.setValueFromResponse, source);
|
643
|
-
this.addCommand(command);
|
644
|
-
return source;
|
613
|
+
return this.addCommand(webdriver.CommandName.GET_PAGE_SOURCE).
|
614
|
+
getFutureResult();
|
645
615
|
};
|
646
616
|
|
647
617
|
|
@@ -651,7 +621,7 @@ webdriver.WebDriver.prototype.getPageSource = function() {
|
|
651
621
|
* script window (e.g. the window sending commands to the driver)</strong>
|
652
622
|
*/
|
653
623
|
webdriver.WebDriver.prototype.close = function() {
|
654
|
-
this.addCommand(
|
624
|
+
this.addCommand(webdriver.CommandName.CLOSE);
|
655
625
|
};
|
656
626
|
|
657
627
|
|
@@ -664,7 +634,7 @@ webdriver.WebDriver.prototype.close = function() {
|
|
664
634
|
* @see {webdriver.WebDriver.prototype.executeScript}
|
665
635
|
* @private
|
666
636
|
*/
|
667
|
-
webdriver.WebDriver.
|
637
|
+
webdriver.WebDriver.wrapScriptArgument_ = function(arg) {
|
668
638
|
var type, value;
|
669
639
|
if (arg instanceof webdriver.WebElement) {
|
670
640
|
type = 'ELEMENT';
|
@@ -674,6 +644,9 @@ webdriver.WebDriver.mapToExecuteScriptArgument_ = function(arg) {
|
|
674
644
|
goog.isString(arg)) {
|
675
645
|
type = goog.typeOf(arg).toUpperCase();
|
676
646
|
value = arg;
|
647
|
+
} else if (goog.isArray(arg)) {
|
648
|
+
type = goog.typeOf(arg).toUpperCase();
|
649
|
+
value = goog.array.map(arg, webdriver.WebDriver.wrapScriptArgument_);
|
677
650
|
} else {
|
678
651
|
throw new Error('Invalid script argument type: ' + goog.typeOf(arg));
|
679
652
|
}
|
@@ -681,6 +654,30 @@ webdriver.WebDriver.mapToExecuteScriptArgument_ = function(arg) {
|
|
681
654
|
};
|
682
655
|
|
683
656
|
|
657
|
+
/**
|
658
|
+
* Helper function for unwrapping an executeScript result.
|
659
|
+
* @param {{type:string,value:*}|Array.<{type:string,value:*}>} result The
|
660
|
+
* result to unwrap.
|
661
|
+
* @return {*} The unwrapped result.
|
662
|
+
* @private
|
663
|
+
*/
|
664
|
+
webdriver.WebDriver.prototype.unwrapScriptResult_ = function(result) {
|
665
|
+
switch (result.type) {
|
666
|
+
case 'ELEMENT':
|
667
|
+
var element = new webdriver.WebElement(this);
|
668
|
+
element.getId().setValue(result.value);
|
669
|
+
return element;
|
670
|
+
|
671
|
+
case 'ARRAY':
|
672
|
+
return goog.array.map(result.value, goog.bind(
|
673
|
+
this.unwrapScriptResult_, this));
|
674
|
+
|
675
|
+
default:
|
676
|
+
return result.value;
|
677
|
+
}
|
678
|
+
};
|
679
|
+
|
680
|
+
|
684
681
|
/**
|
685
682
|
* Adds a command to execute a JavaScript snippet in the window of the page
|
686
683
|
* currently under test.
|
@@ -692,29 +689,13 @@ webdriver.WebDriver.mapToExecuteScriptArgument_ = function(arg) {
|
|
692
689
|
webdriver.WebDriver.prototype.executeScript = function(script, var_args) {
|
693
690
|
var args = goog.array.map(
|
694
691
|
goog.array.slice(arguments, 1),
|
695
|
-
webdriver.WebDriver.
|
696
|
-
|
697
|
-
this.addCommand(new webdriver.Command(webdriver.CommandName.EXECUTE_SCRIPT).
|
692
|
+
webdriver.WebDriver.wrapScriptArgument_);
|
693
|
+
return this.addCommand(webdriver.CommandName.EXECUTE_SCRIPT).
|
698
694
|
setParameters(script, args).
|
699
695
|
setSuccessCallback(function(response) {
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
break;
|
704
|
-
|
705
|
-
case 'ELEMENT':
|
706
|
-
var id = response.value;
|
707
|
-
response.value = new webdriver.WebElement(this);
|
708
|
-
response.value.getId().setValue(id);
|
709
|
-
break;
|
710
|
-
|
711
|
-
case 'OTHER': // Fall-through
|
712
|
-
default:
|
713
|
-
break;
|
714
|
-
}
|
715
|
-
result.setValue(response.value);
|
716
|
-
}, this));
|
717
|
-
return result;
|
696
|
+
response.value = this.unwrapScriptResult_(response.value);
|
697
|
+
}, this).
|
698
|
+
getFutureResult();
|
718
699
|
};
|
719
700
|
|
720
701
|
|
@@ -723,11 +704,11 @@ webdriver.WebDriver.prototype.executeScript = function(script, var_args) {
|
|
723
704
|
* @param {goog.Uri|string} url The URL to fetch.
|
724
705
|
*/
|
725
706
|
webdriver.WebDriver.prototype.get = function(url) {
|
726
|
-
this.addCommand(
|
707
|
+
this.addCommand(webdriver.CommandName.GET).
|
727
708
|
setParameters(url.toString()).
|
728
709
|
setSuccessCallback(function(response) {
|
729
710
|
this.context_ = response.context;
|
730
|
-
}, this)
|
711
|
+
}, this);
|
731
712
|
};
|
732
713
|
|
733
714
|
|
@@ -735,7 +716,7 @@ webdriver.WebDriver.prototype.get = function(url) {
|
|
735
716
|
* Navigate backwards in the current browser window's history.
|
736
717
|
*/
|
737
718
|
webdriver.WebDriver.prototype.back = function() {
|
738
|
-
this.addCommand(
|
719
|
+
this.addCommand(webdriver.CommandName.BACK);
|
739
720
|
};
|
740
721
|
|
741
722
|
|
@@ -743,7 +724,7 @@ webdriver.WebDriver.prototype.back = function() {
|
|
743
724
|
* Navigate forwards in the current browser window's history.
|
744
725
|
*/
|
745
726
|
webdriver.WebDriver.prototype.forward = function() {
|
746
|
-
this.addCommand(
|
727
|
+
this.addCommand(webdriver.CommandName.FORWARD);
|
747
728
|
};
|
748
729
|
|
749
730
|
|
@@ -751,7 +732,7 @@ webdriver.WebDriver.prototype.forward = function() {
|
|
751
732
|
* Refresh the current page.
|
752
733
|
*/
|
753
734
|
webdriver.WebDriver.prototype.refresh = function() {
|
754
|
-
this.addCommand(
|
735
|
+
this.addCommand(webdriver.CommandName.REFRESH);
|
755
736
|
};
|
756
737
|
|
757
738
|
|
@@ -760,10 +741,8 @@ webdriver.WebDriver.prototype.refresh = function() {
|
|
760
741
|
* @return {webdriver.Future} The current URL in a webdriver.Future.
|
761
742
|
*/
|
762
743
|
webdriver.WebDriver.prototype.getCurrentUrl = function() {
|
763
|
-
|
764
|
-
|
765
|
-
setSuccessCallback(url.setValueFromResponse, url));
|
766
|
-
return url;
|
744
|
+
return this.addCommand(webdriver.CommandName.GET_CURRENT_URL).
|
745
|
+
getFutureResult();
|
767
746
|
};
|
768
747
|
|
769
748
|
|
@@ -772,10 +751,8 @@ webdriver.WebDriver.prototype.getCurrentUrl = function() {
|
|
772
751
|
* @return {webdriver.Future} The current page title.
|
773
752
|
*/
|
774
753
|
webdriver.WebDriver.prototype.getTitle = function() {
|
775
|
-
|
776
|
-
|
777
|
-
setSuccessCallback(title.setValueFromResponse, title));
|
778
|
-
return title;
|
754
|
+
return this.addCommand(webdriver.CommandName.GET_TITLE).
|
755
|
+
getFutureResult();
|
779
756
|
};
|
780
757
|
|
781
758
|
|
@@ -831,8 +808,8 @@ webdriver.WebDriver.prototype.findElements = function(by) {
|
|
831
808
|
* @param {webdriver.WebDriver.Speed} speed The new speed setting.
|
832
809
|
*/
|
833
810
|
webdriver.WebDriver.prototype.setMouseSpeed = function(speed) {
|
834
|
-
this.addCommand(
|
835
|
-
setParameters(speed)
|
811
|
+
this.addCommand(webdriver.CommandName.SET_MOUSE_SPEED).
|
812
|
+
setParameters(speed);
|
836
813
|
};
|
837
814
|
|
838
815
|
|
@@ -842,12 +819,6 @@ webdriver.WebDriver.prototype.setMouseSpeed = function(speed) {
|
|
842
819
|
* when the query command completes.
|
843
820
|
*/
|
844
821
|
webdriver.WebDriver.prototype.getMouseSpeed = function() {
|
845
|
-
|
846
|
-
|
847
|
-
new webdriver.Command(webdriver.CommandName.GET_MOUSE_SPEED).
|
848
|
-
setSuccessCallback(function(response) {
|
849
|
-
response.value = Number(response.value);
|
850
|
-
speed.setValue(response.value);
|
851
|
-
}));
|
852
|
-
return speed;
|
822
|
+
return this.addCommand(webdriver.CommandName.GET_MOUSE_SPEED).
|
823
|
+
getFutureResult();
|
853
824
|
};
|