selenium-webdriver 4.0.0-alpha.5 → 4.0.0-beta.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 (49) hide show
  1. package/CHANGES.md +35 -1
  2. package/LICENSE +1 -1
  3. package/NOTICE +1 -1
  4. package/README.md +4 -4
  5. package/chrome.js +72 -592
  6. package/chromium.js +829 -0
  7. package/devtools/CDPConnection.js +37 -0
  8. package/edge.js +124 -86
  9. package/example/chrome_android.js +16 -13
  10. package/example/chrome_mobile_emulation.js +18 -14
  11. package/example/firefox_channels.js +35 -28
  12. package/example/google_search.js +9 -9
  13. package/example/google_search_test.js +20 -22
  14. package/example/headless.js +27 -19
  15. package/example/logging.js +34 -38
  16. package/firefox.js +200 -200
  17. package/http/index.js +131 -115
  18. package/http/util.js +56 -64
  19. package/ie.js +180 -104
  20. package/index.js +246 -199
  21. package/io/exec.js +34 -39
  22. package/io/index.js +142 -152
  23. package/io/zip.js +75 -65
  24. package/lib/actions.js +140 -122
  25. package/lib/atoms/find-elements.js +124 -0
  26. package/lib/atoms/get-attribute.js +79 -59
  27. package/lib/atoms/is-displayed.js +72 -73
  28. package/lib/atoms/mutation-listener.js +38 -0
  29. package/lib/by.js +192 -65
  30. package/lib/capabilities.js +82 -78
  31. package/lib/command.js +20 -20
  32. package/lib/error.js +134 -168
  33. package/lib/http.js +337 -230
  34. package/lib/input.js +325 -302
  35. package/lib/logging.js +127 -138
  36. package/lib/promise.js +60 -66
  37. package/lib/proxy.js +31 -41
  38. package/lib/session.js +12 -15
  39. package/lib/symbols.js +3 -4
  40. package/lib/until.js +162 -160
  41. package/lib/webdriver.js +1024 -541
  42. package/net/index.js +30 -36
  43. package/net/portprober.js +31 -144
  44. package/opera.js +406 -0
  45. package/package.json +19 -12
  46. package/proxy.js +2 -2
  47. package/remote/index.js +190 -187
  48. package/safari.js +40 -49
  49. package/testing/index.js +166 -155
package/testing/index.js CHANGED
@@ -30,55 +30,60 @@
30
30
  * function maybe() { return Math.random() < 0.5; }
31
31
  */
32
32
 
33
- 'use strict';
34
-
35
- const {isatty} = require('tty');
36
-
37
- const chrome = require('../chrome');
38
- const edge = require('../edge');
39
- const firefox = require('../firefox');
40
- const ie = require('../ie');
41
- const remote = require('../remote');
42
- const safari = require('../safari');
43
- const {Browser} = require('../lib/capabilities');
44
- const {Builder} = require('../index');
45
-
33
+ 'use strict'
34
+
35
+ const { isatty } = require('tty')
36
+ const chrome = require('../chrome')
37
+ const edge = require('../edge')
38
+ const firefox = require('../firefox')
39
+ const ie = require('../ie')
40
+ const remote = require('../remote')
41
+ const safari = require('../safari')
42
+ const opera = require('../opera')
43
+ const { Browser } = require('../lib/capabilities')
44
+ const { Builder } = require('../index')
46
45
 
47
46
  /**
48
- * Describes a browser targetted by a {@linkplain suite test suite}.
47
+ * Describes a browser targeted by a {@linkplain suite test suite}.
49
48
  * @record
50
49
  */
51
- function TargetBrowser() {}
50
+ function TargetBrowser() { }
52
51
 
53
52
  /**
54
- * The {@linkplain Browser name} of the targetted browser.
53
+ * The {@linkplain Browser name} of the targeted browser.
55
54
  * @type {string}
56
55
  */
57
- TargetBrowser.prototype.name;
56
+ TargetBrowser.prototype.name
58
57
 
59
58
  /**
60
- * The specific version of the targetted browser, if any.
59
+ * The specific version of the targeted browser, if any.
61
60
  * @type {(string|undefined)}
62
61
  */
63
- TargetBrowser.prototype.version;
62
+ TargetBrowser.prototype.version
64
63
 
65
64
  /**
66
65
  * The specific {@linkplain ../lib/capabilities.Platform platform} for the
67
- * targetted browser, if any.
66
+ * targeted browser, if any.
68
67
  * @type {(string|undefined)}.
69
68
  */
70
- TargetBrowser.prototype.platform;
71
-
69
+ TargetBrowser.prototype.platform
72
70
 
73
71
  /** @suppress {checkTypes} */
74
72
  function color(c, s) {
75
- return isatty(process.stdout) ? `\u001b[${c}m${s}\u001b[0m` : s;
73
+ return isatty(process.stdout) ? `\u001b[${c}m${s}\u001b[0m` : s
74
+ }
75
+ function green(s) {
76
+ return color(32, s)
77
+ }
78
+ function cyan(s) {
79
+ return color(36, s)
80
+ }
81
+ function info(msg) {
82
+ console.info(`${green('[INFO]')} ${msg}`)
83
+ }
84
+ function warn(msg) {
85
+ console.warn(`${cyan('[WARNING]')} ${msg}`)
76
86
  }
77
- function green(s) { return color(32, s); }
78
- function cyan(s) { return color(36, s); }
79
- function info(msg) { console.info(`${green('[INFO]')} ${msg}`); }
80
- function warn(msg) { console.warn(`${cyan('[WARNING]')} ${msg}`); }
81
-
82
87
 
83
88
  /**
84
89
  * Extracts the browsers for a test suite to target from the `SELENIUM_BROWSER`
@@ -87,62 +92,68 @@ function warn(msg) { console.warn(`${cyan('[WARNING]')} ${msg}`); }
87
92
  * @return {!Array<!TargetBrowser>} the browsers to target.
88
93
  */
89
94
  function getBrowsersToTestFromEnv() {
90
- let browsers = process.env['SELENIUM_BROWSER'];
95
+ let browsers = process.env['SELENIUM_BROWSER']
91
96
  if (!browsers) {
92
- return [];
97
+ return []
93
98
  }
94
- return browsers.split(',').map(spec => {
95
- const parts = spec.split(/:/, 3);
96
- let name = parts[0];
99
+ return browsers.split(',').map((spec) => {
100
+ const parts = spec.split(/:/, 3)
101
+ let name = parts[0]
97
102
  if (name === 'ie') {
98
- name = Browser.IE;
103
+ name = Browser.IE
99
104
  } else if (name === 'edge') {
100
- name = Browser.EDGE;
105
+ name = Browser.EDGE
101
106
  }
102
- let version = parts[1];
103
- let platform = parts[2];
104
- return {name, version, platform};
105
- });
107
+ let version = parts[1]
108
+ let platform = parts[2]
109
+ return { name, version, platform }
110
+ })
106
111
  }
107
112
 
108
-
109
113
  /**
110
114
  * @return {!Array<!TargetBrowser>} the browsers available for testing on this
111
115
  * system.
112
116
  */
113
117
  function getAvailableBrowsers() {
114
- info(`Searching for WebDriver executables installed on the current system...`);
118
+ info(`Searching for WebDriver executables installed on the current system...`)
115
119
 
116
120
  let targets = [
117
121
  [chrome.locateSynchronously, Browser.CHROME],
118
122
  [edge.locateSynchronously, Browser.EDGE],
123
+ [
124
+ () => edge.locateSynchronously('msedge'),
125
+ Browser.EDGE,
126
+ { 'ms:edgeChromium': true },
127
+ ],
119
128
  [firefox.locateSynchronously, Browser.FIREFOX],
120
129
  [ie.locateSynchronously, Browser.IE],
121
130
  [safari.locateSynchronously, Browser.SAFARI],
122
- ];
131
+ [opera.locateSynchronously, Browser.OPERA],
132
+ ]
123
133
 
124
- let availableBrowsers = [];
134
+ let availableBrowsers = []
125
135
  for (let pair of targets) {
126
- const fn = pair[0];
127
- const name = pair[1];
136
+ const fn = pair[0]
137
+ const name = pair[1]
138
+ const capabilities = pair[2]
128
139
  if (fn()) {
129
- info(`... located ${name}`);
130
- availableBrowsers.push({name});
140
+ info(`... located ${name}`)
141
+ availableBrowsers.push({ name, capabilities })
131
142
  }
132
143
  }
133
144
 
134
145
  if (availableBrowsers.length === 0) {
135
- warn(`Unable to locate any WebDriver executables for testing`);
146
+ warn(`Unable to locate any WebDriver executables for testing`)
136
147
  }
137
148
 
138
- return availableBrowsers;
149
+ return availableBrowsers
139
150
  }
140
151
 
141
- let wasInit;
142
- let targetBrowsers;
143
- let seleniumJar;
144
- let seleniumUrl;
145
- let seleniumServer;
152
+ let wasInit
153
+ let targetBrowsers
154
+ let seleniumJar
155
+ let seleniumUrl
156
+ let seleniumServer
146
157
 
147
158
  /**
148
159
  * Initializes this module by determining which browsers a
@@ -158,10 +169,10 @@ let seleniumServer;
158
169
  * SELENIUM_BROWSER=chrome,firefox mocha --recursive tests/
159
170
  *
160
171
  * The `SELENIUM_REMOTE_URL` environment variable may be set to configure tests
161
- * to run againt an externally managed (usually remote) Selenium server. When
172
+ * to run against an externally managed (usually remote) Selenium server. When
162
173
  * set, the WebDriver builder provided by each
163
174
  * {@linkplain TestEnvironment#builder TestEnvironment} will automatically be
164
- * configured to use this server instead of starting a browser drively locally.
175
+ * configured to use this server instead of starting a browser driver locally.
165
176
  *
166
177
  * The `SELENIUM_SERVER_JAR` environment variable may be set to the path of a
167
178
  * standalone Selenium server on the local machine that should be used for
@@ -181,80 +192,79 @@ let seleniumServer;
181
192
  */
182
193
  function init(force = false) {
183
194
  if (wasInit && !force) {
184
- return;
195
+ return
185
196
  }
186
- wasInit = true;
197
+ wasInit = true
187
198
 
188
199
  // If force re-init, kill the current server if there is one.
189
200
  if (seleniumServer) {
190
- seleniumServer.kill();
191
- seleniumServer = null;
201
+ seleniumServer.kill()
202
+ seleniumServer = null
192
203
  }
193
204
 
194
- seleniumJar = process.env['SELENIUM_SERVER_JAR'];
195
- seleniumUrl = process.env['SELENIUM_REMOTE_URL'];
205
+ seleniumJar = process.env['SELENIUM_SERVER_JAR']
206
+ seleniumUrl = process.env['SELENIUM_REMOTE_URL']
196
207
  if (seleniumJar) {
197
- info(`Using Selenium server jar: ${seleniumJar}`);
208
+ info(`Using Selenium server jar: ${seleniumJar}`)
198
209
  }
199
210
 
200
211
  if (seleniumUrl) {
201
- info(`Using Selenium remote end: ${seleniumUrl}`);
212
+ info(`Using Selenium remote end: ${seleniumUrl}`)
202
213
  }
203
214
 
204
215
  if (seleniumJar && seleniumUrl) {
205
216
  throw Error(
206
- 'Ambiguous test configuration: both SELENIUM_REMOTE_URL'
207
- + ' && SELENIUM_SERVER_JAR environment variables are set');
217
+ 'Ambiguous test configuration: both SELENIUM_REMOTE_URL' +
218
+ ' && SELENIUM_SERVER_JAR environment variables are set'
219
+ )
208
220
  }
209
221
 
210
- const envBrowsers = getBrowsersToTestFromEnv();
222
+ const envBrowsers = getBrowsersToTestFromEnv()
211
223
  if ((seleniumJar || seleniumUrl) && envBrowsers.length === 0) {
212
224
  throw Error(
213
- 'Ambiguous test configuration: when either the SELENIUM_REMOTE_URL or'
214
- + ' SELENIUM_SERVER_JAR environment variable is set, the'
215
- + ' SELENIUM_BROWSER variable must also be set.');
225
+ 'Ambiguous test configuration: when either the SELENIUM_REMOTE_URL or' +
226
+ ' SELENIUM_SERVER_JAR environment variable is set, the' +
227
+ ' SELENIUM_BROWSER variable must also be set.'
228
+ )
216
229
  }
217
230
 
218
- targetBrowsers =
219
- envBrowsers.length > 0 ? envBrowsers : getAvailableBrowsers();
220
- info(`Running tests against [${targetBrowsers.map(b => b.name).join(', ')}]`);
231
+ targetBrowsers = envBrowsers.length > 0 ? envBrowsers : getAvailableBrowsers()
232
+ info(
233
+ `Running tests against [${targetBrowsers.map((b) => b.name).join(', ')}]`
234
+ )
221
235
 
222
- after(function() {
236
+ after(function () {
223
237
  if (seleniumServer) {
224
- return seleniumServer.kill();
238
+ return seleniumServer.kill()
225
239
  }
226
- });
240
+ })
227
241
  }
228
242
 
229
-
230
-
231
- const TARGET_MAP = /** !WeakMap<!Environment, !TargetBrowser> */new WeakMap;
232
- const URL_MAP =
233
- /** !WeakMap<!Environment, ?(string|remote.SeleniumServer)> */new WeakMap;
234
-
243
+ const TARGET_MAP = /** !WeakMap<!Environment, !TargetBrowser> */ new WeakMap()
244
+ const URL_MAP = /** !WeakMap<!Environment, ?(string|remote.SeleniumServer)> */ new WeakMap()
235
245
 
236
246
  /**
237
247
  * Defines the environment a {@linkplain suite test suite} is running against.
238
248
  * @final
239
249
  */
240
250
  class Environment {
241
-
242
251
  /**
243
252
  * @param {!TargetBrowser} browser the browser targetted in this environment.
244
253
  * @param {?(string|remote.SeleniumServer)=} url remote URL of an existing
245
254
  * Selenium server to test against.
246
255
  */
247
256
  constructor(browser, url = undefined) {
248
- browser =
249
- /** @type {!TargetBrowser} */(Object.seal(Object.assign({}, browser)));
257
+ browser = /** @type {!TargetBrowser} */ (Object.seal(
258
+ Object.assign({}, browser)
259
+ ))
250
260
 
251
- TARGET_MAP.set(this, browser);
252
- URL_MAP.set(this, url || null);
261
+ TARGET_MAP.set(this, browser)
262
+ URL_MAP.set(this, url || null)
253
263
  }
254
264
 
255
265
  /** @return {!TargetBrowser} the target browser for this test environment. */
256
266
  get browser() {
257
- return TARGET_MAP.get(this);
267
+ return TARGET_MAP.get(this)
258
268
  }
259
269
 
260
270
  /**
@@ -267,7 +277,7 @@ class Environment {
267
277
  * @return {function(): boolean} a new predicate function.
268
278
  */
269
279
  browsers(...browsersToIgnore) {
270
- return () => browsersToIgnore.indexOf(this.browser.name) != -1;
280
+ return () => browsersToIgnore.indexOf(this.browser.name) != -1
271
281
  }
272
282
 
273
283
  /**
@@ -275,43 +285,46 @@ class Environment {
275
285
  * environment's {@linkplain #browser browser}.
276
286
  */
277
287
  builder() {
278
- const browser = this.browser;
279
- const urlOrServer = URL_MAP.get(this);
288
+ const browser = this.browser
289
+ const urlOrServer = URL_MAP.get(this)
290
+
291
+ const builder = new Builder()
292
+ builder.disableEnvironmentOverrides()
280
293
 
281
- const builder = new Builder();
282
- builder.disableEnvironmentOverrides();
294
+ const realBuild = builder.build
295
+ builder.build = function () {
296
+
297
+ builder.forBrowser(browser.name, browser.version, browser.platform)
298
+
299
+ if (browser.capabilities) {
300
+ builder.getCapabilities().merge(browser.capabilities)
301
+ }
283
302
 
284
- const realBuild = builder.build;
285
- builder.build = function() {
286
- builder.forBrowser(browser.name, browser.version, browser.platform);
287
303
  if (typeof urlOrServer === 'string') {
288
- builder.usingServer(urlOrServer);
304
+ builder.usingServer(urlOrServer)
289
305
  } else if (urlOrServer) {
290
- builder.usingServer(urlOrServer.address());
306
+ builder.usingServer(urlOrServer.address())
291
307
  }
292
- return realBuild.call(builder);
293
- };
308
+ return realBuild.call(builder)
309
+ }
294
310
 
295
- return builder;
311
+ return builder
296
312
  }
297
313
  }
298
314
 
299
-
300
315
  /**
301
316
  * Configuration options for a {@linkplain ./index.suite test suite}.
302
317
  * @record
303
318
  */
304
- function SuiteOptions() {}
319
+ function SuiteOptions() { }
305
320
 
306
321
  /**
307
322
  * The browsers to run the test suite against.
308
323
  * @type {!Array<!(Browser|TargetBrowser)>}
309
324
  */
310
- SuiteOptions.prototype.browsers;
311
-
312
-
313
- let inSuite = false;
325
+ SuiteOptions.prototype.browsers
314
326
 
327
+ let inSuite = false
315
328
 
316
329
  /**
317
330
  * Defines a test suite by calling the provided function once for each of the
@@ -358,56 +371,55 @@ let inSuite = false;
358
371
  */
359
372
  function suite(fn, options = undefined) {
360
373
  if (inSuite) {
361
- throw Error('Calls to suite() may not be nested');
374
+ throw Error('Calls to suite() may not be nested')
362
375
  }
363
376
  try {
364
- init();
365
- inSuite = true;
377
+ init()
378
+ inSuite = true
366
379
 
367
- const suiteBrowsers = new Map;
380
+ const suiteBrowsers = new Map()
368
381
  if (options && options.browsers) {
369
382
  for (let browser of options.browsers) {
370
383
  if (typeof browser === 'string') {
371
- suiteBrowsers.set(browser, {name: browser});
384
+ suiteBrowsers.set(browser, { name: browser })
372
385
  } else {
373
- suiteBrowsers.set(browser.name, browser);
386
+ suiteBrowsers.set(browser.name, browser)
374
387
  }
375
388
  }
376
389
  }
377
390
 
378
391
  for (let browser of targetBrowsers) {
379
392
  if (suiteBrowsers.size > 0 && !suiteBrowsers.has(browser.name)) {
380
- continue;
393
+ continue
381
394
  }
382
395
 
383
- describe(`[${browser.name}]`, function() {
396
+ describe(`[${browser.name}]`, function () {
384
397
  if (!seleniumUrl && seleniumJar && !seleniumServer) {
385
- seleniumServer = new remote.SeleniumServer(seleniumJar);
398
+ seleniumServer = new remote.SeleniumServer(seleniumJar)
386
399
 
387
- const startTimeout = 65 * 1000;
400
+ const startTimeout = 65 * 1000
401
+ // eslint-disable-next-line no-inner-declarations
388
402
  function startSelenium() {
389
403
  if (typeof this.timeout === 'function') {
390
- this.timeout(startTimeout); // For mocha.
404
+ this.timeout(startTimeout) // For mocha.
391
405
  }
392
406
 
393
- info(`Starting selenium server ${seleniumJar}`);
394
- return seleniumServer.start(60 * 1000);
407
+ info(`Starting selenium server ${seleniumJar}`)
408
+ return seleniumServer.start(60 * 1000)
395
409
  }
396
410
 
397
- const /** !Function */beforeHook = global.beforeAll || global.before;
398
- beforeHook(startSelenium, startTimeout);
411
+ const /** !Function */ beforeHook = global.beforeAll || global.before
412
+ beforeHook(startSelenium, startTimeout)
399
413
  }
400
414
 
401
- fn(new Environment(browser, seleniumUrl || seleniumServer));
402
- });
415
+ fn(new Environment(browser, seleniumUrl || seleniumServer))
416
+ })
403
417
  }
404
418
  } finally {
405
- inSuite = false;
419
+ inSuite = false
406
420
  }
407
421
  }
408
422
 
409
-
410
-
411
423
  /**
412
424
  * Returns an object with wrappers for the standard mocha/jasmine test
413
425
  * functions: `describe` and `it`, which will redirect to `xdescribe` and `xit`,
@@ -434,65 +446,64 @@ function suite(fn, options = undefined) {
434
446
  * versions of the `describe` and `it` wtest functions.
435
447
  */
436
448
  function ignore(predicateFn) {
437
- const isJasmine = global.jasmine && typeof global.jasmine === 'object';
449
+ const isJasmine = global.jasmine && typeof global.jasmine === 'object'
438
450
 
439
451
  const hooks = {
440
452
  describe: getTestHook('describe'),
441
453
  xdescribe: getTestHook('xdescribe'),
442
454
  it: getTestHook('it'),
443
- xit: getTestHook('xit')
444
- };
445
- hooks.fdescribe = isJasmine ? getTestHook('fdescribe') : hooks.describe.only;
446
- hooks.fit = isJasmine ? getTestHook('fit') : hooks.it.only;
455
+ xit: getTestHook('xit'),
456
+ }
457
+ hooks.fdescribe = isJasmine ? getTestHook('fdescribe') : hooks.describe.only
458
+ hooks.fit = isJasmine ? getTestHook('fit') : hooks.it.only
447
459
 
448
- let describe = wrap(hooks.xdescribe, hooks.describe);
449
- let fdescribe = wrap(hooks.xdescribe, hooks.fdescribe);
450
- describe.only = fdescribe;
460
+ let describe = wrap(hooks.xdescribe, hooks.describe)
461
+ let fdescribe = wrap(hooks.xdescribe, hooks.fdescribe)
462
+ //eslint-disable-next-line no-only-tests/no-only-tests
463
+ describe.only = fdescribe
451
464
 
452
- let it = wrap(hooks.xit, hooks.it);
453
- let fit = wrap(hooks.xit, hooks.fit);
454
- it.only = fit;
465
+ let it = wrap(hooks.xit, hooks.it)
466
+ let fit = wrap(hooks.xit, hooks.fit)
467
+ //eslint-disable-next-line no-only-tests/no-only-tests
468
+ it.only = fit
455
469
 
456
- return {describe, it};
470
+ return { describe, it }
457
471
 
458
472
  function wrap(onSkip, onRun) {
459
- return function(...args) {
473
+ return function (...args) {
460
474
  if (predicateFn()) {
461
- onSkip(...args);
475
+ onSkip(...args)
462
476
  } else {
463
- onRun(...args);
477
+ onRun(...args)
464
478
  }
465
- };
479
+ }
466
480
  }
467
481
  }
468
482
 
469
-
470
483
  /**
471
484
  * @param {string} name
472
485
  * @return {!Function}
473
486
  * @throws {TypeError}
474
487
  */
475
488
  function getTestHook(name) {
476
- let fn = global[name];
477
- let type = typeof fn;
489
+ let fn = global[name]
490
+ let type = typeof fn
478
491
  if (type !== 'function') {
479
492
  throw TypeError(
480
- `Expected global.${name} to be a function, but is ${type}.`
481
- + ' This can happen if you try using this module when running with'
482
- + ' node directly instead of using jasmine or mocha');
493
+ `Expected global.${name} to be a function, but is ${type}.` +
494
+ ' This can happen if you try using this module when running with' +
495
+ ' node directly instead of using jasmine or mocha'
496
+ )
483
497
  }
484
- return fn;
498
+ return fn
485
499
  }
486
500
 
487
-
488
501
  // PUBLIC API
489
502
 
490
-
491
503
  module.exports = {
492
504
  Environment,
493
- TargetBrowser,
494
505
  SuiteOptions,
495
506
  init,
496
507
  ignore,
497
- suite
498
- };
508
+ suite,
509
+ }