selenium-webdriver 4.0.0-beta.2 → 4.0.0-rc-2

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/lib/input.js CHANGED
@@ -20,14 +20,8 @@
20
20
  /**
21
21
  * @fileoverview Defines types related to user input with the WebDriver API.
22
22
  */
23
-
24
- const promise = require('./promise')
25
23
  const { Command, Name } = require('./command')
26
- const {
27
- InvalidArgumentError,
28
- UnknownCommandError,
29
- UnsupportedOperationError,
30
- } = require('./error')
24
+ const { InvalidArgumentError } = require('./error')
31
25
 
32
26
  /**
33
27
  * Enumeration of the buttons used in the advanced interactions API.
@@ -489,67 +483,6 @@ Pointer.Type = {
489
483
  * | Keyboard | pause(100) | keyDown(SHIFT) |
490
484
  * | Mouse | move({duration: 300}) | |
491
485
  *
492
- *
493
- * #### Bridge Mode
494
- *
495
- * As of January 2018, only Firefox natively supports this API. For other
496
- * browsers, you may either use the
497
- * {@link ./actions.LegacyActionSequence LegacyActionSequence} class, _or_ you
498
- * can put the Actions class into bridge mode by passing `{bridge: true}` on
499
- * creation:
500
- *
501
- * const actions = driver.actions({bridge: true});
502
- * await actions.click(element).sendKeys('abc').perform();
503
- *
504
- * In bridge mode, {@link #perform perform()} will first attempt to execute the
505
- * configured action sequence using the W3C action protocol. If this is rejected
506
- * by the remote end, the sequence will be translated to and executed against
507
- * the legacy protocol.
508
- *
509
- * Bridge mode __is not enabled by default__ as there are several notable
510
- * differences between W3C-specified and legacy protocols. Care must be
511
- * taken to configure your action sequences to account for these differences:
512
- *
513
- * 1. For W3C actions, the entire action sequence is executed in a single
514
- * call to the remote end. For legacy sequences, multiple calls must be
515
- * made for each step in the sequence. This introduces additional latency
516
- * which may impact how the browser responds to the emulated user actions.
517
- *
518
- * 2. For the legacy actions, {@linkplain #pause pauses} are handled _locally_.
519
- *
520
- * 3. For legacy actions, a {@linkplain #keyDown keyDown()} for a
521
- * _non-modifier key_ **must** be followed by a {@linkplain #keyUP keyUp()}
522
- * for the same key. This will be handled for you if you use the
523
- * {@linkplain #sendKeys sendKeys()} method.
524
- *
525
- * 4. Mouse movements may not be specified relative to
526
- * {@linkplain ./input.Origin.VIEWPORT Origin.VIEWPORT}.
527
- * All movements must be relative to an element or the mouse's current
528
- * position ({@linkplain ./input.Origin.POINTER Origin.POINTER}).
529
- * The {@linkplain #move move()} method defaults to viewport relative
530
- * offsets, so you must always specify an appropriate origin in bridge mode:
531
- *
532
- * driver.actions({bridge: true})
533
- * .move({x: 0, y: 0, origin: Origin.POINTER})
534
- * .perform();
535
- * driver.actions({bridge: true})
536
- * .move({x: 0, y: 0, origin: someWebElement})
537
- * .perform();
538
- *
539
- * 5. The legacy protocol does not support specifying the duration of a
540
- * {@linkplain #move mouse movement}; any specified duration _is ignored_
541
- * when translating actions to the legacy protocol.
542
- *
543
- * 6. For W3C actions, move offsets relative to a
544
- * {@linkplain ./webdriver.WebElement WebElement} are interpreted relative
545
- * to the center of an element's _first_ [client rect] in the viewport. For
546
- * legacy actions, element offsets are relative to the top-left corner of
547
- * the element's [bounding client rect]. When translating actions to the
548
- * legacy protocol in bridge mode, an extra command must be inserted to
549
- * translate move offsets from one frame of reference to the other. This
550
- * extra command contributes to the overall latency issue outlined in
551
- * point 1.
552
- *
553
486
  * [client rect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getClientRects
554
487
  * [bounding client rect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
555
488
  *
@@ -560,26 +493,16 @@ class Actions {
560
493
  /**
561
494
  * @param {!Executor} executor The object to execute the configured
562
495
  * actions with.
563
- * @param {{async: (boolean|undefined),
564
- * bridge: (boolean|undefined)}} options Options for this action
496
+ * @param {{async: (boolean|undefined)}} options Options for this action
565
497
  * sequence (see class description for details).
566
498
  */
567
- constructor(executor, { async = false, bridge = false } = {}) {
568
- if (async && bridge) {
569
- throw new InvalidArgumentError(
570
- 'Async sequences not supported with bridge mode'
571
- )
572
- }
573
-
499
+ constructor(executor, { async = false } = {}) {
574
500
  /** @private @const */
575
501
  this.executor_ = executor
576
502
 
577
503
  /** @private @const */
578
504
  this.sync_ = !async
579
505
 
580
- /** @private @const */
581
- this.bridge_ = !!bridge
582
-
583
506
  /** @private @const */
584
507
  this.keyboard_ = new Keyboard('default keyboard')
585
508
 
@@ -952,20 +875,9 @@ class Actions {
952
875
  return Promise.resolve()
953
876
  }
954
877
 
955
- try {
956
- await this.executor_.execute(
957
- new Command(Name.ACTIONS).setParameter('actions', _actions)
958
- )
959
- } catch (ex) {
960
- if (
961
- this.bridge_ &&
962
- (ex instanceof UnknownCommandError ||
963
- ex instanceof UnsupportedOperationError)
964
- ) {
965
- return executeLegacy(this.executor_, this.sequences_)
966
- }
967
- throw ex
968
- }
878
+ await this.executor_.execute(
879
+ new Command(Name.ACTIONS).setParameter('actions', _actions)
880
+ )
969
881
  }
970
882
  }
971
883
 
@@ -980,213 +892,6 @@ function isIdle(actions) {
980
892
  )
981
893
  }
982
894
 
983
- const MODIFIER_KEYS = new Set([Key.ALT, Key.CONTROL, Key.SHIFT, Key.COMMAND])
984
-
985
- /**
986
- * @param {!Executor} executor
987
- * @param {!Map<!Device, !Array<!Action>>} sequences
988
- * @return {!Promise<void>}
989
- * @suppress {deprecated} Ignore warnings about using LegacyActionSequence.
990
- */
991
- async function executeLegacy(executor, sequences) {
992
- let maxLength = 0
993
- sequences.forEach((seq) => (maxLength = Math.max(maxLength, seq.length)))
994
-
995
- const actions = []
996
- for (let i = 0; i < maxLength; i++) {
997
- let next
998
- for (const device of sequences.keys()) {
999
- const seq = sequences.get(device)
1000
-
1001
- if (
1002
- device instanceof Pointer &&
1003
- device.pointerType_ !== Pointer.Type.MOUSE
1004
- ) {
1005
- throw new UnsupportedOperationError(
1006
- `${device.pointerType_} pointer not supported in bridge mode`
1007
- )
1008
- }
1009
-
1010
- const action = seq[i]
1011
- if (!action || (action.type === Action.Type.PAUSE && !action.duration)) {
1012
- continue
1013
- }
1014
-
1015
- // - If we've already found an action for this tick:
1016
- // - If we have two pauses, use the one with a longer duration
1017
- // - If one is a pause and the other isn't, use the non-pause
1018
- // - Otherwise, two non-pauses is an error.
1019
- // - Otherwise, we haven't selected an action yet.
1020
- if (next) {
1021
- if (next.type === Action.Type.PAUSE) {
1022
- if (action.type === Action.Type.PAUSE) {
1023
- next = next.duration > action.duration ? next : action
1024
- } else {
1025
- next = action
1026
- }
1027
- } else if (action.type !== Action.Type.PAUSE) {
1028
- throw new UnsupportedOperationError(
1029
- 'parallel actions not supported in bridge mode'
1030
- )
1031
- }
1032
- } else {
1033
- next = action
1034
- }
1035
-
1036
- if (action.type === Action.Type.KEY_DOWN) {
1037
- // If this action is a keydown for a non-modifier key, the next action
1038
- // must be a keyup for the same key, otherwise it cannot be translated
1039
- // to the legacy action API.
1040
- if (!MODIFIER_KEYS.has(action.value)) {
1041
- const nextAction = seq[i + 1]
1042
- if (
1043
- !nextAction ||
1044
- nextAction.type !== Action.Type.KEY_UP ||
1045
- nextAction.value !== action.value
1046
- ) {
1047
- throw new UnsupportedOperationError(
1048
- `in bridge mode, keydown for <${action.value}> must be followed` +
1049
- ' by a keyup for the same key'
1050
- )
1051
- }
1052
- }
1053
- } else if (
1054
- action.type === Action.Type.KEY_UP &&
1055
- !MODIFIER_KEYS.has(action.value)
1056
- ) {
1057
- next = null
1058
- }
1059
- }
1060
-
1061
- if (next) {
1062
- actions.push(next)
1063
- }
1064
- }
1065
-
1066
- for (let i = 0; i < actions.length; i++) {
1067
- const action = actions[i]
1068
- switch (action.type) {
1069
- case Action.Type.PAUSE: {
1070
- await promise.delayed(action.duration || 0)
1071
- break
1072
- }
1073
- case Action.Type.KEY_DOWN: {
1074
- const keys = [action.value]
1075
- if (!MODIFIER_KEYS.has(action.value)) {
1076
- // eslint-disable-next-line no-inner-declarations
1077
- function nextIsKeyDown() {
1078
- const next = actions[i + 1]
1079
- return (
1080
- !!next &&
1081
- next.type === Action.Type.KEY_DOWN &&
1082
- !MODIFIER_KEYS.has(next.value)
1083
- )
1084
- }
1085
- for (; nextIsKeyDown(); i++) {
1086
- keys.push(actions[i + 1].value)
1087
- }
1088
- }
1089
- await executor.execute(
1090
- new Command(Name.LEGACY_ACTION_SEND_KEYS).setParameter('value', keys)
1091
- )
1092
- break
1093
- }
1094
- case Action.Type.KEY_UP: {
1095
- await executor.execute(
1096
- new Command(Name.LEGACY_ACTION_SEND_KEYS).setParameter('value', [
1097
- action.value,
1098
- ])
1099
- )
1100
- break
1101
- }
1102
- case Action.Type.POINTER_DOWN: {
1103
- // eslint-disable-next-line no-inner-declarations
1104
- function isClick(startAt) {
1105
- const first = actions[startAt]
1106
- const second = actions[startAt + 1]
1107
- return (
1108
- !!first &&
1109
- !!second &&
1110
- first.type === Action.Type.POINTER_DOWN &&
1111
- second.type === Action.Type.POINTER_UP &&
1112
- first.button === second.button
1113
- )
1114
- }
1115
-
1116
- // eslint-disable-next-line no-inner-declarations
1117
- function isDoubleClick(startAt) {
1118
- return (
1119
- isClick(startAt) &&
1120
- isClick(startAt + 2) &&
1121
- actions[startAt].button === actions[(startAt = 2)].button
1122
- )
1123
- }
1124
-
1125
- let cmd
1126
- if (isDoubleClick(i)) {
1127
- i += 3 // Consume the pointer up/down/up.
1128
- cmd = Name.LEGACY_ACTION_DOUBLE_CLICK
1129
- } else if (isClick(i)) {
1130
- i++ // Consume the pointer-up.
1131
- cmd = Name.LEGACY_ACTION_CLICK
1132
- } else {
1133
- cmd = Name.LEGACY_ACTION_MOUSE_DOWN
1134
- }
1135
- await executor.execute(
1136
- new Command(cmd).setParameter('button', action.button)
1137
- )
1138
- break
1139
- }
1140
- case Action.Type.POINTER_UP: {
1141
- await executor.execute(
1142
- new Command(Name.LEGACY_ACTION_MOUSE_UP).setParameter(
1143
- 'button',
1144
- action.button
1145
- )
1146
- )
1147
- break
1148
- }
1149
- case Action.Type.POINTER_MOVE: {
1150
- if (action.origin === Origin.VIEWPORT) {
1151
- throw new UnsupportedOperationError(
1152
- `pointer movements relative to ${Origin.VIEWPORT} are not` +
1153
- ' supported in bridge mode'
1154
- )
1155
- }
1156
-
1157
- let x = action.x
1158
- let y = action.y
1159
- const cmd = new Command(Name.LEGACY_ACTION_MOUSE_MOVE)
1160
- if (action.origin && action.origin !== Origin.POINTER) {
1161
- const el = /** @type {!./webdriver.WebElement} */ (action.origin)
1162
-
1163
- // Need to translate frame of reference from center of element's first
1164
- // client rect to the top-left of its bounding client rect. See:
1165
- // https://w3c.github.io/webdriver/webdriver-spec.html#dfn-center-point
1166
- let diff = await executor.execute(
1167
- new Command(Name.EXECUTE_SCRIPT)
1168
- .setParameter('script', INTERNAL_COMPUTE_OFFSET_SCRIPT)
1169
- .setParameter('args', [el])
1170
- )
1171
- x += diff[0]
1172
- y += diff[1]
1173
-
1174
- const id = await el.getId()
1175
- cmd.setParameter('element', id)
1176
- }
1177
- cmd.setParameter('xoffset', x).setParameter('yoffset', y)
1178
- await executor.execute(cmd)
1179
- break
1180
- }
1181
- default: {
1182
- throw new UnsupportedOperationError(
1183
- `${action.type} actions not supported in bridge mode`
1184
- )
1185
- }
1186
- }
1187
- }
1188
- }
1189
-
1190
895
  /**
1191
896
  * Script used to compute the offset from the center of a DOM element's first
1192
897
  * client rect from the top-left corner of the element's bounding client rect.
package/lib/promise.js CHANGED
@@ -30,17 +30,7 @@
30
30
  * @return {boolean} Whether the value is a promise.
31
31
  */
32
32
  function isPromise(value) {
33
- try {
34
- // Use array notation so the Closure compiler does not obfuscate away our
35
- // contract.
36
- return (
37
- value &&
38
- (typeof value === 'object' || typeof value === 'function') &&
39
- typeof value['then'] === 'function'
40
- )
41
- } catch (ex) {
42
- return false
43
- }
33
+ return Object.prototype.toString.call(value) === '[object Promise]'
44
34
  }
45
35
 
46
36
  /**
@@ -50,9 +40,7 @@ function isPromise(value) {
50
40
  * @return {!Promise<void>} The promise.
51
41
  */
52
42
  function delayed(ms) {
53
- return new Promise((resolve) => {
54
- setTimeout(resolve, ms)
55
- })
43
+ return new Promise((resolve) => setTimeout(resolve, ms))
56
44
  }
57
45
 
58
46
  /**
@@ -199,8 +187,8 @@ async function filter(array, fn, self = undefined) {
199
187
 
200
188
  for (let i = 0; i < n; i++) {
201
189
  if (i in arr) {
202
- let value = arr[i]
203
- let include = await fn.call(self, value, i, arr)
190
+ const value = arr[i]
191
+ const include = await fn.call(self, value, i, arr)
204
192
  if (include) {
205
193
  values[valuesLength++] = value
206
194
  }
package/lib/until.js CHANGED
@@ -137,14 +137,13 @@ exports.alertIsPresent = function alertIsPresent() {
137
137
  * @return {!Condition<boolean>} The new condition.
138
138
  */
139
139
  exports.titleIs = function titleIs(title) {
140
- return new Condition(
141
- 'for title to be ' + JSON.stringify(title),
142
- function (driver) {
143
- return driver.getTitle().then(function (t) {
144
- return t === title
145
- })
146
- }
147
- )
140
+ return new Condition('for title to be ' + JSON.stringify(title), function (
141
+ driver
142
+ ) {
143
+ return driver.getTitle().then(function (t) {
144
+ return t === title
145
+ })
146
+ })
148
147
  }
149
148
 
150
149
  /**
@@ -189,14 +188,13 @@ exports.titleMatches = function titleMatches(regex) {
189
188
  * @return {!Condition<boolean>} The new condition.
190
189
  */
191
190
  exports.urlIs = function urlIs(url) {
192
- return new Condition(
193
- 'for URL to be ' + JSON.stringify(url),
194
- function (driver) {
195
- return driver.getCurrentUrl().then(function (u) {
196
- return u === url
197
- })
198
- }
199
- )
191
+ return new Condition('for URL to be ' + JSON.stringify(url), function (
192
+ driver
193
+ ) {
194
+ return driver.getCurrentUrl().then(function (u) {
195
+ return u === url
196
+ })
197
+ })
200
198
  }
201
199
 
202
200
  /**
package/lib/webdriver.js CHANGED
@@ -36,19 +36,21 @@ 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([
42
43
  'acceptInsecureCerts',
43
44
  'browserName',
44
45
  'browserVersion',
45
- 'platformName',
46
46
  'pageLoadStrategy',
47
+ 'platformName',
47
48
  'proxy',
48
49
  'setWindowRect',
49
- 'timeouts',
50
50
  'strictFileInteractability',
51
+ 'timeouts',
51
52
  'unhandledPromptBehavior',
53
+ 'webSocketUrl'
52
54
  ])
53
55
 
54
56
  /**
@@ -649,7 +651,6 @@ function filterNonW3CCaps(capabilities) {
649
651
  * @implements {IWebDriver}
650
652
  */
651
653
  class WebDriver {
652
-
653
654
  /**
654
655
  * @param {!(./session.Session|IThenable<!./session.Session>)} session Either
655
656
  * a known session or a promise that will be resolved to a session.
@@ -972,16 +973,46 @@ class WebDriver {
972
973
  /** @override */
973
974
  findElement(locator) {
974
975
  let id
975
- locator = by.checkedLocator(locator)
976
+ let cmd = null
977
+
978
+ if (locator instanceof RelativeBy) {
979
+ cmd = new command.Command(
980
+ command.Name.FIND_ELEMENTS_RELATIVE
981
+ ).setParameter('args', locator.marshall())
982
+ } else {
983
+ locator = by.checkedLocator(locator)
984
+ }
985
+
976
986
  if (typeof locator === 'function') {
977
987
  id = this.findElementInternal_(locator, this)
978
- } else {
979
- let cmd = new command.Command(command.Name.FIND_ELEMENT)
988
+ return new WebElementPromise(this, id)
989
+ } else if (cmd === null) {
990
+ cmd = new command.Command(command.Name.FIND_ELEMENT)
980
991
  .setParameter('using', locator.using)
981
992
  .setParameter('value', locator.value)
982
- id = this.execute(cmd)
983
993
  }
984
- return new WebElementPromise(this, id)
994
+
995
+ id = this.execute(cmd)
996
+ if (locator instanceof RelativeBy) {
997
+ return this.normalize_(id)
998
+ } else {
999
+ return new WebElementPromise(this, id)
1000
+ }
1001
+ }
1002
+
1003
+ /**
1004
+ * @param {!Function} webElementPromise The webElement in unresolved state
1005
+ * @return {!Promise<!WebElement>} First single WebElement from array of resolved promises
1006
+ */
1007
+ async normalize_(webElementPromise) {
1008
+ let result = await webElementPromise
1009
+ if (result.length === 0) {
1010
+ throw new NoSuchElementError(
1011
+ 'Cannot locate an element with provided parameters'
1012
+ )
1013
+ } else {
1014
+ return result[0]
1015
+ }
985
1016
  }
986
1017
 
987
1018
  /**
@@ -1166,7 +1197,7 @@ class WebDriver {
1166
1197
  caps['map_'].get(this.VENDOR_COMMAND_PREFIX + ':chromeOptions') ||
1167
1198
  caps['map_'].get(this.VENDOR_CAPABILITY_PREFIX + ':edgeOptions') ||
1168
1199
  caps['map_'].get('moz:debuggerAddress') ||
1169
- new Map();
1200
+ new Map()
1170
1201
  const debuggerUrl = seCdp || vendorInfo['debuggerAddress'] || vendorInfo
1171
1202
  this._wsUrl = await this.getWsUrl(debuggerUrl, target)
1172
1203
 
@@ -1199,23 +1230,25 @@ class WebDriver {
1199
1230
  if (target && cdpTargets.indexOf(target.toLowerCase()) === -1) {
1200
1231
  throw new error.InvalidArgumentError('invalid target value')
1201
1232
  }
1202
- let path
1203
- if (target === 'page') {
1204
- path = '/json'
1205
- } else {
1206
- path = '/json/version'
1233
+
1234
+ if (debuggerAddress.match(/\/se\/cdp/)) {
1235
+ if (debuggerAddress.match("ws:\/\/", "http:\/\/")) {
1236
+ return debuggerAddress.replace("ws:\/\/", "http:\/\/")
1237
+ }
1238
+ else if (debuggerAddress.match("wss:\/\/", "https:\/\/")) {
1239
+ return debuggerAddress.replace("wss:\/\/", "https:\/\/")
1240
+ }
1241
+ else {
1242
+ return debuggerAddress
1243
+ }
1207
1244
  }
1245
+
1246
+ const path = '/json/version'
1208
1247
  let request = new http.Request('GET', path)
1209
1248
  let client = new http.HttpClient('http://' + debuggerAddress)
1210
1249
  let response = await client.send(request)
1211
- let url
1212
- if (target.toLowerCase() === 'page') {
1213
- url = JSON.parse(response.body)[0]['webSocketDebuggerUrl']
1214
- } else {
1215
- url = JSON.parse(response.body)['webSocketDebuggerUrl']
1216
- }
1217
1250
 
1218
- return url
1251
+ return JSON.parse(response.body)['webSocketDebuggerUrl']
1219
1252
  }
1220
1253
 
1221
1254
  /**
@@ -1227,14 +1260,6 @@ class WebDriver {
1227
1260
  * @param connection CDP Connection
1228
1261
  */
1229
1262
  async register(username, password, connection) {
1230
- await connection.execute(
1231
- 'Network.setCacheDisabled',
1232
- this.getRandomNumber(1, 10),
1233
- {
1234
- cacheDisabled: true,
1235
- },
1236
- null
1237
- )
1238
1263
 
1239
1264
  this._wsConnection.on('message', (message) => {
1240
1265
  const params = JSON.parse(message)
@@ -1273,8 +1298,69 @@ class WebDriver {
1273
1298
  },
1274
1299
  null
1275
1300
  )
1301
+ await connection.execute(
1302
+ 'Network.setCacheDisabled',
1303
+ this.getRandomNumber(1, 10),
1304
+ {
1305
+ cacheDisabled: true,
1306
+ },
1307
+ null
1308
+ )
1276
1309
  }
1277
1310
 
1311
+ /**
1312
+ * Handle Network interception requests
1313
+ * @param connection WebSocket connection to the browser
1314
+ * @param httpResponse Object representing what we are intercepting
1315
+ * as well as what should be returned.
1316
+ * @param callback callback called when we intercept requests.
1317
+ */
1318
+ async onIntercept(connection, httpResponse, callback) {
1319
+
1320
+ this._wsConnection.on('message', (message) => {
1321
+ const params = JSON.parse(message)
1322
+ if (params.method === 'Fetch.requestPaused') {
1323
+ const requestPausedParams = params['params']
1324
+ if (requestPausedParams.request.url == httpResponse.urlToIntercept) {
1325
+ connection.execute(
1326
+ 'Fetch.continueRequest',
1327
+ this.getRandomNumber(1, 10),
1328
+ {
1329
+ requestId: requestPausedParams['requestId'],
1330
+ url: httpResponse.urlToIntercept,
1331
+ method: httpResponse.method,
1332
+ headers: httpResponse.headers,
1333
+ postData: httpResponse.body
1334
+ }
1335
+ )
1336
+ callback()
1337
+ } else {
1338
+ connection.execute(
1339
+ 'Fetch.continueRequest',
1340
+ this.getRandomNumber(1, 10),
1341
+ {
1342
+ requestId: requestPausedParams['requestId'],
1343
+ }
1344
+ )
1345
+ }
1346
+ }
1347
+ })
1348
+
1349
+ await connection.execute(
1350
+ 'Fetch.enable',
1351
+ 1,
1352
+ {},
1353
+ null
1354
+ )
1355
+ await connection.execute(
1356
+ 'Network.setCacheDisabled',
1357
+ this.getRandomNumber(1, 10),
1358
+ {
1359
+ cacheDisabled: true,
1360
+ },
1361
+ null
1362
+ )
1363
+ }
1278
1364
  /**
1279
1365
  *
1280
1366
  * @param connection
@@ -1282,12 +1368,7 @@ class WebDriver {
1282
1368
  * @returns {Promise<void>}
1283
1369
  */
1284
1370
  async onLogEvent(connection, callback) {
1285
- await connection.execute(
1286
- 'Runtime.enable',
1287
- this.getRandomNumber(1, 10),
1288
- {},
1289
- null
1290
- )
1371
+
1291
1372
 
1292
1373
  this._wsConnection.on('message', (message) => {
1293
1374
  const params = JSON.parse(message)
@@ -1303,6 +1384,12 @@ class WebDriver {
1303
1384
  callback(event)
1304
1385
  }
1305
1386
  })
1387
+ await connection.execute(
1388
+ 'Runtime.enable',
1389
+ this.getRandomNumber(1, 10),
1390
+ {},
1391
+ null
1392
+ )
1306
1393
  }
1307
1394
 
1308
1395
  /**
@@ -1374,7 +1461,10 @@ class WebDriver {
1374
1461
  .toString()
1375
1462
  } catch {
1376
1463
  mutationListener = fs
1377
- .readFileSync(path.resolve(__dirname, './atoms/mutation-listener.js'), 'utf-8')
1464
+ .readFileSync(
1465
+ path.resolve(__dirname, './atoms/mutation-listener.js'),
1466
+ 'utf-8'
1467
+ )
1378
1468
  .toString()
1379
1469
  }
1380
1470
 
@@ -2692,18 +2782,12 @@ class WebElement {
2692
2782
  * Take a screenshot of the visible region encompassed by this element's
2693
2783
  * bounding rectangle.
2694
2784
  *
2695
- * @param {boolean=} scroll Optional argument that indicates whether the
2696
- * element should be scrolled into view before taking a screenshot.
2697
- * Defaults to false.
2698
2785
  * @return {!Promise<string>} A promise that will be
2699
2786
  * resolved to the screenshot as a base-64 encoded PNG.
2700
2787
  */
2701
- takeScreenshot(scroll = false) {
2788
+ takeScreenshot() {
2702
2789
  return this.execute_(
2703
- new command.Command(command.Name.TAKE_ELEMENT_SCREENSHOT).setParameter(
2704
- 'scroll',
2705
- scroll
2706
- )
2790
+ new command.Command(command.Name.TAKE_ELEMENT_SCREENSHOT)
2707
2791
  )
2708
2792
  }
2709
2793
  }