selenium-webdriver 3.0.0-beta-1 → 3.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.
- package/CHANGES.md +109 -0
- package/LICENSE +1 -1
- package/README.md +7 -6
- package/chrome.js +31 -128
- package/edge.js +13 -91
- package/example/chrome_android.js +18 -13
- package/example/chrome_mobile_emulation.js +19 -15
- package/example/google_search.js +11 -11
- package/example/google_search_generator.js +23 -18
- package/example/google_search_test.js +31 -17
- package/example/logging.js +9 -17
- package/example/parallel_flows.js +3 -0
- package/firefox/binary.js +17 -0
- package/firefox/index.js +198 -101
- package/firefox/profile.js +24 -3
- package/http/util.js +95 -59
- package/ie.js +6 -10
- package/index.js +636 -2
- package/lib/actions.js +18 -10
- package/lib/atoms/getAttribute.js +11 -0
- package/lib/atoms/isDisplayed.js +106 -0
- package/lib/firefox/amd64/libnoblur64.so +0 -0
- package/lib/firefox/i386/libnoblur.so +0 -0
- package/lib/firefox/webdriver.xpi +0 -0
- package/lib/http.js +159 -46
- package/lib/logging.js +7 -1
- package/lib/promise.js +602 -358
- package/lib/proxy.js +28 -0
- package/lib/session.js +1 -1
- package/lib/test/build.js +26 -28
- package/lib/test/data/formPage.html +1 -0
- package/lib/test/fileserver.js +12 -10
- package/lib/test/httpserver.js +4 -6
- package/lib/test/index.js +18 -11
- package/lib/test/promise.js +79 -0
- package/lib/webdriver.js +587 -479
- package/opera.js +12 -88
- package/package.json +13 -14
- package/phantomjs.js +7 -14
- package/remote/index.js +201 -30
- package/safari.js +62 -416
- package/test/actions_test.js +9 -11
- package/test/chrome/options_test.js +8 -8
- package/test/chrome/service_test.js +2 -2
- package/test/cookie_test.js +57 -57
- package/test/element_finding_test.js +201 -185
- package/test/execute_script_test.js +108 -111
- package/test/fingerprint_test.js +16 -11
- package/test/firefox/firefox_test.js +75 -49
- package/test/firefox/profile_test.js +1 -3
- package/test/http/util_test.js +21 -27
- package/test/io_test.js +2 -5
- package/test/lib/http_test.js +8 -6
- package/test/lib/promise_aplus_test.js +48 -44
- package/test/lib/promise_error_test.js +687 -611
- package/test/lib/promise_flow_test.js +1810 -1806
- package/test/lib/promise_generator_test.js +227 -225
- package/test/lib/promise_test.js +864 -835
- package/test/lib/until_test.js +1 -1
- package/test/lib/webdriver_test.js +520 -424
- package/test/logging_test.js +43 -45
- package/test/net/portprober_test.js +23 -24
- package/test/page_loading_test.js +84 -78
- package/test/phantomjs/execute_phantomjs_test.js +11 -25
- package/test/proxy_test.js +23 -23
- package/test/remote_test.js +22 -22
- package/test/safari_test.js +108 -0
- package/test/session_test.js +11 -10
- package/test/stale_element_test.js +18 -16
- package/test/tag_name_test.js +7 -5
- package/test/testing/assert_test.js +2 -3
- package/test/testing/index_test.js +163 -117
- package/test/upload_test.js +13 -13
- package/test/window_test.js +94 -70
- package/testing/index.js +176 -37
- package/builder.js +0 -553
- package/lib/safari/client.js +0 -56
package/lib/webdriver.js
CHANGED
|
@@ -28,7 +28,7 @@ const command = require('./command');
|
|
|
28
28
|
const error = require('./error');
|
|
29
29
|
const input = require('./input');
|
|
30
30
|
const logging = require('./logging');
|
|
31
|
-
const Session = require('./session')
|
|
31
|
+
const {Session} = require('./session');
|
|
32
32
|
const Symbols = require('./symbols');
|
|
33
33
|
const promise = require('./promise');
|
|
34
34
|
|
|
@@ -64,13 +64,13 @@ class Condition {
|
|
|
64
64
|
/**
|
|
65
65
|
* Defines a condition that will result in a {@link WebElement}.
|
|
66
66
|
*
|
|
67
|
-
* @extends {Condition<!(WebElement|
|
|
67
|
+
* @extends {Condition<!(WebElement|IThenable<!WebElement>)>}
|
|
68
68
|
*/
|
|
69
69
|
class WebElementCondition extends Condition {
|
|
70
70
|
/**
|
|
71
71
|
* @param {string} message A descriptive error message. Should complete the
|
|
72
72
|
* sentence "Waiting [...]"
|
|
73
|
-
* @param {function(!WebDriver): !(WebElement|
|
|
73
|
+
* @param {function(!WebDriver): !(WebElement|IThenable<!WebElement>)}
|
|
74
74
|
* fn The condition function to evaluate on each iteration of the wait
|
|
75
75
|
* loop.
|
|
76
76
|
*/
|
|
@@ -237,45 +237,445 @@ function fromWireValue(driver, value) {
|
|
|
237
237
|
|
|
238
238
|
|
|
239
239
|
/**
|
|
240
|
-
*
|
|
240
|
+
* Structural interface for a WebDriver client.
|
|
241
241
|
*
|
|
242
|
-
*
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
242
|
+
* @record
|
|
243
|
+
*/
|
|
244
|
+
class IWebDriver {
|
|
245
|
+
|
|
246
|
+
/** @return {!promise.ControlFlow} The control flow used by this instance. */
|
|
247
|
+
controlFlow() {}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Schedules a {@link command.Command} to be executed by this driver's
|
|
251
|
+
* {@link command.Executor}.
|
|
252
|
+
*
|
|
253
|
+
* @param {!command.Command} command The command to schedule.
|
|
254
|
+
* @param {string} description A description of the command for debugging.
|
|
255
|
+
* @return {!promise.Thenable<T>} A promise that will be resolved
|
|
256
|
+
* with the command result.
|
|
257
|
+
* @template T
|
|
258
|
+
*/
|
|
259
|
+
schedule(command, description) {}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Sets the {@linkplain input.FileDetector file detector} that should be
|
|
263
|
+
* used with this instance.
|
|
264
|
+
* @param {input.FileDetector} detector The detector to use or {@code null}.
|
|
265
|
+
*/
|
|
266
|
+
setFileDetector(detector) {}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* @return {!command.Executor} The command executor used by this instance.
|
|
270
|
+
*/
|
|
271
|
+
getExecutor() {}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* @return {!promise.Thenable<!Session>} A promise for this client's session.
|
|
275
|
+
*/
|
|
276
|
+
getSession() {}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* @return {!promise.Thenable<!Capabilities>} A promise that will resolve with
|
|
280
|
+
* the this instance's capabilities.
|
|
281
|
+
*/
|
|
282
|
+
getCapabilities() {}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Terminates the browser session. After calling quit, this instance will be
|
|
286
|
+
* invalidated and may no longer be used to issue commands against the
|
|
287
|
+
* browser.
|
|
288
|
+
*
|
|
289
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved when the
|
|
290
|
+
* command has completed.
|
|
291
|
+
*/
|
|
292
|
+
quit() {}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Creates a new action sequence using this driver. The sequence will not be
|
|
296
|
+
* scheduled for execution until {@link actions.ActionSequence#perform} is
|
|
297
|
+
* called. Example:
|
|
298
|
+
*
|
|
299
|
+
* driver.actions().
|
|
300
|
+
* mouseDown(element1).
|
|
301
|
+
* mouseMove(element2).
|
|
302
|
+
* mouseUp().
|
|
303
|
+
* perform();
|
|
304
|
+
*
|
|
305
|
+
* @return {!actions.ActionSequence} A new action sequence for this instance.
|
|
306
|
+
*/
|
|
307
|
+
actions() {}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Creates a new touch sequence using this driver. The sequence will not be
|
|
311
|
+
* scheduled for execution until {@link actions.TouchSequence#perform} is
|
|
312
|
+
* called. Example:
|
|
313
|
+
*
|
|
314
|
+
* driver.touchActions().
|
|
315
|
+
* tap(element1).
|
|
316
|
+
* doubleTap(element2).
|
|
317
|
+
* perform();
|
|
318
|
+
*
|
|
319
|
+
* @return {!actions.TouchSequence} A new touch sequence for this instance.
|
|
320
|
+
*/
|
|
321
|
+
touchActions() {}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Schedules a command to execute JavaScript in the context of the currently
|
|
325
|
+
* selected frame or window. The script fragment will be executed as the body
|
|
326
|
+
* of an anonymous function. If the script is provided as a function object,
|
|
327
|
+
* that function will be converted to a string for injection into the target
|
|
328
|
+
* window.
|
|
329
|
+
*
|
|
330
|
+
* Any arguments provided in addition to the script will be included as script
|
|
331
|
+
* arguments and may be referenced using the {@code arguments} object.
|
|
332
|
+
* Arguments may be a boolean, number, string, or {@linkplain WebElement}.
|
|
333
|
+
* Arrays and objects may also be used as script arguments as long as each item
|
|
334
|
+
* adheres to the types previously mentioned.
|
|
335
|
+
*
|
|
336
|
+
* The script may refer to any variables accessible from the current window.
|
|
337
|
+
* Furthermore, the script will execute in the window's context, thus
|
|
338
|
+
* {@code document} may be used to refer to the current document. Any local
|
|
339
|
+
* variables will not be available once the script has finished executing,
|
|
340
|
+
* though global variables will persist.
|
|
341
|
+
*
|
|
342
|
+
* If the script has a return value (i.e. if the script contains a return
|
|
343
|
+
* statement), then the following steps will be taken for resolving this
|
|
344
|
+
* functions return value:
|
|
345
|
+
*
|
|
346
|
+
* - For a HTML element, the value will resolve to a {@linkplain WebElement}
|
|
347
|
+
* - Null and undefined return values will resolve to null</li>
|
|
348
|
+
* - Booleans, numbers, and strings will resolve as is</li>
|
|
349
|
+
* - Functions will resolve to their string representation</li>
|
|
350
|
+
* - For arrays and objects, each member item will be converted according to
|
|
351
|
+
* the rules above
|
|
352
|
+
*
|
|
353
|
+
* @param {!(string|Function)} script The script to execute.
|
|
354
|
+
* @param {...*} var_args The arguments to pass to the script.
|
|
355
|
+
* @return {!promise.Thenable<T>} A promise that will resolve to the
|
|
356
|
+
* scripts return value.
|
|
357
|
+
* @template T
|
|
358
|
+
*/
|
|
359
|
+
executeScript(script, var_args) {}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Schedules a command to execute asynchronous JavaScript in the context of the
|
|
363
|
+
* currently selected frame or window. The script fragment will be executed as
|
|
364
|
+
* the body of an anonymous function. If the script is provided as a function
|
|
365
|
+
* object, that function will be converted to a string for injection into the
|
|
366
|
+
* target window.
|
|
367
|
+
*
|
|
368
|
+
* Any arguments provided in addition to the script will be included as script
|
|
369
|
+
* arguments and may be referenced using the {@code arguments} object.
|
|
370
|
+
* Arguments may be a boolean, number, string, or {@code WebElement}.
|
|
371
|
+
* Arrays and objects may also be used as script arguments as long as each item
|
|
372
|
+
* adheres to the types previously mentioned.
|
|
373
|
+
*
|
|
374
|
+
* Unlike executing synchronous JavaScript with {@link #executeScript},
|
|
375
|
+
* scripts executed with this function must explicitly signal they are finished
|
|
376
|
+
* by invoking the provided callback. This callback will always be injected
|
|
377
|
+
* into the executed function as the last argument, and thus may be referenced
|
|
378
|
+
* with {@code arguments[arguments.length - 1]}. The following steps will be
|
|
379
|
+
* taken for resolving this functions return value against the first argument
|
|
380
|
+
* to the script's callback function:
|
|
381
|
+
*
|
|
382
|
+
* - For a HTML element, the value will resolve to a
|
|
383
|
+
* {@link WebElement}
|
|
384
|
+
* - Null and undefined return values will resolve to null
|
|
385
|
+
* - Booleans, numbers, and strings will resolve as is
|
|
386
|
+
* - Functions will resolve to their string representation
|
|
387
|
+
* - For arrays and objects, each member item will be converted according to
|
|
388
|
+
* the rules above
|
|
389
|
+
*
|
|
390
|
+
* __Example #1:__ Performing a sleep that is synchronized with the currently
|
|
391
|
+
* selected window:
|
|
392
|
+
*
|
|
393
|
+
* var start = new Date().getTime();
|
|
394
|
+
* driver.executeAsyncScript(
|
|
395
|
+
* 'window.setTimeout(arguments[arguments.length - 1], 500);').
|
|
396
|
+
* then(function() {
|
|
397
|
+
* console.log(
|
|
398
|
+
* 'Elapsed time: ' + (new Date().getTime() - start) + ' ms');
|
|
399
|
+
* });
|
|
400
|
+
*
|
|
401
|
+
* __Example #2:__ Synchronizing a test with an AJAX application:
|
|
402
|
+
*
|
|
403
|
+
* var button = driver.findElement(By.id('compose-button'));
|
|
404
|
+
* button.click();
|
|
405
|
+
* driver.executeAsyncScript(
|
|
406
|
+
* 'var callback = arguments[arguments.length - 1];' +
|
|
407
|
+
* 'mailClient.getComposeWindowWidget().onload(callback);');
|
|
408
|
+
* driver.switchTo().frame('composeWidget');
|
|
409
|
+
* driver.findElement(By.id('to')).sendKeys('dog@example.com');
|
|
410
|
+
*
|
|
411
|
+
* __Example #3:__ Injecting a XMLHttpRequest and waiting for the result. In
|
|
412
|
+
* this example, the inject script is specified with a function literal. When
|
|
413
|
+
* using this format, the function is converted to a string for injection, so it
|
|
414
|
+
* should not reference any symbols not defined in the scope of the page under
|
|
415
|
+
* test.
|
|
416
|
+
*
|
|
417
|
+
* driver.executeAsyncScript(function() {
|
|
418
|
+
* var callback = arguments[arguments.length - 1];
|
|
419
|
+
* var xhr = new XMLHttpRequest();
|
|
420
|
+
* xhr.open("GET", "/resource/data.json", true);
|
|
421
|
+
* xhr.onreadystatechange = function() {
|
|
422
|
+
* if (xhr.readyState == 4) {
|
|
423
|
+
* callback(xhr.responseText);
|
|
424
|
+
* }
|
|
425
|
+
* };
|
|
426
|
+
* xhr.send('');
|
|
427
|
+
* }).then(function(str) {
|
|
428
|
+
* console.log(JSON.parse(str)['food']);
|
|
429
|
+
* });
|
|
430
|
+
*
|
|
431
|
+
* @param {!(string|Function)} script The script to execute.
|
|
432
|
+
* @param {...*} var_args The arguments to pass to the script.
|
|
433
|
+
* @return {!promise.Thenable<T>} A promise that will resolve to the
|
|
434
|
+
* scripts return value.
|
|
435
|
+
* @template T
|
|
436
|
+
*/
|
|
437
|
+
executeAsyncScript(script, var_args) {}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Schedules a command to execute a custom function.
|
|
441
|
+
* @param {function(...): (T|IThenable<T>)} fn The function to execute.
|
|
442
|
+
* @param {Object=} opt_scope The object in whose scope to execute the function.
|
|
443
|
+
* @param {...*} var_args Any arguments to pass to the function.
|
|
444
|
+
* @return {!promise.Thenable<T>} A promise that will be resolved'
|
|
445
|
+
* with the function's result.
|
|
446
|
+
* @template T
|
|
447
|
+
*/
|
|
448
|
+
call(fn, opt_scope, var_args) {}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Schedules a command to wait for a condition to hold. The condition may be
|
|
452
|
+
* specified by a {@link Condition}, as a custom function, or as any
|
|
453
|
+
* promise-like thenable.
|
|
454
|
+
*
|
|
455
|
+
* For a {@link Condition} or function, the wait will repeatedly
|
|
456
|
+
* evaluate the condition until it returns a truthy value. If any errors occur
|
|
457
|
+
* while evaluating the condition, they will be allowed to propagate. In the
|
|
458
|
+
* event a condition returns a {@link promise.Promise promise}, the polling
|
|
459
|
+
* loop will wait for it to be resolved and use the resolved value for whether
|
|
460
|
+
* the condition has been satisified. Note the resolution time for a promise
|
|
461
|
+
* is factored into whether a wait has timed out.
|
|
462
|
+
*
|
|
463
|
+
* Note, if the provided condition is a {@link WebElementCondition}, then
|
|
464
|
+
* the wait will return a {@link WebElementPromise} that will resolve to the
|
|
465
|
+
* element that satisified the condition.
|
|
466
|
+
*
|
|
467
|
+
* _Example:_ waiting up to 10 seconds for an element to be present on the
|
|
468
|
+
* page.
|
|
469
|
+
*
|
|
470
|
+
* var button = driver.wait(until.elementLocated(By.id('foo')), 10000);
|
|
471
|
+
* button.click();
|
|
472
|
+
*
|
|
473
|
+
* This function may also be used to block the command flow on the resolution
|
|
474
|
+
* of any thenable promise object. When given a promise, the command will
|
|
475
|
+
* simply wait for its resolution before completing. A timeout may be provided
|
|
476
|
+
* to fail the command if the promise does not resolve before the timeout
|
|
477
|
+
* expires.
|
|
478
|
+
*
|
|
479
|
+
* _Example:_ Suppose you have a function, `startTestServer`, that returns a
|
|
480
|
+
* promise for when a server is ready for requests. You can block a WebDriver
|
|
481
|
+
* client on this promise with:
|
|
482
|
+
*
|
|
483
|
+
* var started = startTestServer();
|
|
484
|
+
* driver.wait(started, 5 * 1000, 'Server should start within 5 seconds');
|
|
485
|
+
* driver.get(getServerUrl());
|
|
486
|
+
*
|
|
487
|
+
* @param {!(IThenable<T>|
|
|
488
|
+
* Condition<T>|
|
|
489
|
+
* function(!WebDriver): T)} condition The condition to
|
|
490
|
+
* wait on, defined as a promise, condition object, or a function to
|
|
491
|
+
* evaluate as a condition.
|
|
492
|
+
* @param {number=} opt_timeout How long to wait for the condition to be true.
|
|
493
|
+
* @param {string=} opt_message An optional message to use if the wait times
|
|
494
|
+
* out.
|
|
495
|
+
* @return {!(promise.Thenable<T>|WebElementPromise)} A promise that will be
|
|
496
|
+
* resolved with the first truthy value returned by the condition
|
|
497
|
+
* function, or rejected if the condition times out. If the input
|
|
498
|
+
* input condition is an instance of a {@link WebElementCondition},
|
|
499
|
+
* the returned value will be a {@link WebElementPromise}.
|
|
500
|
+
* @throws {TypeError} if the provided `condition` is not a valid type.
|
|
501
|
+
* @template T
|
|
502
|
+
*/
|
|
503
|
+
wait(condition, opt_timeout, opt_message) {}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Schedules a command to make the driver sleep for the given amount of time.
|
|
507
|
+
* @param {number} ms The amount of time, in milliseconds, to sleep.
|
|
508
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
509
|
+
* when the sleep has finished.
|
|
510
|
+
*/
|
|
511
|
+
sleep(ms) {}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Schedules a command to retrieve the current window handle.
|
|
515
|
+
* @return {!promise.Thenable<string>} A promise that will be
|
|
516
|
+
* resolved with the current window handle.
|
|
517
|
+
*/
|
|
518
|
+
getWindowHandle() {}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Schedules a command to retrieve the current list of available window handles.
|
|
522
|
+
* @return {!promise.Thenable<!Array<string>>} A promise that will
|
|
523
|
+
* be resolved with an array of window handles.
|
|
524
|
+
*/
|
|
525
|
+
getAllWindowHandles() {}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Schedules a command to retrieve the current page's source. The page source
|
|
529
|
+
* returned is a representation of the underlying DOM: do not expect it to be
|
|
530
|
+
* formatted or escaped in the same way as the response sent from the web
|
|
531
|
+
* server.
|
|
532
|
+
* @return {!promise.Thenable<string>} A promise that will be
|
|
533
|
+
* resolved with the current page source.
|
|
534
|
+
*/
|
|
535
|
+
getPageSource() {}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Schedules a command to close the current window.
|
|
539
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
540
|
+
* when this command has completed.
|
|
541
|
+
*/
|
|
542
|
+
close() {}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Schedules a command to navigate to the given URL.
|
|
546
|
+
* @param {string} url The fully qualified URL to open.
|
|
547
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
548
|
+
* when the document has finished loading.
|
|
549
|
+
*/
|
|
550
|
+
get(url) {}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Schedules a command to retrieve the URL of the current page.
|
|
554
|
+
* @return {!promise.Thenable<string>} A promise that will be
|
|
555
|
+
* resolved with the current URL.
|
|
556
|
+
*/
|
|
557
|
+
getCurrentUrl() {}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Schedules a command to retrieve the current page's title.
|
|
561
|
+
* @return {!promise.Thenable<string>} A promise that will be
|
|
562
|
+
* resolved with the current page's title.
|
|
563
|
+
*/
|
|
564
|
+
getTitle() {}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Schedule a command to find an element on the page. If the element cannot be
|
|
568
|
+
* found, a {@link bot.ErrorCode.NO_SUCH_ELEMENT} result will be returned
|
|
569
|
+
* by the driver. Unlike other commands, this error cannot be suppressed. In
|
|
570
|
+
* other words, scheduling a command to find an element doubles as an assert
|
|
571
|
+
* that the element is present on the page. To test whether an element is
|
|
572
|
+
* present on the page, use {@link #findElements}:
|
|
573
|
+
*
|
|
574
|
+
* driver.findElements(By.id('foo'))
|
|
575
|
+
* .then(found => console.log('Element found? %s', !!found.length));
|
|
576
|
+
*
|
|
577
|
+
* The search criteria for an element may be defined using one of the
|
|
578
|
+
* factories in the {@link webdriver.By} namespace, or as a short-hand
|
|
579
|
+
* {@link webdriver.By.Hash} object. For example, the following two statements
|
|
580
|
+
* are equivalent:
|
|
581
|
+
*
|
|
582
|
+
* var e1 = driver.findElement(By.id('foo'));
|
|
583
|
+
* var e2 = driver.findElement({id:'foo'});
|
|
584
|
+
*
|
|
585
|
+
* You may also provide a custom locator function, which takes as input this
|
|
586
|
+
* instance and returns a {@link WebElement}, or a promise that will resolve
|
|
587
|
+
* to a WebElement. If the returned promise resolves to an array of
|
|
588
|
+
* WebElements, WebDriver will use the first element. For example, to find the
|
|
589
|
+
* first visible link on a page, you could write:
|
|
590
|
+
*
|
|
591
|
+
* var link = driver.findElement(firstVisibleLink);
|
|
592
|
+
*
|
|
593
|
+
* function firstVisibleLink(driver) {
|
|
594
|
+
* var links = driver.findElements(By.tagName('a'));
|
|
595
|
+
* return promise.filter(links, function(link) {
|
|
596
|
+
* return link.isDisplayed();
|
|
597
|
+
* });
|
|
598
|
+
* }
|
|
599
|
+
*
|
|
600
|
+
* @param {!(by.By|Function)} locator The locator to use.
|
|
601
|
+
* @return {!WebElementPromise} A WebElement that can be used to issue
|
|
602
|
+
* commands against the located element. If the element is not found, the
|
|
603
|
+
* element will be invalidated and all scheduled commands aborted.
|
|
604
|
+
*/
|
|
605
|
+
findElement(locator) {}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Schedule a command to search for multiple elements on the page.
|
|
609
|
+
*
|
|
610
|
+
* @param {!(by.By|Function)} locator The locator to use.
|
|
611
|
+
* @return {!promise.Thenable<!Array<!WebElement>>} A
|
|
612
|
+
* promise that will resolve to an array of WebElements.
|
|
613
|
+
*/
|
|
614
|
+
findElements(locator) {}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Schedule a command to take a screenshot. The driver makes a best effort to
|
|
618
|
+
* return a screenshot of the following, in order of preference:
|
|
619
|
+
*
|
|
620
|
+
* 1. Entire page
|
|
621
|
+
* 2. Current window
|
|
622
|
+
* 3. Visible portion of the current frame
|
|
623
|
+
* 4. The entire display containing the browser
|
|
624
|
+
*
|
|
625
|
+
* @return {!promise.Thenable<string>} A promise that will be
|
|
626
|
+
* resolved to the screenshot as a base-64 encoded PNG.
|
|
627
|
+
*/
|
|
628
|
+
takeScreenshot() {}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* @return {!Options} The options interface for this instance.
|
|
632
|
+
*/
|
|
633
|
+
manage() {}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* @return {!Navigation} The navigation interface for this instance.
|
|
637
|
+
*/
|
|
638
|
+
navigate() {}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* @return {!TargetLocator} The target locator interface for this
|
|
642
|
+
* instance.
|
|
643
|
+
*/
|
|
644
|
+
switchTo() {}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Each WebDriver instance provides automated control over a browser session.
|
|
256
650
|
*
|
|
651
|
+
* @implements {IWebDriver}
|
|
257
652
|
*/
|
|
258
653
|
class WebDriver {
|
|
259
654
|
/**
|
|
260
|
-
* @param {!(Session|
|
|
261
|
-
*
|
|
655
|
+
* @param {!(Session|IThenable<!Session>)} session Either a known session or a
|
|
656
|
+
* promise that will be resolved to a session.
|
|
262
657
|
* @param {!command.Executor} executor The executor to use when sending
|
|
263
658
|
* commands to the browser.
|
|
264
659
|
* @param {promise.ControlFlow=} opt_flow The flow to
|
|
265
660
|
* schedule commands through. Defaults to the active flow object.
|
|
661
|
+
* @param {(function(this: void): ?)=} opt_onQuit A function to call, if any,
|
|
662
|
+
* when the session is terminated.
|
|
266
663
|
*/
|
|
267
|
-
constructor(session, executor, opt_flow) {
|
|
268
|
-
/** @private {!promise.
|
|
269
|
-
this.
|
|
664
|
+
constructor(session, executor, opt_flow, opt_onQuit) {
|
|
665
|
+
/** @private {!promise.ControlFlow} */
|
|
666
|
+
this.flow_ = opt_flow || promise.controlFlow();
|
|
667
|
+
|
|
668
|
+
/** @private {!promise.Thenable<!Session>} */
|
|
669
|
+
this.session_ = this.flow_.promise(resolve => resolve(session));
|
|
270
670
|
|
|
271
671
|
/** @private {!command.Executor} */
|
|
272
672
|
this.executor_ = executor;
|
|
273
673
|
|
|
274
|
-
/** @private {!promise.ControlFlow} */
|
|
275
|
-
this.flow_ = opt_flow || promise.controlFlow();
|
|
276
|
-
|
|
277
674
|
/** @private {input.FileDetector} */
|
|
278
675
|
this.fileDetector_ = null;
|
|
676
|
+
|
|
677
|
+
/** @private @const {(function(this: void): ?|undefined)} */
|
|
678
|
+
this.onQuit_ = opt_onQuit;
|
|
279
679
|
}
|
|
280
680
|
|
|
281
681
|
/**
|
|
@@ -350,9 +750,20 @@ class WebDriver {
|
|
|
350
750
|
* commands should execute under, including the initial session creation.
|
|
351
751
|
* Defaults to the {@link promise.controlFlow() currently active}
|
|
352
752
|
* control flow.
|
|
753
|
+
* @param {(function(new: WebDriver,
|
|
754
|
+
* !IThenable<!Session>,
|
|
755
|
+
* !command.Executor,
|
|
756
|
+
* promise.ControlFlow=))=} opt_ctor
|
|
757
|
+
* A reference to the constructor of the specific type of WebDriver client
|
|
758
|
+
* to instantiate. Will create a vanilla {@linkplain WebDriver} instance
|
|
759
|
+
* if a constructor is not provided.
|
|
760
|
+
* @param {(function(this: void): ?)=} opt_onQuit A callback to invoke when
|
|
761
|
+
* the newly created session is terminated. This should be used to clean
|
|
762
|
+
* up any resources associated with the session.
|
|
353
763
|
* @return {!WebDriver} The driver for the newly created session.
|
|
354
764
|
*/
|
|
355
|
-
static createSession(
|
|
765
|
+
static createSession(
|
|
766
|
+
executor, capabilities, opt_flow, opt_ctor, opt_onQuit) {
|
|
356
767
|
let flow = opt_flow || promise.controlFlow();
|
|
357
768
|
let cmd = new command.Command(command.Name.NEW_SESSION);
|
|
358
769
|
|
|
@@ -366,31 +777,22 @@ class WebDriver {
|
|
|
366
777
|
let session = flow.execute(
|
|
367
778
|
() => executeCommand(executor, cmd),
|
|
368
779
|
'WebDriver.createSession()');
|
|
369
|
-
|
|
780
|
+
if (typeof opt_onQuit === 'function') {
|
|
781
|
+
session = session.catch(err => {
|
|
782
|
+
return Promise.resolve(opt_onQuit.call(void 0)).then(_ => {throw err});
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
const ctor = opt_ctor || WebDriver;
|
|
786
|
+
return new ctor(session, executor, flow, opt_onQuit);
|
|
370
787
|
}
|
|
371
788
|
|
|
372
|
-
/**
|
|
373
|
-
* @return {!promise.ControlFlow} The control flow used by this
|
|
374
|
-
* instance.
|
|
375
|
-
*/
|
|
789
|
+
/** @override */
|
|
376
790
|
controlFlow() {
|
|
377
791
|
return this.flow_;
|
|
378
792
|
}
|
|
379
793
|
|
|
380
|
-
/**
|
|
381
|
-
* Schedules a {@link command.Command} to be executed by this driver's
|
|
382
|
-
* {@link command.Executor}.
|
|
383
|
-
*
|
|
384
|
-
* @param {!command.Command} command The command to schedule.
|
|
385
|
-
* @param {string} description A description of the command for debugging.
|
|
386
|
-
* @return {!promise.Promise<T>} A promise that will be resolved
|
|
387
|
-
* with the command result.
|
|
388
|
-
* @template T
|
|
389
|
-
*/
|
|
794
|
+
/** @override */
|
|
390
795
|
schedule(command, description) {
|
|
391
|
-
var self = this;
|
|
392
|
-
|
|
393
|
-
checkHasNotQuit();
|
|
394
796
|
command.setParameter('sessionId', this.session_);
|
|
395
797
|
|
|
396
798
|
// If any of the command parameters are rejected promises, those
|
|
@@ -411,149 +813,71 @@ class WebDriver {
|
|
|
411
813
|
|
|
412
814
|
var flow = this.flow_;
|
|
413
815
|
var executor = this.executor_;
|
|
414
|
-
return flow.execute(
|
|
415
|
-
// A call to WebDriver.quit() may have been scheduled in the same event
|
|
416
|
-
// loop as this |command|, which would prevent us from detecting that the
|
|
417
|
-
// driver has quit above. Therefore, we need to make another quick check.
|
|
418
|
-
// We still check above so we can fail as early as possible.
|
|
419
|
-
checkHasNotQuit();
|
|
420
|
-
|
|
816
|
+
return flow.execute(() => {
|
|
421
817
|
// Retrieve resolved command parameters; any previously suppressed errors
|
|
422
818
|
// will now propagate up through the control flow as part of the command
|
|
423
819
|
// execution.
|
|
424
820
|
return prepCommand.then(function(parameters) {
|
|
425
821
|
command.setParameters(parameters);
|
|
426
822
|
return executor.execute(command);
|
|
427
|
-
}).then(value => fromWireValue(
|
|
823
|
+
}).then(value => fromWireValue(this, value));
|
|
428
824
|
}, description);
|
|
429
|
-
|
|
430
|
-
function checkHasNotQuit() {
|
|
431
|
-
if (!self.session_) {
|
|
432
|
-
throw new error.NoSuchSessionError(
|
|
433
|
-
'This driver instance does not have a valid session ID ' +
|
|
434
|
-
'(did you call WebDriver.quit()?) and may no longer be ' +
|
|
435
|
-
'used.');
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
825
|
}
|
|
439
826
|
|
|
440
|
-
/**
|
|
441
|
-
* Sets the {@linkplain input.FileDetector file detector} that should be
|
|
442
|
-
* used with this instance.
|
|
443
|
-
* @param {input.FileDetector} detector The detector to use or {@code null}.
|
|
444
|
-
*/
|
|
827
|
+
/** @override */
|
|
445
828
|
setFileDetector(detector) {
|
|
446
829
|
this.fileDetector_ = detector;
|
|
447
830
|
}
|
|
448
831
|
|
|
449
|
-
/**
|
|
450
|
-
* @return {!command.Executor} The command executor used by this instance.
|
|
451
|
-
*/
|
|
832
|
+
/** @override */
|
|
452
833
|
getExecutor() {
|
|
453
834
|
return this.executor_;
|
|
454
835
|
}
|
|
455
836
|
|
|
456
|
-
/**
|
|
457
|
-
* @return {!promise.Promise<!Session>} A promise for this client's
|
|
458
|
-
* session.
|
|
459
|
-
*/
|
|
837
|
+
/** @override */
|
|
460
838
|
getSession() {
|
|
461
839
|
return this.session_;
|
|
462
840
|
}
|
|
463
841
|
|
|
464
|
-
/**
|
|
465
|
-
* @return {!promise.Promise<!Capabilities>} A promise
|
|
466
|
-
* that will resolve with the this instance's capabilities.
|
|
467
|
-
*/
|
|
842
|
+
/** @override */
|
|
468
843
|
getCapabilities() {
|
|
469
|
-
return this.session_.then(
|
|
844
|
+
return this.session_.then(s => s.getCapabilities());
|
|
470
845
|
}
|
|
471
846
|
|
|
472
|
-
/**
|
|
473
|
-
* Schedules a command to quit the current session. After calling quit, this
|
|
474
|
-
* instance will be invalidated and may no longer be used to issue commands
|
|
475
|
-
* against the browser.
|
|
476
|
-
* @return {!promise.Promise<void>} A promise that will be resolved
|
|
477
|
-
* when the command has completed.
|
|
478
|
-
*/
|
|
847
|
+
/** @override */
|
|
479
848
|
quit() {
|
|
480
849
|
var result = this.schedule(
|
|
481
850
|
new command.Command(command.Name.QUIT),
|
|
482
851
|
'WebDriver.quit()');
|
|
483
852
|
// Delete our session ID when the quit command finishes; this will allow us
|
|
484
853
|
// to throw an error when attemnpting to use a driver post-quit.
|
|
485
|
-
return
|
|
854
|
+
return /** @type {!promise.Thenable} */(promise.finally(result, () => {
|
|
855
|
+
this.session_ = this.flow_.promise((_, reject) => {
|
|
856
|
+
reject(new error.NoSuchSessionError(
|
|
857
|
+
'This driver instance does not have a valid session ID ' +
|
|
858
|
+
'(did you call WebDriver.quit()?) and may no longer be used.'));
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
// Only want the session rejection to bubble if accessed.
|
|
862
|
+
this.session_.catch(function() {});
|
|
863
|
+
|
|
864
|
+
if (this.onQuit_) {
|
|
865
|
+
return this.onQuit_.call(void 0);
|
|
866
|
+
}
|
|
867
|
+
}));
|
|
486
868
|
}
|
|
487
869
|
|
|
488
|
-
/**
|
|
489
|
-
* Creates a new action sequence using this driver. The sequence will not be
|
|
490
|
-
* scheduled for execution until {@link actions.ActionSequence#perform} is
|
|
491
|
-
* called. Example:
|
|
492
|
-
*
|
|
493
|
-
* driver.actions().
|
|
494
|
-
* mouseDown(element1).
|
|
495
|
-
* mouseMove(element2).
|
|
496
|
-
* mouseUp().
|
|
497
|
-
* perform();
|
|
498
|
-
*
|
|
499
|
-
* @return {!actions.ActionSequence} A new action sequence for this instance.
|
|
500
|
-
*/
|
|
870
|
+
/** @override */
|
|
501
871
|
actions() {
|
|
502
872
|
return new actions.ActionSequence(this);
|
|
503
873
|
}
|
|
504
874
|
|
|
505
|
-
/**
|
|
506
|
-
* Creates a new touch sequence using this driver. The sequence will not be
|
|
507
|
-
* scheduled for execution until {@link actions.TouchSequence#perform} is
|
|
508
|
-
* called. Example:
|
|
509
|
-
*
|
|
510
|
-
* driver.touchActions().
|
|
511
|
-
* tap(element1).
|
|
512
|
-
* doubleTap(element2).
|
|
513
|
-
* perform();
|
|
514
|
-
*
|
|
515
|
-
* @return {!actions.TouchSequence} A new touch sequence for this instance.
|
|
516
|
-
*/
|
|
875
|
+
/** @override */
|
|
517
876
|
touchActions() {
|
|
518
877
|
return new actions.TouchSequence(this);
|
|
519
878
|
}
|
|
520
|
-
|
|
521
|
-
/**
|
|
522
|
-
* Schedules a command to execute JavaScript in the context of the currently
|
|
523
|
-
* selected frame or window. The script fragment will be executed as the body
|
|
524
|
-
* of an anonymous function. If the script is provided as a function object,
|
|
525
|
-
* that function will be converted to a string for injection into the target
|
|
526
|
-
* window.
|
|
527
|
-
*
|
|
528
|
-
* Any arguments provided in addition to the script will be included as script
|
|
529
|
-
* arguments and may be referenced using the {@code arguments} object.
|
|
530
|
-
* Arguments may be a boolean, number, string, or {@linkplain WebElement}.
|
|
531
|
-
* Arrays and objects may also be used as script arguments as long as each item
|
|
532
|
-
* adheres to the types previously mentioned.
|
|
533
|
-
*
|
|
534
|
-
* The script may refer to any variables accessible from the current window.
|
|
535
|
-
* Furthermore, the script will execute in the window's context, thus
|
|
536
|
-
* {@code document} may be used to refer to the current document. Any local
|
|
537
|
-
* variables will not be available once the script has finished executing,
|
|
538
|
-
* though global variables will persist.
|
|
539
|
-
*
|
|
540
|
-
* If the script has a return value (i.e. if the script contains a return
|
|
541
|
-
* statement), then the following steps will be taken for resolving this
|
|
542
|
-
* functions return value:
|
|
543
|
-
*
|
|
544
|
-
* - For a HTML element, the value will resolve to a {@linkplain WebElement}
|
|
545
|
-
* - Null and undefined return values will resolve to null</li>
|
|
546
|
-
* - Booleans, numbers, and strings will resolve as is</li>
|
|
547
|
-
* - Functions will resolve to their string representation</li>
|
|
548
|
-
* - For arrays and objects, each member item will be converted according to
|
|
549
|
-
* the rules above
|
|
550
|
-
*
|
|
551
|
-
* @param {!(string|Function)} script The script to execute.
|
|
552
|
-
* @param {...*} var_args The arguments to pass to the script.
|
|
553
|
-
* @return {!promise.Promise<T>} A promise that will resolve to the
|
|
554
|
-
* scripts return value.
|
|
555
|
-
* @template T
|
|
556
|
-
*/
|
|
879
|
+
|
|
880
|
+
/** @override */
|
|
557
881
|
executeScript(script, var_args) {
|
|
558
882
|
if (typeof script === 'function') {
|
|
559
883
|
script = 'return (' + script + ').apply(null, arguments);';
|
|
@@ -567,82 +891,7 @@ class WebDriver {
|
|
|
567
891
|
'WebDriver.executeScript()');
|
|
568
892
|
}
|
|
569
893
|
|
|
570
|
-
/**
|
|
571
|
-
* Schedules a command to execute asynchronous JavaScript in the context of the
|
|
572
|
-
* currently selected frame or window. The script fragment will be executed as
|
|
573
|
-
* the body of an anonymous function. If the script is provided as a function
|
|
574
|
-
* object, that function will be converted to a string for injection into the
|
|
575
|
-
* target window.
|
|
576
|
-
*
|
|
577
|
-
* Any arguments provided in addition to the script will be included as script
|
|
578
|
-
* arguments and may be referenced using the {@code arguments} object.
|
|
579
|
-
* Arguments may be a boolean, number, string, or {@code WebElement}.
|
|
580
|
-
* Arrays and objects may also be used as script arguments as long as each item
|
|
581
|
-
* adheres to the types previously mentioned.
|
|
582
|
-
*
|
|
583
|
-
* Unlike executing synchronous JavaScript with {@link #executeScript},
|
|
584
|
-
* scripts executed with this function must explicitly signal they are finished
|
|
585
|
-
* by invoking the provided callback. This callback will always be injected
|
|
586
|
-
* into the executed function as the last argument, and thus may be referenced
|
|
587
|
-
* with {@code arguments[arguments.length - 1]}. The following steps will be
|
|
588
|
-
* taken for resolving this functions return value against the first argument
|
|
589
|
-
* to the script's callback function:
|
|
590
|
-
*
|
|
591
|
-
* - For a HTML element, the value will resolve to a
|
|
592
|
-
* {@link WebElement}
|
|
593
|
-
* - Null and undefined return values will resolve to null
|
|
594
|
-
* - Booleans, numbers, and strings will resolve as is
|
|
595
|
-
* - Functions will resolve to their string representation
|
|
596
|
-
* - For arrays and objects, each member item will be converted according to
|
|
597
|
-
* the rules above
|
|
598
|
-
*
|
|
599
|
-
* __Example #1:__ Performing a sleep that is synchronized with the currently
|
|
600
|
-
* selected window:
|
|
601
|
-
*
|
|
602
|
-
* var start = new Date().getTime();
|
|
603
|
-
* driver.executeAsyncScript(
|
|
604
|
-
* 'window.setTimeout(arguments[arguments.length - 1], 500);').
|
|
605
|
-
* then(function() {
|
|
606
|
-
* console.log(
|
|
607
|
-
* 'Elapsed time: ' + (new Date().getTime() - start) + ' ms');
|
|
608
|
-
* });
|
|
609
|
-
*
|
|
610
|
-
* __Example #2:__ Synchronizing a test with an AJAX application:
|
|
611
|
-
*
|
|
612
|
-
* var button = driver.findElement(By.id('compose-button'));
|
|
613
|
-
* button.click();
|
|
614
|
-
* driver.executeAsyncScript(
|
|
615
|
-
* 'var callback = arguments[arguments.length - 1];' +
|
|
616
|
-
* 'mailClient.getComposeWindowWidget().onload(callback);');
|
|
617
|
-
* driver.switchTo().frame('composeWidget');
|
|
618
|
-
* driver.findElement(By.id('to')).sendKeys('dog@example.com');
|
|
619
|
-
*
|
|
620
|
-
* __Example #3:__ Injecting a XMLHttpRequest and waiting for the result. In
|
|
621
|
-
* this example, the inject script is specified with a function literal. When
|
|
622
|
-
* using this format, the function is converted to a string for injection, so it
|
|
623
|
-
* should not reference any symbols not defined in the scope of the page under
|
|
624
|
-
* test.
|
|
625
|
-
*
|
|
626
|
-
* driver.executeAsyncScript(function() {
|
|
627
|
-
* var callback = arguments[arguments.length - 1];
|
|
628
|
-
* var xhr = new XMLHttpRequest();
|
|
629
|
-
* xhr.open("GET", "/resource/data.json", true);
|
|
630
|
-
* xhr.onreadystatechange = function() {
|
|
631
|
-
* if (xhr.readyState == 4) {
|
|
632
|
-
* callback(xhr.responseText);
|
|
633
|
-
* }
|
|
634
|
-
* };
|
|
635
|
-
* xhr.send('');
|
|
636
|
-
* }).then(function(str) {
|
|
637
|
-
* console.log(JSON.parse(str)['food']);
|
|
638
|
-
* });
|
|
639
|
-
*
|
|
640
|
-
* @param {!(string|Function)} script The script to execute.
|
|
641
|
-
* @param {...*} var_args The arguments to pass to the script.
|
|
642
|
-
* @return {!promise.Promise<T>} A promise that will resolve to the
|
|
643
|
-
* scripts return value.
|
|
644
|
-
* @template T
|
|
645
|
-
*/
|
|
894
|
+
/** @override */
|
|
646
895
|
executeAsyncScript(script, var_args) {
|
|
647
896
|
if (typeof script === 'function') {
|
|
648
897
|
script = 'return (' + script + ').apply(null, arguments);';
|
|
@@ -655,20 +904,10 @@ class WebDriver {
|
|
|
655
904
|
'WebDriver.executeScript()');
|
|
656
905
|
}
|
|
657
906
|
|
|
658
|
-
/**
|
|
659
|
-
* Schedules a command to execute a custom function.
|
|
660
|
-
* @param {function(...): (T|promise.Promise<T>)} fn The function to
|
|
661
|
-
* execute.
|
|
662
|
-
* @param {Object=} opt_scope The object in whose scope to execute the function.
|
|
663
|
-
* @param {...*} var_args Any arguments to pass to the function.
|
|
664
|
-
* @return {!promise.Promise<T>} A promise that will be resolved'
|
|
665
|
-
* with the function's result.
|
|
666
|
-
* @template T
|
|
667
|
-
*/
|
|
907
|
+
/** @override */
|
|
668
908
|
call(fn, opt_scope, var_args) {
|
|
669
909
|
let args = Array.prototype.slice.call(arguments, 2);
|
|
670
|
-
|
|
671
|
-
return flow.execute(function() {
|
|
910
|
+
return this.flow_.execute(function() {
|
|
672
911
|
return promise.fullyResolved(args).then(function(args) {
|
|
673
912
|
if (promise.isGenerator(fn)) {
|
|
674
913
|
args.unshift(fn, opt_scope);
|
|
@@ -679,62 +918,11 @@ class WebDriver {
|
|
|
679
918
|
}, 'WebDriver.call(' + (fn.name || 'function') + ')');
|
|
680
919
|
}
|
|
681
920
|
|
|
682
|
-
/**
|
|
683
|
-
* Schedules a command to wait for a condition to hold. The condition may be
|
|
684
|
-
* specified by a {@link Condition}, as a custom function, or as any
|
|
685
|
-
* promise-like thenable.
|
|
686
|
-
*
|
|
687
|
-
* For a {@link Condition} or function, the wait will repeatedly
|
|
688
|
-
* evaluate the condition until it returns a truthy value. If any errors occur
|
|
689
|
-
* while evaluating the condition, they will be allowed to propagate. In the
|
|
690
|
-
* event a condition returns a {@link promise.Promise promise}, the polling
|
|
691
|
-
* loop will wait for it to be resolved and use the resolved value for whether
|
|
692
|
-
* the condition has been satisified. Note the resolution time for a promise
|
|
693
|
-
* is factored into whether a wait has timed out.
|
|
694
|
-
*
|
|
695
|
-
* Note, if the provided condition is a {@link WebElementCondition}, then
|
|
696
|
-
* the wait will return a {@link WebElementPromise} that will resolve to the
|
|
697
|
-
* element that satisified the condition.
|
|
698
|
-
*
|
|
699
|
-
* _Example:_ waiting up to 10 seconds for an element to be present on the
|
|
700
|
-
* page.
|
|
701
|
-
*
|
|
702
|
-
* var button = driver.wait(until.elementLocated(By.id('foo')), 10000);
|
|
703
|
-
* button.click();
|
|
704
|
-
*
|
|
705
|
-
* This function may also be used to block the command flow on the resolution
|
|
706
|
-
* of any thenable promise object. When given a promise, the command will
|
|
707
|
-
* simply wait for its resolution before completing. A timeout may be provided
|
|
708
|
-
* to fail the command if the promise does not resolve before the timeout
|
|
709
|
-
* expires.
|
|
710
|
-
*
|
|
711
|
-
* _Example:_ Suppose you have a function, `startTestServer`, that returns a
|
|
712
|
-
* promise for when a server is ready for requests. You can block a WebDriver
|
|
713
|
-
* client on this promise with:
|
|
714
|
-
*
|
|
715
|
-
* var started = startTestServer();
|
|
716
|
-
* driver.wait(started, 5 * 1000, 'Server should start within 5 seconds');
|
|
717
|
-
* driver.get(getServerUrl());
|
|
718
|
-
*
|
|
719
|
-
* @param {!(promise.Promise<T>|
|
|
720
|
-
* Condition<T>|
|
|
721
|
-
* function(!WebDriver): T)} condition The condition to
|
|
722
|
-
* wait on, defined as a promise, condition object, or a function to
|
|
723
|
-
* evaluate as a condition.
|
|
724
|
-
* @param {number=} opt_timeout How long to wait for the condition to be true.
|
|
725
|
-
* @param {string=} opt_message An optional message to use if the wait times
|
|
726
|
-
* out.
|
|
727
|
-
* @return {!(promise.Promise<T>|WebElementPromise)} A promise that will be
|
|
728
|
-
* resolved with the first truthy value returned by the condition
|
|
729
|
-
* function, or rejected if the condition times out. If the input
|
|
730
|
-
* input condition is an instance of a {@link WebElementCondition},
|
|
731
|
-
* the returned value will be a {@link WebElementPromise}.
|
|
732
|
-
* @template T
|
|
733
|
-
*/
|
|
921
|
+
/** @override */
|
|
734
922
|
wait(condition, opt_timeout, opt_message) {
|
|
735
923
|
if (promise.isPromise(condition)) {
|
|
736
924
|
return this.flow_.wait(
|
|
737
|
-
/** @type {!
|
|
925
|
+
/** @type {!IThenable} */(condition),
|
|
738
926
|
opt_timeout, opt_message);
|
|
739
927
|
}
|
|
740
928
|
|
|
@@ -745,6 +933,12 @@ class WebDriver {
|
|
|
745
933
|
fn = condition.fn;
|
|
746
934
|
}
|
|
747
935
|
|
|
936
|
+
if (typeof fn !== 'function') {
|
|
937
|
+
throw TypeError(
|
|
938
|
+
'Wait condition must be a promise-like object, function, or a '
|
|
939
|
+
+ 'Condition object');
|
|
940
|
+
}
|
|
941
|
+
|
|
748
942
|
var driver = this;
|
|
749
943
|
var result = this.flow_.wait(function() {
|
|
750
944
|
if (promise.isGenerator(fn)) {
|
|
@@ -766,129 +960,57 @@ class WebDriver {
|
|
|
766
960
|
return result;
|
|
767
961
|
}
|
|
768
962
|
|
|
769
|
-
/**
|
|
770
|
-
* Schedules a command to make the driver sleep for the given amount of time.
|
|
771
|
-
* @param {number} ms The amount of time, in milliseconds, to sleep.
|
|
772
|
-
* @return {!promise.Promise<void>} A promise that will be resolved
|
|
773
|
-
* when the sleep has finished.
|
|
774
|
-
*/
|
|
963
|
+
/** @override */
|
|
775
964
|
sleep(ms) {
|
|
776
965
|
return this.flow_.timeout(ms, 'WebDriver.sleep(' + ms + ')');
|
|
777
966
|
}
|
|
778
967
|
|
|
779
|
-
/**
|
|
780
|
-
* Schedules a command to retrieve the current window handle.
|
|
781
|
-
* @return {!promise.Promise<string>} A promise that will be
|
|
782
|
-
* resolved with the current window handle.
|
|
783
|
-
*/
|
|
968
|
+
/** @override */
|
|
784
969
|
getWindowHandle() {
|
|
785
970
|
return this.schedule(
|
|
786
971
|
new command.Command(command.Name.GET_CURRENT_WINDOW_HANDLE),
|
|
787
972
|
'WebDriver.getWindowHandle()');
|
|
788
973
|
}
|
|
789
974
|
|
|
790
|
-
/**
|
|
791
|
-
* Schedules a command to retrieve the current list of available window handles.
|
|
792
|
-
* @return {!promise.Promise.<!Array<string>>} A promise that will
|
|
793
|
-
* be resolved with an array of window handles.
|
|
794
|
-
*/
|
|
975
|
+
/** @override */
|
|
795
976
|
getAllWindowHandles() {
|
|
796
977
|
return this.schedule(
|
|
797
978
|
new command.Command(command.Name.GET_WINDOW_HANDLES),
|
|
798
979
|
'WebDriver.getAllWindowHandles()');
|
|
799
980
|
}
|
|
800
981
|
|
|
801
|
-
/**
|
|
802
|
-
* Schedules a command to retrieve the current page's source. The page source
|
|
803
|
-
* returned is a representation of the underlying DOM: do not expect it to be
|
|
804
|
-
* formatted or escaped in the same way as the response sent from the web
|
|
805
|
-
* server.
|
|
806
|
-
* @return {!promise.Promise<string>} A promise that will be
|
|
807
|
-
* resolved with the current page source.
|
|
808
|
-
*/
|
|
982
|
+
/** @override */
|
|
809
983
|
getPageSource() {
|
|
810
984
|
return this.schedule(
|
|
811
985
|
new command.Command(command.Name.GET_PAGE_SOURCE),
|
|
812
986
|
'WebDriver.getPageSource()');
|
|
813
987
|
}
|
|
814
988
|
|
|
815
|
-
/**
|
|
816
|
-
* Schedules a command to close the current window.
|
|
817
|
-
* @return {!promise.Promise<void>} A promise that will be resolved
|
|
818
|
-
* when this command has completed.
|
|
819
|
-
*/
|
|
989
|
+
/** @override */
|
|
820
990
|
close() {
|
|
821
991
|
return this.schedule(new command.Command(command.Name.CLOSE),
|
|
822
992
|
'WebDriver.close()');
|
|
823
993
|
}
|
|
824
994
|
|
|
825
|
-
/**
|
|
826
|
-
* Schedules a command to navigate to the given URL.
|
|
827
|
-
* @param {string} url The fully qualified URL to open.
|
|
828
|
-
* @return {!promise.Promise<void>} A promise that will be resolved
|
|
829
|
-
* when the document has finished loading.
|
|
830
|
-
*/
|
|
995
|
+
/** @override */
|
|
831
996
|
get(url) {
|
|
832
997
|
return this.navigate().to(url);
|
|
833
998
|
}
|
|
834
999
|
|
|
835
|
-
/**
|
|
836
|
-
* Schedules a command to retrieve the URL of the current page.
|
|
837
|
-
* @return {!promise.Promise<string>} A promise that will be
|
|
838
|
-
* resolved with the current URL.
|
|
839
|
-
*/
|
|
1000
|
+
/** @override */
|
|
840
1001
|
getCurrentUrl() {
|
|
841
1002
|
return this.schedule(
|
|
842
1003
|
new command.Command(command.Name.GET_CURRENT_URL),
|
|
843
1004
|
'WebDriver.getCurrentUrl()');
|
|
844
1005
|
}
|
|
845
1006
|
|
|
846
|
-
/**
|
|
847
|
-
* Schedules a command to retrieve the current page's title.
|
|
848
|
-
* @return {!promise.Promise<string>} A promise that will be
|
|
849
|
-
* resolved with the current page's title.
|
|
850
|
-
*/
|
|
1007
|
+
/** @override */
|
|
851
1008
|
getTitle() {
|
|
852
1009
|
return this.schedule(new command.Command(command.Name.GET_TITLE),
|
|
853
1010
|
'WebDriver.getTitle()');
|
|
854
1011
|
}
|
|
855
1012
|
|
|
856
|
-
/**
|
|
857
|
-
* Schedule a command to find an element on the page. If the element cannot be
|
|
858
|
-
* found, a {@link bot.ErrorCode.NO_SUCH_ELEMENT} result will be returned
|
|
859
|
-
* by the driver. Unlike other commands, this error cannot be suppressed. In
|
|
860
|
-
* other words, scheduling a command to find an element doubles as an assert
|
|
861
|
-
* that the element is present on the page. To test whether an element is
|
|
862
|
-
* present on the page, use {@link #isElementPresent} instead.
|
|
863
|
-
*
|
|
864
|
-
* The search criteria for an element may be defined using one of the
|
|
865
|
-
* factories in the {@link webdriver.By} namespace, or as a short-hand
|
|
866
|
-
* {@link webdriver.By.Hash} object. For example, the following two statements
|
|
867
|
-
* are equivalent:
|
|
868
|
-
*
|
|
869
|
-
* var e1 = driver.findElement(By.id('foo'));
|
|
870
|
-
* var e2 = driver.findElement({id:'foo'});
|
|
871
|
-
*
|
|
872
|
-
* You may also provide a custom locator function, which takes as input this
|
|
873
|
-
* instance and returns a {@link WebElement}, or a promise that will resolve
|
|
874
|
-
* to a WebElement. If the returned promise resolves to an array of
|
|
875
|
-
* WebElements, WebDriver will use the first element. For example, to find the
|
|
876
|
-
* first visible link on a page, you could write:
|
|
877
|
-
*
|
|
878
|
-
* var link = driver.findElement(firstVisibleLink);
|
|
879
|
-
*
|
|
880
|
-
* function firstVisibleLink(driver) {
|
|
881
|
-
* var links = driver.findElements(By.tagName('a'));
|
|
882
|
-
* return promise.filter(links, function(link) {
|
|
883
|
-
* return link.isDisplayed();
|
|
884
|
-
* });
|
|
885
|
-
* }
|
|
886
|
-
*
|
|
887
|
-
* @param {!(by.By|Function)} locator The locator to use.
|
|
888
|
-
* @return {!WebElementPromise} A WebElement that can be used to issue
|
|
889
|
-
* commands against the located element. If the element is not found, the
|
|
890
|
-
* element will be invalidated and all scheduled commands aborted.
|
|
891
|
-
*/
|
|
1013
|
+
/** @override */
|
|
892
1014
|
findElement(locator) {
|
|
893
1015
|
let id;
|
|
894
1016
|
locator = by.checkedLocator(locator);
|
|
@@ -907,7 +1029,7 @@ class WebDriver {
|
|
|
907
1029
|
* @param {!Function} locatorFn The locator function to use.
|
|
908
1030
|
* @param {!(WebDriver|WebElement)} context The search
|
|
909
1031
|
* context.
|
|
910
|
-
* @return {!promise.
|
|
1032
|
+
* @return {!promise.Thenable<!WebElement>} A
|
|
911
1033
|
* promise that will resolve to a list of WebElements.
|
|
912
1034
|
* @private
|
|
913
1035
|
*/
|
|
@@ -923,13 +1045,7 @@ class WebDriver {
|
|
|
923
1045
|
});
|
|
924
1046
|
}
|
|
925
1047
|
|
|
926
|
-
/**
|
|
927
|
-
* Schedule a command to search for multiple elements on the page.
|
|
928
|
-
*
|
|
929
|
-
* @param {!(by.By|Function)} locator The locator to use.
|
|
930
|
-
* @return {!promise.Promise.<!Array.<!WebElement>>} A
|
|
931
|
-
* promise that will resolve to an array of WebElements.
|
|
932
|
-
*/
|
|
1048
|
+
/** @override */
|
|
933
1049
|
findElements(locator) {
|
|
934
1050
|
locator = by.checkedLocator(locator);
|
|
935
1051
|
if (typeof locator === 'function') {
|
|
@@ -951,7 +1067,7 @@ class WebDriver {
|
|
|
951
1067
|
/**
|
|
952
1068
|
* @param {!Function} locatorFn The locator function to use.
|
|
953
1069
|
* @param {!(WebDriver|WebElement)} context The search context.
|
|
954
|
-
* @return {!promise.
|
|
1070
|
+
* @return {!promise.Thenable<!Array<!WebElement>>} A promise that
|
|
955
1071
|
* will resolve to an array of WebElements.
|
|
956
1072
|
* @private
|
|
957
1073
|
*/
|
|
@@ -971,41 +1087,23 @@ class WebDriver {
|
|
|
971
1087
|
});
|
|
972
1088
|
}
|
|
973
1089
|
|
|
974
|
-
/**
|
|
975
|
-
* Schedule a command to take a screenshot. The driver makes a best effort to
|
|
976
|
-
* return a screenshot of the following, in order of preference:
|
|
977
|
-
*
|
|
978
|
-
* 1. Entire page
|
|
979
|
-
* 2. Current window
|
|
980
|
-
* 3. Visible portion of the current frame
|
|
981
|
-
* 4. The entire display containing the browser
|
|
982
|
-
*
|
|
983
|
-
* @return {!promise.Promise<string>} A promise that will be
|
|
984
|
-
* resolved to the screenshot as a base-64 encoded PNG.
|
|
985
|
-
*/
|
|
1090
|
+
/** @override */
|
|
986
1091
|
takeScreenshot() {
|
|
987
1092
|
return this.schedule(new command.Command(command.Name.SCREENSHOT),
|
|
988
1093
|
'WebDriver.takeScreenshot()');
|
|
989
1094
|
}
|
|
990
1095
|
|
|
991
|
-
/**
|
|
992
|
-
* @return {!Options} The options interface for this instance.
|
|
993
|
-
*/
|
|
1096
|
+
/** @override */
|
|
994
1097
|
manage() {
|
|
995
1098
|
return new Options(this);
|
|
996
1099
|
}
|
|
997
1100
|
|
|
998
|
-
/**
|
|
999
|
-
* @return {!Navigation} The navigation interface for this instance.
|
|
1000
|
-
*/
|
|
1101
|
+
/** @override */
|
|
1001
1102
|
navigate() {
|
|
1002
1103
|
return new Navigation(this);
|
|
1003
1104
|
}
|
|
1004
1105
|
|
|
1005
|
-
/**
|
|
1006
|
-
* @return {!TargetLocator} The target locator interface for this
|
|
1007
|
-
* instance.
|
|
1008
|
-
*/
|
|
1106
|
+
/** @override */
|
|
1009
1107
|
switchTo() {
|
|
1010
1108
|
return new TargetLocator(this);
|
|
1011
1109
|
}
|
|
@@ -1015,7 +1113,7 @@ class WebDriver {
|
|
|
1015
1113
|
/**
|
|
1016
1114
|
* Interface for navigating back and forth in the browser history.
|
|
1017
1115
|
*
|
|
1018
|
-
* This class should never be instantiated directly.
|
|
1116
|
+
* This class should never be instantiated directly. Instead, obtain an instance
|
|
1019
1117
|
* with
|
|
1020
1118
|
*
|
|
1021
1119
|
* webdriver.navigate()
|
|
@@ -1035,7 +1133,7 @@ class Navigation {
|
|
|
1035
1133
|
/**
|
|
1036
1134
|
* Schedules a command to navigate to a new URL.
|
|
1037
1135
|
* @param {string} url The URL to navigate to.
|
|
1038
|
-
* @return {!promise.
|
|
1136
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1039
1137
|
* when the URL has been loaded.
|
|
1040
1138
|
*/
|
|
1041
1139
|
to(url) {
|
|
@@ -1047,7 +1145,7 @@ class Navigation {
|
|
|
1047
1145
|
|
|
1048
1146
|
/**
|
|
1049
1147
|
* Schedules a command to move backwards in the browser history.
|
|
1050
|
-
* @return {!promise.
|
|
1148
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1051
1149
|
* when the navigation event has completed.
|
|
1052
1150
|
*/
|
|
1053
1151
|
back() {
|
|
@@ -1058,7 +1156,7 @@ class Navigation {
|
|
|
1058
1156
|
|
|
1059
1157
|
/**
|
|
1060
1158
|
* Schedules a command to move forwards in the browser history.
|
|
1061
|
-
* @return {!promise.
|
|
1159
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1062
1160
|
* when the navigation event has completed.
|
|
1063
1161
|
*/
|
|
1064
1162
|
forward() {
|
|
@@ -1069,7 +1167,7 @@ class Navigation {
|
|
|
1069
1167
|
|
|
1070
1168
|
/**
|
|
1071
1169
|
* Schedules a command to refresh the current page.
|
|
1072
|
-
* @return {!promise.
|
|
1170
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1073
1171
|
* when the navigation event has completed.
|
|
1074
1172
|
*/
|
|
1075
1173
|
refresh() {
|
|
@@ -1116,7 +1214,7 @@ class Options {
|
|
|
1116
1214
|
* });
|
|
1117
1215
|
*
|
|
1118
1216
|
* @param {!Options.Cookie} spec Defines the cookie to add.
|
|
1119
|
-
* @return {!promise.
|
|
1217
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1120
1218
|
* when the cookie has been added to the page.
|
|
1121
1219
|
* @throws {error.InvalidArgumentError} if any of the cookie parameters are
|
|
1122
1220
|
* invalid.
|
|
@@ -1171,7 +1269,7 @@ class Options {
|
|
|
1171
1269
|
|
|
1172
1270
|
/**
|
|
1173
1271
|
* Schedules a command to delete all cookies visible to the current page.
|
|
1174
|
-
* @return {!promise.
|
|
1272
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1175
1273
|
* when all cookies have been deleted.
|
|
1176
1274
|
*/
|
|
1177
1275
|
deleteAllCookies() {
|
|
@@ -1185,7 +1283,7 @@ class Options {
|
|
|
1185
1283
|
* is a no-op if there is no cookie with the given name visible to the current
|
|
1186
1284
|
* page.
|
|
1187
1285
|
* @param {string} name The name of the cookie to delete.
|
|
1188
|
-
* @return {!promise.
|
|
1286
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1189
1287
|
* when the cookie has been deleted.
|
|
1190
1288
|
*/
|
|
1191
1289
|
deleteCookie(name) {
|
|
@@ -1199,7 +1297,7 @@ class Options {
|
|
|
1199
1297
|
* Schedules a command to retrieve all cookies visible to the current page.
|
|
1200
1298
|
* Each cookie will be returned as a JSON object as described by the WebDriver
|
|
1201
1299
|
* wire protocol.
|
|
1202
|
-
* @return {!promise.
|
|
1300
|
+
* @return {!promise.Thenable<!Array<!Options.Cookie>>} A promise that will be
|
|
1203
1301
|
* resolved with the cookies visible to the current browsing context.
|
|
1204
1302
|
*/
|
|
1205
1303
|
getCookies() {
|
|
@@ -1214,7 +1312,7 @@ class Options {
|
|
|
1214
1312
|
* described by the WebDriver wire protocol.
|
|
1215
1313
|
*
|
|
1216
1314
|
* @param {string} name The name of the cookie to retrieve.
|
|
1217
|
-
* @return {!promise.
|
|
1315
|
+
* @return {!promise.Thenable<?Options.Cookie>} A promise that will be resolved
|
|
1218
1316
|
* with the named cookie, or `null` if there is no such cookie.
|
|
1219
1317
|
*/
|
|
1220
1318
|
getCookie(name) {
|
|
@@ -1365,7 +1463,7 @@ class Timeouts {
|
|
|
1365
1463
|
* slower location strategies like XPath.
|
|
1366
1464
|
*
|
|
1367
1465
|
* @param {number} ms The amount of time to wait, in milliseconds.
|
|
1368
|
-
* @return {!promise.
|
|
1466
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1369
1467
|
* when the implicit wait timeout has been set.
|
|
1370
1468
|
*/
|
|
1371
1469
|
implicitlyWait(ms) {
|
|
@@ -1378,7 +1476,7 @@ class Timeouts {
|
|
|
1378
1476
|
* less than or equal to 0, the script will be allowed to run indefinitely.
|
|
1379
1477
|
*
|
|
1380
1478
|
* @param {number} ms The amount of time to wait, in milliseconds.
|
|
1381
|
-
* @return {!promise.
|
|
1479
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1382
1480
|
* when the script timeout has been set.
|
|
1383
1481
|
*/
|
|
1384
1482
|
setScriptTimeout(ms) {
|
|
@@ -1391,7 +1489,7 @@ class Timeouts {
|
|
|
1391
1489
|
* indefinite.
|
|
1392
1490
|
*
|
|
1393
1491
|
* @param {number} ms The amount of time to wait, in milliseconds.
|
|
1394
|
-
* @return {!promise.
|
|
1492
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1395
1493
|
* when the timeout has been set.
|
|
1396
1494
|
*/
|
|
1397
1495
|
pageLoadTimeout(ms) {
|
|
@@ -1411,7 +1509,7 @@ class Timeouts {
|
|
|
1411
1509
|
/**
|
|
1412
1510
|
* An interface for managing the current window.
|
|
1413
1511
|
*
|
|
1414
|
-
* This class should never be instantiated directly.
|
|
1512
|
+
* This class should never be instantiated directly. Instead, obtain an instance
|
|
1415
1513
|
* with
|
|
1416
1514
|
*
|
|
1417
1515
|
* webdriver.manage().window()
|
|
@@ -1432,7 +1530,7 @@ class Window {
|
|
|
1432
1530
|
/**
|
|
1433
1531
|
* Retrieves the window's current position, relative to the top left corner of
|
|
1434
1532
|
* the screen.
|
|
1435
|
-
* @return {!promise.
|
|
1533
|
+
* @return {!promise.Thenable<{x: number, y: number}>} A promise
|
|
1436
1534
|
* that will be resolved with the window's position in the form of a
|
|
1437
1535
|
* {x:number, y:number} object literal.
|
|
1438
1536
|
*/
|
|
@@ -1449,7 +1547,7 @@ class Window {
|
|
|
1449
1547
|
* side of the screen.
|
|
1450
1548
|
* @param {number} y The desired vertical position, relative to the top of the
|
|
1451
1549
|
* of the screen.
|
|
1452
|
-
* @return {!promise.
|
|
1550
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1453
1551
|
* when the command has completed.
|
|
1454
1552
|
*/
|
|
1455
1553
|
setPosition(x, y) {
|
|
@@ -1463,7 +1561,7 @@ class Window {
|
|
|
1463
1561
|
|
|
1464
1562
|
/**
|
|
1465
1563
|
* Retrieves the window's current size.
|
|
1466
|
-
* @return {!promise.
|
|
1564
|
+
* @return {!promise.Thenable<{width: number, height: number}>} A
|
|
1467
1565
|
* promise that will be resolved with the window's size in the form of a
|
|
1468
1566
|
* {width:number, height:number} object literal.
|
|
1469
1567
|
*/
|
|
@@ -1478,7 +1576,7 @@ class Window {
|
|
|
1478
1576
|
* Resizes the current window.
|
|
1479
1577
|
* @param {number} width The desired window width.
|
|
1480
1578
|
* @param {number} height The desired window height.
|
|
1481
|
-
* @return {!promise.
|
|
1579
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1482
1580
|
* when the command has completed.
|
|
1483
1581
|
*/
|
|
1484
1582
|
setSize(width, height) {
|
|
@@ -1492,7 +1590,7 @@ class Window {
|
|
|
1492
1590
|
|
|
1493
1591
|
/**
|
|
1494
1592
|
* Maximizes the current window.
|
|
1495
|
-
* @return {!promise.
|
|
1593
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1496
1594
|
* when the command has completed.
|
|
1497
1595
|
*/
|
|
1498
1596
|
maximize() {
|
|
@@ -1534,7 +1632,7 @@ class Logs {
|
|
|
1534
1632
|
* entries since the last call, or from the start of the session.
|
|
1535
1633
|
*
|
|
1536
1634
|
* @param {!logging.Type} type The desired log type.
|
|
1537
|
-
* @return {!promise.
|
|
1635
|
+
* @return {!promise.Thenable<!Array.<!logging.Entry>>} A
|
|
1538
1636
|
* promise that will resolve to a list of log entries for the specified
|
|
1539
1637
|
* type.
|
|
1540
1638
|
*/
|
|
@@ -1557,7 +1655,7 @@ class Logs {
|
|
|
1557
1655
|
|
|
1558
1656
|
/**
|
|
1559
1657
|
* Retrieves the log types available to this driver.
|
|
1560
|
-
* @return {!promise.
|
|
1658
|
+
* @return {!promise.Thenable<!Array<!logging.Type>>} A
|
|
1561
1659
|
* promise that will resolve to a list of available log types.
|
|
1562
1660
|
*/
|
|
1563
1661
|
getAvailableLogTypes() {
|
|
@@ -1604,7 +1702,7 @@ class TargetLocator {
|
|
|
1604
1702
|
/**
|
|
1605
1703
|
* Schedules a command to switch focus of all future commands to the topmost
|
|
1606
1704
|
* frame on the page.
|
|
1607
|
-
* @return {!promise.
|
|
1705
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1608
1706
|
* when the driver has changed focus to the default content.
|
|
1609
1707
|
*/
|
|
1610
1708
|
defaultContent() {
|
|
@@ -1630,7 +1728,7 @@ class TargetLocator {
|
|
|
1630
1728
|
* rejected with a {@linkplain error.NoSuchFrameError}.
|
|
1631
1729
|
*
|
|
1632
1730
|
* @param {(number|WebElement|null)} id The frame locator.
|
|
1633
|
-
* @return {!promise.
|
|
1731
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1634
1732
|
* when the driver has changed focus to the specified frame.
|
|
1635
1733
|
*/
|
|
1636
1734
|
frame(id) {
|
|
@@ -1650,13 +1748,16 @@ class TargetLocator {
|
|
|
1650
1748
|
*
|
|
1651
1749
|
* @param {string} nameOrHandle The name or window handle of the window to
|
|
1652
1750
|
* switch focus to.
|
|
1653
|
-
* @return {!promise.
|
|
1751
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1654
1752
|
* when the driver has changed focus to the specified window.
|
|
1655
1753
|
*/
|
|
1656
1754
|
window(nameOrHandle) {
|
|
1657
1755
|
return this.driver_.schedule(
|
|
1658
1756
|
new command.Command(command.Name.SWITCH_TO_WINDOW).
|
|
1659
|
-
|
|
1757
|
+
// "name" supports the legacy drivers. "handle" is the W3C
|
|
1758
|
+
// compliant parameter.
|
|
1759
|
+
setParameter('name', nameOrHandle).
|
|
1760
|
+
setParameter('handle', nameOrHandle),
|
|
1660
1761
|
'WebDriver.switchTo().window(' + nameOrHandle + ')');
|
|
1661
1762
|
}
|
|
1662
1763
|
|
|
@@ -1711,8 +1812,8 @@ class WebElement {
|
|
|
1711
1812
|
/** @private {!WebDriver} */
|
|
1712
1813
|
this.driver_ = driver;
|
|
1713
1814
|
|
|
1714
|
-
/** @private {!promise.
|
|
1715
|
-
this.id_ =
|
|
1815
|
+
/** @private {!promise.Thenable<string>} */
|
|
1816
|
+
this.id_ = driver.controlFlow().promise(resolve => resolve(id));
|
|
1716
1817
|
}
|
|
1717
1818
|
|
|
1718
1819
|
/**
|
|
@@ -1759,12 +1860,12 @@ class WebElement {
|
|
|
1759
1860
|
*
|
|
1760
1861
|
* @param {!WebElement} a A WebElement.
|
|
1761
1862
|
* @param {!WebElement} b A WebElement.
|
|
1762
|
-
* @return {!promise.
|
|
1863
|
+
* @return {!promise.Thenable<boolean>} A promise that will be
|
|
1763
1864
|
* resolved to whether the two WebElements are equal.
|
|
1764
1865
|
*/
|
|
1765
1866
|
static equals(a, b) {
|
|
1766
1867
|
if (a === b) {
|
|
1767
|
-
return
|
|
1868
|
+
return a.driver_.controlFlow().promise(resolve => resolve(true));
|
|
1768
1869
|
}
|
|
1769
1870
|
let ids = [a.getId(), b.getId()];
|
|
1770
1871
|
return promise.all(ids).then(function(ids) {
|
|
@@ -1788,7 +1889,7 @@ class WebElement {
|
|
|
1788
1889
|
}
|
|
1789
1890
|
|
|
1790
1891
|
/**
|
|
1791
|
-
* @return {!promise.
|
|
1892
|
+
* @return {!promise.Thenable<string>} A promise that resolves to
|
|
1792
1893
|
* the server-assigned opaque ID assigned to this element.
|
|
1793
1894
|
*/
|
|
1794
1895
|
getId() {
|
|
@@ -1809,14 +1910,14 @@ class WebElement {
|
|
|
1809
1910
|
*
|
|
1810
1911
|
* @param {!command.Command} command The command to schedule.
|
|
1811
1912
|
* @param {string} description A description of the command for debugging.
|
|
1812
|
-
* @return {!promise.
|
|
1913
|
+
* @return {!promise.Thenable<T>} A promise that will be resolved
|
|
1813
1914
|
* with the command result.
|
|
1814
1915
|
* @template T
|
|
1815
1916
|
* @see WebDriver#schedule
|
|
1816
1917
|
* @private
|
|
1817
1918
|
*/
|
|
1818
1919
|
schedule_(command, description) {
|
|
1819
|
-
command.setParameter('id', this
|
|
1920
|
+
command.setParameter('id', this);
|
|
1820
1921
|
return this.driver_.schedule(command, description);
|
|
1821
1922
|
}
|
|
1822
1923
|
|
|
@@ -1875,7 +1976,7 @@ class WebElement {
|
|
|
1875
1976
|
*
|
|
1876
1977
|
* @param {!(by.By|Function)} locator The locator strategy to use when
|
|
1877
1978
|
* searching for the element.
|
|
1878
|
-
* @return {!promise.
|
|
1979
|
+
* @return {!promise.Thenable<!Array<!WebElement>>} A
|
|
1879
1980
|
* promise that will resolve to an array of WebElements.
|
|
1880
1981
|
*/
|
|
1881
1982
|
findElements(locator) {
|
|
@@ -1894,7 +1995,7 @@ class WebElement {
|
|
|
1894
1995
|
|
|
1895
1996
|
/**
|
|
1896
1997
|
* Schedules a command to click on this element.
|
|
1897
|
-
* @return {!promise.
|
|
1998
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1898
1999
|
* when the click command has completed.
|
|
1899
2000
|
*/
|
|
1900
2001
|
click() {
|
|
@@ -1956,7 +2057,7 @@ class WebElement {
|
|
|
1956
2057
|
* sequence of keys to type. Number keys may be referenced numerically or
|
|
1957
2058
|
* by string (1 or '1'). All arguments will be joined into a single
|
|
1958
2059
|
* sequence.
|
|
1959
|
-
* @return {!promise.
|
|
2060
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1960
2061
|
* when all keys have been typed.
|
|
1961
2062
|
*/
|
|
1962
2063
|
sendKeys(var_args) {
|
|
@@ -1990,14 +2091,14 @@ class WebElement {
|
|
|
1990
2091
|
keys.catch(function() {});
|
|
1991
2092
|
|
|
1992
2093
|
var element = this;
|
|
1993
|
-
return this.
|
|
2094
|
+
return this.getDriver().controlFlow().execute(function() {
|
|
1994
2095
|
return keys.then(function(keys) {
|
|
1995
2096
|
return element.driver_.fileDetector_
|
|
1996
2097
|
.handleFile(element.driver_, keys.join(''));
|
|
1997
2098
|
}).then(function(keys) {
|
|
1998
2099
|
return element.schedule_(
|
|
1999
2100
|
new command.Command(command.Name.SEND_KEYS_TO_ELEMENT).
|
|
2000
|
-
setParameter('value',
|
|
2101
|
+
setParameter('value', keys.split('')),
|
|
2001
2102
|
'WebElement.sendKeys()');
|
|
2002
2103
|
});
|
|
2003
2104
|
}, 'WebElement.sendKeys()');
|
|
@@ -2005,7 +2106,7 @@ class WebElement {
|
|
|
2005
2106
|
|
|
2006
2107
|
/**
|
|
2007
2108
|
* Schedules a command to query for the tag/node name of this element.
|
|
2008
|
-
* @return {!promise.
|
|
2109
|
+
* @return {!promise.Thenable<string>} A promise that will be
|
|
2009
2110
|
* resolved with the element's tag name.
|
|
2010
2111
|
*/
|
|
2011
2112
|
getTagName() {
|
|
@@ -2026,7 +2127,7 @@ class WebElement {
|
|
|
2026
2127
|
*
|
|
2027
2128
|
* @param {string} cssStyleProperty The name of the CSS style property to look
|
|
2028
2129
|
* up.
|
|
2029
|
-
* @return {!promise.
|
|
2130
|
+
* @return {!promise.Thenable<string>} A promise that will be
|
|
2030
2131
|
* resolved with the requested CSS value.
|
|
2031
2132
|
*/
|
|
2032
2133
|
getCssValue(cssStyleProperty) {
|
|
@@ -2062,7 +2163,7 @@ class WebElement {
|
|
|
2062
2163
|
* - "readonly"
|
|
2063
2164
|
*
|
|
2064
2165
|
* @param {string} attributeName The name of the attribute to query.
|
|
2065
|
-
* @return {!promise.
|
|
2166
|
+
* @return {!promise.Thenable<?string>} A promise that will be
|
|
2066
2167
|
* resolved with the attribute's value. The returned value will always be
|
|
2067
2168
|
* either a string or null.
|
|
2068
2169
|
*/
|
|
@@ -2077,7 +2178,7 @@ class WebElement {
|
|
|
2077
2178
|
* Get the visible (i.e. not hidden by CSS) innerText of this element,
|
|
2078
2179
|
* including sub-elements, without any leading or trailing whitespace.
|
|
2079
2180
|
*
|
|
2080
|
-
* @return {!promise.
|
|
2181
|
+
* @return {!promise.Thenable<string>} A promise that will be
|
|
2081
2182
|
* resolved with the element's visible text.
|
|
2082
2183
|
*/
|
|
2083
2184
|
getText() {
|
|
@@ -2089,7 +2190,7 @@ class WebElement {
|
|
|
2089
2190
|
/**
|
|
2090
2191
|
* Schedules a command to compute the size of this element's bounding box, in
|
|
2091
2192
|
* pixels.
|
|
2092
|
-
* @return {!promise.
|
|
2193
|
+
* @return {!promise.Thenable<{width: number, height: number}>} A
|
|
2093
2194
|
* promise that will be resolved with the element's size as a
|
|
2094
2195
|
* {@code {width:number, height:number}} object.
|
|
2095
2196
|
*/
|
|
@@ -2101,7 +2202,7 @@ class WebElement {
|
|
|
2101
2202
|
|
|
2102
2203
|
/**
|
|
2103
2204
|
* Schedules a command to compute the location of this element in page space.
|
|
2104
|
-
* @return {!promise.
|
|
2205
|
+
* @return {!promise.Thenable<{x: number, y: number}>} A promise that
|
|
2105
2206
|
* will be resolved to the element's location as a
|
|
2106
2207
|
* {@code {x:number, y:number}} object.
|
|
2107
2208
|
*/
|
|
@@ -2114,7 +2215,7 @@ class WebElement {
|
|
|
2114
2215
|
/**
|
|
2115
2216
|
* Schedules a command to query whether the DOM element represented by this
|
|
2116
2217
|
* instance is enabled, as dicted by the {@code disabled} attribute.
|
|
2117
|
-
* @return {!promise.
|
|
2218
|
+
* @return {!promise.Thenable<boolean>} A promise that will be
|
|
2118
2219
|
* resolved with whether this element is currently enabled.
|
|
2119
2220
|
*/
|
|
2120
2221
|
isEnabled() {
|
|
@@ -2125,7 +2226,7 @@ class WebElement {
|
|
|
2125
2226
|
|
|
2126
2227
|
/**
|
|
2127
2228
|
* Schedules a command to query whether this element is selected.
|
|
2128
|
-
* @return {!promise.
|
|
2229
|
+
* @return {!promise.Thenable<boolean>} A promise that will be
|
|
2129
2230
|
* resolved with whether this element is currently selected.
|
|
2130
2231
|
*/
|
|
2131
2232
|
isSelected() {
|
|
@@ -2138,7 +2239,7 @@ class WebElement {
|
|
|
2138
2239
|
* Schedules a command to submit the form containing this element (or this
|
|
2139
2240
|
* element if it is a FORM element). This command is a no-op if the element is
|
|
2140
2241
|
* not contained in a form.
|
|
2141
|
-
* @return {!promise.
|
|
2242
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
2142
2243
|
* when the form has been submitted.
|
|
2143
2244
|
*/
|
|
2144
2245
|
submit() {
|
|
@@ -2151,7 +2252,7 @@ class WebElement {
|
|
|
2151
2252
|
* Schedules a command to clear the `value` of this element. This command has
|
|
2152
2253
|
* no effect if the underlying DOM element is neither a text INPUT element
|
|
2153
2254
|
* nor a TEXTAREA element.
|
|
2154
|
-
* @return {!promise.
|
|
2255
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
2155
2256
|
* when the element has been cleared.
|
|
2156
2257
|
*/
|
|
2157
2258
|
clear() {
|
|
@@ -2162,7 +2263,7 @@ class WebElement {
|
|
|
2162
2263
|
|
|
2163
2264
|
/**
|
|
2164
2265
|
* Schedules a command to test whether this element is currently displayed.
|
|
2165
|
-
* @return {!promise.
|
|
2266
|
+
* @return {!promise.Thenable<boolean>} A promise that will be
|
|
2166
2267
|
* resolved with whether this element is currently visible on the page.
|
|
2167
2268
|
*/
|
|
2168
2269
|
isDisplayed() {
|
|
@@ -2178,7 +2279,7 @@ class WebElement {
|
|
|
2178
2279
|
* @param {boolean=} opt_scroll Optional argument that indicates whether the
|
|
2179
2280
|
* element should be scrolled into view before taking a screenshot.
|
|
2180
2281
|
* Defaults to false.
|
|
2181
|
-
* @return {!promise.
|
|
2282
|
+
* @return {!promise.Thenable<string>} A promise that will be
|
|
2182
2283
|
* resolved to the screenshot as a base-64 encoded PNG.
|
|
2183
2284
|
*/
|
|
2184
2285
|
takeScreenshot(opt_scroll) {
|
|
@@ -2203,24 +2304,30 @@ class WebElement {
|
|
|
2203
2304
|
* return el.click();
|
|
2204
2305
|
* });
|
|
2205
2306
|
*
|
|
2206
|
-
* @implements {promise.
|
|
2307
|
+
* @implements {promise.CancellableThenable<!WebElement>}
|
|
2207
2308
|
* @final
|
|
2208
2309
|
*/
|
|
2209
2310
|
class WebElementPromise extends WebElement {
|
|
2210
2311
|
/**
|
|
2211
2312
|
* @param {!WebDriver} driver The parent WebDriver instance for this
|
|
2212
2313
|
* element.
|
|
2213
|
-
* @param {!promise.
|
|
2314
|
+
* @param {!promise.Thenable<!WebElement>} el A promise
|
|
2214
2315
|
* that will resolve to the promised element.
|
|
2215
2316
|
*/
|
|
2216
2317
|
constructor(driver, el) {
|
|
2217
2318
|
super(driver, 'unused');
|
|
2218
2319
|
|
|
2219
|
-
/**
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2320
|
+
/**
|
|
2321
|
+
* Cancel operation is only supported if the wrapped thenable is also
|
|
2322
|
+
* cancellable.
|
|
2323
|
+
* @param {(string|Error)=} opt_reason
|
|
2324
|
+
* @override
|
|
2325
|
+
*/
|
|
2326
|
+
this.cancel = function(opt_reason) {
|
|
2327
|
+
if (promise.CancellableThenable.isImplementation(el)) {
|
|
2328
|
+
/** @type {!promise.CancellableThenable} */(el).cancel(opt_reason);
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2224
2331
|
|
|
2225
2332
|
/** @override */
|
|
2226
2333
|
this.then = el.then.bind(el);
|
|
@@ -2228,9 +2335,6 @@ class WebElementPromise extends WebElement {
|
|
|
2228
2335
|
/** @override */
|
|
2229
2336
|
this.catch = el.catch.bind(el);
|
|
2230
2337
|
|
|
2231
|
-
/** @override */
|
|
2232
|
-
this.finally = el.finally.bind(el);
|
|
2233
|
-
|
|
2234
2338
|
/**
|
|
2235
2339
|
* Defers returning the element ID until the wrapped WebElement has been
|
|
2236
2340
|
* resolved.
|
|
@@ -2243,7 +2347,7 @@ class WebElementPromise extends WebElement {
|
|
|
2243
2347
|
};
|
|
2244
2348
|
}
|
|
2245
2349
|
}
|
|
2246
|
-
promise.
|
|
2350
|
+
promise.CancellableThenable.addImplementation(WebElementPromise);
|
|
2247
2351
|
|
|
2248
2352
|
|
|
2249
2353
|
//////////////////////////////////////////////////////////////////////////////
|
|
@@ -2269,15 +2373,15 @@ class Alert {
|
|
|
2269
2373
|
/** @private {!WebDriver} */
|
|
2270
2374
|
this.driver_ = driver;
|
|
2271
2375
|
|
|
2272
|
-
/** @private {!promise.
|
|
2273
|
-
this.text_ =
|
|
2376
|
+
/** @private {!promise.Thenable<string>} */
|
|
2377
|
+
this.text_ = driver.controlFlow().promise(resolve => resolve(text));
|
|
2274
2378
|
}
|
|
2275
2379
|
|
|
2276
2380
|
/**
|
|
2277
2381
|
* Retrieves the message text displayed with this alert. For instance, if the
|
|
2278
2382
|
* alert were opened with alert("hello"), then this would return "hello".
|
|
2279
2383
|
*
|
|
2280
|
-
* @return {!promise.
|
|
2384
|
+
* @return {!promise.Thenable<string>} A promise that will be
|
|
2281
2385
|
* resolved to the text displayed with this alert.
|
|
2282
2386
|
*/
|
|
2283
2387
|
getText() {
|
|
@@ -2291,7 +2395,7 @@ class Alert {
|
|
|
2291
2395
|
*
|
|
2292
2396
|
* @param {string} username The username to send.
|
|
2293
2397
|
* @param {string} password The password to send.
|
|
2294
|
-
* @return {!promise.
|
|
2398
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved when this
|
|
2295
2399
|
* command has completed.
|
|
2296
2400
|
*/
|
|
2297
2401
|
authenticateAs(username, password) {
|
|
@@ -2304,7 +2408,7 @@ class Alert {
|
|
|
2304
2408
|
/**
|
|
2305
2409
|
* Accepts this alert.
|
|
2306
2410
|
*
|
|
2307
|
-
* @return {!promise.
|
|
2411
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
2308
2412
|
* when this command has completed.
|
|
2309
2413
|
*/
|
|
2310
2414
|
accept() {
|
|
@@ -2316,7 +2420,7 @@ class Alert {
|
|
|
2316
2420
|
/**
|
|
2317
2421
|
* Dismisses this alert.
|
|
2318
2422
|
*
|
|
2319
|
-
* @return {!promise.
|
|
2423
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
2320
2424
|
* when this command has completed.
|
|
2321
2425
|
*/
|
|
2322
2426
|
dismiss() {
|
|
@@ -2331,7 +2435,7 @@ class Alert {
|
|
|
2331
2435
|
* window.confirm).
|
|
2332
2436
|
*
|
|
2333
2437
|
* @param {string} text The text to set.
|
|
2334
|
-
* @return {!promise.
|
|
2438
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
2335
2439
|
* when this command has completed.
|
|
2336
2440
|
*/
|
|
2337
2441
|
sendKeys(text) {
|
|
@@ -2354,7 +2458,7 @@ class Alert {
|
|
|
2354
2458
|
* return alert.dismiss();
|
|
2355
2459
|
* });
|
|
2356
2460
|
*
|
|
2357
|
-
* @implements {promise.
|
|
2461
|
+
* @implements {promise.CancellableThenable<!webdriver.Alert>}
|
|
2358
2462
|
* @final
|
|
2359
2463
|
*/
|
|
2360
2464
|
class AlertPromise extends Alert {
|
|
@@ -2367,11 +2471,17 @@ class AlertPromise extends Alert {
|
|
|
2367
2471
|
constructor(driver, alert) {
|
|
2368
2472
|
super(driver, 'unused');
|
|
2369
2473
|
|
|
2370
|
-
/**
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2474
|
+
/**
|
|
2475
|
+
* Cancel operation is only supported if the wrapped thenable is also
|
|
2476
|
+
* cancellable.
|
|
2477
|
+
* @param {(string|Error)=} opt_reason
|
|
2478
|
+
* @override
|
|
2479
|
+
*/
|
|
2480
|
+
this.cancel = function(opt_reason) {
|
|
2481
|
+
if (promise.CancellableThenable.isImplementation(alert)) {
|
|
2482
|
+
/** @type {!promise.CancellableThenable} */(alert).cancel(opt_reason);
|
|
2483
|
+
}
|
|
2484
|
+
};
|
|
2375
2485
|
|
|
2376
2486
|
/** @override */
|
|
2377
2487
|
this.then = alert.then.bind(alert);
|
|
@@ -2379,9 +2489,6 @@ class AlertPromise extends Alert {
|
|
|
2379
2489
|
/** @override */
|
|
2380
2490
|
this.catch = alert.catch.bind(alert);
|
|
2381
2491
|
|
|
2382
|
-
/** @override */
|
|
2383
|
-
this.finally = alert.finally.bind(alert);
|
|
2384
|
-
|
|
2385
2492
|
/**
|
|
2386
2493
|
* Defer returning text until the promised alert has been resolved.
|
|
2387
2494
|
* @override
|
|
@@ -2433,7 +2540,7 @@ class AlertPromise extends Alert {
|
|
|
2433
2540
|
};
|
|
2434
2541
|
}
|
|
2435
2542
|
}
|
|
2436
|
-
promise.
|
|
2543
|
+
promise.CancellableThenable.addImplementation(AlertPromise);
|
|
2437
2544
|
|
|
2438
2545
|
|
|
2439
2546
|
// PUBLIC API
|
|
@@ -2448,6 +2555,7 @@ module.exports = {
|
|
|
2448
2555
|
Options: Options,
|
|
2449
2556
|
TargetLocator: TargetLocator,
|
|
2450
2557
|
Timeouts: Timeouts,
|
|
2558
|
+
IWebDriver: IWebDriver,
|
|
2451
2559
|
WebDriver: WebDriver,
|
|
2452
2560
|
WebElement: WebElement,
|
|
2453
2561
|
WebElementCondition: WebElementCondition,
|