selenium-webdriver 4.0.0-rc-1 → 4.1.1
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 +51 -1
- package/LICENSE +1 -1
- package/NOTICE +1 -1
- package/chrome.js +10 -6
- package/chromium.js +75 -27
- package/devtools/CDPConnection.js +9 -4
- package/devtools/networkinterceptor.js +88 -0
- package/edge.js +8 -6
- package/example/google_search.js +1 -1
- package/firefox.js +39 -17
- package/http/index.js +13 -14
- package/http/util.js +14 -20
- package/index.js +26 -13
- package/io/index.js +58 -55
- package/io/zip.js +1 -3
- package/lib/atoms/find-elements.js +2 -2
- package/lib/atoms/get-attribute.js +25 -25
- package/lib/by.js +8 -9
- package/lib/capabilities.js +1 -1
- package/lib/command.js +6 -11
- package/lib/error.js +24 -19
- package/lib/http.js +64 -156
- package/lib/input.js +1 -1
- package/lib/promise.js +12 -17
- package/lib/proxy.js +15 -5
- package/lib/session.js +1 -1
- package/lib/webdriver.js +422 -176
- package/net/index.js +14 -7
- package/net/portprober.js +5 -4
- package/opera.js +19 -22
- package/package.json +1 -2
- package/remote/index.js +13 -10
- package/testing/index.js +16 -10
package/lib/command.js
CHANGED
|
@@ -83,7 +83,6 @@ class Command {
|
|
|
83
83
|
* will support.
|
|
84
84
|
* @enum {string}
|
|
85
85
|
*/
|
|
86
|
-
// TODO: Delete obsolete command names.
|
|
87
86
|
const Name = {
|
|
88
87
|
GET_SERVER_STATUS: 'getStatus',
|
|
89
88
|
|
|
@@ -115,14 +114,9 @@ const Name = {
|
|
|
115
114
|
CLEAR_ELEMENT: 'clearElement',
|
|
116
115
|
CLICK_ELEMENT: 'clickElement',
|
|
117
116
|
SEND_KEYS_TO_ELEMENT: 'sendKeysToElement',
|
|
118
|
-
SUBMIT_ELEMENT: 'submitElement',
|
|
119
117
|
|
|
120
118
|
GET_CURRENT_WINDOW_HANDLE: 'getCurrentWindowHandle',
|
|
121
119
|
GET_WINDOW_HANDLES: 'getWindowHandles',
|
|
122
|
-
GET_WINDOW_POSITION: 'getWindowPosition',
|
|
123
|
-
SET_WINDOW_POSITION: 'setWindowPosition',
|
|
124
|
-
GET_WINDOW_SIZE: 'getWindowSize',
|
|
125
|
-
SET_WINDOW_SIZE: 'setWindowSize',
|
|
126
120
|
GET_WINDOW_RECT: 'getWindowRect',
|
|
127
121
|
SET_WINDOW_RECT: 'setWindowRect',
|
|
128
122
|
MAXIMIZE_WINDOW: 'maximizeWindow',
|
|
@@ -146,17 +140,14 @@ const Name = {
|
|
|
146
140
|
IS_ELEMENT_SELECTED: 'isElementSelected',
|
|
147
141
|
IS_ELEMENT_ENABLED: 'isElementEnabled',
|
|
148
142
|
IS_ELEMENT_DISPLAYED: 'isElementDisplayed',
|
|
149
|
-
GET_ELEMENT_LOCATION: 'getElementLocation',
|
|
150
|
-
GET_ELEMENT_LOCATION_IN_VIEW: 'getElementLocationOnceScrolledIntoView',
|
|
151
143
|
GET_ELEMENT_RECT: 'getElementRect',
|
|
152
|
-
GET_ELEMENT_SIZE: 'getElementSize',
|
|
153
144
|
GET_ELEMENT_ATTRIBUTE: 'getElementAttribute',
|
|
145
|
+
GET_DOM_ATTRIBUTE: 'getDomAttribute',
|
|
154
146
|
GET_ELEMENT_VALUE_OF_CSS_PROPERTY: 'getElementValueOfCssProperty',
|
|
155
147
|
GET_ELEMENT_PROPERTY: 'getElementProperty',
|
|
156
148
|
|
|
157
149
|
SCREENSHOT: 'screenshot',
|
|
158
150
|
TAKE_ELEMENT_SCREENSHOT: 'takeElementScreenshot',
|
|
159
|
-
SET_SCRIPT_TIMEOUT: 'setScriptTimeout',
|
|
160
151
|
|
|
161
152
|
PRINT_PAGE: 'printPage',
|
|
162
153
|
|
|
@@ -168,9 +159,13 @@ const Name = {
|
|
|
168
159
|
GET_ALERT_TEXT: 'getAlertText',
|
|
169
160
|
SET_ALERT_TEXT: 'setAlertValue',
|
|
170
161
|
|
|
162
|
+
// Shadow DOM Commands
|
|
163
|
+
GET_SHADOW_ROOT: 'getShadowRoot',
|
|
164
|
+
FIND_ELEMENT_FROM_SHADOWROOT: 'findElementFromShadowRoot',
|
|
165
|
+
FIND_ELEMENTS_FROM_SHADOWROOT: 'findElementsFromShadowRoot',
|
|
166
|
+
|
|
171
167
|
GET_AVAILABLE_LOG_TYPES: 'getAvailableLogTypes',
|
|
172
168
|
GET_LOG: 'getLog',
|
|
173
|
-
GET_SESSION_LOGS: 'getSessionLogs',
|
|
174
169
|
|
|
175
170
|
// Non-standard commands used by the standalone Selenium server.
|
|
176
171
|
UPLOAD_FILE: 'uploadFile',
|
package/lib/error.js
CHANGED
|
@@ -39,6 +39,16 @@ class WebDriverError extends Error {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Indicates the shadow root is no longer attached to the DOM
|
|
44
|
+
*/
|
|
45
|
+
class DetachedShadowRootError extends WebDriverError {
|
|
46
|
+
/** @param {string=} opt_error the error message, if any. */
|
|
47
|
+
constructor(opt_error) {
|
|
48
|
+
super(opt_error)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
42
52
|
/**
|
|
43
53
|
* Indicates a {@linkplain ./webdriver.WebElement#click click command} could not
|
|
44
54
|
* completed because the click target is obscured by other elements on the
|
|
@@ -201,6 +211,16 @@ class NoSuchElementError extends WebDriverError {
|
|
|
201
211
|
}
|
|
202
212
|
}
|
|
203
213
|
|
|
214
|
+
/**
|
|
215
|
+
* A ShadowRoot could not be located on the element
|
|
216
|
+
*/
|
|
217
|
+
class NoSuchShadowRootError extends WebDriverError {
|
|
218
|
+
/** @param {string=} opt_error the error message, if any. */
|
|
219
|
+
constructor(opt_error) {
|
|
220
|
+
super(opt_error)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
204
224
|
/**
|
|
205
225
|
* A request to switch to a frame could not be satisfied because the frame
|
|
206
226
|
* could not be found.
|
|
@@ -420,6 +440,7 @@ const LEGACY_ERROR_CODE_TO_TYPE = new Map([
|
|
|
420
440
|
|
|
421
441
|
const ERROR_CODE_TO_TYPE = new Map([
|
|
422
442
|
['unknown error', WebDriverError],
|
|
443
|
+
['detached shadow root', DetachedShadowRootError],
|
|
423
444
|
['element click intercepted', ElementClickInterceptedError],
|
|
424
445
|
['element not interactable', ElementNotInteractableError],
|
|
425
446
|
['element not selectable', ElementNotSelectableError],
|
|
@@ -436,6 +457,7 @@ const ERROR_CODE_TO_TYPE = new Map([
|
|
|
436
457
|
['no such cookie', NoSuchCookieError],
|
|
437
458
|
['no such element', NoSuchElementError],
|
|
438
459
|
['no such frame', NoSuchFrameError],
|
|
460
|
+
['no such shadow root', NoSuchShadowRootError],
|
|
439
461
|
['no such window', NoSuchWindowError],
|
|
440
462
|
['script timeout', ScriptTimeoutError],
|
|
441
463
|
['session not created', SessionNotCreatedError],
|
|
@@ -473,23 +495,6 @@ function encodeError(err) {
|
|
|
473
495
|
return { error: code, message: message }
|
|
474
496
|
}
|
|
475
497
|
|
|
476
|
-
/**
|
|
477
|
-
* Checks a response object from a server that adheres to the W3C WebDriver
|
|
478
|
-
* protocol.
|
|
479
|
-
* @param {*} data The response data to check.
|
|
480
|
-
* @return {*} The response data if it was not an encoded error.
|
|
481
|
-
* @throws {WebDriverError} the decoded error, if present in the data object.
|
|
482
|
-
* @deprecated Use {@link #throwDecodedError(data)} instead.
|
|
483
|
-
* @see https://w3c.github.io/webdriver/webdriver-spec.html#protocol
|
|
484
|
-
*/
|
|
485
|
-
function checkResponse(data) {
|
|
486
|
-
if (data && typeof data.error === 'string') {
|
|
487
|
-
let ctor = ERROR_CODE_TO_TYPE.get(data.error) || WebDriverError
|
|
488
|
-
throw new ctor(data.message)
|
|
489
|
-
}
|
|
490
|
-
return data
|
|
491
|
-
}
|
|
492
|
-
|
|
493
498
|
/**
|
|
494
499
|
* Tests if the given value is a valid error response object according to the
|
|
495
500
|
* W3C WebDriver spec.
|
|
@@ -569,6 +574,7 @@ module.exports = {
|
|
|
569
574
|
ErrorCode,
|
|
570
575
|
|
|
571
576
|
WebDriverError,
|
|
577
|
+
DetachedShadowRootError,
|
|
572
578
|
ElementClickInterceptedError,
|
|
573
579
|
ElementNotInteractableError,
|
|
574
580
|
ElementNotSelectableError,
|
|
@@ -584,6 +590,7 @@ module.exports = {
|
|
|
584
590
|
NoSuchCookieError,
|
|
585
591
|
NoSuchElementError,
|
|
586
592
|
NoSuchFrameError,
|
|
593
|
+
NoSuchShadowRootError,
|
|
587
594
|
NoSuchSessionError,
|
|
588
595
|
NoSuchWindowError,
|
|
589
596
|
ScriptTimeoutError,
|
|
@@ -596,8 +603,6 @@ module.exports = {
|
|
|
596
603
|
UnknownCommandError,
|
|
597
604
|
UnknownMethodError,
|
|
598
605
|
UnsupportedOperationError,
|
|
599
|
-
|
|
600
|
-
checkResponse,
|
|
601
606
|
checkLegacyResponse,
|
|
602
607
|
encodeError,
|
|
603
608
|
isErrorResponse,
|
package/lib/http.js
CHANGED
|
@@ -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
|
}
|
|
@@ -178,7 +178,8 @@ class InternalTypeError extends TypeError {}
|
|
|
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,39 @@ 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
|
-
|
|
313
|
-
[cmd.Name.GET_SERVER_STATUS, get('/status')],
|
|
200
|
+
|
|
314
201
|
// Session management.
|
|
315
202
|
[cmd.Name.NEW_SESSION, post('/session')],
|
|
316
203
|
[cmd.Name.QUIT, del('/session/:sessionId')],
|
|
204
|
+
|
|
205
|
+
// Server status.
|
|
206
|
+
[cmd.Name.GET_SERVER_STATUS, get('/status')],
|
|
207
|
+
|
|
208
|
+
// timeouts
|
|
317
209
|
[cmd.Name.GET_TIMEOUT, get('/session/:sessionId/timeouts')],
|
|
318
210
|
[cmd.Name.SET_TIMEOUT, post('/session/:sessionId/timeouts')],
|
|
211
|
+
|
|
319
212
|
// Navigation.
|
|
320
213
|
[cmd.Name.GET_CURRENT_URL, get('/session/:sessionId/url')],
|
|
321
214
|
[cmd.Name.GET, post('/session/:sessionId/url')],
|
|
322
215
|
[cmd.Name.GO_BACK, post('/session/:sessionId/back')],
|
|
323
216
|
[cmd.Name.GO_FORWARD, post('/session/:sessionId/forward')],
|
|
324
217
|
[cmd.Name.REFRESH, post('/session/:sessionId/refresh')],
|
|
218
|
+
|
|
325
219
|
// Page inspection.
|
|
326
220
|
[cmd.Name.GET_PAGE_SOURCE, get('/session/:sessionId/source')],
|
|
327
221
|
[cmd.Name.GET_TITLE, get('/session/:sessionId/title')],
|
|
222
|
+
|
|
328
223
|
// Script execution.
|
|
329
224
|
[cmd.Name.EXECUTE_SCRIPT, post('/session/:sessionId/execute/sync')],
|
|
330
225
|
[cmd.Name.EXECUTE_ASYNC_SCRIPT, post('/session/:sessionId/execute/async')],
|
|
226
|
+
|
|
331
227
|
// Frame selection.
|
|
332
228
|
[cmd.Name.SWITCH_TO_FRAME, post('/session/:sessionId/frame')],
|
|
333
229
|
[cmd.Name.SWITCH_TO_FRAME_PARENT, post('/session/:sessionId/frame/parent')],
|
|
230
|
+
|
|
334
231
|
// Window management.
|
|
335
232
|
[cmd.Name.GET_CURRENT_WINDOW_HANDLE, get('/session/:sessionId/window')],
|
|
336
233
|
[cmd.Name.CLOSE, del('/session/:sessionId/window')],
|
|
@@ -342,9 +239,13 @@ const W3C_COMMAND_MAP = new Map([
|
|
|
342
239
|
[cmd.Name.MAXIMIZE_WINDOW, post('/session/:sessionId/window/maximize')],
|
|
343
240
|
[cmd.Name.MINIMIZE_WINDOW, post('/session/:sessionId/window/minimize')],
|
|
344
241
|
[cmd.Name.FULLSCREEN_WINDOW, post('/session/:sessionId/window/fullscreen')],
|
|
242
|
+
|
|
345
243
|
// Actions.
|
|
346
244
|
[cmd.Name.ACTIONS, post('/session/:sessionId/actions')],
|
|
347
245
|
[cmd.Name.CLEAR_ACTIONS, del('/session/:sessionId/actions')],
|
|
246
|
+
[cmd.Name.PRINT_PAGE, post('/session/:sessionId/print')],
|
|
247
|
+
|
|
248
|
+
|
|
348
249
|
// Locating elements.
|
|
349
250
|
[cmd.Name.GET_ACTIVE_ELEMENT, get('/session/:sessionId/element/active')],
|
|
350
251
|
[cmd.Name.FIND_ELEMENT, post('/session/:sessionId/element')],
|
|
@@ -365,6 +266,13 @@ const W3C_COMMAND_MAP = new Map([
|
|
|
365
266
|
],
|
|
366
267
|
// Element interaction.
|
|
367
268
|
[cmd.Name.GET_ELEMENT_TAG_NAME, get('/session/:sessionId/element/:id/name')],
|
|
269
|
+
[cmd.Name.GET_DOM_ATTRIBUTE, get('/session/:sessionId/element/:id/attribute/:name')],
|
|
270
|
+
[
|
|
271
|
+
cmd.Name.GET_ELEMENT_ATTRIBUTE,
|
|
272
|
+
(cmd) => {
|
|
273
|
+
return toExecuteAtomCommand(cmd, Atom.GET_ATTRIBUTE, 'id', 'name')
|
|
274
|
+
},
|
|
275
|
+
],
|
|
368
276
|
[
|
|
369
277
|
cmd.Name.GET_ELEMENT_PROPERTY,
|
|
370
278
|
get('/session/:sessionId/element/:id/property/:name'),
|
|
@@ -391,39 +299,53 @@ const W3C_COMMAND_MAP = new Map([
|
|
|
391
299
|
],
|
|
392
300
|
[cmd.Name.IS_ELEMENT_ENABLED, get('/session/:sessionId/element/:id/enabled')],
|
|
393
301
|
[
|
|
394
|
-
cmd.Name.
|
|
395
|
-
(
|
|
396
|
-
return toExecuteAtomCommand(cmd, Atom.GET_ATTRIBUTE, 'id', 'name')
|
|
397
|
-
},
|
|
302
|
+
cmd.Name.IS_ELEMENT_SELECTED,
|
|
303
|
+
get('/session/:sessionId/element/:id/selected'),
|
|
398
304
|
],
|
|
305
|
+
|
|
399
306
|
[
|
|
400
307
|
cmd.Name.IS_ELEMENT_DISPLAYED,
|
|
401
308
|
(cmd) => {
|
|
402
309
|
return toExecuteAtomCommand(cmd, Atom.IS_DISPLAYED, 'id')
|
|
403
310
|
},
|
|
404
311
|
],
|
|
312
|
+
|
|
405
313
|
// Cookie management.
|
|
406
314
|
[cmd.Name.GET_ALL_COOKIES, get('/session/:sessionId/cookie')],
|
|
407
315
|
[cmd.Name.ADD_COOKIE, post('/session/:sessionId/cookie')],
|
|
408
316
|
[cmd.Name.DELETE_ALL_COOKIES, del('/session/:sessionId/cookie')],
|
|
409
317
|
[cmd.Name.GET_COOKIE, get('/session/:sessionId/cookie/:name')],
|
|
410
318
|
[cmd.Name.DELETE_COOKIE, del('/session/:sessionId/cookie/:name')],
|
|
319
|
+
|
|
411
320
|
// Alert management.
|
|
412
321
|
[cmd.Name.ACCEPT_ALERT, post('/session/:sessionId/alert/accept')],
|
|
413
322
|
[cmd.Name.DISMISS_ALERT, post('/session/:sessionId/alert/dismiss')],
|
|
414
323
|
[cmd.Name.GET_ALERT_TEXT, get('/session/:sessionId/alert/text')],
|
|
415
324
|
[cmd.Name.SET_ALERT_TEXT, post('/session/:sessionId/alert/text')],
|
|
325
|
+
|
|
416
326
|
// Screenshots.
|
|
417
327
|
[cmd.Name.SCREENSHOT, get('/session/:sessionId/screenshot')],
|
|
418
328
|
[
|
|
419
329
|
cmd.Name.TAKE_ELEMENT_SCREENSHOT,
|
|
420
330
|
get('/session/:sessionId/element/:id/screenshot'),
|
|
421
331
|
],
|
|
422
|
-
|
|
423
|
-
|
|
332
|
+
|
|
333
|
+
// Shadow Root
|
|
334
|
+
[cmd.Name.GET_SHADOW_ROOT, get('/session/:sessionId/element/:id/shadow')],
|
|
335
|
+
[
|
|
336
|
+
cmd.Name.FIND_ELEMENT_FROM_SHADOWROOT,
|
|
337
|
+
post('/session/:sessionId/shadow/:id/element'),
|
|
338
|
+
],
|
|
339
|
+
[
|
|
340
|
+
cmd.Name.FIND_ELEMENTS_FROM_SHADOWROOT,
|
|
341
|
+
post('/session/:sessionId/shadow/:id/elements'),
|
|
342
|
+
],
|
|
424
343
|
// Log extensions.
|
|
425
344
|
[cmd.Name.GET_LOG, post('/session/:sessionId/se/log')],
|
|
426
345
|
[cmd.Name.GET_AVAILABLE_LOG_TYPES, get('/session/:sessionId/se/log/types')],
|
|
346
|
+
|
|
347
|
+
// Server Extensions
|
|
348
|
+
[cmd.Name.UPLOAD_FILE, post('/session/:sessionId/se/file')],
|
|
427
349
|
])
|
|
428
350
|
|
|
429
351
|
/**
|
|
@@ -441,37 +363,29 @@ class Client {
|
|
|
441
363
|
* @return {!Promise<Response>} A promise that will be fulfilled with the
|
|
442
364
|
* server's response.
|
|
443
365
|
*/
|
|
444
|
-
send(httpRequest) {} // eslint-disable-line
|
|
366
|
+
send(httpRequest) { } // eslint-disable-line
|
|
445
367
|
}
|
|
446
368
|
|
|
447
369
|
/**
|
|
448
370
|
* @param {Map<string, CommandSpec>} customCommands
|
|
449
371
|
* A map of custom command definitions.
|
|
450
|
-
* @param {boolean} w3c Whether to use W3C command mappings.
|
|
451
372
|
* @param {!cmd.Command} command The command to resolve.
|
|
452
373
|
* @return {!Request} A promise that will resolve with the
|
|
453
374
|
* command to execute.
|
|
454
375
|
*/
|
|
455
|
-
function buildRequest(customCommands,
|
|
376
|
+
function buildRequest(customCommands, command) {
|
|
456
377
|
LOG.finest(() => `Translating command: ${command.getName()}`)
|
|
457
378
|
let spec = customCommands && customCommands.get(command.getName())
|
|
458
379
|
if (spec) {
|
|
459
380
|
return toHttpRequest(spec)
|
|
460
381
|
}
|
|
461
382
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
} else if (spec) {
|
|
469
|
-
return toHttpRequest(spec)
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
spec = COMMAND_MAP.get(command.getName())
|
|
474
|
-
if (spec) {
|
|
383
|
+
spec = W3C_COMMAND_MAP.get(command.getName())
|
|
384
|
+
if (typeof spec === 'function') {
|
|
385
|
+
LOG.finest(() => `Transforming command for W3C: ${command.getName()}`)
|
|
386
|
+
let newCommand = spec(command)
|
|
387
|
+
return buildRequest(customCommands, newCommand)
|
|
388
|
+
} else if (spec) {
|
|
475
389
|
return toHttpRequest(spec)
|
|
476
390
|
}
|
|
477
391
|
throw new error.UnknownCommandError(
|
|
@@ -515,15 +429,6 @@ class Executor {
|
|
|
515
429
|
constructor(client) {
|
|
516
430
|
CLIENTS.set(this, client)
|
|
517
431
|
|
|
518
|
-
/**
|
|
519
|
-
* Whether this executor should use the W3C wire protocol. The executor
|
|
520
|
-
* will automatically switch if the remote end sends a compliant response
|
|
521
|
-
* to a new session command, however, this property may be directly set to
|
|
522
|
-
* `true` to force the executor into W3C mode.
|
|
523
|
-
* @type {boolean}
|
|
524
|
-
*/
|
|
525
|
-
this.w3c = false
|
|
526
|
-
|
|
527
432
|
/** @private {Map<string, CommandSpec>} */
|
|
528
433
|
this.customCommands_ = null
|
|
529
434
|
|
|
@@ -553,7 +458,7 @@ class Executor {
|
|
|
553
458
|
|
|
554
459
|
/** @override */
|
|
555
460
|
async execute(command) {
|
|
556
|
-
let request = buildRequest(this.customCommands_,
|
|
461
|
+
let request = buildRequest(this.customCommands_, command)
|
|
557
462
|
this.log_.finer(() => `>>> ${request.method} ${request.path}`)
|
|
558
463
|
|
|
559
464
|
let client = CLIENTS.get(this)
|
|
@@ -654,7 +559,7 @@ function parseHttpResponse(command, httpResponse) {
|
|
|
654
559
|
|
|
655
560
|
// 404 represents an unknown command; anything else > 399 is a generic unknown
|
|
656
561
|
// error.
|
|
657
|
-
if (httpResponse.status
|
|
562
|
+
if (httpResponse.status === 404) {
|
|
658
563
|
throw new error.UnsupportedOperationError(command.getName() + ': ' + value)
|
|
659
564
|
} else if (httpResponse.status >= 400) {
|
|
660
565
|
throw new error.WebDriverError(value)
|
|
@@ -698,8 +603,11 @@ function buildPath(path, parameters) {
|
|
|
698
603
|
|
|
699
604
|
// PUBLIC API
|
|
700
605
|
|
|
701
|
-
exports
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
606
|
+
module.exports = {
|
|
607
|
+
Executor: Executor,
|
|
608
|
+
Client: Client,
|
|
609
|
+
Request: Request,
|
|
610
|
+
Response: Response,
|
|
611
|
+
// Exported for testing.
|
|
612
|
+
buildPath: buildPath
|
|
613
|
+
}
|
package/lib/input.js
CHANGED
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