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/firefox.js CHANGED
@@ -79,7 +79,7 @@
79
79
  * .setFirefoxOptions(options)
80
80
  * .build();
81
81
  *
82
- * On all platforms, you may configrue WebDriver to use a Firefox specific
82
+ * On all platforms, you may configure WebDriver to use a Firefox specific
83
83
  * executable:
84
84
  *
85
85
  * let options = new firefox.Options()
@@ -89,7 +89,7 @@
89
89
  *
90
90
  * You may customize the Firefox binary and profile when running against a
91
91
  * remote Selenium server. Your custom profile will be packaged as a zip and
92
- * transfered to the remote host for use. The profile will be transferred
92
+ * transferred to the remote host for use. The profile will be transferred
93
93
  * _once for each new session_. The performance impact should be minimal if
94
94
  * you've only configured a few extra browser preferences. If you have a large
95
95
  * profile with several extensions, you should consider installing it on the
@@ -114,25 +114,18 @@
114
114
  * [PATH]: http://en.wikipedia.org/wiki/PATH_%28variable%29
115
115
  */
116
116
 
117
- 'use strict';
118
-
119
- const path = require('path');
120
- const url = require('url');
121
-
122
- const Symbols = require('./lib/symbols');
123
- const command = require('./lib/command');
124
- const exec = require('./io/exec');
125
- const http = require('./http');
126
- const httpUtil = require('./http/util');
127
- const io = require('./io');
128
- const net = require('./net');
129
- const portprober = require('./net/portprober');
130
- const remote = require('./remote');
131
- const webdriver = require('./lib/webdriver');
132
- const zip = require('./io/zip');
133
- const {Browser, Capabilities} = require('./lib/capabilities');
134
- const {Zip} = require('./io/zip');
117
+ 'use strict'
135
118
 
119
+ const path = require('path')
120
+ const Symbols = require('./lib/symbols')
121
+ const command = require('./lib/command')
122
+ const http = require('./http')
123
+ const io = require('./io')
124
+ const remote = require('./remote')
125
+ const webdriver = require('./lib/webdriver')
126
+ const zip = require('./io/zip')
127
+ const { Browser, Capabilities } = require('./lib/capabilities')
128
+ const { Zip } = require('./io/zip')
136
129
 
137
130
  /**
138
131
  * Thrown when there an add-on is malformed.
@@ -141,13 +134,12 @@ const {Zip} = require('./io/zip');
141
134
  class AddonFormatError extends Error {
142
135
  /** @param {string} msg The error message. */
143
136
  constructor(msg) {
144
- super(msg);
137
+ super(msg)
145
138
  /** @override */
146
- this.name = this.constructor.name;
139
+ this.name = this.constructor.name
147
140
  }
148
141
  }
149
142
 
150
-
151
143
  /**
152
144
  * Installs an extension to the given directory.
153
145
  * @param {string} extension Path to the xpi extension file to install.
@@ -156,56 +148,53 @@ class AddonFormatError extends Error {
156
148
  * installed.
157
149
  */
158
150
  async function installExtension(extension, dir) {
159
- if (extension.slice(-4) !== '.xpi') {
160
- throw Error('Path ath is not a xpi file: ' + extension);
151
+ const ext = extension.slice(-4)
152
+ if (ext !== '.xpi' && ext !== '.zip') {
153
+ throw Error('File name does not end in ".zip" or ".xpi": ' + ext)
161
154
  }
162
155
 
163
- let archive = await zip.load(extension);
156
+ let archive = await zip.load(extension)
164
157
  if (!archive.has('manifest.json')) {
165
- throw new AddonFormatError(`Couldn't find manifest.json in ${extension}`);
158
+ throw new AddonFormatError(`Couldn't find manifest.json in ${extension}`)
166
159
  }
167
160
 
168
- let buf = await archive.getFile('manifest.json');
169
- let parsedJSON = JSON.parse(buf.toString('utf8'));
170
-
161
+ let buf = await archive.getFile('manifest.json')
162
+ let parsedJSON = JSON.parse(buf.toString('utf8'))
163
+
171
164
  let { browser_specific_settings } =
172
165
  /** @type {{browser_specific_settings:{gecko:{id:string}}}} */
173
- parsedJSON;
166
+ parsedJSON
174
167
 
175
- if (
176
- browser_specific_settings &&
177
- browser_specific_settings.gecko
178
- ) {
168
+ if (browser_specific_settings && browser_specific_settings.gecko) {
179
169
  /* browser_specific_settings is an alternative to applications
180
170
  * It is meant to facilitate cross-browser plugins since Firefox48
181
171
  * see https://bugzilla.mozilla.org/show_bug.cgi?id=1262005
182
172
  */
183
- parsedJSON.applications = browser_specific_settings;
173
+ parsedJSON.applications = browser_specific_settings
184
174
  }
185
175
 
186
176
  let { applications } =
187
177
  /** @type {{applications:{gecko:{id:string}}}} */
188
- parsedJSON;
178
+ parsedJSON
189
179
  if (!(applications && applications.gecko && applications.gecko.id)) {
190
- throw new AddonFormatError(`Could not find add-on ID for ${extension}`);
180
+ throw new AddonFormatError(`Could not find add-on ID for ${extension}`)
191
181
  }
192
182
 
193
- await io.copy(extension, `${path.join(dir, applications.gecko.id)}.xpi`);
194
- return applications.gecko.id;
183
+ await io.copy(extension, `${path.join(dir, applications.gecko.id)}.xpi`)
184
+ return applications.gecko.id
195
185
  }
196
186
 
197
-
198
187
  class Profile {
199
188
  constructor() {
200
189
  /** @private {?string} */
201
- this.template_ = null;
190
+ this.template_ = null
202
191
 
203
192
  /** @private {!Array<string>} */
204
- this.extensions_ = [];
193
+ this.extensions_ = []
205
194
  }
206
195
 
207
- addExtensions(/** !Array<string> */paths) {
208
- this.extensions_ = this.extensions_.concat(...paths);
196
+ addExtensions(/** !Array<string> */ paths) {
197
+ this.extensions_ = this.extensions_.concat(...paths)
209
198
  }
210
199
 
211
200
  /**
@@ -214,13 +203,12 @@ class Profile {
214
203
  */
215
204
  [Symbols.serialize]() {
216
205
  if (this.template_ || this.extensions_.length) {
217
- return buildProfile(this.template_, this.extensions_);
206
+ return buildProfile(this.template_, this.extensions_)
218
207
  }
219
- return undefined;
208
+ return undefined
220
209
  }
221
210
  }
222
211
 
223
-
224
212
  /**
225
213
  * @param {?string} template path to an existing profile to use as a template.
226
214
  * @param {!Array<string>} extensions paths to extensions to install in the new
@@ -228,31 +216,33 @@ class Profile {
228
216
  * @return {!Promise<string>} a promise for the base64 encoded profile.
229
217
  */
230
218
  async function buildProfile(template, extensions) {
231
- let dir = template;
219
+ let dir = template
232
220
 
233
221
  if (extensions.length) {
234
- dir = await io.tmpDir();
222
+ dir = await io.tmpDir()
235
223
  if (template) {
236
224
  await io.copyDir(
237
- /** @type {string} */(template),
238
- dir, /(parent\.lock|lock|\.parentlock)/);
225
+ /** @type {string} */ (template),
226
+ dir,
227
+ /(parent\.lock|lock|\.parentlock)/
228
+ )
239
229
  }
240
230
 
241
- const extensionsDir = path.join(dir, 'extensions');
242
- await io.mkdir(extensionsDir);
231
+ const extensionsDir = path.join(dir, 'extensions')
232
+ await io.mkdir(extensionsDir)
243
233
 
244
234
  for (let i = 0; i < extensions.length; i++) {
245
- await installExtension(extensions[i], extensionsDir);
235
+ await installExtension(extensions[i], extensionsDir)
246
236
  }
247
237
  }
248
238
 
249
- let zip = new Zip;
250
- return zip.addDir(dir)
251
- .then(() => zip.toBuffer())
252
- .then(buf => buf.toString('base64'));
239
+ let zip = new Zip()
240
+ return zip
241
+ .addDir(dir)
242
+ .then(() => zip.toBuffer())
243
+ .then((buf) => buf.toString('base64'))
253
244
  }
254
245
 
255
-
256
246
  /**
257
247
  * Configuration options for the FirefoxDriver.
258
248
  */
@@ -262,8 +252,8 @@ class Options extends Capabilities {
262
252
  * capabilities to initialize this instance from.
263
253
  */
264
254
  constructor(other) {
265
- super(other);
266
- this.setBrowserName(Browser.FIREFOX);
255
+ super(other)
256
+ this.setBrowserName(Browser.FIREFOX)
267
257
  }
268
258
 
269
259
  /**
@@ -271,12 +261,12 @@ class Options extends Capabilities {
271
261
  * @private
272
262
  */
273
263
  firefoxOptions_() {
274
- let options = this.get('moz:firefoxOptions');
264
+ let options = this.get('moz:firefoxOptions')
275
265
  if (!options) {
276
- options = {};
277
- this.set('moz:firefoxOptions', options);
266
+ options = {}
267
+ this.set('moz:firefoxOptions', options)
278
268
  }
279
- return options;
269
+ return options
280
270
  }
281
271
 
282
272
  /**
@@ -284,11 +274,11 @@ class Options extends Capabilities {
284
274
  * @private
285
275
  */
286
276
  profile_() {
287
- let options = this.firefoxOptions_();
277
+ let options = this.firefoxOptions_()
288
278
  if (!options.profile) {
289
- options.profile = new Profile();
279
+ options.profile = new Profile()
290
280
  }
291
- return options.profile;
281
+ return options.profile
292
282
  }
293
283
 
294
284
  /**
@@ -300,10 +290,10 @@ class Options extends Capabilities {
300
290
  */
301
291
  addArguments(...args) {
302
292
  if (args.length) {
303
- let options = this.firefoxOptions_();
304
- options.args = options.args ? options.args.concat(...args) : args;
293
+ let options = this.firefoxOptions_()
294
+ options.args = options.args ? options.args.concat(...args) : args
305
295
  }
306
- return this;
296
+ return this
307
297
  }
308
298
 
309
299
  /**
@@ -312,7 +302,7 @@ class Options extends Capabilities {
312
302
  * @return {!Options} A self reference.
313
303
  */
314
304
  headless() {
315
- return this.addArguments('-headless');
305
+ return this.addArguments('-headless')
316
306
  }
317
307
 
318
308
  /**
@@ -324,15 +314,15 @@ class Options extends Capabilities {
324
314
  * @throws {TypeError} if width or height is unspecified, not a number, or
325
315
  * less than or equal to 0.
326
316
  */
327
- windowSize({width, height}) {
317
+ windowSize({ width, height }) {
328
318
  function checkArg(arg) {
329
319
  if (typeof arg !== 'number' || arg <= 0) {
330
- throw TypeError('Arguments must be {width, height} with numbers > 0');
320
+ throw TypeError('Arguments must be {width, height} with numbers > 0')
331
321
  }
332
322
  }
333
- checkArg(width);
334
- checkArg(height);
335
- return this.addArguments(`--width=${width}`, `--height=${height}`);
323
+ checkArg(width)
324
+ checkArg(height)
325
+ return this.addArguments(`--width=${width}`, `--height=${height}`)
336
326
  }
337
327
 
338
328
  /**
@@ -342,8 +332,8 @@ class Options extends Capabilities {
342
332
  * @return {!Options} A self reference.
343
333
  */
344
334
  addExtensions(...paths) {
345
- this.profile_().addExtensions(paths);
346
- return this;
335
+ this.profile_().addExtensions(paths)
336
+ return this
347
337
  }
348
338
 
349
339
  /**
@@ -354,18 +344,21 @@ class Options extends Capabilities {
354
344
  */
355
345
  setPreference(key, value) {
356
346
  if (typeof key !== 'string') {
357
- throw TypeError(`key must be a string, but got ${typeof key}`);
347
+ throw TypeError(`key must be a string, but got ${typeof key}`)
358
348
  }
359
- if (typeof value !== 'string'
360
- && typeof value !== 'number'
361
- && typeof value !== 'boolean') {
349
+ if (
350
+ typeof value !== 'string' &&
351
+ typeof value !== 'number' &&
352
+ typeof value !== 'boolean'
353
+ ) {
362
354
  throw TypeError(
363
- `value must be a string, number, or boolean, but got ${typeof value}`);
355
+ `value must be a string, number, or boolean, but got ${typeof value}`
356
+ )
364
357
  }
365
- let options = this.firefoxOptions_();
366
- options.prefs = options.prefs || {};
367
- options.prefs[key] = value;
368
- return this;
358
+ let options = this.firefoxOptions_()
359
+ options.prefs = options.prefs || {}
360
+ options.prefs[key] = value
361
+ return this
369
362
  }
370
363
 
371
364
  /**
@@ -379,10 +372,10 @@ class Options extends Capabilities {
379
372
  */
380
373
  setProfile(profile) {
381
374
  if (typeof profile !== 'string') {
382
- throw TypeError(`profile must be a string, but got ${typeof profile}`);
375
+ throw TypeError(`profile must be a string, but got ${typeof profile}`)
383
376
  }
384
- this.profile_().template_ = profile;
385
- return this;
377
+ this.profile_().template_ = profile
378
+ return this
386
379
  }
387
380
 
388
381
  /**
@@ -395,14 +388,13 @@ class Options extends Capabilities {
395
388
  */
396
389
  setBinary(binary) {
397
390
  if (binary instanceof Channel || typeof binary === 'string') {
398
- this.firefoxOptions_().binary = binary;
399
- return this;
391
+ this.firefoxOptions_().binary = binary
392
+ return this
400
393
  }
401
- throw TypeError('binary must be a string path or Channel object');
394
+ throw TypeError('binary must be a string path or Channel object')
402
395
  }
403
396
  }
404
397
 
405
-
406
398
  /**
407
399
  * Enum of available command contexts.
408
400
  *
@@ -414,14 +406,12 @@ class Options extends Capabilities {
414
406
  * @enum {string}
415
407
  */
416
408
  const Context = {
417
- CONTENT: "content",
418
- CHROME: "chrome",
419
- };
420
-
409
+ CONTENT: 'content',
410
+ CHROME: 'chrome',
411
+ }
421
412
 
422
413
  const GECKO_DRIVER_EXE =
423
- process.platform === 'win32' ? 'geckodriver.exe' : 'geckodriver';
424
-
414
+ process.platform === 'win32' ? 'geckodriver.exe' : 'geckodriver'
425
415
 
426
416
  /**
427
417
  * _Synchronously_ attempts to locate the geckodriver executable on the current
@@ -430,27 +420,28 @@ const GECKO_DRIVER_EXE =
430
420
  * @return {?string} the located executable, or `null`.
431
421
  */
432
422
  function locateSynchronously() {
433
- return io.findInPath(GECKO_DRIVER_EXE, true);
423
+ return io.findInPath(GECKO_DRIVER_EXE, true)
434
424
  }
435
425
 
436
-
437
426
  /**
438
427
  * @return {string} .
439
428
  * @throws {Error}
440
429
  */
441
430
  function findGeckoDriver() {
442
- let exe = locateSynchronously();
431
+ let exe = locateSynchronously()
443
432
  if (!exe) {
444
433
  throw Error(
445
- 'The ' + GECKO_DRIVER_EXE + ' executable could not be found on the current ' +
446
- 'PATH. Please download the latest version from ' +
447
- 'https://github.com/mozilla/geckodriver/releases/ ' +
448
- 'and ensure it can be found on your PATH.');
434
+ 'The ' +
435
+ GECKO_DRIVER_EXE +
436
+ ' executable could not be found on the current ' +
437
+ 'PATH. Please download the latest version from ' +
438
+ 'https://github.com/mozilla/geckodriver/releases/ ' +
439
+ 'and ensure it can be found on your PATH.'
440
+ )
449
441
  }
450
- return exe;
442
+ return exe
451
443
  }
452
444
 
453
-
454
445
  /**
455
446
  * @param {string} file Path to the file to find, relative to the program files
456
447
  * root.
@@ -460,24 +451,24 @@ function findGeckoDriver() {
460
451
  function findInProgramFiles(file) {
461
452
  let files = [
462
453
  process.env['PROGRAMFILES'] || 'C:\\Program Files',
463
- process.env['PROGRAMFILES(X86)'] || 'C:\\Program Files (x86)'
464
- ].map(prefix => path.join(prefix, file));
465
- return io.exists(files[0]).then(function(exists) {
466
- return exists ? files[0] : io.exists(files[1]).then(function(exists) {
467
- return exists ? files[1] : null;
468
- });
469
- });
454
+ process.env['PROGRAMFILES(X86)'] || 'C:\\Program Files (x86)',
455
+ ].map((prefix) => path.join(prefix, file))
456
+ return io.exists(files[0]).then(function (exists) {
457
+ return exists
458
+ ? files[0]
459
+ : io.exists(files[1]).then(function (exists) {
460
+ return exists ? files[1] : null
461
+ })
462
+ })
470
463
  }
471
464
 
472
-
473
465
  /** @enum {string} */
474
466
  const ExtensionCommand = {
475
467
  GET_CONTEXT: 'getContext',
476
468
  SET_CONTEXT: 'setContext',
477
469
  INSTALL_ADDON: 'install addon',
478
470
  UNINSTALL_ADDON: 'uninstall addon',
479
- };
480
-
471
+ }
481
472
 
482
473
  /**
483
474
  * Creates a command executor with support for Marionette's custom commands.
@@ -485,40 +476,42 @@ const ExtensionCommand = {
485
476
  * @return {!command.Executor} The new command executor.
486
477
  */
487
478
  function createExecutor(serverUrl) {
488
- let client = serverUrl.then(url => new http.HttpClient(url));
489
- let executor = new http.Executor(client);
490
- configureExecutor(executor);
491
- return executor;
479
+ let client = serverUrl.then((url) => new http.HttpClient(url))
480
+ let executor = new http.Executor(client)
481
+ configureExecutor(executor)
482
+ return executor
492
483
  }
493
484
 
494
-
495
485
  /**
496
486
  * Configures the given executor with Firefox-specific commands.
497
487
  * @param {!http.Executor} executor the executor to configure.
498
488
  */
499
489
  function configureExecutor(executor) {
500
490
  executor.defineCommand(
501
- ExtensionCommand.GET_CONTEXT,
502
- 'GET',
503
- '/session/:sessionId/moz/context');
491
+ ExtensionCommand.GET_CONTEXT,
492
+ 'GET',
493
+ '/session/:sessionId/moz/context'
494
+ )
504
495
 
505
496
  executor.defineCommand(
506
- ExtensionCommand.SET_CONTEXT,
507
- 'POST',
508
- '/session/:sessionId/moz/context');
497
+ ExtensionCommand.SET_CONTEXT,
498
+ 'POST',
499
+ '/session/:sessionId/moz/context'
500
+ )
509
501
 
510
502
  executor.defineCommand(
511
- ExtensionCommand.INSTALL_ADDON,
512
- 'POST',
513
- '/session/:sessionId/moz/addon/install');
503
+ ExtensionCommand.INSTALL_ADDON,
504
+ 'POST',
505
+ '/session/:sessionId/moz/addon/install'
506
+ )
514
507
 
515
508
  executor.defineCommand(
516
- ExtensionCommand.UNINSTALL_ADDON,
517
- 'POST',
518
- '/session/:sessionId/moz/addon/uninstall');
509
+ ExtensionCommand.UNINSTALL_ADDON,
510
+ 'POST',
511
+ '/session/:sessionId/moz/addon/uninstall'
512
+ )
519
513
  }
520
514
 
521
-
522
515
  /**
523
516
  * Creates {@link selenium-webdriver/remote.DriverService} instances that manage
524
517
  * a [geckodriver](https://github.com/mozilla/geckodriver) server in a child
@@ -530,8 +523,8 @@ class ServiceBuilder extends remote.DriverService.Builder {
530
523
  * the builder will attempt to locate the geckodriver on the system PATH.
531
524
  */
532
525
  constructor(opt_exe) {
533
- super(opt_exe || findGeckoDriver());
534
- this.setLoopback(true); // Required.
526
+ super(opt_exe || findGeckoDriver())
527
+ this.setLoopback(true) // Required.
535
528
  }
536
529
 
537
530
  /**
@@ -542,11 +535,10 @@ class ServiceBuilder extends remote.DriverService.Builder {
542
535
  * @return {!ServiceBuilder} A self reference.
543
536
  */
544
537
  enableVerboseLogging(opt_trace) {
545
- return this.addArguments(opt_trace ? '-vv' : '-v');
538
+ return this.addArguments(opt_trace ? '-vv' : '-v')
546
539
  }
547
540
  }
548
541
 
549
-
550
542
  /**
551
543
  * A WebDriver client for Firefox.
552
544
  */
@@ -575,25 +567,24 @@ class Driver extends webdriver.WebDriver {
575
567
  */
576
568
  static createSession(opt_config, opt_executor) {
577
569
  let caps =
578
- opt_config instanceof Capabilities
579
- ? opt_config : new Options(opt_config);
570
+ opt_config instanceof Capabilities ? opt_config : new Options(opt_config)
580
571
 
581
- let executor;
582
- let onQuit;
572
+ let executor
573
+ let onQuit
583
574
 
584
575
  if (opt_executor instanceof http.Executor) {
585
- executor = opt_executor;
586
- configureExecutor(executor);
576
+ executor = opt_executor
577
+ configureExecutor(executor)
587
578
  } else if (opt_executor instanceof remote.DriverService) {
588
- executor = createExecutor(opt_executor.start());
589
- onQuit = () => opt_executor.kill();
579
+ executor = createExecutor(opt_executor.start())
580
+ onQuit = () => opt_executor.kill()
590
581
  } else {
591
- let service = new ServiceBuilder().build();
592
- executor = createExecutor(service.start());
593
- onQuit = () => service.kill();
582
+ let service = new ServiceBuilder().build()
583
+ executor = createExecutor(service.start())
584
+ onQuit = () => service.kill()
594
585
  }
595
586
 
596
- return /** @type {!Driver} */(super.createSession(executor, caps, onQuit));
587
+ return /** @type {!Driver} */ (super.createSession(executor, caps, onQuit))
597
588
  }
598
589
 
599
590
  /**
@@ -601,8 +592,7 @@ class Driver extends webdriver.WebDriver {
601
592
  * implementation.
602
593
  * @override
603
594
  */
604
- setFileDetector() {
605
- }
595
+ setFileDetector() {}
606
596
 
607
597
  /**
608
598
  * Get the context that is currently in effect.
@@ -610,7 +600,7 @@ class Driver extends webdriver.WebDriver {
610
600
  * @return {!Promise<Context>} Current context.
611
601
  */
612
602
  getContext() {
613
- return this.execute(new command.Command(ExtensionCommand.GET_CONTEXT));
603
+ return this.execute(new command.Command(ExtensionCommand.GET_CONTEXT))
614
604
  }
615
605
 
616
606
  /**
@@ -629,8 +619,11 @@ class Driver extends webdriver.WebDriver {
629
619
  */
630
620
  setContext(ctx) {
631
621
  return this.execute(
632
- new command.Command(ExtensionCommand.SET_CONTEXT)
633
- .setParameter("context", ctx));
622
+ new command.Command(ExtensionCommand.SET_CONTEXT).setParameter(
623
+ 'context',
624
+ ctx
625
+ )
626
+ )
634
627
  }
635
628
 
636
629
  /**
@@ -641,18 +634,19 @@ class Driver extends webdriver.WebDriver {
641
634
  *
642
635
  * @param {string} path Path on the local filesystem to the web extension to
643
636
  * install.
644
- * @param {boolean} temporary Flag indicating whether the extension should be
637
+ * @param {boolean} temporary Flag indicating whether the extension should be
645
638
  * installed temporarily - gets removed on restart
646
639
  * @return {!Promise<string>} A promise that will resolve to an ID for the
647
640
  * newly installed addon.
648
641
  * @see #uninstallAddon
649
642
  */
650
- async installAddon(path, temporary=false) {
651
- let buf = await io.read(path);
643
+ async installAddon(path, temporary = false) {
644
+ let buf = await io.read(path)
652
645
  return this.execute(
653
- new command.Command(ExtensionCommand.INSTALL_ADDON)
654
- .setParameter('addon', buf.toString('base64'))
655
- .setParameter('temporary', temporary));
646
+ new command.Command(ExtensionCommand.INSTALL_ADDON)
647
+ .setParameter('addon', buf.toString('base64'))
648
+ .setParameter('temporary', temporary)
649
+ )
656
650
  }
657
651
 
658
652
  /**
@@ -664,14 +658,16 @@ class Driver extends webdriver.WebDriver {
664
658
  * @see #installAddon
665
659
  */
666
660
  async uninstallAddon(id) {
667
- id = await Promise.resolve(id);
661
+ id = await Promise.resolve(id)
668
662
  return this.execute(
669
- new command.Command(ExtensionCommand.UNINSTALL_ADDON)
670
- .setParameter('id', id));
663
+ new command.Command(ExtensionCommand.UNINSTALL_ADDON).setParameter(
664
+ 'id',
665
+ id
666
+ )
667
+ )
671
668
  }
672
669
  }
673
670
 
674
-
675
671
  /**
676
672
  * Provides methods for locating the executable for a Firefox release channel
677
673
  * on Windows and MacOS. For other systems (i.e. Linux), Firefox will always
@@ -685,10 +681,10 @@ class Channel {
685
681
  * @param {string} win32 The path to check when running on Windows.
686
682
  */
687
683
  constructor(darwin, win32) {
688
- /** @private @const */ this.darwin_ = darwin;
689
- /** @private @const */ this.win32_ = win32;
684
+ /** @private @const */ this.darwin_ = darwin
685
+ /** @private @const */ this.win32_ = win32
690
686
  /** @private {Promise<string>} */
691
- this.found_ = null;
687
+ this.found_ = null
692
688
  }
693
689
 
694
690
  /**
@@ -702,43 +698,44 @@ class Channel {
702
698
  */
703
699
  locate() {
704
700
  if (this.found_) {
705
- return this.found_;
701
+ return this.found_
706
702
  }
707
703
 
708
- let found;
704
+ let found
709
705
  switch (process.platform) {
710
706
  case 'darwin':
711
- found = io.exists(this.darwin_)
712
- .then(exists => exists ? this.darwin_ : io.findInPath('firefox'));
713
- break;
707
+ found = io
708
+ .exists(this.darwin_)
709
+ .then((exists) => (exists ? this.darwin_ : io.findInPath('firefox')))
710
+ break
714
711
 
715
712
  case 'win32':
716
- found = findInProgramFiles(this.win32_)
717
- .then(found => found || io.findInPath('firefox.exe'));
718
- break;
713
+ found = findInProgramFiles(this.win32_).then(
714
+ (found) => found || io.findInPath('firefox.exe')
715
+ )
716
+ break
719
717
 
720
718
  default:
721
- found = Promise.resolve(io.findInPath('firefox'));
722
- break;
719
+ found = Promise.resolve(io.findInPath('firefox'))
720
+ break
723
721
  }
724
722
 
725
- this.found_ = found.then(found => {
723
+ this.found_ = found.then((found) => {
726
724
  if (found) {
727
725
  // TODO: verify version info.
728
- return found;
726
+ return found
729
727
  }
730
- throw Error('Could not locate Firefox on the current system');
731
- });
732
- return this.found_;
728
+ throw Error('Could not locate Firefox on the current system')
729
+ })
730
+ return this.found_
733
731
  }
734
732
 
735
733
  /** @return {!Promise<string>} */
736
734
  [Symbols.serialize]() {
737
- return this.locate();
735
+ return this.locate()
738
736
  }
739
737
  }
740
738
 
741
-
742
739
  /**
743
740
  * Firefox's developer channel.
744
741
  * @const
@@ -746,7 +743,8 @@ class Channel {
746
743
  */
747
744
  Channel.AURORA = new Channel(
748
745
  '/Applications/FirefoxDeveloperEdition.app/Contents/MacOS/firefox-bin',
749
- 'Firefox Developer Edition\\firefox.exe');
746
+ 'Firefox Developer Edition\\firefox.exe'
747
+ )
750
748
 
751
749
  /**
752
750
  * Firefox's beta channel. Note this is provided mainly for convenience as
@@ -757,7 +755,8 @@ Channel.AURORA = new Channel(
757
755
  */
758
756
  Channel.BETA = new Channel(
759
757
  '/Applications/Firefox.app/Contents/MacOS/firefox-bin',
760
- 'Mozilla Firefox\\firefox.exe');
758
+ 'Mozilla Firefox\\firefox.exe'
759
+ )
761
760
 
762
761
  /**
763
762
  * Firefox's release channel.
@@ -766,7 +765,8 @@ Channel.BETA = new Channel(
766
765
  */
767
766
  Channel.RELEASE = new Channel(
768
767
  '/Applications/Firefox.app/Contents/MacOS/firefox-bin',
769
- 'Mozilla Firefox\\firefox.exe');
768
+ 'Mozilla Firefox\\firefox.exe'
769
+ )
770
770
 
771
771
  /**
772
772
  * Firefox's nightly release channel.
@@ -775,15 +775,14 @@ Channel.RELEASE = new Channel(
775
775
  */
776
776
  Channel.NIGHTLY = new Channel(
777
777
  '/Applications/Firefox Nightly.app/Contents/MacOS/firefox-bin',
778
- 'Nightly\\firefox.exe');
779
-
778
+ 'Nightly\\firefox.exe'
779
+ )
780
780
 
781
781
  // PUBLIC API
782
782
 
783
-
784
- exports.Channel = Channel;
785
- exports.Context = Context;
786
- exports.Driver = Driver;
787
- exports.Options = Options;
788
- exports.ServiceBuilder = ServiceBuilder;
789
- exports.locateSynchronously = locateSynchronously;
783
+ exports.Channel = Channel
784
+ exports.Context = Context
785
+ exports.Driver = Driver
786
+ exports.Options = Options
787
+ exports.ServiceBuilder = ServiceBuilder
788
+ exports.locateSynchronously = locateSynchronously