selenium-webdriver 4.1.0 → 4.2.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 +506 -565
- package/LICENSE +1 -1
- package/NOTICE +1 -1
- package/README.md +4 -4
- package/chrome.js +13 -10
- package/chromium.js +48 -9
- package/edge.js +10 -8
- package/example/google_search.js +1 -1
- package/firefox.js +32 -17
- package/index.js +4 -50
- package/io/exec.js +2 -1
- package/io/index.js +23 -21
- package/io/zip.js +1 -3
- package/lib/by.js +6 -6
- package/lib/capabilities.js +0 -8
- package/lib/command.js +1 -11
- package/lib/error.js +1 -20
- package/lib/http.js +66 -161
- package/lib/input.js +71 -5
- package/lib/promise.js +12 -17
- package/lib/proxy.js +15 -5
- package/lib/session.js +1 -1
- package/lib/until.js +14 -16
- package/lib/webdriver.js +151 -143
- package/net/index.js +15 -8
- package/net/portprober.js +4 -3
- package/package.json +2 -2
- package/remote/index.js +12 -9
- package/safari.js +3 -3
- package/testing/index.js +18 -13
- package/opera.js +0 -406
package/lib/error.js
CHANGED
|
@@ -217,7 +217,7 @@ class NoSuchElementError extends WebDriverError {
|
|
|
217
217
|
class NoSuchShadowRootError extends WebDriverError {
|
|
218
218
|
/** @param {string=} opt_error the error message, if any. */
|
|
219
219
|
constructor(opt_error) {
|
|
220
|
-
super(opt_error)
|
|
220
|
+
super(opt_error)
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
|
|
@@ -495,23 +495,6 @@ function encodeError(err) {
|
|
|
495
495
|
return { error: code, message: message }
|
|
496
496
|
}
|
|
497
497
|
|
|
498
|
-
/**
|
|
499
|
-
* Checks a response object from a server that adheres to the W3C WebDriver
|
|
500
|
-
* protocol.
|
|
501
|
-
* @param {*} data The response data to check.
|
|
502
|
-
* @return {*} The response data if it was not an encoded error.
|
|
503
|
-
* @throws {WebDriverError} the decoded error, if present in the data object.
|
|
504
|
-
* @deprecated Use {@link #throwDecodedError(data)} instead.
|
|
505
|
-
* @see https://w3c.github.io/webdriver/webdriver-spec.html#protocol
|
|
506
|
-
*/
|
|
507
|
-
function checkResponse(data) {
|
|
508
|
-
if (data && typeof data.error === 'string') {
|
|
509
|
-
let ctor = ERROR_CODE_TO_TYPE.get(data.error) || WebDriverError
|
|
510
|
-
throw new ctor(data.message)
|
|
511
|
-
}
|
|
512
|
-
return data
|
|
513
|
-
}
|
|
514
|
-
|
|
515
498
|
/**
|
|
516
499
|
* Tests if the given value is a valid error response object according to the
|
|
517
500
|
* W3C WebDriver spec.
|
|
@@ -620,8 +603,6 @@ module.exports = {
|
|
|
620
603
|
UnknownCommandError,
|
|
621
604
|
UnknownMethodError,
|
|
622
605
|
UnsupportedOperationError,
|
|
623
|
-
|
|
624
|
-
checkResponse,
|
|
625
606
|
checkLegacyResponse,
|
|
626
607
|
encodeError,
|
|
627
608
|
isErrorResponse,
|
package/lib/http.js
CHANGED
|
@@ -31,7 +31,7 @@ const error = require('./error')
|
|
|
31
31
|
const logging = require('./logging')
|
|
32
32
|
const promise = require('./promise')
|
|
33
33
|
const { Session } = require('./session')
|
|
34
|
-
const { WebElement
|
|
34
|
+
const { WebElement } = require('./webdriver')
|
|
35
35
|
|
|
36
36
|
const getAttribute = requireAtom(
|
|
37
37
|
'get-attribute.js',
|
|
@@ -63,8 +63,8 @@ function requireAtom(module, bazelTarget) {
|
|
|
63
63
|
console.log(ex2)
|
|
64
64
|
throw Error(
|
|
65
65
|
`Failed to import atoms module ${module}. If running in dev mode, you` +
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
` need to run \`bazel build ${bazelTarget}\` from the project` +
|
|
67
|
+
`root: ${ex}`
|
|
68
68
|
)
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -173,12 +173,13 @@ var CommandSpec // eslint-disable-line
|
|
|
173
173
|
/** @typedef {function(!cmd.Command): !cmd.Command} */
|
|
174
174
|
var CommandTransformer // eslint-disable-line
|
|
175
175
|
|
|
176
|
-
class InternalTypeError extends TypeError {
|
|
176
|
+
class InternalTypeError extends TypeError {}
|
|
177
177
|
|
|
178
178
|
/**
|
|
179
179
|
* @param {!cmd.Command} command The initial command.
|
|
180
180
|
* @param {Atom} atom The name of the atom to execute.
|
|
181
|
-
* @
|
|
181
|
+
* @param params
|
|
182
|
+
* @return {!Command} The transformed command to execute.
|
|
182
183
|
*/
|
|
183
184
|
function toExecuteAtomCommand(command, atom, ...params) {
|
|
184
185
|
if (typeof atom !== 'function') {
|
|
@@ -194,143 +195,38 @@ function toExecuteAtomCommand(command, atom, ...params) {
|
|
|
194
195
|
)
|
|
195
196
|
}
|
|
196
197
|
|
|
197
|
-
/** @const {!Map<string, CommandSpec>} */
|
|
198
|
-
const COMMAND_MAP = new Map([
|
|
199
|
-
[cmd.Name.GET_SERVER_STATUS, get('/status')],
|
|
200
|
-
[cmd.Name.NEW_SESSION, post('/session')],
|
|
201
|
-
[cmd.Name.GET_SESSIONS, get('/sessions')],
|
|
202
|
-
[cmd.Name.QUIT, del('/session/:sessionId')],
|
|
203
|
-
[cmd.Name.CLOSE, del('/session/:sessionId/window')],
|
|
204
|
-
[
|
|
205
|
-
cmd.Name.GET_CURRENT_WINDOW_HANDLE,
|
|
206
|
-
get('/session/:sessionId/window_handle'),
|
|
207
|
-
],
|
|
208
|
-
[cmd.Name.GET_WINDOW_HANDLES, get('/session/:sessionId/window_handles')],
|
|
209
|
-
[cmd.Name.GET_CURRENT_URL, get('/session/:sessionId/url')],
|
|
210
|
-
[cmd.Name.GET, post('/session/:sessionId/url')],
|
|
211
|
-
[cmd.Name.GO_BACK, post('/session/:sessionId/back')],
|
|
212
|
-
[cmd.Name.GO_FORWARD, post('/session/:sessionId/forward')],
|
|
213
|
-
[cmd.Name.REFRESH, post('/session/:sessionId/refresh')],
|
|
214
|
-
[cmd.Name.ADD_COOKIE, post('/session/:sessionId/cookie')],
|
|
215
|
-
[cmd.Name.GET_ALL_COOKIES, get('/session/:sessionId/cookie')],
|
|
216
|
-
[cmd.Name.DELETE_ALL_COOKIES, del('/session/:sessionId/cookie')],
|
|
217
|
-
[cmd.Name.DELETE_COOKIE, del('/session/:sessionId/cookie/:name')],
|
|
218
|
-
[cmd.Name.FIND_ELEMENT, post('/session/:sessionId/element')],
|
|
219
|
-
[cmd.Name.FIND_ELEMENTS, post('/session/:sessionId/elements')],
|
|
220
|
-
[cmd.Name.GET_ACTIVE_ELEMENT, post('/session/:sessionId/element/active')],
|
|
221
|
-
[
|
|
222
|
-
cmd.Name.FIND_CHILD_ELEMENT,
|
|
223
|
-
post('/session/:sessionId/element/:id/element'),
|
|
224
|
-
],
|
|
225
|
-
[
|
|
226
|
-
cmd.Name.FIND_CHILD_ELEMENTS,
|
|
227
|
-
post('/session/:sessionId/element/:id/elements'),
|
|
228
|
-
],
|
|
229
|
-
[cmd.Name.CLEAR_ELEMENT, post('/session/:sessionId/element/:id/clear')],
|
|
230
|
-
[cmd.Name.CLICK_ELEMENT, post('/session/:sessionId/element/:id/click')],
|
|
231
|
-
[
|
|
232
|
-
cmd.Name.SEND_KEYS_TO_ELEMENT,
|
|
233
|
-
post('/session/:sessionId/element/:id/value'),
|
|
234
|
-
],
|
|
235
|
-
[cmd.Name.SUBMIT_ELEMENT, post('/session/:sessionId/element/:id/submit')],
|
|
236
|
-
[cmd.Name.GET_ELEMENT_TEXT, get('/session/:sessionId/element/:id/text')],
|
|
237
|
-
[
|
|
238
|
-
cmd.Name.GET_COMPUTED_ROLE,
|
|
239
|
-
get('/session/:sessionId/element/:id/computedrole'),
|
|
240
|
-
],
|
|
241
|
-
[
|
|
242
|
-
cmd.Name.GET_COMPUTED_LABEL,
|
|
243
|
-
get('/session/:sessionId/element/:id/computedlabel'),
|
|
244
|
-
],
|
|
245
|
-
[cmd.Name.GET_ELEMENT_TAG_NAME, get('/session/:sessionId/element/:id/name')],
|
|
246
|
-
[
|
|
247
|
-
cmd.Name.IS_ELEMENT_SELECTED,
|
|
248
|
-
get('/session/:sessionId/element/:id/selected'),
|
|
249
|
-
],
|
|
250
|
-
[cmd.Name.IS_ELEMENT_ENABLED, get('/session/:sessionId/element/:id/enabled')],
|
|
251
|
-
[
|
|
252
|
-
cmd.Name.IS_ELEMENT_DISPLAYED,
|
|
253
|
-
get('/session/:sessionId/element/:id/displayed'),
|
|
254
|
-
],
|
|
255
|
-
[
|
|
256
|
-
cmd.Name.GET_ELEMENT_LOCATION,
|
|
257
|
-
get('/session/:sessionId/element/:id/location'),
|
|
258
|
-
],
|
|
259
|
-
[cmd.Name.GET_ELEMENT_SIZE, get('/session/:sessionId/element/:id/size')],
|
|
260
|
-
[
|
|
261
|
-
cmd.Name.GET_ELEMENT_ATTRIBUTE,
|
|
262
|
-
get('/session/:sessionId/element/:id/attribute/:name'),
|
|
263
|
-
],
|
|
264
|
-
[
|
|
265
|
-
cmd.Name.GET_ELEMENT_PROPERTY,
|
|
266
|
-
get('/session/:sessionId/element/:id/property/:name'),
|
|
267
|
-
],
|
|
268
|
-
[
|
|
269
|
-
cmd.Name.GET_ELEMENT_VALUE_OF_CSS_PROPERTY,
|
|
270
|
-
get('/session/:sessionId/element/:id/css/:propertyName'),
|
|
271
|
-
],
|
|
272
|
-
[
|
|
273
|
-
cmd.Name.TAKE_ELEMENT_SCREENSHOT,
|
|
274
|
-
get('/session/:sessionId/element/:id/screenshot'),
|
|
275
|
-
],
|
|
276
|
-
[cmd.Name.SWITCH_TO_WINDOW, post('/session/:sessionId/window')],
|
|
277
|
-
[
|
|
278
|
-
cmd.Name.MAXIMIZE_WINDOW,
|
|
279
|
-
post('/session/:sessionId/window/current/maximize'),
|
|
280
|
-
],
|
|
281
|
-
[
|
|
282
|
-
cmd.Name.GET_WINDOW_POSITION,
|
|
283
|
-
get('/session/:sessionId/window/current/position'),
|
|
284
|
-
],
|
|
285
|
-
[
|
|
286
|
-
cmd.Name.SET_WINDOW_POSITION,
|
|
287
|
-
post('/session/:sessionId/window/current/position'),
|
|
288
|
-
],
|
|
289
|
-
[cmd.Name.GET_WINDOW_SIZE, get('/session/:sessionId/window/current/size')],
|
|
290
|
-
[cmd.Name.SET_WINDOW_SIZE, post('/session/:sessionId/window/current/size')],
|
|
291
|
-
[cmd.Name.SWITCH_TO_FRAME, post('/session/:sessionId/frame')],
|
|
292
|
-
[cmd.Name.SWITCH_TO_FRAME_PARENT, post('/session/:sessionId/frame/parent')],
|
|
293
|
-
[cmd.Name.GET_PAGE_SOURCE, get('/session/:sessionId/source')],
|
|
294
|
-
[cmd.Name.GET_TITLE, get('/session/:sessionId/title')],
|
|
295
|
-
[cmd.Name.EXECUTE_SCRIPT, post('/session/:sessionId/execute')],
|
|
296
|
-
[cmd.Name.EXECUTE_ASYNC_SCRIPT, post('/session/:sessionId/execute_async')],
|
|
297
|
-
[cmd.Name.SCREENSHOT, get('/session/:sessionId/screenshot')],
|
|
298
|
-
[cmd.Name.GET_TIMEOUT, get('/session/:sessionId/timeouts')],
|
|
299
|
-
[cmd.Name.SET_TIMEOUT, post('/session/:sessionId/timeouts')],
|
|
300
|
-
[cmd.Name.ACCEPT_ALERT, post('/session/:sessionId/accept_alert')],
|
|
301
|
-
[cmd.Name.DISMISS_ALERT, post('/session/:sessionId/dismiss_alert')],
|
|
302
|
-
[cmd.Name.GET_ALERT_TEXT, get('/session/:sessionId/alert_text')],
|
|
303
|
-
[cmd.Name.SET_ALERT_TEXT, post('/session/:sessionId/alert_text')],
|
|
304
|
-
[cmd.Name.GET_LOG, post('/session/:sessionId/log')],
|
|
305
|
-
[cmd.Name.GET_AVAILABLE_LOG_TYPES, get('/session/:sessionId/log/types')],
|
|
306
|
-
[cmd.Name.GET_SESSION_LOGS, post('/logs')],
|
|
307
|
-
[cmd.Name.UPLOAD_FILE, post('/session/:sessionId/se/file')],
|
|
308
|
-
])
|
|
309
|
-
|
|
310
198
|
/** @const {!Map<string, (CommandSpec|CommandTransformer)>} */
|
|
311
199
|
const W3C_COMMAND_MAP = new Map([
|
|
312
|
-
// Server status.
|
|
313
|
-
[cmd.Name.GET_SERVER_STATUS, get('/status')],
|
|
314
200
|
// Session management.
|
|
315
201
|
[cmd.Name.NEW_SESSION, post('/session')],
|
|
316
202
|
[cmd.Name.QUIT, del('/session/:sessionId')],
|
|
203
|
+
|
|
204
|
+
// Server status.
|
|
205
|
+
[cmd.Name.GET_SERVER_STATUS, get('/status')],
|
|
206
|
+
|
|
207
|
+
// timeouts
|
|
317
208
|
[cmd.Name.GET_TIMEOUT, get('/session/:sessionId/timeouts')],
|
|
318
209
|
[cmd.Name.SET_TIMEOUT, post('/session/:sessionId/timeouts')],
|
|
210
|
+
|
|
319
211
|
// Navigation.
|
|
320
212
|
[cmd.Name.GET_CURRENT_URL, get('/session/:sessionId/url')],
|
|
321
213
|
[cmd.Name.GET, post('/session/:sessionId/url')],
|
|
322
214
|
[cmd.Name.GO_BACK, post('/session/:sessionId/back')],
|
|
323
215
|
[cmd.Name.GO_FORWARD, post('/session/:sessionId/forward')],
|
|
324
216
|
[cmd.Name.REFRESH, post('/session/:sessionId/refresh')],
|
|
217
|
+
|
|
325
218
|
// Page inspection.
|
|
326
219
|
[cmd.Name.GET_PAGE_SOURCE, get('/session/:sessionId/source')],
|
|
327
220
|
[cmd.Name.GET_TITLE, get('/session/:sessionId/title')],
|
|
221
|
+
|
|
328
222
|
// Script execution.
|
|
329
223
|
[cmd.Name.EXECUTE_SCRIPT, post('/session/:sessionId/execute/sync')],
|
|
330
224
|
[cmd.Name.EXECUTE_ASYNC_SCRIPT, post('/session/:sessionId/execute/async')],
|
|
225
|
+
|
|
331
226
|
// Frame selection.
|
|
332
227
|
[cmd.Name.SWITCH_TO_FRAME, post('/session/:sessionId/frame')],
|
|
333
228
|
[cmd.Name.SWITCH_TO_FRAME_PARENT, post('/session/:sessionId/frame/parent')],
|
|
229
|
+
|
|
334
230
|
// Window management.
|
|
335
231
|
[cmd.Name.GET_CURRENT_WINDOW_HANDLE, get('/session/:sessionId/window')],
|
|
336
232
|
[cmd.Name.CLOSE, del('/session/:sessionId/window')],
|
|
@@ -342,9 +238,12 @@ const W3C_COMMAND_MAP = new Map([
|
|
|
342
238
|
[cmd.Name.MAXIMIZE_WINDOW, post('/session/:sessionId/window/maximize')],
|
|
343
239
|
[cmd.Name.MINIMIZE_WINDOW, post('/session/:sessionId/window/minimize')],
|
|
344
240
|
[cmd.Name.FULLSCREEN_WINDOW, post('/session/:sessionId/window/fullscreen')],
|
|
241
|
+
|
|
345
242
|
// Actions.
|
|
346
243
|
[cmd.Name.ACTIONS, post('/session/:sessionId/actions')],
|
|
347
244
|
[cmd.Name.CLEAR_ACTIONS, del('/session/:sessionId/actions')],
|
|
245
|
+
[cmd.Name.PRINT_PAGE, post('/session/:sessionId/print')],
|
|
246
|
+
|
|
348
247
|
// Locating elements.
|
|
349
248
|
[cmd.Name.GET_ACTIVE_ELEMENT, get('/session/:sessionId/element/active')],
|
|
350
249
|
[cmd.Name.FIND_ELEMENT, post('/session/:sessionId/element')],
|
|
@@ -365,6 +264,16 @@ const W3C_COMMAND_MAP = new Map([
|
|
|
365
264
|
],
|
|
366
265
|
// Element interaction.
|
|
367
266
|
[cmd.Name.GET_ELEMENT_TAG_NAME, get('/session/:sessionId/element/:id/name')],
|
|
267
|
+
[
|
|
268
|
+
cmd.Name.GET_DOM_ATTRIBUTE,
|
|
269
|
+
get('/session/:sessionId/element/:id/attribute/:name'),
|
|
270
|
+
],
|
|
271
|
+
[
|
|
272
|
+
cmd.Name.GET_ELEMENT_ATTRIBUTE,
|
|
273
|
+
(cmd) => {
|
|
274
|
+
return toExecuteAtomCommand(cmd, Atom.GET_ATTRIBUTE, 'id', 'name')
|
|
275
|
+
},
|
|
276
|
+
],
|
|
368
277
|
[
|
|
369
278
|
cmd.Name.GET_ELEMENT_PROPERTY,
|
|
370
279
|
get('/session/:sessionId/element/:id/property/:name'),
|
|
@@ -391,43 +300,53 @@ const W3C_COMMAND_MAP = new Map([
|
|
|
391
300
|
],
|
|
392
301
|
[cmd.Name.IS_ELEMENT_ENABLED, get('/session/:sessionId/element/:id/enabled')],
|
|
393
302
|
[
|
|
394
|
-
cmd.Name.
|
|
395
|
-
(
|
|
396
|
-
return toExecuteAtomCommand(cmd, Atom.GET_ATTRIBUTE, 'id', 'name')
|
|
397
|
-
},
|
|
303
|
+
cmd.Name.IS_ELEMENT_SELECTED,
|
|
304
|
+
get('/session/:sessionId/element/:id/selected'),
|
|
398
305
|
],
|
|
306
|
+
|
|
399
307
|
[
|
|
400
308
|
cmd.Name.IS_ELEMENT_DISPLAYED,
|
|
401
309
|
(cmd) => {
|
|
402
310
|
return toExecuteAtomCommand(cmd, Atom.IS_DISPLAYED, 'id')
|
|
403
311
|
},
|
|
404
312
|
],
|
|
313
|
+
|
|
405
314
|
// Cookie management.
|
|
406
315
|
[cmd.Name.GET_ALL_COOKIES, get('/session/:sessionId/cookie')],
|
|
407
316
|
[cmd.Name.ADD_COOKIE, post('/session/:sessionId/cookie')],
|
|
408
317
|
[cmd.Name.DELETE_ALL_COOKIES, del('/session/:sessionId/cookie')],
|
|
409
318
|
[cmd.Name.GET_COOKIE, get('/session/:sessionId/cookie/:name')],
|
|
410
319
|
[cmd.Name.DELETE_COOKIE, del('/session/:sessionId/cookie/:name')],
|
|
320
|
+
|
|
411
321
|
// Alert management.
|
|
412
322
|
[cmd.Name.ACCEPT_ALERT, post('/session/:sessionId/alert/accept')],
|
|
413
323
|
[cmd.Name.DISMISS_ALERT, post('/session/:sessionId/alert/dismiss')],
|
|
414
324
|
[cmd.Name.GET_ALERT_TEXT, get('/session/:sessionId/alert/text')],
|
|
415
325
|
[cmd.Name.SET_ALERT_TEXT, post('/session/:sessionId/alert/text')],
|
|
326
|
+
|
|
416
327
|
// Screenshots.
|
|
417
328
|
[cmd.Name.SCREENSHOT, get('/session/:sessionId/screenshot')],
|
|
418
329
|
[
|
|
419
330
|
cmd.Name.TAKE_ELEMENT_SCREENSHOT,
|
|
420
331
|
get('/session/:sessionId/element/:id/screenshot'),
|
|
421
332
|
],
|
|
422
|
-
|
|
423
|
-
[cmd.Name.PRINT_PAGE, post('/session/:sessionId/print')],
|
|
333
|
+
|
|
424
334
|
// Shadow Root
|
|
425
335
|
[cmd.Name.GET_SHADOW_ROOT, get('/session/:sessionId/element/:id/shadow')],
|
|
426
|
-
[
|
|
427
|
-
|
|
336
|
+
[
|
|
337
|
+
cmd.Name.FIND_ELEMENT_FROM_SHADOWROOT,
|
|
338
|
+
post('/session/:sessionId/shadow/:id/element'),
|
|
339
|
+
],
|
|
340
|
+
[
|
|
341
|
+
cmd.Name.FIND_ELEMENTS_FROM_SHADOWROOT,
|
|
342
|
+
post('/session/:sessionId/shadow/:id/elements'),
|
|
343
|
+
],
|
|
428
344
|
// Log extensions.
|
|
429
345
|
[cmd.Name.GET_LOG, post('/session/:sessionId/se/log')],
|
|
430
346
|
[cmd.Name.GET_AVAILABLE_LOG_TYPES, get('/session/:sessionId/se/log/types')],
|
|
347
|
+
|
|
348
|
+
// Server Extensions
|
|
349
|
+
[cmd.Name.UPLOAD_FILE, post('/session/:sessionId/se/file')],
|
|
431
350
|
])
|
|
432
351
|
|
|
433
352
|
/**
|
|
@@ -445,37 +364,29 @@ class Client {
|
|
|
445
364
|
* @return {!Promise<Response>} A promise that will be fulfilled with the
|
|
446
365
|
* server's response.
|
|
447
366
|
*/
|
|
448
|
-
send(httpRequest) {
|
|
367
|
+
send(httpRequest) {} // eslint-disable-line
|
|
449
368
|
}
|
|
450
369
|
|
|
451
370
|
/**
|
|
452
371
|
* @param {Map<string, CommandSpec>} customCommands
|
|
453
372
|
* A map of custom command definitions.
|
|
454
|
-
* @param {boolean} w3c Whether to use W3C command mappings.
|
|
455
373
|
* @param {!cmd.Command} command The command to resolve.
|
|
456
374
|
* @return {!Request} A promise that will resolve with the
|
|
457
375
|
* command to execute.
|
|
458
376
|
*/
|
|
459
|
-
function buildRequest(customCommands,
|
|
377
|
+
function buildRequest(customCommands, command) {
|
|
460
378
|
LOG.finest(() => `Translating command: ${command.getName()}`)
|
|
461
379
|
let spec = customCommands && customCommands.get(command.getName())
|
|
462
380
|
if (spec) {
|
|
463
381
|
return toHttpRequest(spec)
|
|
464
382
|
}
|
|
465
383
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
} else if (spec) {
|
|
473
|
-
return toHttpRequest(spec)
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
spec = COMMAND_MAP.get(command.getName())
|
|
478
|
-
if (spec) {
|
|
384
|
+
spec = W3C_COMMAND_MAP.get(command.getName())
|
|
385
|
+
if (typeof spec === 'function') {
|
|
386
|
+
LOG.finest(() => `Transforming command for W3C: ${command.getName()}`)
|
|
387
|
+
let newCommand = spec(command)
|
|
388
|
+
return buildRequest(customCommands, newCommand)
|
|
389
|
+
} else if (spec) {
|
|
479
390
|
return toHttpRequest(spec)
|
|
480
391
|
}
|
|
481
392
|
throw new error.UnknownCommandError(
|
|
@@ -519,15 +430,6 @@ class Executor {
|
|
|
519
430
|
constructor(client) {
|
|
520
431
|
CLIENTS.set(this, client)
|
|
521
432
|
|
|
522
|
-
/**
|
|
523
|
-
* Whether this executor should use the W3C wire protocol. The executor
|
|
524
|
-
* will automatically switch if the remote end sends a compliant response
|
|
525
|
-
* to a new session command, however, this property may be directly set to
|
|
526
|
-
* `true` to force the executor into W3C mode.
|
|
527
|
-
* @type {boolean}
|
|
528
|
-
*/
|
|
529
|
-
this.w3c = false
|
|
530
|
-
|
|
531
433
|
/** @private {Map<string, CommandSpec>} */
|
|
532
434
|
this.customCommands_ = null
|
|
533
435
|
|
|
@@ -557,7 +459,7 @@ class Executor {
|
|
|
557
459
|
|
|
558
460
|
/** @override */
|
|
559
461
|
async execute(command) {
|
|
560
|
-
let request = buildRequest(this.customCommands_,
|
|
462
|
+
let request = buildRequest(this.customCommands_, command)
|
|
561
463
|
this.log_.finer(() => `>>> ${request.method} ${request.path}`)
|
|
562
464
|
|
|
563
465
|
let client = CLIENTS.get(this)
|
|
@@ -588,7 +490,7 @@ class Executor {
|
|
|
588
490
|
// No implementations use the `capabilities` key yet...
|
|
589
491
|
let capabilities = value.capabilities || value.value
|
|
590
492
|
return new Session(
|
|
591
|
-
/** @type {{sessionId: string}} */(value).sessionId,
|
|
493
|
+
/** @type {{sessionId: string}} */ (value).sessionId,
|
|
592
494
|
capabilities
|
|
593
495
|
)
|
|
594
496
|
}
|
|
@@ -658,7 +560,7 @@ function parseHttpResponse(command, httpResponse) {
|
|
|
658
560
|
|
|
659
561
|
// 404 represents an unknown command; anything else > 399 is a generic unknown
|
|
660
562
|
// error.
|
|
661
|
-
if (httpResponse.status
|
|
563
|
+
if (httpResponse.status === 404) {
|
|
662
564
|
throw new error.UnsupportedOperationError(command.getName() + ': ' + value)
|
|
663
565
|
} else if (httpResponse.status >= 400) {
|
|
664
566
|
throw new error.WebDriverError(value)
|
|
@@ -702,8 +604,11 @@ function buildPath(path, parameters) {
|
|
|
702
604
|
|
|
703
605
|
// PUBLIC API
|
|
704
606
|
|
|
705
|
-
exports
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
607
|
+
module.exports = {
|
|
608
|
+
Executor: Executor,
|
|
609
|
+
Client: Client,
|
|
610
|
+
Request: Request,
|
|
611
|
+
Response: Response,
|
|
612
|
+
// Exported for testing.
|
|
613
|
+
buildPath: buildPath,
|
|
614
|
+
}
|
package/lib/input.js
CHANGED
|
@@ -200,6 +200,7 @@ Action.Type = {
|
|
|
200
200
|
POINTER_UP: 'pointerUp',
|
|
201
201
|
POINTER_MOVE: 'pointerMove',
|
|
202
202
|
POINTER_CANCEL: 'pointerCancel',
|
|
203
|
+
SCROLL: 'scroll',
|
|
203
204
|
}
|
|
204
205
|
|
|
205
206
|
/**
|
|
@@ -233,6 +234,7 @@ Device.Type = {
|
|
|
233
234
|
KEY: 'key',
|
|
234
235
|
NONE: 'none',
|
|
235
236
|
POINTER: 'pointer',
|
|
237
|
+
WHEEL: 'wheel',
|
|
236
238
|
}
|
|
237
239
|
|
|
238
240
|
/**
|
|
@@ -250,7 +252,7 @@ function checkCodePoint(key) {
|
|
|
250
252
|
}
|
|
251
253
|
|
|
252
254
|
key = key.normalize()
|
|
253
|
-
if (Array.from(key).length
|
|
255
|
+
if (Array.from(key).length !== 1) {
|
|
254
256
|
throw new InvalidArgumentError(
|
|
255
257
|
`key input is not a single code point: ${key}`
|
|
256
258
|
)
|
|
@@ -347,8 +349,14 @@ class Pointer extends Device {
|
|
|
347
349
|
* @return {!Action} An action to press the specified button with this device.
|
|
348
350
|
* @package
|
|
349
351
|
*/
|
|
350
|
-
press(button = Button.LEFT
|
|
351
|
-
|
|
352
|
+
press(button = Button.LEFT, width = 0, height = 0, pressure = 0,
|
|
353
|
+
tangentialPressure = 0, tiltX = 0, tiltY = 0, twist = 0,
|
|
354
|
+
altitudeAngle = 0, azimuthAngle = 0) {
|
|
355
|
+
return {
|
|
356
|
+
type: Action.Type.POINTER_DOWN, button, width, height,
|
|
357
|
+
pressure, tangentialPressure, tiltX, tiltY, twist,
|
|
358
|
+
altitudeAngle, azimuthAngle
|
|
359
|
+
}
|
|
352
360
|
}
|
|
353
361
|
|
|
354
362
|
/**
|
|
@@ -377,8 +385,16 @@ class Pointer extends Device {
|
|
|
377
385
|
* @return {!Action} The new action.
|
|
378
386
|
* @package
|
|
379
387
|
*/
|
|
380
|
-
move({ x = 0, y = 0, duration = 100, origin = Origin.VIEWPORT
|
|
381
|
-
|
|
388
|
+
move({ x = 0, y = 0, duration = 100, origin = Origin.VIEWPORT,
|
|
389
|
+
width = 0, height = 0, pressure = 0,
|
|
390
|
+
tangentialPressure = 0, tiltX = 0, tiltY = 0, twist = 0,
|
|
391
|
+
altitudeAngle = 0, azimuthAngle = 0
|
|
392
|
+
}) {
|
|
393
|
+
return {
|
|
394
|
+
type: Action.Type.POINTER_MOVE, origin, duration, x, y,
|
|
395
|
+
width, height, pressure, tangentialPressure, tiltX, tiltY, twist,
|
|
396
|
+
altitudeAngle, azimuthAngle
|
|
397
|
+
}
|
|
382
398
|
}
|
|
383
399
|
}
|
|
384
400
|
|
|
@@ -392,6 +408,34 @@ Pointer.Type = {
|
|
|
392
408
|
TOUCH: 'touch',
|
|
393
409
|
}
|
|
394
410
|
|
|
411
|
+
class Wheel extends Device {
|
|
412
|
+
/**
|
|
413
|
+
* @param {string} id the device ID.
|
|
414
|
+
* @param {Pointer.Type} type the pointer type.
|
|
415
|
+
*/
|
|
416
|
+
constructor(id, type) {
|
|
417
|
+
super(Device.Type.WHEEL, id)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Scrolls a page via the coordinates given
|
|
422
|
+
* @param {number} x starting x coordinate
|
|
423
|
+
* @param {number} y starting y coordinate
|
|
424
|
+
* @param {number} deltaX Delta X to scroll to target
|
|
425
|
+
* @param {number} deltaY Delta Y to scroll to target
|
|
426
|
+
* @param {number} duration duration ratio be the ratio of time delta and duration
|
|
427
|
+
* @returns {!Action} An action to scroll with this device.
|
|
428
|
+
*/
|
|
429
|
+
scroll(x, y, deltaX, deltaY, origin, duration) {
|
|
430
|
+
return {
|
|
431
|
+
type: Action.Type.SCROLL,
|
|
432
|
+
duration: duration, x: x, y: y,
|
|
433
|
+
deltaX: deltaX, deltaY: deltaY,
|
|
434
|
+
origin: origin
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
395
439
|
/**
|
|
396
440
|
* User facing API for generating complex user gestures. This class should not
|
|
397
441
|
* be instantiated directly. Instead, users should create new instances by
|
|
@@ -509,10 +553,14 @@ class Actions {
|
|
|
509
553
|
/** @private @const */
|
|
510
554
|
this.mouse_ = new Pointer('default mouse', Pointer.Type.MOUSE)
|
|
511
555
|
|
|
556
|
+
/** @private @const */
|
|
557
|
+
this.wheel_ = new Wheel('default wheel')
|
|
558
|
+
|
|
512
559
|
/** @private @const {!Map<!Device, !Array<!Action>>} */
|
|
513
560
|
this.sequences_ = new Map([
|
|
514
561
|
[this.keyboard_, []],
|
|
515
562
|
[this.mouse_, []],
|
|
563
|
+
[this.wheel_, []],
|
|
516
564
|
])
|
|
517
565
|
}
|
|
518
566
|
|
|
@@ -526,6 +574,11 @@ class Actions {
|
|
|
526
574
|
return this.mouse_
|
|
527
575
|
}
|
|
528
576
|
|
|
577
|
+
/** @return {!Wheel} the wheel device handle. */
|
|
578
|
+
wheel() {
|
|
579
|
+
return this.wheel_
|
|
580
|
+
}
|
|
581
|
+
|
|
529
582
|
/**
|
|
530
583
|
* @param {!Device} device
|
|
531
584
|
* @return {!Array<!Action>}
|
|
@@ -735,6 +788,19 @@ class Actions {
|
|
|
735
788
|
return this.insert(this.mouse_, this.mouse_.release(button))
|
|
736
789
|
}
|
|
737
790
|
|
|
791
|
+
/**
|
|
792
|
+
* scrolls a page via the coordinates given
|
|
793
|
+
* @param {number} x starting x coordinate
|
|
794
|
+
* @param {number} y starting y coordinate
|
|
795
|
+
* @param {number} deltax delta x to scroll to target
|
|
796
|
+
* @param {number} deltay delta y to scroll to target
|
|
797
|
+
* @param {number} duration duration ratio be the ratio of time delta and duration
|
|
798
|
+
* @returns {!Action} An action to scroll with this device.
|
|
799
|
+
*/
|
|
800
|
+
scroll(x, y, targetDeltaX, targetDeltaY, origin, duration) {
|
|
801
|
+
return this.insert(this.wheel_, this.wheel_.scroll(x, y, targetDeltaX, targetDeltaY, origin, duration))
|
|
802
|
+
}
|
|
803
|
+
|
|
738
804
|
/**
|
|
739
805
|
* Inserts an action for moving the mouse `x` and `y` pixels relative to the
|
|
740
806
|
* specified `origin`. The `origin` may be defined as the mouse's
|
package/lib/promise.js
CHANGED
|
@@ -142,14 +142,12 @@ async function map(array, fn, self = undefined) {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
const arr = /** @type {!Array} */ (v)
|
|
145
|
-
const
|
|
146
|
-
const values = new Array(n)
|
|
145
|
+
const values = []
|
|
147
146
|
|
|
148
|
-
for (
|
|
149
|
-
|
|
150
|
-
values[i] = await Promise.resolve(fn.call(self, arr[i], i, arr))
|
|
151
|
-
}
|
|
147
|
+
for (const [index, item] of arr.entries()) {
|
|
148
|
+
values.push(await Promise.resolve(fn.call(self, item, index, arr)))
|
|
152
149
|
}
|
|
150
|
+
|
|
153
151
|
return values
|
|
154
152
|
}
|
|
155
153
|
|
|
@@ -181,19 +179,17 @@ async function filter(array, fn, self = undefined) {
|
|
|
181
179
|
}
|
|
182
180
|
|
|
183
181
|
const arr = /** @type {!Array} */ (v)
|
|
184
|
-
const n = arr.length
|
|
185
182
|
const values = []
|
|
186
|
-
let valuesLength = 0
|
|
187
183
|
|
|
188
|
-
for (
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
184
|
+
for (const [index, item] of arr.entries()) {
|
|
185
|
+
const isConditionTrue = await Promise.resolve(
|
|
186
|
+
fn.call(self, item, index, arr)
|
|
187
|
+
)
|
|
188
|
+
if (isConditionTrue) {
|
|
189
|
+
values.push(item)
|
|
195
190
|
}
|
|
196
191
|
}
|
|
192
|
+
|
|
197
193
|
return values
|
|
198
194
|
}
|
|
199
195
|
|
|
@@ -266,8 +262,7 @@ async function fullyResolveKeys(obj) {
|
|
|
266
262
|
) {
|
|
267
263
|
return
|
|
268
264
|
}
|
|
269
|
-
|
|
270
|
-
obj[key] = resolvedValue
|
|
265
|
+
obj[key] = await fullyResolved(partialValue)
|
|
271
266
|
})
|
|
272
267
|
return obj
|
|
273
268
|
}
|
package/lib/proxy.js
CHANGED
|
@@ -130,7 +130,7 @@ ManualConfig.prototype.socksVersion
|
|
|
130
130
|
* Configures WebDriver to bypass all browser proxies.
|
|
131
131
|
* @return {!Config} A new proxy configuration object.
|
|
132
132
|
*/
|
|
133
|
-
|
|
133
|
+
function direct() {
|
|
134
134
|
return { proxyType: Type.DIRECT }
|
|
135
135
|
}
|
|
136
136
|
|
|
@@ -155,7 +155,7 @@ exports.direct = function () {
|
|
|
155
155
|
* configuration options.
|
|
156
156
|
* @return {!ManualConfig} A new proxy configuration object.
|
|
157
157
|
*/
|
|
158
|
-
|
|
158
|
+
function manual({ ftp, http, https, bypass }) {
|
|
159
159
|
return {
|
|
160
160
|
proxyType: Type.MANUAL,
|
|
161
161
|
ftpProxy: ftp,
|
|
@@ -185,7 +185,7 @@ exports.manual = function ({ ftp, http, https, bypass }) {
|
|
|
185
185
|
* @return {!ManualConfig} A new proxy configuration object.
|
|
186
186
|
* @see https://en.wikipedia.org/wiki/SOCKS
|
|
187
187
|
*/
|
|
188
|
-
|
|
188
|
+
function socks(socksProxy, socksVersion = undefined) {
|
|
189
189
|
return /** @type {!Config} */ ({
|
|
190
190
|
proxyType: Type.MANUAL,
|
|
191
191
|
socksProxy,
|
|
@@ -199,7 +199,7 @@ exports.socks = function (socksProxy, socksVersion = undefined) {
|
|
|
199
199
|
* @param {string} proxyAutoconfigUrl URL for the PAC proxy to use.
|
|
200
200
|
* @return {!PacConfig} A new proxy configuration object.
|
|
201
201
|
*/
|
|
202
|
-
|
|
202
|
+
function pac(proxyAutoconfigUrl) {
|
|
203
203
|
return { proxyType: Type.PAC, proxyAutoconfigUrl }
|
|
204
204
|
}
|
|
205
205
|
|
|
@@ -207,6 +207,16 @@ exports.pac = function (proxyAutoconfigUrl) {
|
|
|
207
207
|
* Configures WebDriver to use the current system's proxy.
|
|
208
208
|
* @return {!Config} A new proxy configuration object.
|
|
209
209
|
*/
|
|
210
|
-
|
|
210
|
+
function system() {
|
|
211
211
|
return { proxyType: Type.SYSTEM }
|
|
212
212
|
}
|
|
213
|
+
|
|
214
|
+
// PUBLIC API
|
|
215
|
+
|
|
216
|
+
module.exports = {
|
|
217
|
+
system,
|
|
218
|
+
pac,
|
|
219
|
+
socks,
|
|
220
|
+
manual,
|
|
221
|
+
direct,
|
|
222
|
+
}
|
package/lib/session.js
CHANGED