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/opera.js CHANGED
@@ -98,7 +98,7 @@ const OPERADRIVER_EXE =
98
98
  * [OperaDriver](https://github.com/operasoftware/operachromiumdriver)
99
99
  * server in a child process.
100
100
  */
101
- class ServiceBuilder {
101
+ class ServiceBuilder extends remote.DriverService.Builder {
102
102
  /**
103
103
  * @param {string=} opt_exe Path to the server executable to use. If omitted,
104
104
  * the builder will attempt to locate the operadriver on the current
@@ -116,39 +116,8 @@ class ServiceBuilder {
116
116
  'ensure it can be found on your PATH.');
117
117
  }
118
118
 
119
- /** @private {string} */
120
- this.exe_ = /** @type {string} */(exe);
121
- if (!fs.existsSync(this.exe_)) {
122
- throw Error('File does not exist: ' + this.exe_);
123
- }
124
-
125
- /** @private {!Array.<string>} */
126
- this.args_ = [];
127
-
128
- /** @private {number} */
129
- this.port_ = 0;
130
-
131
- /**
132
- * @private {(string|!Array<string|number|!stream.Stream|null|undefined>)}
133
- */
134
- this.stdio_ = 'ignore';
135
-
136
- /** @private {Object.<string, string>} */
137
- this.env_ = null;
138
- }
139
-
140
- /**
141
- * Sets the port to start the OperaDriver on.
142
- * @param {number} port The port to use, or 0 for any free port.
143
- * @return {!ServiceBuilder} A self reference.
144
- * @throws {Error} If the port is invalid.
145
- */
146
- usingPort(port) {
147
- if (port < 0) {
148
- throw Error('port must be >= 0: ' + port);
149
- }
150
- this.port_ = port;
151
- return this;
119
+ super(exe);
120
+ this.setLoopback(true);
152
121
  }
153
122
 
154
123
  /**
@@ -158,8 +127,7 @@ class ServiceBuilder {
158
127
  * @return {!ServiceBuilder} A self reference.
159
128
  */
160
129
  loggingTo(path) {
161
- this.args_.push('--log-path=' + path);
162
- return this;
130
+ return this.addArguments('--log-path=' + path);
163
131
  }
164
132
 
165
133
  /**
@@ -167,8 +135,7 @@ class ServiceBuilder {
167
135
  * @return {!ServiceBuilder} A self reference.
168
136
  */
169
137
  enableVerboseLogging() {
170
- this.args_.push('--verbose');
171
- return this;
138
+ return this.addArguments('--verbose');
172
139
  }
173
140
 
174
141
  /**
@@ -176,54 +143,8 @@ class ServiceBuilder {
176
143
  * @return {!ServiceBuilder} A self reference.
177
144
  */
178
145
  silent() {
179
- this.args_.push('--silent');
180
- return this;
146
+ return this.addArguments('--silent');
181
147
  }
182
-
183
- /**
184
- * Defines the stdio configuration for the driver service. See
185
- * {@code child_process.spawn} for more information.
186
- * @param {(string|!Array<string|number|!stream.Stream|null|undefined>)}
187
- * config The configuration to use.
188
- * @return {!ServiceBuilder} A self reference.
189
- */
190
- setStdio(config) {
191
- this.stdio_ = config;
192
- return this;
193
- }
194
-
195
- /**
196
- * Defines the environment to start the server under. This settings will be
197
- * inherited by every browser session started by the server.
198
- * @param {!Object.<string, string>} env The environment to use.
199
- * @return {!ServiceBuilder} A self reference.
200
- */
201
- withEnvironment(env) {
202
- this.env_ = env;
203
- return this;
204
- }
205
-
206
- /**
207
- * Creates a new DriverService using this instance's current configuration.
208
- * @return {!remote.DriverService} A new driver service using this instance's
209
- * current configuration.
210
- * @throws {Error} If the driver exectuable was not specified and a default
211
- * could not be found on the current PATH.
212
- */
213
- build() {
214
- var port = this.port_ || portprober.findFreePort();
215
- var args = this.args_.concat(); // Defensive copy.
216
-
217
- return new remote.DriverService(this.exe_, {
218
- loopback: true,
219
- port: port,
220
- args: Promise.resolve(port).then(function(port) {
221
- return args.concat('--port=' + port);
222
- }),
223
- env: this.env_,
224
- stdio: this.stdio_
225
- });
226
- };
227
148
  }
228
149
 
229
150
 
@@ -427,14 +348,17 @@ class Options {
427
348
  */
428
349
  class Driver extends webdriver.WebDriver {
429
350
  /**
351
+ * Creates a new session for Opera.
352
+ *
430
353
  * @param {(capabilities.Capabilities|Options)=} opt_config The configuration
431
354
  * options.
432
355
  * @param {remote.DriverService=} opt_service The session to use; will use
433
356
  * the {@link getDefaultService default service} by default.
434
357
  * @param {promise.ControlFlow=} opt_flow The control flow to use,
435
358
  * or {@code null} to use the currently active flow.
359
+ * @return {!Driver} A new driver instance.
436
360
  */
437
- constructor(opt_config, opt_service, opt_flow) {
361
+ static createSession(opt_config, opt_service, opt_flow) {
438
362
  var service = opt_service || getDefaultService();
439
363
  var client = service.start().then(url => new http.HttpClient(url));
440
364
  var executor = new http.Executor(client);
@@ -458,8 +382,8 @@ class Driver extends webdriver.WebDriver {
458
382
  caps = options.toCapabilities(caps);
459
383
  }
460
384
 
461
- var driver = webdriver.WebDriver.createSession(executor, caps, opt_flow);
462
- super(driver.getSession(), executor, driver.controlFlow());
385
+ return /** @type {!Driver} */(
386
+ webdriver.WebDriver.createSession(executor, caps, opt_flow, this));
463
387
  }
464
388
 
465
389
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selenium-webdriver",
3
- "version": "3.0.0-beta-1",
3
+ "version": "3.0.1",
4
4
  "description": "The official WebDriver JavaScript bindings from the Selenium project",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -20,24 +20,23 @@
20
20
  "url": "https://github.com/SeleniumHQ/selenium.git"
21
21
  },
22
22
  "engines": {
23
- "node": ">= 4.2.x"
23
+ "node": ">= 6.9.0"
24
24
  },
25
25
  "dependencies": {
26
- "adm-zip": "0.4.4",
27
- "rimraf": "^2.2.8",
28
- "tmp": "0.0.24",
29
- "ws": "^1.0.1",
30
- "xml2js": "0.4.4"
26
+ "adm-zip": "^0.4.7",
27
+ "rimraf": "^2.5.4",
28
+ "tmp": "0.0.30",
29
+ "xml2js": "^0.4.17"
31
30
  },
32
31
  "devDependencies": {
33
- "express": "^4.11.2",
34
- "mocha": ">= 1.21.x",
35
- "multer": "^0.1.7",
36
- "promises-aplus-tests": "^2.1.0",
37
- "serve-index": "^1.6.1",
38
- "sinon": "^1.17.2"
32
+ "express": "^4.14.0",
33
+ "mocha": "^3.1.2",
34
+ "multer": "^1.2.0",
35
+ "promises-aplus-tests": "^2.1.2",
36
+ "serve-index": "^1.8.0",
37
+ "sinon": "^1.17.6"
39
38
  },
40
39
  "scripts": {
41
- "test": "mocha --harmony -t 600000 --recursive test"
40
+ "test": "mocha -t 600000 --recursive test"
42
41
  }
43
42
  }
package/phantomjs.js CHANGED
@@ -148,6 +148,8 @@ function createExecutor(url) {
148
148
  */
149
149
  class Driver extends webdriver.WebDriver {
150
150
  /**
151
+ * Creates a new PhantomJS session.
152
+ *
151
153
  * @param {capabilities.Capabilities=} opt_capabilities The desired
152
154
  * capabilities.
153
155
  * @param {promise.ControlFlow=} opt_flow The control flow to use,
@@ -155,8 +157,9 @@ class Driver extends webdriver.WebDriver {
155
157
  * @param {string=} opt_logFile Path to the log file for the phantomjs
156
158
  * executable's output. For convenience, this may be set at runtime with
157
159
  * the `SELENIUM_PHANTOMJS_LOG` environment variable.
160
+ * @return {!Driver} A new driver reference.
158
161
  */
159
- constructor(opt_capabilities, opt_flow, opt_logFile) {
162
+ static createSession(opt_capabilities, opt_flow, opt_logFile) {
160
163
  // TODO: add an Options class for consistency with the other driver types.
161
164
 
162
165
  var caps = opt_capabilities || capabilities.Capabilities.phantomjs();
@@ -207,7 +210,6 @@ class Driver extends webdriver.WebDriver {
207
210
  var port = portprober.findFreePort();
208
211
  var service = new remote.DriverService(exe, {
209
212
  port: port,
210
- stdio: 'inherit',
211
213
  args: Promise.resolve(port).then(function(port) {
212
214
  args.push('--webdriver=' + port);
213
215
  return args;
@@ -215,17 +217,8 @@ class Driver extends webdriver.WebDriver {
215
217
  });
216
218
 
217
219
  var executor = createExecutor(service.start());
218
- var driver = webdriver.WebDriver.createSession(executor, caps, opt_flow);
219
-
220
- super(driver.getSession(), executor, driver.controlFlow());
221
-
222
- var boundQuit = this.quit.bind(this);
223
-
224
- /** @override */
225
- this.quit = function() {
226
- let killService = () => service.kill();
227
- return boundQuit().then(killService, killService);
228
- };
220
+ return /** @type {!Driver} */(webdriver.WebDriver.createSession(
221
+ executor, caps, opt_flow, this, () => service.kill()));
229
222
  }
230
223
 
231
224
  /**
@@ -265,7 +258,7 @@ class Driver extends webdriver.WebDriver {
265
258
  *
266
259
  * @param {(string|!Function)} script The script to execute.
267
260
  * @param {...*} var_args The arguments to pass to the script.
268
- * @return {!promise.Promise<T>} A promise that resolve to the
261
+ * @return {!promise.Thenable<T>} A promise that resolve to the
269
262
  * script's return value.
270
263
  * @template T
271
264
  */
package/remote/index.js CHANGED
@@ -17,22 +17,33 @@
17
17
 
18
18
  'use strict';
19
19
 
20
- const AdmZip = require('adm-zip'),
21
- fs = require('fs'),
22
- path = require('path'),
23
- url = require('url'),
24
- util = require('util');
20
+ const AdmZip = require('adm-zip');
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+ const url = require('url');
24
+ const util = require('util');
25
+
26
+ const httpUtil = require('../http/util');
27
+ const io = require('../io');
28
+ const exec = require('../io/exec');
29
+ const cmd = require('../lib/command');
30
+ const input = require('../lib/input');
31
+ const promise = require('../lib/promise');
32
+ const webdriver = require('../lib/webdriver');
33
+ const net = require('../net');
34
+ const portprober = require('../net/portprober');
25
35
 
26
- const httpUtil = require('../http/util'),
27
- io = require('../io'),
28
- exec = require('../io/exec'),
29
- cmd = require('../lib/command'),
30
- input = require('../lib/input'),
31
- promise = require('../lib/promise'),
32
- webdriver = require('../lib/webdriver'),
33
- net = require('../net'),
34
- portprober = require('../net/portprober');
35
36
 
37
+ /**
38
+ * @typedef {(string|!Array<string|number|!stream.Stream|null|undefined>)}
39
+ */
40
+ var StdIoOptions;
41
+
42
+
43
+ /**
44
+ * @typedef {(string|!IThenable<string>)}
45
+ */
46
+ var CommandLineFlag;
36
47
 
37
48
 
38
49
  /**
@@ -70,7 +81,7 @@ ServiceOptions.prototype.port;
70
81
  * The arguments to pass to the service. If a promise is provided, the service
71
82
  * will wait for it to resolve before starting.
72
83
  *
73
- * @type {!(Array<string>|IThenable<!Array<string>>)}
84
+ * @type {!(Array<CommandLineFlag>|IThenable<!Array<CommandLineFlag>>)}
74
85
  */
75
86
  ServiceOptions.prototype.args;
76
87
 
@@ -94,8 +105,7 @@ ServiceOptions.prototype.env;
94
105
  * IO configuration for the spawned server process. For more information, refer
95
106
  * to the documentation of `child_process.spawn`.
96
107
  *
97
- * @type {(string|!Array<string|number|!stream.Stream|null|undefined>|
98
- * undefined)}
108
+ * @type {(StdIoOptions|undefined)}
99
109
  * @see https://nodejs.org/dist/latest-v4.x/docs/api/child_process.html#child_process_options_stdio
100
110
  */
101
111
  ServiceOptions.prototype.stdio;
@@ -128,7 +138,8 @@ class DriverService {
128
138
  this.port_ = options.port;
129
139
 
130
140
  /**
131
- * @private {!(Array<string>|IThenable<!Array<string>>)}
141
+ * @private {!(Array<CommandLineFlag>|
142
+ * IThenable<!Array<CommandLineFlag>>)}
132
143
  */
133
144
  this.args_ = options.args;
134
145
 
@@ -199,11 +210,12 @@ class DriverService {
199
210
  this.command_ = new Promise(resolve => resolveCommand = resolve);
200
211
 
201
212
  this.address_ = new Promise((resolveAddress, rejectAddress) => {
202
- resolveAddress(Promise.resolve(this.port_).then(function(port) {
213
+ resolveAddress(Promise.resolve(this.port_).then(port => {
203
214
  if (port <= 0) {
204
215
  throw Error('Port must be > 0: ' + port);
205
216
  }
206
- return Promise.resolve(self.args_).then(function(args) {
217
+
218
+ return resolveCommandLineFlags(this.args_).then(args => {
207
219
  var command = exec(self.executable_, {
208
220
  args: args,
209
221
  env: self.env_,
@@ -235,15 +247,18 @@ class DriverService {
235
247
  pathname: self.path_
236
248
  });
237
249
 
238
- return new Promise(function(fulfill, reject) {
239
- var ready = httpUtil.waitForServer(serverUrl, timeout)
240
- .then(fulfill, reject);
241
- earlyTermination.catch(function(e) {
242
- ready.cancel(/** @type {Error} */(e));
243
- reject(Error(e.message));
244
- });
245
- }).then(function() {
246
- return serverUrl;
250
+ return new Promise((fulfill, reject) => {
251
+ let cancelToken =
252
+ earlyTermination.catch(e => reject(Error(e.message)));
253
+
254
+ httpUtil.waitForServer(serverUrl, timeout, cancelToken)
255
+ .then(_ => fulfill(serverUrl), err => {
256
+ if (err instanceof promise.CancellationError) {
257
+ fulfill(serverUrl);
258
+ } else {
259
+ reject(err);
260
+ }
261
+ });
247
262
  });
248
263
  });
249
264
  }));
@@ -271,7 +286,7 @@ class DriverService {
271
286
  /**
272
287
  * Schedules a task in the current control flow to stop the server if it is
273
288
  * currently running.
274
- * @return {!promise.Promise} A promise that will be resolved when
289
+ * @return {!promise.Thenable} A promise that will be resolved when
275
290
  * the server has been stopped.
276
291
  */
277
292
  stop() {
@@ -280,6 +295,17 @@ class DriverService {
280
295
  }
281
296
 
282
297
 
298
+ /**
299
+ * @param {!(Array<CommandLineFlag>|IThenable<!Array<CommandLineFlag>>)} args
300
+ * @return {!Promise<!Array<string>>}
301
+ */
302
+ function resolveCommandLineFlags(args) {
303
+ // Resolve the outer array, then the individual flags.
304
+ return Promise.resolve(args)
305
+ .then(/** !Array<CommandLineFlag> */args => Promise.all(args));
306
+ }
307
+
308
+
283
309
  /**
284
310
  * The default amount of time, in milliseconds, to wait for the server to
285
311
  * start.
@@ -288,6 +314,151 @@ class DriverService {
288
314
  DriverService.DEFAULT_START_TIMEOUT_MS = 30 * 1000;
289
315
 
290
316
 
317
+ /**
318
+ * Creates {@link DriverService} objects that manage a WebDriver server in a
319
+ * child process.
320
+ */
321
+ DriverService.Builder = class {
322
+ /**
323
+ * @param {string} exe Path to the executable to use. This executable must
324
+ * accept the `--port` flag for defining the port to start the server on.
325
+ * @throws {Error} If the provided executable path does not exist.
326
+ */
327
+ constructor(exe) {
328
+ if (!fs.existsSync(exe)) {
329
+ throw Error(`The specified executable path does not exist: ${exe}`);
330
+ }
331
+
332
+ /** @private @const {string} */
333
+ this.exe_ = exe;
334
+
335
+ /** @private {!ServiceOptions} */
336
+ this.options_ = {
337
+ args: [],
338
+ port: 0,
339
+ env: null,
340
+ stdio: 'ignore'
341
+ };
342
+ }
343
+
344
+ /**
345
+ * Define additional command line arguments to use when starting the server.
346
+ *
347
+ * @param {...CommandLineFlag} var_args The arguments to include.
348
+ * @return {!THIS} A self reference.
349
+ * @this {THIS}
350
+ * @template THIS
351
+ */
352
+ addArguments(var_args) {
353
+ let args = Array.prototype.slice.call(arguments, 0);
354
+ this.options_.args = this.options_.args.concat(args);
355
+ return this;
356
+ }
357
+
358
+ /**
359
+ * Sets the host name to access the server on. If specified, the
360
+ * {@linkplain #setLoopback() loopback} setting will be ignored.
361
+ *
362
+ * @param {string} hostname
363
+ * @return {!DriverService.Builder} A self reference.
364
+ */
365
+ setHostname(hostname) {
366
+ this.options_.hostname = hostname;
367
+ return this;
368
+ }
369
+
370
+ /**
371
+ * Sets whether the service should be accessed at this host's loopback
372
+ * address.
373
+ *
374
+ * @param {boolean} loopback
375
+ * @return {!DriverService.Builder} A self reference.
376
+ */
377
+ setLoopback(loopback) {
378
+ this.options_.loopback = loopback;
379
+ return this;
380
+ }
381
+
382
+ /**
383
+ * Sets the base path for WebDriver REST commands (e.g. "/wd/hub").
384
+ * By default, the driver will accept commands relative to "/".
385
+ *
386
+ * @param {?string} basePath The base path to use, or `null` to use the
387
+ * default.
388
+ * @return {!DriverService.Builder} A self reference.
389
+ */
390
+ setPath(basePath) {
391
+ this.options_.path = basePath;
392
+ return this;
393
+ }
394
+
395
+ /**
396
+ * Sets the port to start the server on.
397
+ *
398
+ * @param {number} port The port to use, or 0 for any free port.
399
+ * @return {!DriverService.Builder} A self reference.
400
+ * @throws {Error} If an invalid port is specified.
401
+ */
402
+ setPort(port) {
403
+ if (port < 0) {
404
+ throw Error(`port must be >= 0: ${port}`);
405
+ }
406
+ this.options_.port = port;
407
+ return this;
408
+ }
409
+
410
+ /**
411
+ * Defines the environment to start the server under. This setting will be
412
+ * inherited by every browser session started by the server. By default, the
413
+ * server will inherit the enviroment of the current process.
414
+ *
415
+ * @param {(Map<string, string>|Object<string, string>|null)} env The desired
416
+ * environment to use, or `null` if the server should inherit the
417
+ * current environment.
418
+ * @return {!DriverService.Builder} A self reference.
419
+ */
420
+ setEnvironment(env) {
421
+ if (env instanceof Map) {
422
+ let tmp = {};
423
+ env.forEach((value, key) => tmp[key] = value);
424
+ env = tmp;
425
+ }
426
+ this.options_.env = env;
427
+ return this;
428
+ }
429
+
430
+ /**
431
+ * IO configuration for the spawned server process. For more information,
432
+ * refer to the documentation of `child_process.spawn`.
433
+ *
434
+ * @param {StdIoOptions} config The desired IO configuration.
435
+ * @return {!DriverService.Builder} A self reference.
436
+ * @see https://nodejs.org/dist/latest-v4.x/docs/api/child_process.html#child_process_options_stdio
437
+ */
438
+ setStdio(config) {
439
+ this.options_.stdio = config;
440
+ return this;
441
+ }
442
+
443
+ /**
444
+ * Creates a new DriverService using this instance's current configuration.
445
+ *
446
+ * @return {!DriverService} A new driver service.
447
+ */
448
+ build() {
449
+ let port = this.options_.port || portprober.findFreePort();
450
+ let args = Promise.resolve(port).then(port => {
451
+ return this.options_.args.concat('--port=' + port);
452
+ });
453
+
454
+ let options =
455
+ /** @type {!ServiceOptions} */
456
+ (Object.assign({}, this.options_, {args, port}));
457
+ return new DriverService(this.exe_, options);
458
+ }
459
+ };
460
+
461
+
291
462
  /**
292
463
  * Manages the life and death of the
293
464
  * <a href="http://selenium-release.storage.googleapis.com/index.html">