selenium-webdriver 4.0.0-beta.3 → 4.0.0-beta.4

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.
package/CHANGES.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## v4.0.0-beta.4
2
+
3
+ * Add windowTypes option support for ChromiumDriver (#7897)
4
+ * Allow relativeby with findElement (#9396)
5
+
1
6
  ## v4.0.0-beta.3
2
7
 
3
8
  * Removed support for legacy actions.
package/chromium.js CHANGED
@@ -549,6 +549,22 @@ class Options extends Capabilities {
549
549
  return this
550
550
  }
551
551
 
552
+ /**
553
+ * Sets a list of the window types that will appear when getting window
554
+ * handles. For access to <webview> elements, include "webview" in the list.
555
+ * @param {...(string|!Array<string>)} args The window types that will appear
556
+ * when getting window handles.
557
+ * @return {!Options} A self reference.
558
+ */
559
+ windowTypes(...args) {
560
+ let windowTypes = (this.options_.windowTypes || []).concat(...args);
561
+ if (windowTypes.length) {
562
+ this.options_.windowTypes = windowTypes;
563
+ }
564
+ return this;
565
+ }
566
+
567
+
552
568
  /**
553
569
  * Converts this instance to its JSON wire protocol representation. Note this
554
570
  * function is an implementation not intended for general use.
package/lib/webdriver.js CHANGED
@@ -36,6 +36,7 @@ const http = require('../http/index')
36
36
  const fs = require('fs')
37
37
  const { Capabilities } = require('./capabilities')
38
38
  const path = require('path')
39
+ const { NoSuchElementError } = require('./error')
39
40
 
40
41
  // Capability names that are defined in the W3C spec.
41
42
  const W3C_CAPABILITY_NAMES = new Set([
@@ -257,18 +258,18 @@ class IWebDriver {
257
258
  /**
258
259
  * @return {!command.Executor} The command executor used by this instance.
259
260
  */
260
- getExecutor() { }
261
+ getExecutor() {}
261
262
 
262
263
  /**
263
264
  * @return {!Promise<!Session>} A promise for this client's session.
264
265
  */
265
- getSession() { }
266
+ getSession() {}
266
267
 
267
268
  /**
268
269
  * @return {!Promise<!Capabilities>} A promise that will resolve with
269
270
  * the this instance's capabilities.
270
271
  */
271
- getCapabilities() { }
272
+ getCapabilities() {}
272
273
 
273
274
  /**
274
275
  * Terminates the browser session. After calling quit, this instance will be
@@ -278,7 +279,7 @@ class IWebDriver {
278
279
  * @return {!Promise<void>} A promise that will be resolved when the
279
280
  * command has completed.
280
281
  */
281
- quit() { }
282
+ quit() {}
282
283
 
283
284
  /**
284
285
  * Creates a new action sequence using this driver. The sequence will not be
@@ -457,7 +458,7 @@ class IWebDriver {
457
458
  timeout = undefined, // eslint-disable-line
458
459
  message = undefined, // eslint-disable-line
459
460
  pollTimeout = undefined // eslint-disable-line
460
- ) { }
461
+ ) {}
461
462
 
462
463
  /**
463
464
  * Makes the driver sleep for the given amount of time.
@@ -474,7 +475,7 @@ class IWebDriver {
474
475
  * @return {!Promise<string>} A promise that will be resolved with the current
475
476
  * window handle.
476
477
  */
477
- getWindowHandle() { }
478
+ getWindowHandle() {}
478
479
 
479
480
  /**
480
481
  * Retrieves a list of all available window handles.
@@ -482,7 +483,7 @@ class IWebDriver {
482
483
  * @return {!Promise<!Array<string>>} A promise that will be resolved with an
483
484
  * array of window handles.
484
485
  */
485
- getAllWindowHandles() { }
486
+ getAllWindowHandles() {}
486
487
 
487
488
  /**
488
489
  * Retrieves the current page's source. The returned source is a representation
@@ -492,7 +493,7 @@ class IWebDriver {
492
493
  * @return {!Promise<string>} A promise that will be resolved with the current
493
494
  * page source.
494
495
  */
495
- getPageSource() { }
496
+ getPageSource() {}
496
497
 
497
498
  /**
498
499
  * Closes the current window.
@@ -500,7 +501,7 @@ class IWebDriver {
500
501
  * @return {!Promise<void>} A promise that will be resolved when this command
501
502
  * has completed.
502
503
  */
503
- close() { }
504
+ close() {}
504
505
 
505
506
  /**
506
507
  * Navigates to the given URL.
@@ -517,7 +518,7 @@ class IWebDriver {
517
518
  * @return {!Promise<string>} A promise that will be resolved with the
518
519
  * current URL.
519
520
  */
520
- getCurrentUrl() { }
521
+ getCurrentUrl() {}
521
522
 
522
523
  /**
523
524
  * Retrieves the current page title.
@@ -525,7 +526,7 @@ class IWebDriver {
525
526
  * @return {!Promise<string>} A promise that will be resolved with the current
526
527
  * page's title.
527
528
  */
528
- getTitle() { }
529
+ getTitle() {}
529
530
 
530
531
  /**
531
532
  * Locates an element on the page. If the element cannot be found, a
@@ -589,23 +590,23 @@ class IWebDriver {
589
590
  * @return {!Promise<string>} A promise that will be resolved to the
590
591
  * screenshot as a base-64 encoded PNG.
591
592
  */
592
- takeScreenshot() { }
593
+ takeScreenshot() {}
593
594
 
594
595
  /**
595
596
  * @return {!Options} The options interface for this instance.
596
597
  */
597
- manage() { }
598
+ manage() {}
598
599
 
599
600
  /**
600
601
  * @return {!Navigation} The navigation interface for this instance.
601
602
  */
602
- navigate() { }
603
+ navigate() {}
603
604
 
604
605
  /**
605
606
  * @return {!TargetLocator} The target locator interface for this
606
607
  * instance.
607
608
  */
608
- switchTo() { }
609
+ switchTo() {}
609
610
 
610
611
  /**
611
612
  *
@@ -649,7 +650,6 @@ function filterNonW3CCaps(capabilities) {
649
650
  * @implements {IWebDriver}
650
651
  */
651
652
  class WebDriver {
652
-
653
653
  /**
654
654
  * @param {!(./session.Session|IThenable<!./session.Session>)} session Either
655
655
  * a known session or a promise that will be resolved to a session.
@@ -665,7 +665,7 @@ class WebDriver {
665
665
  // If session is a rejected promise, add a no-op rejection handler.
666
666
  // This effectively hides setup errors until users attempt to interact
667
667
  // with the session.
668
- this.session_.catch(function () { })
668
+ this.session_.catch(function () {})
669
669
 
670
670
  /** @private {!command.Executor} */
671
671
  this.executor_ = executor
@@ -761,12 +761,12 @@ class WebDriver {
761
761
  this.session_ = Promise.reject(
762
762
  new error.NoSuchSessionError(
763
763
  'This driver instance does not have a valid session ID ' +
764
- '(did you call WebDriver.quit()?) and may no longer be used.'
764
+ '(did you call WebDriver.quit()?) and may no longer be used.'
765
765
  )
766
766
  )
767
767
 
768
768
  // Only want the session rejection to bubble if accessed.
769
- this.session_.catch(function () { })
769
+ this.session_.catch(function () {})
770
770
 
771
771
  if (this.onQuit_) {
772
772
  return this.onQuit_.call(void 0)
@@ -827,15 +827,18 @@ class WebDriver {
827
827
  let timeoutMessage = resolveWaitMessage(message)
828
828
  reject(
829
829
  new error.TimeoutError(
830
- `${timeoutMessage}Timed out waiting for promise to resolve after ${Date.now() - start
830
+ `${timeoutMessage}Timed out waiting for promise to resolve after ${
831
+ Date.now() - start
831
832
  }ms`
832
833
  )
833
834
  )
834
835
  } catch (ex) {
835
836
  reject(
836
837
  new error.TimeoutError(
837
- `${ex.message
838
- }\nTimed out waiting for promise to resolve after ${Date.now() - start
838
+ `${
839
+ ex.message
840
+ }\nTimed out waiting for promise to resolve after ${
841
+ Date.now() - start
839
842
  }ms`
840
843
  )
841
844
  )
@@ -865,7 +868,7 @@ class WebDriver {
865
868
  if (typeof fn !== 'function') {
866
869
  throw TypeError(
867
870
  'Wait condition must be a promise-like object, function, or a ' +
868
- 'Condition object'
871
+ 'Condition object'
869
872
  )
870
873
  }
871
874
 
@@ -917,7 +920,7 @@ class WebDriver {
917
920
  if (!(value instanceof WebElement)) {
918
921
  throw TypeError(
919
922
  'WebElementCondition did not resolve to a WebElement: ' +
920
- Object.prototype.toString.call(value)
923
+ Object.prototype.toString.call(value)
921
924
  )
922
925
  }
923
926
  return value
@@ -972,16 +975,46 @@ class WebDriver {
972
975
  /** @override */
973
976
  findElement(locator) {
974
977
  let id
975
- locator = by.checkedLocator(locator)
978
+ let cmd = null
979
+
980
+ if (locator instanceof RelativeBy) {
981
+ cmd = new command.Command(
982
+ command.Name.FIND_ELEMENTS_RELATIVE
983
+ ).setParameter('args', locator.marshall())
984
+ } else {
985
+ locator = by.checkedLocator(locator)
986
+ }
987
+
976
988
  if (typeof locator === 'function') {
977
989
  id = this.findElementInternal_(locator, this)
978
- } else {
979
- let cmd = new command.Command(command.Name.FIND_ELEMENT)
990
+ return new WebElementPromise(this, id)
991
+ } else if (cmd === null) {
992
+ cmd = new command.Command(command.Name.FIND_ELEMENT)
980
993
  .setParameter('using', locator.using)
981
994
  .setParameter('value', locator.value)
982
- id = this.execute(cmd)
983
995
  }
984
- return new WebElementPromise(this, id)
996
+
997
+ id = this.execute(cmd)
998
+ if (locator instanceof RelativeBy) {
999
+ return this.normalize_(id)
1000
+ } else {
1001
+ return new WebElementPromise(this, id)
1002
+ }
1003
+ }
1004
+
1005
+ /**
1006
+ * @param {!Function} webElementPromise The webElement in unresolved state
1007
+ * @return {!Promise<!WebElement>} First single WebElement from array of resolved promises
1008
+ */
1009
+ async normalize_(webElementPromise) {
1010
+ let result = await webElementPromise
1011
+ if (result.length === 0) {
1012
+ throw new NoSuchElementError(
1013
+ 'Cannot locate an element with provided parameters'
1014
+ )
1015
+ } else {
1016
+ return result[0]
1017
+ }
985
1018
  }
986
1019
 
987
1020
  /**
@@ -1166,7 +1199,7 @@ class WebDriver {
1166
1199
  caps['map_'].get(this.VENDOR_COMMAND_PREFIX + ':chromeOptions') ||
1167
1200
  caps['map_'].get(this.VENDOR_CAPABILITY_PREFIX + ':edgeOptions') ||
1168
1201
  caps['map_'].get('moz:debuggerAddress') ||
1169
- new Map();
1202
+ new Map()
1170
1203
  const debuggerUrl = seCdp || vendorInfo['debuggerAddress'] || vendorInfo
1171
1204
  this._wsUrl = await this.getWsUrl(debuggerUrl, target)
1172
1205
 
@@ -1374,7 +1407,10 @@ class WebDriver {
1374
1407
  .toString()
1375
1408
  } catch {
1376
1409
  mutationListener = fs
1377
- .readFileSync(path.resolve(__dirname, './atoms/mutation-listener.js'), 'utf-8')
1410
+ .readFileSync(
1411
+ path.resolve(__dirname, './atoms/mutation-listener.js'),
1412
+ 'utf-8'
1413
+ )
1378
1414
  .toString()
1379
1415
  }
1380
1416
 
@@ -1696,7 +1732,7 @@ class Options {
1696
1732
  } else if (typeof value !== 'undefined') {
1697
1733
  throw TypeError(
1698
1734
  'invalid timeouts configuration:' +
1699
- ` expected "${key}" to be a number, got ${typeof value}`
1735
+ ` expected "${key}" to be a number, got ${typeof value}`
1700
1736
  )
1701
1737
  }
1702
1738
  }
@@ -1757,7 +1793,7 @@ function legacyTimeout(driver, type, ms) {
1757
1793
  *
1758
1794
  * @record
1759
1795
  */
1760
- Options.Cookie = function () { }
1796
+ Options.Cookie = function () {}
1761
1797
 
1762
1798
  /**
1763
1799
  * The name of the cookie.
@@ -2462,18 +2498,18 @@ class WebElement {
2462
2498
  */
2463
2499
  async sendKeys(...args) {
2464
2500
  let keys = []
2465
- ; (await Promise.all(args)).forEach((key) => {
2466
- let type = typeof key
2467
- if (type === 'number') {
2468
- key = String(key)
2469
- } else if (type !== 'string') {
2470
- throw TypeError('each key must be a number of string; got ' + type)
2471
- }
2501
+ ;(await Promise.all(args)).forEach((key) => {
2502
+ let type = typeof key
2503
+ if (type === 'number') {
2504
+ key = String(key)
2505
+ } else if (type !== 'string') {
2506
+ throw TypeError('each key must be a number of string; got ' + type)
2507
+ }
2472
2508
 
2473
- // The W3C protocol requires keys to be specified as an array where
2474
- // each element is a single key.
2475
- keys.push(...key.split(''))
2476
- })
2509
+ // The W3C protocol requires keys to be specified as an array where
2510
+ // each element is a single key.
2511
+ keys.push(...key.split(''))
2512
+ })
2477
2513
 
2478
2514
  if (!this.driver_.fileDetector_) {
2479
2515
  return this.execute_(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selenium-webdriver",
3
- "version": "4.0.0-beta.3",
3
+ "version": "4.0.0-beta.4",
4
4
  "description": "The official WebDriver JavaScript bindings from the Selenium project",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -23,24 +23,24 @@
23
23
  "node": ">= 10.15.0"
24
24
  },
25
25
  "dependencies": {
26
- "jszip": "^3.5.0",
27
- "rimraf": "^2.7.1",
26
+ "jszip": "^3.6.0",
27
+ "rimraf": "^3.0.2",
28
28
  "tmp": "^0.2.1",
29
- "ws": "^7.3.1"
29
+ "ws": ">=7.4.6"
30
30
  },
31
31
  "devDependencies": {
32
- "eslint": "^7.15.0",
33
- "eslint-config-prettier": "^7.0.0",
34
- "eslint-plugin-no-only-tests": "^2.4.0",
32
+ "eslint": "^7.26.0",
33
+ "eslint-config-prettier": "^8.3.0",
34
+ "eslint-plugin-no-only-tests": "^2.6.0",
35
35
  "eslint-plugin-node": "^11.1.0",
36
- "eslint-plugin-prettier": "^3.2.0",
36
+ "eslint-plugin-prettier": "^3.4.0",
37
37
  "express": "^4.17.1",
38
38
  "jasmine": "^3.6.1",
39
39
  "mocha": "^8.1.0",
40
40
  "multer": "^1.4.2",
41
- "prettier": "^2.2.1",
41
+ "prettier": "^2.3.0",
42
42
  "serve-index": "^1.9.1",
43
- "sinon": "^7.5.0"
43
+ "sinon": "^10.0.0"
44
44
  },
45
45
  "scripts": {
46
46
  "lint": "eslint --ignore-pattern node_modules --ignore-pattern generator --ext js lib/http.js \"**/*.js\"",