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.
Files changed (77) hide show
  1. package/CHANGES.md +109 -0
  2. package/LICENSE +1 -1
  3. package/README.md +7 -6
  4. package/chrome.js +31 -128
  5. package/edge.js +13 -91
  6. package/example/chrome_android.js +18 -13
  7. package/example/chrome_mobile_emulation.js +19 -15
  8. package/example/google_search.js +11 -11
  9. package/example/google_search_generator.js +23 -18
  10. package/example/google_search_test.js +31 -17
  11. package/example/logging.js +9 -17
  12. package/example/parallel_flows.js +3 -0
  13. package/firefox/binary.js +17 -0
  14. package/firefox/index.js +198 -101
  15. package/firefox/profile.js +24 -3
  16. package/http/util.js +95 -59
  17. package/ie.js +6 -10
  18. package/index.js +636 -2
  19. package/lib/actions.js +18 -10
  20. package/lib/atoms/getAttribute.js +11 -0
  21. package/lib/atoms/isDisplayed.js +106 -0
  22. package/lib/firefox/amd64/libnoblur64.so +0 -0
  23. package/lib/firefox/i386/libnoblur.so +0 -0
  24. package/lib/firefox/webdriver.xpi +0 -0
  25. package/lib/http.js +159 -46
  26. package/lib/logging.js +7 -1
  27. package/lib/promise.js +602 -358
  28. package/lib/proxy.js +28 -0
  29. package/lib/session.js +1 -1
  30. package/lib/test/build.js +26 -28
  31. package/lib/test/data/formPage.html +1 -0
  32. package/lib/test/fileserver.js +12 -10
  33. package/lib/test/httpserver.js +4 -6
  34. package/lib/test/index.js +18 -11
  35. package/lib/test/promise.js +79 -0
  36. package/lib/webdriver.js +587 -479
  37. package/opera.js +12 -88
  38. package/package.json +13 -14
  39. package/phantomjs.js +7 -14
  40. package/remote/index.js +201 -30
  41. package/safari.js +62 -416
  42. package/test/actions_test.js +9 -11
  43. package/test/chrome/options_test.js +8 -8
  44. package/test/chrome/service_test.js +2 -2
  45. package/test/cookie_test.js +57 -57
  46. package/test/element_finding_test.js +201 -185
  47. package/test/execute_script_test.js +108 -111
  48. package/test/fingerprint_test.js +16 -11
  49. package/test/firefox/firefox_test.js +75 -49
  50. package/test/firefox/profile_test.js +1 -3
  51. package/test/http/util_test.js +21 -27
  52. package/test/io_test.js +2 -5
  53. package/test/lib/http_test.js +8 -6
  54. package/test/lib/promise_aplus_test.js +48 -44
  55. package/test/lib/promise_error_test.js +687 -611
  56. package/test/lib/promise_flow_test.js +1810 -1806
  57. package/test/lib/promise_generator_test.js +227 -225
  58. package/test/lib/promise_test.js +864 -835
  59. package/test/lib/until_test.js +1 -1
  60. package/test/lib/webdriver_test.js +520 -424
  61. package/test/logging_test.js +43 -45
  62. package/test/net/portprober_test.js +23 -24
  63. package/test/page_loading_test.js +84 -78
  64. package/test/phantomjs/execute_phantomjs_test.js +11 -25
  65. package/test/proxy_test.js +23 -23
  66. package/test/remote_test.js +22 -22
  67. package/test/safari_test.js +108 -0
  68. package/test/session_test.js +11 -10
  69. package/test/stale_element_test.js +18 -16
  70. package/test/tag_name_test.js +7 -5
  71. package/test/testing/assert_test.js +2 -3
  72. package/test/testing/index_test.js +163 -117
  73. package/test/upload_test.js +13 -13
  74. package/test/window_test.js +94 -70
  75. package/testing/index.js +176 -37
  76. package/builder.js +0 -553
  77. package/lib/safari/client.js +0 -56
package/CHANGES.md CHANGED
@@ -1,3 +1,112 @@
1
+ ## v3.0.1
2
+
3
+ * More API adjustments to align with native Promises
4
+ - Deprecated `promise.fulfilled(value)`, use `promise.Promise#resolve(value)`
5
+ - Deprecated `promise.rejected(reason)`, use `promise.Promise#reject(reason)`
6
+ * When a `wait()` condition times out, the returned promise will now be
7
+ rejected with an `error.TimeoutError` instead of a generic `Error` object.
8
+ * `WebDriver#wait()` will now throw a TypeError if an invalid wait condition is
9
+ provided.
10
+ * Properly catch unhandled promise rejections with an action sequence (only
11
+ impacts when the promise manager is disabled).
12
+
13
+
14
+ ## v3.0.0
15
+
16
+ * (__NOTICE__) The minimum supported version of Node is now 6.9.0 LTS
17
+ * Removed support for the SafariDriver browser extension. This has been
18
+ replaced by Apple's safaridriver, which is included wtih Safari 10
19
+ (available on OS X El Capitan and macOS Sierra).
20
+
21
+ To use Safari 9 or older, users will have to use an older version of Selenium.
22
+
23
+ * geckodriver v0.11.0 or newer is now required for Firefox.
24
+ * Fixed potential reference errors in `selenium-webdriver/testing` when users
25
+ create a cycle with mocha by running with mocha's `--hook` flag.
26
+ * Fixed `WebDriver.switchTo().activeElement()` to use the correct HTTP method
27
+ for compatibility with the W3C spec.
28
+ * Update the `selenium-webdriver/firefox` module to use geckodriver's
29
+ "moz:firefoxOptions" dictionary for Firefox-specific configuration values.
30
+ * Extending the `selenium-webdriver/testing` module to support tests defined
31
+ using generator functions.
32
+ * The promise manager can be disabled by setting an enviornment variable:
33
+ `SELENIUM_PROMISE_MANAGER=0`. This is part of a larger plan to remove the
34
+ promise manager, as documented at
35
+ <https://github.com/SeleniumHQ/selenium/issues/2969>
36
+ * When communicating with a W3C-compliant remote end, use the atoms library for
37
+ the `WebElement.getAttribute()` and `WebElement.isDisplayed()` commands. This
38
+ behavior is consistent with the java, .net, python, and ruby clients.
39
+
40
+
41
+ ### API Changes
42
+
43
+ * Removed `safari.Options#useLegacyDriver()`
44
+ * Reduced the API on `promise.Thenable` for compatibility with native promises:
45
+ - Removed `#isPending()`
46
+ - Removed `#cancel()`
47
+ - Removed `#finally()`
48
+ * Changed all subclasses of `webdriver.WebDriver` to overload the static
49
+ function `WebDriver.createSession()` instead of doing work in the
50
+ constructor. All constructors now inherit the base class' function signature.
51
+ Users are still encouraged to use the `Builder` class instead of creating
52
+ drivers directly.
53
+ * `Builder#build()` now returns a "thenable" WebDriver instance, allowing users
54
+ to immediately schedule commands (as before), or issue them through standard
55
+ promise callbacks. This is the same pattern already employed for WebElements.
56
+ * Removed `Builder#buildAsync()` as it was redundant with the new semantics of
57
+ `build()`.
58
+
59
+
60
+
61
+ ## v3.0.0-beta-3
62
+
63
+ * Fixed a bug where the promise manager would silently drop callbacks after
64
+ recovering from an unhandled promise rejection.
65
+ * Added the `firefox.ServiceBuilder` class, which may be used to customize the
66
+ geckodriver used for `firefox.Driver` instances.
67
+ * Added support for Safari 10 safaridriver. safaridriver may be disabled
68
+ via tha API, `safari.Options#useLegacyDriver`, to use the safari
69
+ extension driver.
70
+ * Updated the `lib/proxy` module to support configuring a SOCKS proxy.
71
+ * For the `promise.ControlFlow`, fire the "uncaughtException" event in a new
72
+ turn of the JS event loop. As a result of this change, any errors thrown by
73
+ an event listener will propagate to the global error handler. Previously,
74
+ this event was fired with in the context of a (native) promise callback,
75
+ causing errors to be silently suppressed in the promise chain.
76
+
77
+ ### API Changes
78
+
79
+ * Added `remote.DriverService.Builder` as a base class for configuring
80
+ DriverService instances that run in a child-process. The
81
+ `chrome.ServiceBuilder`, `edge.ServiceBuilder`, and `opera.ServiceBuilder`
82
+ classes now all extend this base class with browser-specific options.
83
+ * For each of the ServiceBuilder clases, renamed `usingPort` and
84
+ `withEnvironment` to `setPort` and `setEnvironment`, respectively.
85
+ * Renamed `chrome.ServiceBuilder#setUrlBasePath` to `#setPath`
86
+ * Changed the signature of the `firefox.Driver` from `(config, flow, executor)`
87
+ to `(config, executor, flow)`.
88
+ * Exposed the `Condition` and `WebElementCondition` classes from the top-level
89
+ `selenium-webdriver` module (these were previously only available from
90
+ `lib/webdriver`).
91
+
92
+
93
+ ### Changes for W3C WebDriver Spec Compliance
94
+
95
+ * Updated command mappings for [getting](https://w3c.github.io/webdriver/webdriver-spec.html#get-window-position)
96
+ and [setting](https://w3c.github.io/webdriver/webdriver-spec.html#set-window-position)
97
+ the window position.
98
+
99
+
100
+ ## v3.0.0-beta-2
101
+
102
+ ### API Changes
103
+
104
+ * Moved the `builder.Builder` class into the main module (`selenium-webdriver`).
105
+ * Removed the `builder` module.
106
+ * Fix `webdriver.WebDriver#setFileDetector` when driving Chrome or Firefox on a
107
+ remote machine.
108
+
109
+
1
110
  ## v3.0.0-beta-1
2
111
 
3
112
  * Allow users to set the agent used for HTTP connections through
package/LICENSE CHANGED
@@ -187,7 +187,7 @@
187
187
  same "printed page" as the copyright notice for easier
188
188
  identification within third-party archives.
189
189
 
190
- Copyright [yyyy] [name of copyright owner]
190
+ Copyright 2016 Software Freedom Conservancy (SFC)
191
191
 
192
192
  Licensed under the Apache License, Version 2.0 (the "License");
193
193
  you may not use this file except in compliance with the License.
package/README.md CHANGED
@@ -11,16 +11,16 @@ Selenium may be installed via npm with
11
11
  npm install selenium-webdriver
12
12
 
13
13
  You will need to download additional components to work with each of the major
14
- browsers. The drivers for Chrome, Firefox, PhantomJS, Opera, and
14
+ browsers. The drivers for Chrome, Firefox, PhantomJS, Opera, and
15
15
  Microsoft's IE and Edge web browsers are all standalone executables that should
16
- be placed on your system [PATH]. The SafariDriverbrowser extension should be
17
- installed in your browser before using Selenium; we recommend disabling the
18
- extension when using the browser without Selenium or installing the extension in
19
- a profile only used for testing.
16
+ be placed on your system [PATH]. Apple's safaridriver is shipped with
17
+ Safari 10 for OS X El Capitan and macOS Sierra. You will need to enable Remote
18
+ Automation in the Develop menu of Safari 10 before testing.
20
19
 
21
20
  > **NOTE:** Mozilla's [geckodriver] is only required for Firefox 47+.
22
21
  > Everything you need for Firefox 38-46 is included with this package.
23
22
 
23
+
24
24
  | Browser | Component |
25
25
  | ----------------- | ---------------------------------- |
26
26
  | Chrome | [chromedriver(.exe)][chrome] |
@@ -29,7 +29,7 @@ a profile only used for testing.
29
29
  | Firefox 47+ | [geckodriver(.exe)][geckodriver] |
30
30
  | PhantomJS | [phantomjs(.exe)][phantomjs] |
31
31
  | Opera | [operadriver(.exe)][opera] |
32
- | Safari | [SafariDriver.safariextz][release] |
32
+ | Safari | [safaridriver] |
33
33
 
34
34
  ## Usage
35
35
 
@@ -229,3 +229,4 @@ under the License.
229
229
  [reduction]: http://www.webkit.org/quality/reduction.html
230
230
  [release]: http://selenium-release.storage.googleapis.com/index.html
231
231
  [users]: https://groups.google.com/forum/#!forum/selenium-users
232
+ [safaridriver]: https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInSafari/Articles/Safari_10_0.html#//apple_ref/doc/uid/TP40014305-CH11-DontLinkElementID_28
package/chrome.js CHANGED
@@ -119,8 +119,7 @@ const fs = require('fs'),
119
119
 
120
120
  const http = require('./http'),
121
121
  io = require('./io'),
122
- Capabilities = require('./lib/capabilities').Capabilities,
123
- Capability = require('./lib/capabilities').Capability,
122
+ {Capabilities, Capability} = require('./lib/capabilities'),
124
123
  command = require('./lib/command'),
125
124
  logging = require('./lib/logging'),
126
125
  promise = require('./lib/promise'),
@@ -178,7 +177,7 @@ function configureExecutor(executor) {
178
177
  * a [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/)
179
178
  * server in a child process.
180
179
  */
181
- class ServiceBuilder {
180
+ class ServiceBuilder extends remote.DriverService.Builder {
182
181
  /**
183
182
  * @param {string=} opt_exe Path to the server executable to use. If omitted,
184
183
  * the builder will attempt to locate the chromedriver on the current
@@ -196,42 +195,8 @@ class ServiceBuilder {
196
195
  'it can be found on your PATH.');
197
196
  }
198
197
 
199
- if (!fs.existsSync(exe)) {
200
- throw Error('File does not exist: ' + exe);
201
- }
202
- /** @private {string} */
203
- this.exe_ = exe;
204
-
205
- /** @private {!Array<string>} */
206
- this.args_ = [];
207
-
208
- /**
209
- * @private {(string|!Array<string|number|!stream.Stream|null|undefined>)}
210
- */
211
- this.stdio_ = 'ignore';
212
-
213
- /** @private {?string} */
214
- this.path_ = null;
215
-
216
- /** @private {number} */
217
- this.port_ = 0;
218
-
219
- /** @private {Object<string, string>} */
220
- this.env_ = null;
221
- }
222
-
223
- /**
224
- * Sets the port to start the ChromeDriver on.
225
- * @param {number} port The port to use, or 0 for any free port.
226
- * @return {!ServiceBuilder} A self reference.
227
- * @throws {Error} If the port is invalid.
228
- */
229
- usingPort(port) {
230
- if (port < 0) {
231
- throw Error('port must be >= 0: ' + port);
232
- }
233
- this.port_ = port;
234
- return this;
198
+ super(exe);
199
+ this.setLoopback(true); // Required
235
200
  }
236
201
 
237
202
  /**
@@ -243,8 +208,7 @@ class ServiceBuilder {
243
208
  * @return {!ServiceBuilder} A self reference.
244
209
  */
245
210
  setAdbPort(port) {
246
- this.args_.push('--adb-port=' + port);
247
- return this;
211
+ return this.addArguments('--adb-port=' + port);
248
212
  }
249
213
 
250
214
  /**
@@ -254,8 +218,7 @@ class ServiceBuilder {
254
218
  * @return {!ServiceBuilder} A self reference.
255
219
  */
256
220
  loggingTo(path) {
257
- this.args_.push('--log-path=' + path);
258
- return this;
221
+ return this.addArguments('--log-path=' + path);
259
222
  }
260
223
 
261
224
  /**
@@ -263,8 +226,7 @@ class ServiceBuilder {
263
226
  * @return {!ServiceBuilder} A self reference.
264
227
  */
265
228
  enableVerboseLogging() {
266
- this.args_.push('--verbose');
267
- return this;
229
+ return this.addArguments('--verbose');
268
230
  }
269
231
 
270
232
  /**
@@ -274,66 +236,15 @@ class ServiceBuilder {
274
236
  * @return {!ServiceBuilder} A self reference.
275
237
  */
276
238
  setNumHttpThreads(n) {
277
- this.args_.push('--http-threads=' + n);
278
- return this;
239
+ return this.addArguments('--http-threads=' + n);
279
240
  }
280
241
 
281
242
  /**
282
- * Sets the base path for WebDriver REST commands (e.g. "/wd/hub").
283
- * By default, the driver will accept commands relative to "/".
284
- * @param {string} path The base path to use.
285
- * @return {!ServiceBuilder} A self reference.
286
- */
287
- setUrlBasePath(path) {
288
- this.args_.push('--url-base=' + path);
289
- this.path_ = path;
290
- return this;
291
- }
292
-
293
- /**
294
- * Defines the stdio configuration for the driver service. See
295
- * {@code child_process.spawn} for more information.
296
- * @param {(string|!Array<string|number|!stream.Stream|null|undefined>)}
297
- * config The configuration to use.
298
- * @return {!ServiceBuilder} A self reference.
299
- */
300
- setStdio(config) {
301
- this.stdio_ = config;
302
- return this;
303
- }
304
-
305
- /**
306
- * Defines the environment to start the server under. This settings will be
307
- * inherited by every browser session started by the server.
308
- * @param {!Object<string, string>} env The environment to use.
309
- * @return {!ServiceBuilder} A self reference.
310
- */
311
- withEnvironment(env) {
312
- this.env_ = env;
313
- return this;
314
- }
315
-
316
- /**
317
- * Creates a new DriverService using this instance's current configuration.
318
- * @return {!remote.DriverService} A new driver service using this instance's
319
- * current configuration.
320
- * @throws {Error} If the driver exectuable was not specified and a default
321
- * could not be found on the current PATH.
243
+ * @override
322
244
  */
323
- build() {
324
- let port = this.port_ || portprober.findFreePort();
325
- let args = this.args_.concat(); // Defensive copy.
326
-
327
- return new remote.DriverService(this.exe_, {
328
- loopback: true,
329
- path: this.path_,
330
- port: port,
331
- args: Promise.resolve(port).then(function(port) {
332
- return args.concat('--port=' + port);
333
- }),
334
- env: this.env_,
335
- stdio: this.stdio_
336
- });
245
+ setPath(path) {
246
+ super.setPath(path);
247
+ return this.addArguments('--url-base=' + path);
337
248
  }
338
249
  }
339
250
 
@@ -766,34 +677,27 @@ class Options {
766
677
  * Creates a new WebDriver client for Chrome.
767
678
  */
768
679
  class Driver extends webdriver.WebDriver {
680
+
769
681
  /**
770
- * @param {(Capabilities|Options)=} opt_config The configuration
771
- * options.
772
- * @param {remote.DriverService=} opt_service The session to use; will use
773
- * the {@linkplain #getDefaultService default service} by default.
774
- * @param {promise.ControlFlow=} opt_flow The control flow to use,
775
- * or {@code null} to use the currently active flow.
776
- * @param {http.Executor=} opt_executor A pre-configured command executor that
777
- * should be used to send commands to the remote end. The provided
778
- * executor should not be reused with other clients as its internal
779
- * command mappings will be updated to support Chrome-specific commands.
780
- *
781
- * You may provide either a custom executor or a driver service, but not both.
682
+ * Creates a new session with the ChromeDriver.
782
683
  *
783
- * @throws {Error} if both `opt_service` and `opt_executor` are provided.
784
- */
785
- constructor(opt_config, opt_service, opt_flow, opt_executor) {
786
- if (opt_service && opt_executor) {
787
- throw Error(
788
- 'Either a DriverService or Executor may be provided, but not both');
789
- }
790
-
684
+ * @param {(Capabilities|Options)=} opt_config The configuration options.
685
+ * @param {(remote.DriverService|http.Executor)=} opt_serviceExecutor Either
686
+ * a DriverService to use for the remote end, or a preconfigured executor
687
+ * for an externally managed endpoint. If neither is provided, the
688
+ * {@linkplain ##getDefaultService default service} will be used by
689
+ * default.
690
+ * @param {promise.ControlFlow=} opt_flow The control flow to use, or `null`
691
+ * to use the currently active flow.
692
+ * @return {!Driver} A new driver instance.
693
+ */
694
+ static createSession(opt_config, opt_serviceExecutor, opt_flow) {
791
695
  let executor;
792
- if (opt_executor) {
793
- executor = opt_executor;
696
+ if (opt_serviceExecutor instanceof http.Executor) {
697
+ executor = opt_serviceExecutor;
794
698
  configureExecutor(executor);
795
699
  } else {
796
- let service = opt_service || getDefaultService();
700
+ let service = opt_serviceExecutor || getDefaultService();
797
701
  executor = createExecutor(service.start());
798
702
  }
799
703
 
@@ -801,9 +705,8 @@ class Driver extends webdriver.WebDriver {
801
705
  opt_config instanceof Options ? opt_config.toCapabilities() :
802
706
  (opt_config || Capabilities.chrome());
803
707
 
804
- let driver = webdriver.WebDriver.createSession(executor, caps, opt_flow);
805
-
806
- super(driver.getSession(), executor, driver.controlFlow());
708
+ return /** @type {!Driver} */(
709
+ webdriver.WebDriver.createSession(executor, caps, opt_flow, this));
807
710
  }
808
711
 
809
712
  /**
@@ -816,7 +719,7 @@ class Driver extends webdriver.WebDriver {
816
719
  /**
817
720
  * Schedules a command to launch Chrome App with given ID.
818
721
  * @param {string} id ID of the App to launch.
819
- * @return {!promise.Promise<void>} A promise that will be resolved
722
+ * @return {!promise.Thenable<void>} A promise that will be resolved
820
723
  * when app is launched.
821
724
  */
822
725
  launchApp(id) {
package/edge.js CHANGED
@@ -52,7 +52,7 @@
52
52
  * var edge = require('selenium-webdriver/edge');
53
53
  *
54
54
  * var service = new edge.ServiceBuilder()
55
- * .usingPort(55555)
55
+ * .setPort(55555)
56
56
  * .build();
57
57
  *
58
58
  * var options = new edge.Options();
@@ -193,7 +193,7 @@ class Options {
193
193
  * Creates {@link remote.DriverService} instances that manage a
194
194
  * MicrosoftEdgeDriver server in a child process.
195
195
  */
196
- class ServiceBuilder {
196
+ class ServiceBuilder extends remote.DriverService.Builder {
197
197
  /**
198
198
  * @param {string=} opt_exe Path to the server executable to use. If omitted,
199
199
  * the builder will attempt to locate the MicrosoftEdgeDriver on the current
@@ -209,88 +209,14 @@ class ServiceBuilder {
209
209
  'Please download the latest version of the MicrosoftEdgeDriver from ' +
210
210
  'https://www.microsoft.com/en-us/download/details.aspx?id=48212 and ' +
211
211
  'ensure it can be found on your PATH.');
212
- } else if (!fs.existsSync(exe)) {
213
- throw Error('File does not exist: ' + exe);
214
212
  }
215
213
 
216
- /** @private {string} */
217
- this.exe_ = /** @type {string} */(exe);
214
+ super(exe);
218
215
 
219
- /** @private {!Array.<string>} */
220
- this.args_ = [];
221
-
222
- /** @private {number} */
223
- this.port_ = 0;
224
-
225
- /**
226
- * @private {(string|!Array.<string|number|!stream.Stream|null|undefined>)}
227
- */
228
- this.stdio_ = 'ignore';
229
-
230
- /** @private {Object.<string, string>} */
231
- this.env_ = null;
232
- }
233
-
234
- /**
235
- * Defines the stdio configuration for the driver service. See
236
- * {@code child_process.spawn} for more information.
237
- * @param {(string|!Array.<string|number|!stream.Stream|null|undefined>)}
238
- * config The configuration to use.
239
- * @return {!ServiceBuilder} A self reference.
240
- */
241
- setStdio(config) {
242
- this.stdio_ = config;
243
- return this;
244
- }
245
-
246
- /**
247
- * Sets the port to start the MicrosoftEdgeDriver on.
248
- * @param {number} port The port to use, or 0 for any free port.
249
- * @return {!ServiceBuilder} A self reference.
250
- * @throws {Error} If the port is invalid.
251
- */
252
- usingPort(port) {
253
- if (port < 0) {
254
- throw Error('port must be >= 0: ' + port);
255
- }
256
- this.port_ = port;
257
- return this;
258
- }
259
-
260
- /**
261
- * Defines the environment to start the server under. This settings will be
262
- * inherited by every browser session started by the server.
263
- * @param {!Object.<string, string>} env The environment to use.
264
- * @return {!ServiceBuilder} A self reference.
265
- */
266
- withEnvironment(env) {
267
- this.env_ = env;
268
- return this;
269
- }
270
-
271
- /**
272
- * Creates a new DriverService using this instance's current configuration.
273
- * @return {!remote.DriverService} A new driver service using this instance's
274
- * current configuration.
275
- * @throws {Error} If the driver exectuable was not specified and a default
276
- * could not be found on the current PATH.
277
- */
278
- build() {
279
- var port = this.port_ || portprober.findFreePort();
280
- var args = this.args_.concat(); // Defensive copy.
281
-
282
- return new remote.DriverService(this.exe_, {
283
- // Binding to the loopback address will fail if not running with
284
- // administrator privileges. Since we cannot test for that in script
285
- // (or can we?), force the DriverService to use "localhost".
286
- hostname: 'localhost',
287
- port: port,
288
- args: Promise.resolve(port).then(function(port) {
289
- return args.concat('--port=' + port);
290
- }),
291
- env: this.env_,
292
- stdio: this.stdio_
293
- });
216
+ // Binding to the loopback address will fail if not running with
217
+ // administrator privileges. Since we cannot test for that in script
218
+ // (or can we?), force the DriverService to use "localhost".
219
+ this.setHostname('localhost');
294
220
  }
295
221
  }
296
222
 
@@ -333,14 +259,17 @@ function getDefaultService() {
333
259
  */
334
260
  class Driver extends webdriver.WebDriver {
335
261
  /**
262
+ * Creates a new browser session for Microsoft's Edge browser.
263
+ *
336
264
  * @param {(capabilities.Capabilities|Options)=} opt_config The configuration
337
265
  * options.
338
266
  * @param {remote.DriverService=} opt_service The session to use; will use
339
267
  * the {@linkplain #getDefaultService default service} by default.
340
268
  * @param {promise.ControlFlow=} opt_flow The control flow to use, or
341
269
  * {@code null} to use the currently active flow.
270
+ * @return {!Driver} A new driver instance.
342
271
  */
343
- constructor(opt_config, opt_service, opt_flow) {
272
+ static createSession(opt_config, opt_service, opt_flow) {
344
273
  var service = opt_service || getDefaultService();
345
274
  var client = service.start().then(url => new http.HttpClient(url));
346
275
  var executor = new http.Executor(client);
@@ -349,15 +278,8 @@ class Driver extends webdriver.WebDriver {
349
278
  opt_config instanceof Options ? opt_config.toCapabilities() :
350
279
  (opt_config || capabilities.Capabilities.edge());
351
280
 
352
- var driver = webdriver.WebDriver.createSession(executor, caps, opt_flow);
353
- super(driver.getSession(), executor, driver.controlFlow());
354
-
355
- var boundQuit = this.quit.bind(this);
356
-
357
- /** @override */
358
- this.quit = function() {
359
- return boundQuit().finally(service.kill.bind(service));
360
- };
281
+ return /** @type {!Driver} */(webdriver.WebDriver.createSession(
282
+ executor, caps, opt_flow, this, () => service.kill()));
361
283
  }
362
284
 
363
285
  /**
@@ -21,18 +21,23 @@
21
21
  * AVD).
22
22
  */
23
23
 
24
- var webdriver = require('..'),
25
- By = webdriver.By,
26
- until = webdriver.until,
27
- chrome = require('../chrome');
24
+ 'use strict';
28
25
 
29
- var driver = new webdriver.Builder()
30
- .forBrowser('chrome')
31
- .setChromeOptions(new chrome.Options().androidChrome())
32
- .build();
26
+ const {Builder, By, promise, until} = require('..');
27
+ const {Options} = require('../chrome');
33
28
 
34
- driver.get('http://www.google.com/ncr');
35
- driver.findElement(By.name('q')).sendKeys('webdriver');
36
- driver.findElement(By.name('btnG')).click();
37
- driver.wait(until.titleIs('webdriver - Google Search'), 1000);
38
- driver.quit();
29
+ promise.consume(function* () {
30
+ let driver;
31
+ try {
32
+ driver = yield new Builder()
33
+ .forBrowser('chrome')
34
+ .setChromeOptions(new Options().androidChrome())
35
+ .build();
36
+ yield driver.get('http://www.google.com/ncr');
37
+ yield driver.findElement(By.name('q')).sendKeys('webdriver');
38
+ yield driver.findElement(By.name('btnG')).click();
39
+ yield driver.wait(until.titleIs('webdriver - Google Search'), 1000);
40
+ } finally {
41
+ yield driver && driver.quit();
42
+ }
43
+ }).then(_ => console.log('SUCCESS'), err => console.error('ERROR: ' + err));
@@ -20,20 +20,24 @@
20
20
  * ChromeDriver.
21
21
  */
22
22
 
23
- var webdriver = require('..'),
24
- By = webdriver.By,
25
- until = webdriver.until,
26
- chrome = require('../chrome');
23
+ 'use strict';
27
24
 
25
+ const {Builder, By, promise, until} = require('..');
26
+ const {Options} = require('../chrome');
28
27
 
29
- var driver = new webdriver.Builder()
30
- .forBrowser('chrome')
31
- .setChromeOptions(new chrome.Options()
32
- .setMobileEmulation({deviceName: 'Google Nexus 5'}))
33
- .build();
34
-
35
- driver.get('http://www.google.com/ncr');
36
- driver.findElement(By.name('q')).sendKeys('webdriver');
37
- driver.findElement(By.name('btnG')).click();
38
- driver.wait(until.titleIs('webdriver - Google Search'), 1000);
39
- driver.quit();
28
+ promise.consume(function* () {
29
+ let driver;
30
+ try {
31
+ driver = yield new Builder()
32
+ .forBrowser('chrome')
33
+ .setChromeOptions(
34
+ new Options().setMobileEmulation({deviceName: 'Google Nexus 5'}))
35
+ .build();
36
+ yield driver.get('http://www.google.com/ncr');
37
+ yield driver.findElement(By.name('q')).sendKeys('webdriver');
38
+ yield driver.findElement(By.name('btnG')).click();
39
+ yield driver.wait(until.titleIs('webdriver - Google Search'), 1000);
40
+ } finally {
41
+ yield driver && driver.quit();
42
+ }
43
+ }).then(_ => console.log('SUCCESS'), err => console.error('ERROR: ' + err));
@@ -16,8 +16,10 @@
16
16
  // under the License.
17
17
 
18
18
  /**
19
- * @fileoverview An example WebDriver script. This requires the chromedriver
20
- * to be present on the system PATH.
19
+ * @fileoverview An example WebDriver script.
20
+ *
21
+ * Before running this script, ensure that Mozilla's geckodriver is present on
22
+ * your system PATH: <https://github.com/mozilla/geckodriver/releases>
21
23
  *
22
24
  * Usage:
23
25
  * // Default behavior
@@ -35,16 +37,14 @@
35
37
  * node selenium-webdriver/example/google_search.js
36
38
  */
37
39
 
38
- var webdriver = require('..'),
39
- By = webdriver.By,
40
- until = webdriver.until;
40
+ const {Builder, By, until} = require('..');
41
41
 
42
- var driver = new webdriver.Builder()
42
+ var driver = new Builder()
43
43
  .forBrowser('firefox')
44
44
  .build();
45
45
 
46
- driver.get('http://www.google.com/ncr');
47
- driver.findElement(By.name('q')).sendKeys('webdriver');
48
- driver.findElement(By.name('btnG')).click();
49
- driver.wait(until.titleIs('webdriver - Google Search'), 1000);
50
- driver.quit();
46
+ driver.get('http://www.google.com/ncr')
47
+ .then(_ => driver.findElement(By.name('q')).sendKeys('webdriver'))
48
+ .then(_ => driver.findElement(By.name('btnG')).click())
49
+ .then(_ => driver.wait(until.titleIs('webdriver - Google Search'), 1000))
50
+ .then(_ => driver.quit());