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.
- package/CHANGES.md +253 -196
- package/LICENSE +1 -1
- package/NOTICE +1 -1
- package/bidi/addInterceptParameters.js +86 -0
- package/bidi/browsingContext.js +167 -38
- package/bidi/browsingContextInspector.js +13 -40
- package/bidi/evaluateResult.js +4 -10
- package/bidi/filterBy.js +2 -6
- package/bidi/index.js +31 -29
- package/bidi/input.js +97 -0
- package/bidi/interceptPhase.js +24 -0
- package/bidi/logInspector.js +15 -20
- package/bidi/network.js +178 -0
- package/bidi/networkInspector.js +12 -2
- package/bidi/networkTypes.js +22 -49
- package/bidi/protocolType.js +4 -9
- package/bidi/protocolValue.js +48 -17
- package/bidi/realmInfo.js +3 -10
- package/bidi/scriptManager.js +60 -48
- package/bidi/scriptTypes.js +58 -0
- package/bidi/urlPattern.js +58 -0
- package/bin/linux/selenium-manager +0 -0
- package/bin/macos/selenium-manager +0 -0
- package/bin/windows/selenium-manager.exe +0 -0
- package/chrome.js +2 -14
- package/chromium.js +28 -143
- package/common/driverFinder.js +1 -1
- package/common/seleniumManager.js +5 -12
- package/devtools/CDPConnection.js +1 -3
- package/edge.js +1 -3
- package/example/chrome_android.js +2 -5
- package/example/chrome_mobile_emulation.js +2 -4
- package/example/google_search.js +1 -3
- package/example/headless.js +4 -10
- package/example/logging.js +3 -9
- package/firefox.js +37 -111
- package/http/index.js +7 -10
- package/ie.js +5 -15
- package/index.js +10 -32
- package/io/exec.js +1 -2
- package/io/index.js +3 -3
- package/io/zip.js +8 -30
- package/lib/atoms/find-elements.js +1 -1
- package/lib/atoms/get-attribute.js +6 -100
- package/lib/by.js +2 -9
- package/lib/capabilities.js +8 -7
- package/lib/command.js +4 -0
- package/lib/error.js +2 -9
- package/lib/http.js +37 -130
- package/lib/input.js +22 -34
- package/lib/logging.js +3 -11
- package/lib/promise.js +2 -7
- package/lib/select.js +3 -9
- package/lib/until.js +28 -49
- package/lib/util.js +1 -4
- package/lib/virtual_authenticator.js +4 -22
- package/lib/webdriver.js +146 -269
- package/lib/webelement.js +1 -5
- package/net/index.js +1 -4
- package/package.json +2 -1
- package/remote/index.js +9 -24
- package/remote/util.js +6 -19
- package/safari.js +3 -8
- package/testing/index.js +6 -11
- package/example/firefox_channels.js +0 -84
package/lib/input.js
CHANGED
|
@@ -256,9 +256,7 @@ function checkCodePoint(key) {
|
|
|
256
256
|
|
|
257
257
|
key = key.normalize()
|
|
258
258
|
if (Array.from(key).length !== 1) {
|
|
259
|
-
throw new InvalidArgumentError(
|
|
260
|
-
`key input is not a single code point: ${key}`
|
|
261
|
-
)
|
|
259
|
+
throw new InvalidArgumentError(`key input is not a single code point: ${key}`)
|
|
262
260
|
}
|
|
263
261
|
return key
|
|
264
262
|
}
|
|
@@ -333,10 +331,7 @@ class Pointer extends Device {
|
|
|
333
331
|
|
|
334
332
|
/** @override */
|
|
335
333
|
toJSON() {
|
|
336
|
-
return Object.assign(
|
|
337
|
-
{ parameters: { pointerType: this.pointerType_ } },
|
|
338
|
-
super.toJSON()
|
|
339
|
-
)
|
|
334
|
+
return Object.assign({ parameters: { pointerType: this.pointerType_ } }, super.toJSON())
|
|
340
335
|
}
|
|
341
336
|
|
|
342
337
|
/**
|
|
@@ -371,7 +366,7 @@ class Pointer extends Device {
|
|
|
371
366
|
tiltY = 0,
|
|
372
367
|
twist = 0,
|
|
373
368
|
altitudeAngle = 0,
|
|
374
|
-
azimuthAngle = 0
|
|
369
|
+
azimuthAngle = 0,
|
|
375
370
|
) {
|
|
376
371
|
return {
|
|
377
372
|
type: Action.Type.POINTER_DOWN,
|
|
@@ -814,10 +809,7 @@ class Actions {
|
|
|
814
809
|
for (const key of keys) {
|
|
815
810
|
if (typeof key === 'string') {
|
|
816
811
|
for (const symbol of key) {
|
|
817
|
-
actions.push(
|
|
818
|
-
this.keyboard_.keyDown(symbol),
|
|
819
|
-
this.keyboard_.keyUp(symbol)
|
|
820
|
-
)
|
|
812
|
+
actions.push(this.keyboard_.keyDown(symbol), this.keyboard_.keyUp(symbol))
|
|
821
813
|
}
|
|
822
814
|
} else {
|
|
823
815
|
actions.push(this.keyboard_.keyDown(key), this.keyboard_.keyUp(key))
|
|
@@ -857,10 +849,7 @@ class Actions {
|
|
|
857
849
|
* @returns {!Actions} An action to scroll with this device.
|
|
858
850
|
*/
|
|
859
851
|
scroll(x, y, targetDeltaX, targetDeltaY, origin, duration) {
|
|
860
|
-
return this.insert(
|
|
861
|
-
this.wheel_,
|
|
862
|
-
this.wheel_.scroll(x, y, targetDeltaX, targetDeltaY, origin, duration)
|
|
863
|
-
)
|
|
852
|
+
return this.insert(this.wheel_, this.wheel_.scroll(x, y, targetDeltaX, targetDeltaY, origin, duration))
|
|
864
853
|
}
|
|
865
854
|
|
|
866
855
|
/**
|
|
@@ -885,10 +874,7 @@ class Actions {
|
|
|
885
874
|
* @return {!Actions} a self reference.
|
|
886
875
|
*/
|
|
887
876
|
move({ x = 0, y = 0, duration = 100, origin = Origin.VIEWPORT } = {}) {
|
|
888
|
-
return this.insert(
|
|
889
|
-
this.mouse_,
|
|
890
|
-
this.mouse_.move({ x, y, duration, origin })
|
|
891
|
-
)
|
|
877
|
+
return this.insert(this.mouse_, this.mouse_.move({ x, y, duration, origin }))
|
|
892
878
|
}
|
|
893
879
|
|
|
894
880
|
/**
|
|
@@ -953,13 +939,8 @@ class Actions {
|
|
|
953
939
|
dragAndDrop(from, to) {
|
|
954
940
|
// Do not require up top to avoid a cycle that breaks static analysis.
|
|
955
941
|
const { WebElement } = require('./webdriver')
|
|
956
|
-
if (
|
|
957
|
-
|
|
958
|
-
(!to || typeof to.x !== 'number' || typeof to.y !== 'number')
|
|
959
|
-
) {
|
|
960
|
-
throw new InvalidArgumentError(
|
|
961
|
-
'Invalid drag target; must specify a WebElement or {x, y} offset'
|
|
962
|
-
)
|
|
942
|
+
if (!(to instanceof WebElement) && (!to || typeof to.x !== 'number' || typeof to.y !== 'number')) {
|
|
943
|
+
throw new InvalidArgumentError('Invalid drag target; must specify a WebElement or {x, y} offset')
|
|
963
944
|
}
|
|
964
945
|
|
|
965
946
|
this.move({ origin: from }).press()
|
|
@@ -1003,9 +984,19 @@ class Actions {
|
|
|
1003
984
|
return Promise.resolve()
|
|
1004
985
|
}
|
|
1005
986
|
|
|
1006
|
-
await this.executor_.execute(
|
|
1007
|
-
|
|
1008
|
-
|
|
987
|
+
await this.executor_.execute(new Command(Name.ACTIONS).setParameter('actions', _actions))
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
getSequences() {
|
|
991
|
+
const _actions = []
|
|
992
|
+
this.sequences_.forEach((actions, device) => {
|
|
993
|
+
if (!isIdle(actions)) {
|
|
994
|
+
actions = actions.concat()
|
|
995
|
+
_actions.push(Object.assign({ actions }, device.toJSON()))
|
|
996
|
+
}
|
|
997
|
+
})
|
|
998
|
+
|
|
999
|
+
return _actions
|
|
1009
1000
|
}
|
|
1010
1001
|
}
|
|
1011
1002
|
|
|
@@ -1014,10 +1005,7 @@ class Actions {
|
|
|
1014
1005
|
* @return {boolean}
|
|
1015
1006
|
*/
|
|
1016
1007
|
function isIdle(actions) {
|
|
1017
|
-
return (
|
|
1018
|
-
actions.length === 0 ||
|
|
1019
|
-
actions.every((a) => a.type === Action.Type.PAUSE && !a.duration)
|
|
1020
|
-
)
|
|
1008
|
+
return actions.length === 0 || actions.every((a) => a.type === Action.Type.PAUSE && !a.duration)
|
|
1021
1009
|
}
|
|
1022
1010
|
|
|
1023
1011
|
/**
|
package/lib/logging.js
CHANGED
|
@@ -220,8 +220,7 @@ class Entry {
|
|
|
220
220
|
constructor(level, message, opt_timestamp, opt_type) {
|
|
221
221
|
this.level = level instanceof Level ? level : getLevel(level)
|
|
222
222
|
this.message = message
|
|
223
|
-
this.timestamp =
|
|
224
|
-
typeof opt_timestamp === 'number' ? opt_timestamp : Date.now()
|
|
223
|
+
this.timestamp = typeof opt_timestamp === 'number' ? opt_timestamp : Date.now()
|
|
225
224
|
this.type = opt_type || ''
|
|
226
225
|
}
|
|
227
226
|
|
|
@@ -311,10 +310,7 @@ class Logger {
|
|
|
311
310
|
* by this instance.
|
|
312
311
|
*/
|
|
313
312
|
isLoggable(level) {
|
|
314
|
-
return (
|
|
315
|
-
level.value !== Level.OFF.value &&
|
|
316
|
-
level.value >= this.getEffectiveLevel().value
|
|
317
|
-
)
|
|
313
|
+
return level.value !== Level.OFF.value && level.value >= this.getEffectiveLevel().value
|
|
318
314
|
}
|
|
319
315
|
|
|
320
316
|
/**
|
|
@@ -358,11 +354,7 @@ class Logger {
|
|
|
358
354
|
if (!this.isLoggable(level)) {
|
|
359
355
|
return
|
|
360
356
|
}
|
|
361
|
-
let message =
|
|
362
|
-
'[' +
|
|
363
|
-
this.name_ +
|
|
364
|
-
'] ' +
|
|
365
|
-
(typeof loggable === 'function' ? loggable() : loggable)
|
|
357
|
+
let message = '[' + this.name_ + '] ' + (typeof loggable === 'function' ? loggable() : loggable)
|
|
366
358
|
let entry = new Entry(level, message, Date.now())
|
|
367
359
|
for (let logger = this; logger; logger = logger.parent_) {
|
|
368
360
|
if (logger.handlers_) {
|
package/lib/promise.js
CHANGED
|
@@ -173,9 +173,7 @@ async function filter(array, fn, self = undefined) {
|
|
|
173
173
|
const values = []
|
|
174
174
|
|
|
175
175
|
for (const [index, item] of arr.entries()) {
|
|
176
|
-
const isConditionTrue = await Promise.resolve(
|
|
177
|
-
fn.call(self, item, index, arr)
|
|
178
|
-
)
|
|
176
|
+
const isConditionTrue = await Promise.resolve(fn.call(self, item, index, arr))
|
|
179
177
|
if (isConditionTrue) {
|
|
180
178
|
values.push(item)
|
|
181
179
|
}
|
|
@@ -247,10 +245,7 @@ async function fullyResolveKeys(obj) {
|
|
|
247
245
|
|
|
248
246
|
const forEachKey = isArray ? forEachElement : forEachProperty
|
|
249
247
|
await forEachKey(obj, async function (partialValue, key) {
|
|
250
|
-
if (
|
|
251
|
-
!Array.isArray(partialValue) &&
|
|
252
|
-
(!partialValue || typeof partialValue !== 'object')
|
|
253
|
-
) {
|
|
248
|
+
if (!Array.isArray(partialValue) && (!partialValue || typeof partialValue !== 'object')) {
|
|
254
249
|
return
|
|
255
250
|
}
|
|
256
251
|
obj[key] = await fullyResolved(partialValue)
|
package/lib/select.js
CHANGED
|
@@ -184,9 +184,7 @@ class Select {
|
|
|
184
184
|
|
|
185
185
|
if (options.length - 1 < index) {
|
|
186
186
|
throw new Error(
|
|
187
|
-
`Option with index "${index}" not found. Select element only contains ${
|
|
188
|
-
options.length - 1
|
|
189
|
-
} option elements`
|
|
187
|
+
`Option with index "${index}" not found. Select element only contains ${options.length - 1} option elements`,
|
|
190
188
|
)
|
|
191
189
|
}
|
|
192
190
|
|
|
@@ -408,9 +406,7 @@ class Select {
|
|
|
408
406
|
|
|
409
407
|
if (options.length - 1 < index) {
|
|
410
408
|
throw new Error(
|
|
411
|
-
`Option with index "${index}" not found. Select element only contains ${
|
|
412
|
-
options.length - 1
|
|
413
|
-
} option elements`
|
|
409
|
+
`Option with index "${index}" not found. Select element only contains ${options.length - 1} option elements`,
|
|
414
410
|
)
|
|
415
411
|
}
|
|
416
412
|
|
|
@@ -454,9 +450,7 @@ class Select {
|
|
|
454
450
|
async setSelected(option) {
|
|
455
451
|
if (!(await option.isSelected())) {
|
|
456
452
|
if (!(await option.isEnabled())) {
|
|
457
|
-
throw new error.UnsupportedOperationError(
|
|
458
|
-
`You may not select a disabled option`
|
|
459
|
-
)
|
|
453
|
+
throw new error.UnsupportedOperationError(`You may not select a disabled option`)
|
|
460
454
|
}
|
|
461
455
|
await option.click()
|
|
462
456
|
}
|
package/lib/until.js
CHANGED
|
@@ -96,7 +96,7 @@ function ableToSwitchToFrame(frame) {
|
|
|
96
96
|
if (!(e instanceof error.NoSuchFrameError)) {
|
|
97
97
|
throw e
|
|
98
98
|
}
|
|
99
|
-
}
|
|
99
|
+
},
|
|
100
100
|
)
|
|
101
101
|
}
|
|
102
102
|
}
|
|
@@ -119,8 +119,7 @@ function alertIsPresent() {
|
|
|
119
119
|
// XXX: Workaround for GeckoDriver error `TypeError: can't convert null
|
|
120
120
|
// to object`. For more details, see
|
|
121
121
|
// https://github.com/SeleniumHQ/selenium/pull/2137
|
|
122
|
-
(e instanceof error.WebDriverError &&
|
|
123
|
-
e.message === `can't convert null to object`)
|
|
122
|
+
(e instanceof error.WebDriverError && e.message === `can't convert null to object`)
|
|
124
123
|
)
|
|
125
124
|
) {
|
|
126
125
|
throw e
|
|
@@ -137,9 +136,7 @@ function alertIsPresent() {
|
|
|
137
136
|
* @return {!Condition<boolean>} The new condition.
|
|
138
137
|
*/
|
|
139
138
|
function titleIs(title) {
|
|
140
|
-
return new Condition('for title to be ' + JSON.stringify(title), function (
|
|
141
|
-
driver
|
|
142
|
-
) {
|
|
139
|
+
return new Condition('for title to be ' + JSON.stringify(title), function (driver) {
|
|
143
140
|
return driver.getTitle().then(function (t) {
|
|
144
141
|
return t === title
|
|
145
142
|
})
|
|
@@ -155,14 +152,11 @@ function titleIs(title) {
|
|
|
155
152
|
* @return {!Condition<boolean>} The new condition.
|
|
156
153
|
*/
|
|
157
154
|
function titleContains(substr) {
|
|
158
|
-
return new Condition(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
})
|
|
164
|
-
}
|
|
165
|
-
)
|
|
155
|
+
return new Condition('for title to contain ' + JSON.stringify(substr), function (driver) {
|
|
156
|
+
return driver.getTitle().then(function (title) {
|
|
157
|
+
return title.indexOf(substr) !== -1
|
|
158
|
+
})
|
|
159
|
+
})
|
|
166
160
|
}
|
|
167
161
|
|
|
168
162
|
/**
|
|
@@ -188,9 +182,7 @@ function titleMatches(regex) {
|
|
|
188
182
|
* @return {!Condition<boolean>} The new condition.
|
|
189
183
|
*/
|
|
190
184
|
function urlIs(url) {
|
|
191
|
-
return new Condition('for URL to be ' + JSON.stringify(url), function (
|
|
192
|
-
driver
|
|
193
|
-
) {
|
|
185
|
+
return new Condition('for URL to be ' + JSON.stringify(url), function (driver) {
|
|
194
186
|
return driver.getCurrentUrl().then(function (u) {
|
|
195
187
|
return u === url
|
|
196
188
|
})
|
|
@@ -206,14 +198,11 @@ function urlIs(url) {
|
|
|
206
198
|
* @return {!Condition<boolean>} The new condition.
|
|
207
199
|
*/
|
|
208
200
|
function urlContains(substrUrl) {
|
|
209
|
-
return new Condition(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
})
|
|
215
|
-
}
|
|
216
|
-
)
|
|
201
|
+
return new Condition('for URL to contain ' + JSON.stringify(substrUrl), function (driver) {
|
|
202
|
+
return driver.getCurrentUrl().then(function (url) {
|
|
203
|
+
return url && url.includes(substrUrl)
|
|
204
|
+
})
|
|
205
|
+
})
|
|
217
206
|
}
|
|
218
207
|
|
|
219
208
|
/**
|
|
@@ -240,16 +229,12 @@ function urlMatches(regex) {
|
|
|
240
229
|
*/
|
|
241
230
|
function elementLocated(locator) {
|
|
242
231
|
locator = by.checkedLocator(locator)
|
|
243
|
-
let locatorStr =
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
return elements[0]
|
|
250
|
-
})
|
|
251
|
-
}
|
|
252
|
-
)
|
|
232
|
+
let locatorStr = typeof locator === 'function' ? 'by function()' : locator + ''
|
|
233
|
+
return new WebElementCondition('for element to be located ' + locatorStr, function (driver) {
|
|
234
|
+
return driver.findElements(locator).then(function (elements) {
|
|
235
|
+
return elements[0]
|
|
236
|
+
})
|
|
237
|
+
})
|
|
253
238
|
}
|
|
254
239
|
|
|
255
240
|
/**
|
|
@@ -262,16 +247,12 @@ function elementLocated(locator) {
|
|
|
262
247
|
*/
|
|
263
248
|
function elementsLocated(locator) {
|
|
264
249
|
locator = by.checkedLocator(locator)
|
|
265
|
-
let locatorStr =
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
return elements.length > 0 ? elements : null
|
|
272
|
-
})
|
|
273
|
-
}
|
|
274
|
-
)
|
|
250
|
+
let locatorStr = typeof locator === 'function' ? 'by function()' : locator + ''
|
|
251
|
+
return new Condition('for at least one element to be located ' + locatorStr, function (driver) {
|
|
252
|
+
return driver.findElements(locator).then(function (elements) {
|
|
253
|
+
return elements.length > 0 ? elements : null
|
|
254
|
+
})
|
|
255
|
+
})
|
|
275
256
|
}
|
|
276
257
|
|
|
277
258
|
/**
|
|
@@ -293,7 +274,7 @@ function stalenessOf(element) {
|
|
|
293
274
|
return true
|
|
294
275
|
}
|
|
295
276
|
throw e
|
|
296
|
-
}
|
|
277
|
+
},
|
|
297
278
|
)
|
|
298
279
|
})
|
|
299
280
|
}
|
|
@@ -404,9 +385,7 @@ function elementTextIs(element, text) {
|
|
|
404
385
|
*/
|
|
405
386
|
function elementTextContains(element, substr) {
|
|
406
387
|
return new WebElementCondition('until element text contains', function () {
|
|
407
|
-
return element
|
|
408
|
-
.getText()
|
|
409
|
-
.then((t) => (t.indexOf(substr) != -1 ? element : null))
|
|
388
|
+
return element.getText().then((t) => (t.indexOf(substr) != -1 ? element : null))
|
|
410
389
|
})
|
|
411
390
|
}
|
|
412
391
|
|
package/lib/util.js
CHANGED
|
@@ -37,10 +37,7 @@ function isPromise(value) {
|
|
|
37
37
|
try {
|
|
38
38
|
// Use array notation so the Closure compiler does not obfuscate away our
|
|
39
39
|
// contract.
|
|
40
|
-
return (
|
|
41
|
-
(typeof value === 'object' || typeof value === 'function') &&
|
|
42
|
-
typeof value['then'] === 'function'
|
|
43
|
-
)
|
|
40
|
+
return (typeof value === 'object' || typeof value === 'function') && typeof value['then'] === 'function'
|
|
44
41
|
} catch (ex) {
|
|
45
42
|
return false
|
|
46
43
|
}
|
|
@@ -119,14 +119,7 @@ class VirtualAuthenticatorOptions {
|
|
|
119
119
|
* @see https://w3c.github.io/webauthn/#credential-parameters
|
|
120
120
|
*/
|
|
121
121
|
class Credential {
|
|
122
|
-
constructor(
|
|
123
|
-
credentialId,
|
|
124
|
-
isResidentCredential,
|
|
125
|
-
rpId,
|
|
126
|
-
userHandle,
|
|
127
|
-
privateKey,
|
|
128
|
-
signCount
|
|
129
|
-
) {
|
|
122
|
+
constructor(credentialId, isResidentCredential, rpId, userHandle, privateKey, signCount) {
|
|
130
123
|
this._id = credentialId
|
|
131
124
|
this._isResidentCredential = isResidentCredential
|
|
132
125
|
this._rpId = rpId
|
|
@@ -207,9 +200,7 @@ class Credential {
|
|
|
207
200
|
}
|
|
208
201
|
|
|
209
202
|
if (this.userHandle() != null) {
|
|
210
|
-
credentialData['userHandle'] = Buffer.from(this._userHandle).toString(
|
|
211
|
-
'base64url'
|
|
212
|
-
)
|
|
203
|
+
credentialData['userHandle'] = Buffer.from(this._userHandle).toString('base64url')
|
|
213
204
|
}
|
|
214
205
|
|
|
215
206
|
return credentialData
|
|
@@ -222,9 +213,7 @@ class Credential {
|
|
|
222
213
|
let id = new Uint8Array(Buffer.from(data['credentialId'], 'base64url'))
|
|
223
214
|
let isResidentCredential = data['isResidentCredential']
|
|
224
215
|
let rpId = data['rpId']
|
|
225
|
-
let privateKey = Buffer.from(data['privateKey'], 'base64url').toString(
|
|
226
|
-
'binary'
|
|
227
|
-
)
|
|
216
|
+
let privateKey = Buffer.from(data['privateKey'], 'base64url').toString('binary')
|
|
228
217
|
let signCount = data['signCount']
|
|
229
218
|
let userHandle
|
|
230
219
|
|
|
@@ -233,14 +222,7 @@ class Credential {
|
|
|
233
222
|
} else {
|
|
234
223
|
userHandle = null
|
|
235
224
|
}
|
|
236
|
-
return new Credential(
|
|
237
|
-
id,
|
|
238
|
-
isResidentCredential,
|
|
239
|
-
rpId,
|
|
240
|
-
userHandle,
|
|
241
|
-
privateKey,
|
|
242
|
-
signCount
|
|
243
|
-
)
|
|
225
|
+
return new Credential(id, isResidentCredential, rpId, userHandle, privateKey, signCount)
|
|
244
226
|
}
|
|
245
227
|
}
|
|
246
228
|
|