selenium-webdriver 4.0.0-alpha.4 → 4.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.eslintrc.js +27 -0
  2. package/.prettierrc +4 -0
  3. package/CHANGES.md +22 -1
  4. package/README.md +4 -4
  5. package/chrome.js +72 -590
  6. package/chromium.js +1024 -0
  7. package/devtools/CDPConnection.js +37 -0
  8. package/devtools/generator/protocol-dts-generator.js +429 -0
  9. package/edge.js +124 -86
  10. package/firefox.js +201 -202
  11. package/http/index.js +131 -115
  12. package/http/util.js +56 -64
  13. package/ie.js +180 -104
  14. package/index.js +246 -199
  15. package/io/exec.js +34 -39
  16. package/io/index.js +141 -151
  17. package/io/zip.js +75 -65
  18. package/lib/README +5 -0
  19. package/lib/actions.js +138 -121
  20. package/lib/atoms/find-elements.js +123 -0
  21. package/lib/atoms/get-attribute.js +79 -60
  22. package/lib/atoms/is-displayed.js +72 -73
  23. package/{example/chrome_mobile_emulation.js → lib/atoms/make-atoms-module.js} +16 -23
  24. package/lib/by.js +192 -65
  25. package/lib/capabilities.js +82 -78
  26. package/lib/command.js +18 -20
  27. package/lib/error.js +134 -168
  28. package/lib/http.js +324 -230
  29. package/lib/input.js +325 -302
  30. package/lib/logging.js +127 -138
  31. package/lib/promise.js +60 -66
  32. package/lib/proxy.js +31 -41
  33. package/lib/session.js +12 -15
  34. package/lib/symbols.js +3 -4
  35. package/lib/until.js +162 -162
  36. package/lib/webdriver.js +733 -522
  37. package/net/index.js +30 -36
  38. package/net/portprober.js +31 -144
  39. package/opera.js +406 -0
  40. package/package.json +18 -11
  41. package/proxy.js +2 -2
  42. package/remote/index.js +190 -187
  43. package/safari.js +40 -49
  44. package/LICENSE +0 -202
  45. package/NOTICE +0 -2
  46. package/example/chrome_android.js +0 -42
  47. package/example/firefox_channels.js +0 -77
  48. package/example/google_search.js +0 -50
  49. package/example/google_search_test.js +0 -72
  50. package/example/headless.js +0 -55
  51. package/example/logging.js +0 -68
  52. package/testing/index.js +0 -498
package/remote/index.js CHANGED
@@ -15,35 +15,30 @@
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
17
 
18
- 'use strict';
18
+ 'use strict'
19
19
 
20
- const fs = require('fs');
21
- const path = require('path');
22
- const url = require('url');
23
- const util = require('util');
24
-
25
- const httpUtil = require('../http/util');
26
- const io = require('../io');
27
- const exec = require('../io/exec');
28
- const {Zip} = require('../io/zip');
29
- const cmd = require('../lib/command');
30
- const input = require('../lib/input');
31
- const webdriver = require('../lib/webdriver');
32
- const net = require('../net');
33
- const portprober = require('../net/portprober');
20
+ const fs = require('fs')
21
+ const path = require('path')
22
+ const url = require('url')
34
23
 
24
+ const httpUtil = require('../http/util')
25
+ const io = require('../io')
26
+ const exec = require('../io/exec')
27
+ const { Zip } = require('../io/zip')
28
+ const cmd = require('../lib/command')
29
+ const input = require('../lib/input')
30
+ const net = require('../net')
31
+ const portprober = require('../net/portprober')
35
32
 
36
33
  /**
37
34
  * @typedef {(string|!Array<string|number|!stream.Stream|null|undefined>)}
38
35
  */
39
- var StdIoOptions;
40
-
36
+ var StdIoOptions // eslint-disable-line
41
37
 
42
38
  /**
43
39
  * @typedef {(string|!IThenable<string>)}
44
40
  */
45
- var CommandLineFlag;
46
-
41
+ var CommandLineFlag // eslint-disable-line
47
42
 
48
43
  /**
49
44
  * A record object that defines the configuration options for a DriverService
@@ -58,7 +53,7 @@ function ServiceOptions() {}
58
53
  *
59
54
  * @type {(boolean|undefined)}
60
55
  */
61
- ServiceOptions.prototype.loopback;
56
+ ServiceOptions.prototype.loopback
62
57
 
63
58
  /**
64
59
  * The host name to access the server on. If this option is specified, the
@@ -66,7 +61,7 @@ ServiceOptions.prototype.loopback;
66
61
  *
67
62
  * @type {(string|undefined)}
68
63
  */
69
- ServiceOptions.prototype.hostname;
64
+ ServiceOptions.prototype.hostname
70
65
 
71
66
  /**
72
67
  * The port to start the server on (must be > 0). If the port is provided as a
@@ -74,7 +69,7 @@ ServiceOptions.prototype.hostname;
74
69
  *
75
70
  * @type {(number|!IThenable<number>)}
76
71
  */
77
- ServiceOptions.prototype.port;
72
+ ServiceOptions.prototype.port
78
73
 
79
74
  /**
80
75
  * The arguments to pass to the service. If a promise is provided, the service
@@ -82,7 +77,7 @@ ServiceOptions.prototype.port;
82
77
  *
83
78
  * @type {!(Array<CommandLineFlag>|IThenable<!Array<CommandLineFlag>>)}
84
79
  */
85
- ServiceOptions.prototype.args;
80
+ ServiceOptions.prototype.args
86
81
 
87
82
  /**
88
83
  * The base path on the server for the WebDriver wire protocol (e.g. '/wd/hub').
@@ -90,7 +85,7 @@ ServiceOptions.prototype.args;
90
85
  *
91
86
  * @type {(string|undefined|null)}
92
87
  */
93
- ServiceOptions.prototype.path;
88
+ ServiceOptions.prototype.path
94
89
 
95
90
  /**
96
91
  * The environment variables that should be visible to the server process.
@@ -98,7 +93,7 @@ ServiceOptions.prototype.path;
98
93
  *
99
94
  * @type {(Object<string, string>|undefined)}
100
95
  */
101
- ServiceOptions.prototype.env;
96
+ ServiceOptions.prototype.env
102
97
 
103
98
  /**
104
99
  * IO configuration for the spawned server process. For more information, refer
@@ -107,8 +102,7 @@ ServiceOptions.prototype.env;
107
102
  * @type {(StdIoOptions|undefined)}
108
103
  * @see https://nodejs.org/dist/latest-v4.x/docs/api/child_process.html#child_process_options_stdio
109
104
  */
110
- ServiceOptions.prototype.stdio;
111
-
105
+ ServiceOptions.prototype.stdio
112
106
 
113
107
  /**
114
108
  * Manages the life and death of a native executable WebDriver server.
@@ -125,40 +119,40 @@ class DriverService {
125
119
  */
126
120
  constructor(executable, options) {
127
121
  /** @private {string} */
128
- this.executable_ = executable;
122
+ this.executable_ = executable
129
123
 
130
124
  /** @private {boolean} */
131
- this.loopbackOnly_ = !!options.loopback;
125
+ this.loopbackOnly_ = !!options.loopback
132
126
 
133
127
  /** @private {(string|undefined)} */
134
- this.hostname_ = options.hostname;
128
+ this.hostname_ = options.hostname
135
129
 
136
130
  /** @private {(number|!IThenable<number>)} */
137
- this.port_ = options.port;
131
+ this.port_ = options.port
138
132
 
139
133
  /**
140
134
  * @private {!(Array<CommandLineFlag>|
141
135
  * IThenable<!Array<CommandLineFlag>>)}
142
136
  */
143
- this.args_ = options.args;
137
+ this.args_ = options.args
144
138
 
145
139
  /** @private {string} */
146
- this.path_ = options.path || '/';
140
+ this.path_ = options.path || '/'
147
141
 
148
142
  /** @private {!Object<string, string>} */
149
- this.env_ = options.env || process.env;
143
+ this.env_ = options.env || process.env
150
144
 
151
145
  /**
152
146
  * @private {(string|!Array<string|number|!stream.Stream|null|undefined>)}
153
147
  */
154
- this.stdio_ = options.stdio || 'ignore';
148
+ this.stdio_ = options.stdio || 'ignore'
155
149
 
156
150
  /**
157
151
  * A promise for the managed subprocess, or null if the server has not been
158
152
  * started yet. This promise will never be rejected.
159
153
  * @private {Promise<!exec.Command>}
160
154
  */
161
- this.command_ = null;
155
+ this.command_ = null
162
156
 
163
157
  /**
164
158
  * Promise that resolves to the server's address or null if the server has
@@ -166,7 +160,7 @@ class DriverService {
166
160
  * before it starts accepting WebDriver requests.
167
161
  * @private {Promise<string>}
168
162
  */
169
- this.address_ = null;
163
+ this.address_ = null
170
164
  }
171
165
 
172
166
  /**
@@ -175,9 +169,9 @@ class DriverService {
175
169
  */
176
170
  address() {
177
171
  if (this.address_) {
178
- return this.address_;
172
+ return this.address_
179
173
  }
180
- throw Error('Server has not been started.');
174
+ throw Error('Server has not been started.')
181
175
  }
182
176
 
183
177
  /**
@@ -186,7 +180,7 @@ class DriverService {
186
180
  * @return {boolean} Whether the underlying service process is running.
187
181
  */
188
182
  isRunning() {
189
- return !!this.address_;
183
+ return !!this.address_
190
184
  }
191
185
 
192
186
  /**
@@ -199,71 +193,78 @@ class DriverService {
199
193
  */
200
194
  start(opt_timeoutMs) {
201
195
  if (this.address_) {
202
- return this.address_;
196
+ return this.address_
203
197
  }
204
198
 
205
- var timeout = opt_timeoutMs || DriverService.DEFAULT_START_TIMEOUT_MS;
206
- var self = this;
199
+ var timeout = opt_timeoutMs || DriverService.DEFAULT_START_TIMEOUT_MS
200
+ var self = this
207
201
 
208
- let resolveCommand;
209
- this.command_ = new Promise(resolve => resolveCommand = resolve);
202
+ let resolveCommand
203
+ this.command_ = new Promise((resolve) => (resolveCommand = resolve))
210
204
 
211
205
  this.address_ = new Promise((resolveAddress, rejectAddress) => {
212
- resolveAddress(Promise.resolve(this.port_).then(port => {
213
- if (port <= 0) {
214
- throw Error('Port must be > 0: ' + port);
215
- }
216
-
217
- return resolveCommandLineFlags(this.args_).then(args => {
218
- var command = exec(self.executable_, {
219
- args: args,
220
- env: self.env_,
221
- stdio: self.stdio_
222
- });
223
-
224
- resolveCommand(command);
225
-
226
- var earlyTermination = command.result().then(function(result) {
227
- var error = result.code == null ?
228
- Error('Server was killed with ' + result.signal) :
229
- Error('Server terminated early with status ' + result.code);
230
- rejectAddress(error);
231
- self.address_ = null;
232
- self.command_ = null;
233
- throw error;
234
- });
235
-
236
- var hostname = self.hostname_;
237
- if (!hostname) {
238
- hostname = !self.loopbackOnly_ && net.getAddress()
239
- || net.getLoopbackAddress();
206
+ resolveAddress(
207
+ Promise.resolve(this.port_).then((port) => {
208
+ if (port <= 0) {
209
+ throw Error('Port must be > 0: ' + port)
240
210
  }
241
211
 
242
- var serverUrl = url.format({
243
- protocol: 'http',
244
- hostname: hostname,
245
- port: port + '',
246
- pathname: self.path_
247
- });
248
-
249
- return new Promise((fulfill, reject) => {
250
- let cancelToken =
251
- earlyTermination.catch(e => reject(Error(e.message)));
252
-
253
- httpUtil.waitForServer(serverUrl, timeout, cancelToken)
254
- .then(_ => fulfill(serverUrl), err => {
212
+ return resolveCommandLineFlags(this.args_).then((args) => {
213
+ var command = exec(self.executable_, {
214
+ args: args,
215
+ env: self.env_,
216
+ stdio: self.stdio_,
217
+ })
218
+
219
+ resolveCommand(command)
220
+
221
+ var earlyTermination = command.result().then(function (result) {
222
+ var error =
223
+ result.code == null
224
+ ? Error('Server was killed with ' + result.signal)
225
+ : Error('Server terminated early with status ' + result.code)
226
+ rejectAddress(error)
227
+ self.address_ = null
228
+ self.command_ = null
229
+ throw error
230
+ })
231
+
232
+ var hostname = self.hostname_
233
+ if (!hostname) {
234
+ hostname =
235
+ (!self.loopbackOnly_ && net.getAddress()) ||
236
+ net.getLoopbackAddress()
237
+ }
238
+
239
+ var serverUrl = url.format({
240
+ protocol: 'http',
241
+ hostname: hostname,
242
+ port: port + '',
243
+ pathname: self.path_,
244
+ })
245
+
246
+ return new Promise((fulfill, reject) => {
247
+ let cancelToken = earlyTermination.catch((e) =>
248
+ reject(Error(e.message))
249
+ )
250
+
251
+ httpUtil.waitForServer(serverUrl, timeout, cancelToken).then(
252
+ (_) => fulfill(serverUrl),
253
+ (err) => {
255
254
  if (err instanceof httpUtil.CancellationError) {
256
- fulfill(serverUrl);
255
+ fulfill(serverUrl)
257
256
  } else {
258
- reject(err);
257
+ reject(err)
259
258
  }
260
- });
261
- });
262
- });
263
- }));
264
- });
265
-
266
- return this.address_;
259
+ }
260
+ )
261
+ })
262
+ })
263
+ })
264
+ )
265
+ })
266
+
267
+ return this.address_
267
268
  }
268
269
 
269
270
  /**
@@ -275,34 +276,32 @@ class DriverService {
275
276
  */
276
277
  kill() {
277
278
  if (!this.address_ || !this.command_) {
278
- return Promise.resolve(); // Not currently running.
279
+ return Promise.resolve() // Not currently running.
279
280
  }
280
- let cmd = this.command_;
281
- this.address_ = null;
282
- this.command_ = null;
283
- return cmd.then(c => c.kill('SIGTERM'));
281
+ let cmd = this.command_
282
+ this.address_ = null
283
+ this.command_ = null
284
+ return cmd.then((c) => c.kill('SIGTERM'))
284
285
  }
285
286
  }
286
287
 
287
-
288
288
  /**
289
289
  * @param {!(Array<CommandLineFlag>|IThenable<!Array<CommandLineFlag>>)} args
290
290
  * @return {!Promise<!Array<string>>}
291
291
  */
292
292
  function resolveCommandLineFlags(args) {
293
293
  // Resolve the outer array, then the individual flags.
294
- return Promise.resolve(args)
295
- .then(/** !Array<CommandLineFlag> */args => Promise.all(args));
294
+ return Promise.resolve(args).then(
295
+ /** !Array<CommandLineFlag> */ (args) => Promise.all(args)
296
+ )
296
297
  }
297
298
 
298
-
299
299
  /**
300
300
  * The default amount of time, in milliseconds, to wait for the server to
301
301
  * start.
302
302
  * @const {number}
303
303
  */
304
- DriverService.DEFAULT_START_TIMEOUT_MS = 30 * 1000;
305
-
304
+ DriverService.DEFAULT_START_TIMEOUT_MS = 30 * 1000
306
305
 
307
306
  /**
308
307
  * Creates {@link DriverService} objects that manage a WebDriver server in a
@@ -316,19 +315,19 @@ DriverService.Builder = class {
316
315
  */
317
316
  constructor(exe) {
318
317
  if (!fs.existsSync(exe)) {
319
- throw Error(`The specified executable path does not exist: ${exe}`);
318
+ throw Error(`The specified executable path does not exist: ${exe}`)
320
319
  }
321
320
 
322
321
  /** @private @const {string} */
323
- this.exe_ = exe;
322
+ this.exe_ = exe
324
323
 
325
324
  /** @private {!ServiceOptions} */
326
325
  this.options_ = {
327
326
  args: [],
328
327
  port: 0,
329
328
  env: null,
330
- stdio: 'ignore'
331
- };
329
+ stdio: 'ignore',
330
+ }
332
331
  }
333
332
 
334
333
  /**
@@ -339,10 +338,10 @@ DriverService.Builder = class {
339
338
  * @this {THIS}
340
339
  * @template THIS
341
340
  */
342
- addArguments(var_args) {
343
- let args = Array.prototype.slice.call(arguments, 0);
344
- this.options_.args = this.options_.args.concat(args);
345
- return this;
341
+ addArguments(var_args) { // eslint-disable-line
342
+ let args = Array.prototype.slice.call(arguments, 0)
343
+ this.options_.args = this.options_.args.concat(args)
344
+ return this
346
345
  }
347
346
 
348
347
  /**
@@ -353,8 +352,8 @@ DriverService.Builder = class {
353
352
  * @return {!DriverService.Builder} A self reference.
354
353
  */
355
354
  setHostname(hostname) {
356
- this.options_.hostname = hostname;
357
- return this;
355
+ this.options_.hostname = hostname
356
+ return this
358
357
  }
359
358
 
360
359
  /**
@@ -365,8 +364,8 @@ DriverService.Builder = class {
365
364
  * @return {!DriverService.Builder} A self reference.
366
365
  */
367
366
  setLoopback(loopback) {
368
- this.options_.loopback = loopback;
369
- return this;
367
+ this.options_.loopback = loopback
368
+ return this
370
369
  }
371
370
 
372
371
  /**
@@ -378,8 +377,8 @@ DriverService.Builder = class {
378
377
  * @return {!DriverService.Builder} A self reference.
379
378
  */
380
379
  setPath(basePath) {
381
- this.options_.path = basePath;
382
- return this;
380
+ this.options_.path = basePath
381
+ return this
383
382
  }
384
383
 
385
384
  /**
@@ -391,10 +390,10 @@ DriverService.Builder = class {
391
390
  */
392
391
  setPort(port) {
393
392
  if (port < 0) {
394
- throw Error(`port must be >= 0: ${port}`);
393
+ throw Error(`port must be >= 0: ${port}`)
395
394
  }
396
- this.options_.port = port;
397
- return this;
395
+ this.options_.port = port
396
+ return this
398
397
  }
399
398
 
400
399
  /**
@@ -409,12 +408,12 @@ DriverService.Builder = class {
409
408
  */
410
409
  setEnvironment(env) {
411
410
  if (env instanceof Map) {
412
- let tmp = {};
413
- env.forEach((value, key) => tmp[key] = value);
414
- env = tmp;
411
+ let tmp = {}
412
+ env.forEach((value, key) => (tmp[key] = value))
413
+ env = tmp
415
414
  }
416
- this.options_.env = env;
417
- return this;
415
+ this.options_.env = env
416
+ return this
418
417
  }
419
418
 
420
419
  /**
@@ -426,8 +425,8 @@ DriverService.Builder = class {
426
425
  * @see https://nodejs.org/dist/latest-v4.x/docs/api/child_process.html#child_process_options_stdio
427
426
  */
428
427
  setStdio(config) {
429
- this.options_.stdio = config;
430
- return this;
428
+ this.options_.stdio = config
429
+ return this
431
430
  }
432
431
 
433
432
  /**
@@ -436,18 +435,17 @@ DriverService.Builder = class {
436
435
  * @return {!DriverService} A new driver service.
437
436
  */
438
437
  build() {
439
- let port = this.options_.port || portprober.findFreePort();
440
- let args = Promise.resolve(port).then(port => {
441
- return this.options_.args.concat('--port=' + port);
442
- });
438
+ let port = this.options_.port || portprober.findFreePort()
439
+ let args = Promise.resolve(port).then((port) => {
440
+ return this.options_.args.concat('--port=' + port)
441
+ })
443
442
 
444
443
  let options =
445
- /** @type {!ServiceOptions} */
446
- (Object.assign({}, this.options_, {args, port}));
447
- return new DriverService(this.exe_, options);
444
+ /** @type {!ServiceOptions} */
445
+ (Object.assign({}, this.options_, { args, port }))
446
+ return new DriverService(this.exe_, options)
448
447
  }
449
- };
450
-
448
+ }
451
449
 
452
450
  /**
453
451
  * Manages the life and death of the
@@ -464,27 +462,30 @@ class SeleniumServer extends DriverService {
464
462
  */
465
463
  constructor(jar, opt_options) {
466
464
  if (!jar) {
467
- throw Error('Path to the Selenium jar not specified');
465
+ throw Error('Path to the Selenium jar not specified')
468
466
  }
469
467
 
470
- var options = opt_options || {};
468
+ var options = opt_options || {}
471
469
 
472
470
  if (options.port < 0) {
473
- throw Error('Port must be >= 0: ' + options.port);
471
+ throw Error('Port must be >= 0: ' + options.port)
474
472
  }
475
473
 
476
- let port = options.port || portprober.findFreePort();
477
- let args = Promise.all([port, options.jvmArgs || [], options.args || []])
478
- .then(resolved => {
479
- let port = resolved[0];
480
- let jvmArgs = resolved[1];
481
- let args = resolved[2];
482
- return jvmArgs.concat('-jar', jar, '-port', port).concat(args);
483
- });
484
-
485
- let java = 'java';
474
+ let port = options.port || portprober.findFreePort()
475
+ let args = Promise.all([
476
+ port,
477
+ options.jvmArgs || [],
478
+ options.args || [],
479
+ ]).then((resolved) => {
480
+ let port = resolved[0]
481
+ let jvmArgs = resolved[1]
482
+ let args = resolved[2]
483
+ return jvmArgs.concat('-jar', jar, '-port', port).concat(args)
484
+ })
485
+
486
+ let java = 'java'
486
487
  if (process.env['JAVA_HOME']) {
487
- java = path.join(process.env['JAVA_HOME'], 'bin/java');
488
+ java = path.join(process.env['JAVA_HOME'], 'bin/java')
488
489
  }
489
490
 
490
491
  super(java, {
@@ -493,12 +494,11 @@ class SeleniumServer extends DriverService {
493
494
  args: args,
494
495
  path: '/wd/hub',
495
496
  env: options.env,
496
- stdio: options.stdio
497
- });
497
+ stdio: options.stdio,
498
+ })
498
499
  }
499
500
  }
500
501
 
501
-
502
502
  /**
503
503
  * A record object describing configuration options for a {@link SeleniumServer}
504
504
  * instance.
@@ -513,7 +513,7 @@ SeleniumServer.Options = class {
513
513
  *
514
514
  * @type {(boolean|undefined)}
515
515
  */
516
- this.loopback;
516
+ this.loopback
517
517
 
518
518
  /**
519
519
  * The port to start the server on (must be > 0). If the port is provided as
@@ -522,7 +522,7 @@ SeleniumServer.Options = class {
522
522
  *
523
523
  * @type {(number|!IThenable<number>)}
524
524
  */
525
- this.port;
525
+ this.port
526
526
 
527
527
  /**
528
528
  * The arguments to pass to the service. If a promise is provided,
@@ -530,7 +530,7 @@ SeleniumServer.Options = class {
530
530
  *
531
531
  * @type {!(Array<string>|IThenable<!Array<string>>)}
532
532
  */
533
- this.args;
533
+ this.args
534
534
 
535
535
  /**
536
536
  * The arguments to pass to the JVM. If a promise is provided,
@@ -538,7 +538,7 @@ SeleniumServer.Options = class {
538
538
  *
539
539
  * @type {(!Array<string>|!IThenable<!Array<string>>|undefined)}
540
540
  */
541
- this.jvmArgs;
541
+ this.jvmArgs
542
542
 
543
543
  /**
544
544
  * The environment variables that should be visible to the server
@@ -546,7 +546,7 @@ SeleniumServer.Options = class {
546
546
  *
547
547
  * @type {(!Object<string, string>|undefined)}
548
548
  */
549
- this.env;
549
+ this.env
550
550
 
551
551
  /**
552
552
  * IO configuration for the spawned server process. If unspecified, IO will
@@ -556,11 +556,9 @@ SeleniumServer.Options = class {
556
556
  * undefined)}
557
557
  * @see <https://nodejs.org/dist/latest-v8.x/docs/api/child_process.html#child_process_options_stdio>
558
558
  */
559
- this.stdio;
559
+ this.stdio
560
560
  }
561
- };
562
-
563
-
561
+ }
564
562
 
565
563
  /**
566
564
  * A {@link webdriver.FileDetector} that may be used when running
@@ -590,33 +588,38 @@ class FileDetector extends input.FileDetector {
590
588
  * @override
591
589
  */
592
590
  handleFile(driver, file) {
593
- return io.stat(file).then(function(stats) {
594
- if (stats.isDirectory()) {
595
- return file; // Not a valid file, return original input.
596
- }
591
+ return io.stat(file).then(
592
+ function (stats) {
593
+ if (stats.isDirectory()) {
594
+ return file // Not a valid file, return original input.
595
+ }
597
596
 
598
- let zip = new Zip;
599
- return zip.addFile(file)
597
+ let zip = new Zip()
598
+ return zip
599
+ .addFile(file)
600
600
  .then(() => zip.toBuffer())
601
- .then(buf => buf.toString('base64'))
602
- .then(encodedZip => {
603
- let command = new cmd.Command(cmd.Name.UPLOAD_FILE)
604
- .setParameter('file', encodedZip);
605
- return driver.execute(command);
606
- });
607
- }, function(err) {
608
- if (err.code === 'ENOENT') {
609
- return file; // Not a file; return original input.
601
+ .then((buf) => buf.toString('base64'))
602
+ .then((encodedZip) => {
603
+ let command = new cmd.Command(cmd.Name.UPLOAD_FILE).setParameter(
604
+ 'file',
605
+ encodedZip
606
+ )
607
+ return driver.execute(command)
608
+ })
609
+ },
610
+ function (err) {
611
+ if (err.code === 'ENOENT') {
612
+ return file // Not a file; return original input.
613
+ }
614
+ throw err
610
615
  }
611
- throw err;
612
- });
616
+ )
613
617
  }
614
618
  }
615
619
 
616
-
617
620
  // PUBLIC API
618
621
 
619
- exports.DriverService = DriverService;
620
- exports.FileDetector = FileDetector;
621
- exports.SeleniumServer = SeleniumServer;
622
- exports.ServiceOptions = ServiceOptions; // Exported for API docs.
622
+ exports.DriverService = DriverService
623
+ exports.FileDetector = FileDetector
624
+ exports.SeleniumServer = SeleniumServer
625
+ exports.ServiceOptions = ServiceOptions // Exported for API docs.