selenium-webdriver 4.16.0 → 4.18.0

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 (65) hide show
  1. package/CHANGES.md +253 -196
  2. package/LICENSE +1 -1
  3. package/NOTICE +1 -1
  4. package/bidi/addInterceptParameters.js +86 -0
  5. package/bidi/browsingContext.js +167 -38
  6. package/bidi/browsingContextInspector.js +13 -40
  7. package/bidi/evaluateResult.js +4 -10
  8. package/bidi/filterBy.js +2 -6
  9. package/bidi/index.js +31 -29
  10. package/bidi/input.js +97 -0
  11. package/bidi/interceptPhase.js +24 -0
  12. package/bidi/logInspector.js +15 -20
  13. package/bidi/network.js +178 -0
  14. package/bidi/networkInspector.js +12 -2
  15. package/bidi/networkTypes.js +22 -49
  16. package/bidi/protocolType.js +4 -9
  17. package/bidi/protocolValue.js +48 -17
  18. package/bidi/realmInfo.js +3 -10
  19. package/bidi/scriptManager.js +60 -48
  20. package/bidi/scriptTypes.js +58 -0
  21. package/bidi/urlPattern.js +58 -0
  22. package/bin/linux/selenium-manager +0 -0
  23. package/bin/macos/selenium-manager +0 -0
  24. package/bin/windows/selenium-manager.exe +0 -0
  25. package/chrome.js +2 -14
  26. package/chromium.js +28 -143
  27. package/common/driverFinder.js +1 -1
  28. package/common/seleniumManager.js +5 -12
  29. package/devtools/CDPConnection.js +1 -3
  30. package/edge.js +1 -3
  31. package/example/chrome_android.js +2 -5
  32. package/example/chrome_mobile_emulation.js +2 -4
  33. package/example/google_search.js +1 -3
  34. package/example/headless.js +4 -10
  35. package/example/logging.js +3 -9
  36. package/firefox.js +37 -111
  37. package/http/index.js +7 -10
  38. package/ie.js +5 -15
  39. package/index.js +10 -32
  40. package/io/exec.js +1 -2
  41. package/io/index.js +3 -3
  42. package/io/zip.js +8 -30
  43. package/lib/atoms/find-elements.js +1 -1
  44. package/lib/atoms/get-attribute.js +6 -100
  45. package/lib/by.js +2 -9
  46. package/lib/capabilities.js +8 -7
  47. package/lib/command.js +4 -0
  48. package/lib/error.js +2 -9
  49. package/lib/http.js +37 -130
  50. package/lib/input.js +22 -34
  51. package/lib/logging.js +3 -11
  52. package/lib/promise.js +2 -7
  53. package/lib/select.js +3 -9
  54. package/lib/until.js +28 -49
  55. package/lib/util.js +1 -4
  56. package/lib/virtual_authenticator.js +4 -22
  57. package/lib/webdriver.js +146 -269
  58. package/lib/webelement.js +1 -5
  59. package/net/index.js +1 -4
  60. package/package.json +2 -1
  61. package/remote/index.js +9 -24
  62. package/remote/util.js +6 -19
  63. package/safari.js +3 -8
  64. package/testing/index.js +6 -11
  65. package/example/firefox_channels.js +0 -84
@@ -15,17 +15,13 @@
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
17
 
18
- const {
19
- PrimitiveType,
20
- NonPrimitiveType,
21
- RemoteType,
22
- } = require('./protocolType')
18
+ const { PrimitiveType, NonPrimitiveType, RemoteType } = require('./protocolType')
23
19
 
24
20
  const TYPE_CONSTANT = 'type'
25
21
  const VALUE_CONSTANT = 'value'
26
22
  const RemoteReferenceType = {
27
23
  HANDLE: 'handle',
28
- SHARED_ID: 'shareId',
24
+ SHARED_ID: 'sharedId',
29
25
  }
30
26
 
31
27
  class LocalValue {
@@ -98,16 +94,15 @@ class LocalValue {
98
94
  return new LocalValue(NonPrimitiveType.SET, value)
99
95
  }
100
96
 
97
+ static createChannelValue(value) {
98
+ return new LocalValue(NonPrimitiveType.CHANNEL, value)
99
+ }
100
+
101
101
  toJson() {
102
102
  let toReturn = {}
103
103
  toReturn[TYPE_CONSTANT] = this.type
104
104
 
105
- if (
106
- !(
107
- this.type === PrimitiveType.NULL ||
108
- this.type === PrimitiveType.UNDEFINED
109
- )
110
- ) {
105
+ if (!(this.type === PrimitiveType.NULL || this.type === PrimitiveType.UNDEFINED)) {
111
106
  toReturn[VALUE_CONSTANT] = this.value
112
107
  }
113
108
  return toReturn
@@ -165,12 +160,12 @@ class RemoteValue {
165
160
  }
166
161
 
167
162
  class ReferenceValue {
168
- constructor(handle, shareId) {
163
+ constructor(handle, sharedId) {
169
164
  if (handle === RemoteReferenceType.HANDLE) {
170
- this.handle = shareId
165
+ this.handle = sharedId
171
166
  } else {
172
167
  this.handle = handle
173
- this.shareId = shareId
168
+ this.sharedId = sharedId
174
169
  }
175
170
  }
176
171
 
@@ -180,8 +175,8 @@ class ReferenceValue {
180
175
  toReturn[RemoteReferenceType.HANDLE] = this.handle
181
176
  }
182
177
 
183
- if (this.shareId != null) {
184
- toReturn[RemoteReferenceType.SHARED_ID] = this.shareId
178
+ if (this.sharedId != null) {
179
+ toReturn[RemoteReferenceType.SHARED_ID] = this.sharedId
185
180
  }
186
181
 
187
182
  return toReturn
@@ -195,10 +190,46 @@ class RegExpValue {
195
190
  }
196
191
  }
197
192
 
193
+ class SerializationOptions {
194
+ constructor(maxDomDepth = 0, maxObjectDepth = null, includeShadowTree = 'none') {
195
+ this._maxDomDepth = maxDomDepth
196
+ this._maxObjectDepth = maxObjectDepth
197
+
198
+ if (['none', 'open', 'all'].includes(includeShadowTree)) {
199
+ throw Error(`Valid types are 'none', 'open', and 'all'. Received: ${includeShadowTree}`)
200
+ }
201
+ this._includeShadowTree = includeShadowTree
202
+ }
203
+ }
204
+
205
+ class ChannelValue {
206
+ constructor(channel, options = undefined, resultOwnership = undefined) {
207
+ this.channel = channel
208
+
209
+ if (options !== undefined) {
210
+ if (options instanceof SerializationOptions) {
211
+ this.options = options
212
+ } else {
213
+ throw Error(`Pass in SerializationOptions object. Received: ${options} `)
214
+ }
215
+ }
216
+
217
+ if (resultOwnership != undefined) {
218
+ if (['root', 'none'].includes(resultOwnership)) {
219
+ this.resultOwnership = resultOwnership
220
+ } else {
221
+ throw Error(`Valid types are 'root' and 'none. Received: ${resultOwnership}`)
222
+ }
223
+ }
224
+ }
225
+ }
226
+
198
227
  module.exports = {
228
+ ChannelValue,
199
229
  LocalValue,
200
230
  RemoteValue,
201
231
  ReferenceValue,
202
232
  RemoteReferenceType,
203
233
  RegExpValue,
234
+ SerializationOptions,
204
235
  }
package/bidi/realmInfo.js CHANGED
@@ -28,9 +28,7 @@ const RealmType = {
28
28
  findByName(name) {
29
29
  return (
30
30
  Object.values(this).find((type) => {
31
- return (
32
- typeof type === 'string' && name.toLowerCase() === type.toLowerCase()
33
- )
31
+ return typeof type === 'string' && name.toLowerCase() === type.toLowerCase()
34
32
  }) || null
35
33
  )
36
34
  },
@@ -72,13 +70,7 @@ class RealmInfo {
72
70
  }
73
71
 
74
72
  if (realmType === RealmType.WINDOW) {
75
- return new WindowRealmInfo(
76
- realmId,
77
- origin,
78
- realmType,
79
- browsingContext,
80
- sandbox
81
- )
73
+ return new WindowRealmInfo(realmId, origin, realmType, browsingContext, sandbox)
82
74
  }
83
75
 
84
76
  return new RealmInfo(realmId, origin, realmType)
@@ -96,4 +88,5 @@ class WindowRealmInfo extends RealmInfo {
96
88
  module.exports = {
97
89
  RealmInfo,
98
90
  RealmType,
91
+ WindowRealmInfo,
99
92
  }
@@ -21,8 +21,10 @@ const {
21
21
  EvaluateResultException,
22
22
  ExceptionDetails,
23
23
  } = require('./evaluateResult')
24
- const { RealmInfo } = require('./realmInfo')
24
+ const { Message } = require('./scriptTypes')
25
+ const { RealmInfo, RealmType, WindowRealmInfo } = require('./realmInfo')
25
26
  const { RemoteValue } = require('./protocolValue')
27
+ const { Source } = require('./scriptTypes')
26
28
  const { WebDriverError } = require('../lib/error')
27
29
 
28
30
  class ScriptManager {
@@ -53,11 +55,7 @@ class ScriptManager {
53
55
  await this.bidi.send(params)
54
56
  }
55
57
 
56
- async disownBrowsingContextScript(
57
- browsingContextId,
58
- handles,
59
- sandbox = null
60
- ) {
58
+ async disownBrowsingContextScript(browsingContextId, handles, sandbox = null) {
61
59
  const params = {
62
60
  method: 'script.disown',
63
61
  params: {
@@ -81,7 +79,7 @@ class ScriptManager {
81
79
  awaitPromise,
82
80
  argumentValueList = null,
83
81
  thisParameter = null,
84
- resultOwnership = null
82
+ resultOwnership = null,
85
83
  ) {
86
84
  const params = this.getCallFunctionParams(
87
85
  'realm',
@@ -91,7 +89,7 @@ class ScriptManager {
91
89
  awaitPromise,
92
90
  argumentValueList,
93
91
  thisParameter,
94
- resultOwnership
92
+ resultOwnership,
95
93
  )
96
94
 
97
95
  const command = {
@@ -110,7 +108,7 @@ class ScriptManager {
110
108
  argumentValueList = null,
111
109
  thisParameter = null,
112
110
  resultOwnership = null,
113
- sandbox = null
111
+ sandbox = null,
114
112
  ) {
115
113
  const params = this.getCallFunctionParams(
116
114
  'contextTarget',
@@ -120,7 +118,7 @@ class ScriptManager {
120
118
  awaitPromise,
121
119
  argumentValueList,
122
120
  thisParameter,
123
- resultOwnership
121
+ resultOwnership,
124
122
  )
125
123
 
126
124
  const command = {
@@ -131,20 +129,8 @@ class ScriptManager {
131
129
  return this.createEvaluateResult(response)
132
130
  }
133
131
 
134
- async evaluateFunctionInRealm(
135
- realmId,
136
- expression,
137
- awaitPromise,
138
- resultOwnership = null
139
- ) {
140
- const params = this.getEvaluateParams(
141
- 'realm',
142
- realmId,
143
- null,
144
- expression,
145
- awaitPromise,
146
- resultOwnership
147
- )
132
+ async evaluateFunctionInRealm(realmId, expression, awaitPromise, resultOwnership = null) {
133
+ const params = this.getEvaluateParams('realm', realmId, null, expression, awaitPromise, resultOwnership)
148
134
 
149
135
  const command = {
150
136
  method: 'script.evaluate',
@@ -160,7 +146,7 @@ class ScriptManager {
160
146
  expression,
161
147
  awaitPromise,
162
148
  resultOwnership = null,
163
- sandbox = null
149
+ sandbox = null,
164
150
  ) {
165
151
  const params = this.getEvaluateParams(
166
152
  'contextTarget',
@@ -168,7 +154,7 @@ class ScriptManager {
168
154
  sandbox,
169
155
  expression,
170
156
  awaitPromise,
171
- resultOwnership
157
+ resultOwnership,
172
158
  )
173
159
 
174
160
  const command = {
@@ -180,11 +166,7 @@ class ScriptManager {
180
166
  return this.createEvaluateResult(response)
181
167
  }
182
168
 
183
- async addPreloadScript(
184
- functionDeclaration,
185
- argumentValueList = [],
186
- sandbox = null
187
- ) {
169
+ async addPreloadScript(functionDeclaration, argumentValueList = [], sandbox = null) {
188
170
  const params = {
189
171
  functionDeclaration: functionDeclaration,
190
172
  arguments: argumentValueList,
@@ -221,7 +203,7 @@ class ScriptManager {
221
203
  awaitPromise,
222
204
  argumentValueList = null,
223
205
  thisParameter = null,
224
- resultOwnership = null
206
+ resultOwnership = null,
225
207
  ) {
226
208
  const params = {
227
209
  functionDeclaration: functionDeclaration,
@@ -256,14 +238,7 @@ class ScriptManager {
256
238
  return params
257
239
  }
258
240
 
259
- getEvaluateParams(
260
- targetType,
261
- id,
262
- sandbox,
263
- expression,
264
- awaitPromise,
265
- resultOwnership = null
266
- ) {
241
+ getEvaluateParams(targetType, id, sandbox, expression, awaitPromise, resultOwnership = null) {
267
242
  const params = {
268
243
  expression: expression,
269
244
  awaitPromise: awaitPromise,
@@ -291,16 +266,10 @@ class ScriptManager {
291
266
 
292
267
  if (type === EvaluateResultType.SUCCESS) {
293
268
  const result = response.result.result
294
- evaluateResult = new EvaluateResultSuccess(
295
- realmId,
296
- new RemoteValue(result)
297
- )
269
+ evaluateResult = new EvaluateResultSuccess(realmId, new RemoteValue(result))
298
270
  } else {
299
271
  const exceptionDetails = response.result.exceptionDetails
300
- evaluateResult = new EvaluateResultException(
301
- realmId,
302
- new ExceptionDetails(exceptionDetails)
303
- )
272
+ evaluateResult = new EvaluateResultException(realmId, new ExceptionDetails(exceptionDetails))
304
273
  }
305
274
  return evaluateResult
306
275
  }
@@ -348,6 +317,49 @@ class ScriptManager {
348
317
  let response = await this.bidi.send(command)
349
318
  return this.realmInfoMapper(response.result.realms)
350
319
  }
320
+
321
+ async onMessage(callback) {
322
+ await this.subscribeAndHandleEvent('script.message', callback)
323
+ }
324
+
325
+ async onRealmCreated(callback) {
326
+ await this.subscribeAndHandleEvent('script.realmCreated', callback)
327
+ }
328
+
329
+ async onRealmDestroyed(callback) {
330
+ await this.subscribeAndHandleEvent('script.realmDestroyed', callback)
331
+ }
332
+
333
+ async subscribeAndHandleEvent(eventType, callback) {
334
+ if (this._browsingContextIds != null) {
335
+ await this.bidi.subscribe(eventType, this._browsingContextIds)
336
+ } else {
337
+ await this.bidi.subscribe(eventType)
338
+ }
339
+ await this._on(callback)
340
+ }
341
+
342
+ async _on(callback) {
343
+ this.ws = await this.bidi.socket
344
+ this.ws.on('message', (event) => {
345
+ const { params } = JSON.parse(Buffer.from(event.toString()))
346
+ if (params) {
347
+ let response = null
348
+ if ('channel' in params) {
349
+ response = new Message(params.channel, new RemoteValue(params.data), new Source(params.source))
350
+ } else if ('realm' in params) {
351
+ if (params.type === RealmType.WINDOW) {
352
+ response = new WindowRealmInfo(params.realm, params.origin, params.type, params.context, params.sandbox)
353
+ } else if (params.realm !== null && params.type !== null) {
354
+ response = new RealmInfo(params.realm, params.origin, params.type)
355
+ } else if (params.realm !== null) {
356
+ response = params.realm
357
+ }
358
+ }
359
+ callback(response)
360
+ }
361
+ })
362
+ }
351
363
  }
352
364
 
353
365
  async function getScriptManagerInstance(browsingContextId, driver) {
@@ -0,0 +1,58 @@
1
+ // Licensed to the Software Freedom Conservancy (SFC) under one
2
+ // or more contributor license agreements. See the NOTICE file
3
+ // distributed with this work for additional information
4
+ // regarding copyright ownership. The SFC licenses this file
5
+ // to you under the Apache License, Version 2.0 (the
6
+ // "License"); you may not use this file except in compliance
7
+ // with the License. You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing,
12
+ // software distributed under the License is distributed on an
13
+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ // KIND, either express or implied. See the License for the
15
+ // specific language governing permissions and limitations
16
+ // under the License.
17
+
18
+ class Message {
19
+ constructor(channel, data, source) {
20
+ this._channel = channel
21
+ this._data = data
22
+ this._source = source
23
+ }
24
+
25
+ get channel() {
26
+ return this._channel
27
+ }
28
+
29
+ get data() {
30
+ return this._data
31
+ }
32
+
33
+ get source() {
34
+ return this._source
35
+ }
36
+ }
37
+
38
+ class Source {
39
+ constructor(source) {
40
+ this._browsingContextId = null
41
+ this._realmId = source.realm
42
+
43
+ // Browsing context is returned as an optional parameter
44
+ if ('context' in source) {
45
+ this._browsingContextId = source.context
46
+ }
47
+ }
48
+
49
+ get browsingContextId() {
50
+ return this._browsingContextId
51
+ }
52
+
53
+ get realmId() {
54
+ return this._realmId
55
+ }
56
+ }
57
+
58
+ module.exports = { Message, Source }
@@ -0,0 +1,58 @@
1
+ // Licensed to the Software Freedom Conservancy (SFC) under one
2
+ // or more contributor license agreements. See the NOTICE file
3
+ // distributed with this work for additional information
4
+ // regarding copyright ownership. The SFC licenses this file
5
+ // to you under the Apache License, Version 2.0 (the
6
+ // "License"); you may not use this file except in compliance
7
+ // with the License. You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing,
12
+ // software distributed under the License is distributed on an
13
+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ // KIND, either express or implied. See the License for the
15
+ // specific language governing permissions and limitations
16
+ // under the License.
17
+
18
+ const {LocalValue} = require('./protocolValue')
19
+
20
+ class UrlPattern {
21
+ #map = new Map()
22
+
23
+ protocol(protocol) {
24
+ this.#map.set('protocol', protocol)
25
+ return this
26
+ }
27
+
28
+ hostname(hostname) {
29
+ this.#map.set('hostname', hostname)
30
+ return this
31
+ }
32
+
33
+ port(port) {
34
+ if (typeof port === 'number') {
35
+ this.#map.set('port', port.toString())
36
+ } else {
37
+ throw new Error(`Port must be a number. Received:'${port}'`)
38
+ }
39
+ return this
40
+ }
41
+
42
+ pathname(pathname) {
43
+ this.#map.set('pathname', pathname)
44
+ return this
45
+ }
46
+
47
+ search(search) {
48
+ this.#map.set('search', search)
49
+ return this
50
+ }
51
+
52
+ asMap() {
53
+ this.#map.set('type', 'pattern')
54
+ return this.#map
55
+ }
56
+ }
57
+
58
+ module.exports = {UrlPattern}
Binary file
Binary file
Binary file
package/chrome.js CHANGED
@@ -36,17 +36,12 @@
36
36
  * a unique browser session with a clean user profile (unless otherwise
37
37
  * configured through the {@link Options} class).
38
38
  *
39
- * __Headless Chrome__ <a id="headless"></a>
40
- *
41
- * To start Chrome in headless mode, simply call
42
- * {@linkplain Options#headless Options.headless()}.
43
- *
44
39
  * let chrome = require('selenium-webdriver/chrome');
45
40
  * let {Builder} = require('selenium-webdriver');
46
41
  *
47
42
  * let driver = new Builder()
48
43
  * .forBrowser('chrome')
49
- * .setChromeOptions(new chrome.Options().headless())
44
+ * .setChromeOptions(new chrome.Options())
50
45
  * .build();
51
46
  *
52
47
  * __Customizing the ChromeDriver Server__ <a id="custom-server"></a>
@@ -219,14 +214,7 @@ class Driver extends chromium.Driver {
219
214
  */
220
215
  static createSession(opt_config, opt_serviceExecutor) {
221
216
  let caps = opt_config || new Options()
222
- return /** @type {!Driver} */ (
223
- super.createSession(
224
- caps,
225
- opt_serviceExecutor,
226
- 'goog',
227
- CHROME_CAPABILITY_KEY
228
- )
229
- )
217
+ return /** @type {!Driver} */ (super.createSession(caps, opt_serviceExecutor, 'goog', CHROME_CAPABILITY_KEY))
230
218
  }
231
219
 
232
220
  /**