selenium-webdriver 4.0.0-alpha.7 → 4.0.0-alpha.8
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/.eslintrc.js +27 -0
- package/.prettierrc +4 -0
- package/CHANGES.md +21 -0
- package/README.md +2 -0
- package/chrome.js +69 -79
- package/chromium.js +423 -161
- package/devtools/CDPConnection.js +37 -0
- package/devtools/generator/protocol-dts-generator.js +429 -0
- package/edge.js +57 -58
- package/firefox.js +200 -202
- package/http/index.js +128 -116
- package/http/util.js +56 -64
- package/ie.js +180 -104
- package/index.js +246 -199
- package/io/exec.js +34 -39
- package/io/index.js +141 -151
- package/io/zip.js +75 -65
- package/lib/actions.js +137 -120
- package/lib/atoms/find-elements.js +123 -0
- package/lib/atoms/get-attribute.js +79 -59
- package/lib/atoms/is-displayed.js +72 -72
- package/lib/atoms/make-atoms-module.js +13 -7
- package/lib/by.js +192 -65
- package/lib/capabilities.js +75 -84
- package/lib/command.js +17 -20
- package/lib/error.js +134 -168
- package/lib/http.js +321 -232
- package/lib/input.js +319 -296
- package/lib/logging.js +126 -137
- package/lib/promise.js +60 -66
- package/lib/proxy.js +31 -41
- package/lib/session.js +12 -15
- package/lib/symbols.js +3 -4
- package/lib/until.js +162 -162
- package/lib/webdriver.js +711 -530
- package/net/index.js +30 -36
- package/net/portprober.js +30 -143
- package/opera.js +406 -0
- package/package.json +14 -6
- package/proxy.js +2 -2
- package/remote/index.js +190 -187
- package/safari.js +40 -49
package/lib/webdriver.js
CHANGED
|
@@ -19,33 +19,31 @@
|
|
|
19
19
|
* @fileoverview The heart of the WebDriver JavaScript API.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
'use strict'
|
|
23
|
-
|
|
24
|
-
const by = require('./by')
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const {
|
|
33
|
-
|
|
22
|
+
'use strict'
|
|
23
|
+
|
|
24
|
+
const by = require('./by')
|
|
25
|
+
const { RelativeBy } = require('./by')
|
|
26
|
+
const command = require('./command')
|
|
27
|
+
const error = require('./error')
|
|
28
|
+
const input = require('./input')
|
|
29
|
+
const logging = require('./logging')
|
|
30
|
+
const promise = require('./promise')
|
|
31
|
+
const Symbols = require('./symbols')
|
|
32
|
+
const { Capabilities } = require('./capabilities')
|
|
34
33
|
|
|
35
34
|
// Capability names that are defined in the W3C spec.
|
|
36
35
|
const W3C_CAPABILITY_NAMES = new Set([
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
])
|
|
48
|
-
|
|
36
|
+
'acceptInsecureCerts',
|
|
37
|
+
'browserName',
|
|
38
|
+
'browserVersion',
|
|
39
|
+
'platformName',
|
|
40
|
+
'pageLoadStrategy',
|
|
41
|
+
'proxy',
|
|
42
|
+
'setWindowRect',
|
|
43
|
+
'timeouts',
|
|
44
|
+
'strictFileInteractability',
|
|
45
|
+
'unhandledPromptBehavior',
|
|
46
|
+
])
|
|
49
47
|
|
|
50
48
|
/**
|
|
51
49
|
* Defines a condition for use with WebDriver's {@linkplain WebDriver#wait wait
|
|
@@ -62,19 +60,18 @@ class Condition {
|
|
|
62
60
|
*/
|
|
63
61
|
constructor(message, fn) {
|
|
64
62
|
/** @private {string} */
|
|
65
|
-
this.description_ = 'Waiting ' + message
|
|
63
|
+
this.description_ = 'Waiting ' + message
|
|
66
64
|
|
|
67
65
|
/** @type {function(!WebDriver): OUT} */
|
|
68
|
-
this.fn = fn
|
|
66
|
+
this.fn = fn
|
|
69
67
|
}
|
|
70
68
|
|
|
71
69
|
/** @return {string} A description of this condition. */
|
|
72
70
|
description() {
|
|
73
|
-
return this.description_
|
|
71
|
+
return this.description_
|
|
74
72
|
}
|
|
75
73
|
}
|
|
76
74
|
|
|
77
|
-
|
|
78
75
|
/**
|
|
79
76
|
* Defines a condition that will result in a {@link WebElement}.
|
|
80
77
|
*
|
|
@@ -89,18 +86,16 @@ class WebElementCondition extends Condition {
|
|
|
89
86
|
* loop.
|
|
90
87
|
*/
|
|
91
88
|
constructor(message, fn) {
|
|
92
|
-
super(message, fn)
|
|
89
|
+
super(message, fn)
|
|
93
90
|
}
|
|
94
91
|
}
|
|
95
92
|
|
|
96
|
-
|
|
97
93
|
//////////////////////////////////////////////////////////////////////////////
|
|
98
94
|
//
|
|
99
95
|
// WebDriver
|
|
100
96
|
//
|
|
101
97
|
//////////////////////////////////////////////////////////////////////////////
|
|
102
98
|
|
|
103
|
-
|
|
104
99
|
/**
|
|
105
100
|
* Translates a command to its wire-protocol representation before passing it
|
|
106
101
|
* to the given `executor` for execution.
|
|
@@ -109,14 +104,12 @@ class WebElementCondition extends Condition {
|
|
|
109
104
|
* @return {!Promise} A promise that will resolve with the command response.
|
|
110
105
|
*/
|
|
111
106
|
function executeCommand(executor, command) {
|
|
112
|
-
return toWireValue(command.getParameters()).
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
});
|
|
107
|
+
return toWireValue(command.getParameters()).then(function (parameters) {
|
|
108
|
+
command.setParameters(parameters)
|
|
109
|
+
return executor.execute(command)
|
|
110
|
+
})
|
|
117
111
|
}
|
|
118
112
|
|
|
119
|
-
|
|
120
113
|
/**
|
|
121
114
|
* Converts an object to its JSON representation in the WebDriver wire protocol.
|
|
122
115
|
* When converting values of type object, the following steps will be taken:
|
|
@@ -136,64 +129,62 @@ function executeCommand(executor, command) {
|
|
|
136
129
|
* representation.
|
|
137
130
|
*/
|
|
138
131
|
async function toWireValue(obj) {
|
|
139
|
-
let value = await Promise.resolve(obj)
|
|
132
|
+
let value = await Promise.resolve(obj)
|
|
140
133
|
if (value === void 0 || value === null) {
|
|
141
|
-
return value
|
|
134
|
+
return value
|
|
142
135
|
}
|
|
143
136
|
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
137
|
+
if (
|
|
138
|
+
typeof value === 'boolean' ||
|
|
139
|
+
typeof value === 'number' ||
|
|
140
|
+
typeof value === 'string'
|
|
141
|
+
) {
|
|
142
|
+
return value
|
|
148
143
|
}
|
|
149
144
|
|
|
150
145
|
if (Array.isArray(value)) {
|
|
151
|
-
return convertKeys(value)
|
|
146
|
+
return convertKeys(value)
|
|
152
147
|
}
|
|
153
148
|
|
|
154
149
|
if (typeof value === 'function') {
|
|
155
|
-
return '' + value
|
|
150
|
+
return '' + value
|
|
156
151
|
}
|
|
157
152
|
|
|
158
153
|
if (typeof value[Symbols.serialize] === 'function') {
|
|
159
|
-
return toWireValue(value[Symbols.serialize]())
|
|
154
|
+
return toWireValue(value[Symbols.serialize]())
|
|
160
155
|
} else if (typeof value.toJSON === 'function') {
|
|
161
|
-
return toWireValue(value.toJSON())
|
|
156
|
+
return toWireValue(value.toJSON())
|
|
162
157
|
}
|
|
163
|
-
return convertKeys(value)
|
|
158
|
+
return convertKeys(value)
|
|
164
159
|
}
|
|
165
160
|
|
|
166
|
-
|
|
167
161
|
async function convertKeys(obj) {
|
|
168
|
-
const isArray = Array.isArray(obj)
|
|
169
|
-
const numKeys = isArray ? obj.length : Object.keys(obj).length
|
|
170
|
-
const ret = isArray ? new Array(numKeys) : {}
|
|
162
|
+
const isArray = Array.isArray(obj)
|
|
163
|
+
const numKeys = isArray ? obj.length : Object.keys(obj).length
|
|
164
|
+
const ret = isArray ? new Array(numKeys) : {}
|
|
171
165
|
if (!numKeys) {
|
|
172
|
-
return ret
|
|
166
|
+
return ret
|
|
173
167
|
}
|
|
174
168
|
|
|
175
|
-
let numResolved = 0;
|
|
176
|
-
|
|
177
169
|
async function forEachKey(obj, fn) {
|
|
178
170
|
if (Array.isArray(obj)) {
|
|
179
171
|
for (let i = 0, n = obj.length; i < n; i++) {
|
|
180
|
-
await fn(obj[i], i)
|
|
172
|
+
await fn(obj[i], i)
|
|
181
173
|
}
|
|
182
174
|
} else {
|
|
183
175
|
for (let key in obj) {
|
|
184
|
-
await fn(obj[key], key)
|
|
176
|
+
await fn(obj[key], key)
|
|
185
177
|
}
|
|
186
178
|
}
|
|
187
179
|
}
|
|
188
180
|
|
|
189
|
-
await forEachKey(obj, async function(value, key) {
|
|
190
|
-
ret[key] = await toWireValue(value)
|
|
191
|
-
})
|
|
181
|
+
await forEachKey(obj, async function (value, key) {
|
|
182
|
+
ret[key] = await toWireValue(value)
|
|
183
|
+
})
|
|
192
184
|
|
|
193
|
-
return ret
|
|
185
|
+
return ret
|
|
194
186
|
}
|
|
195
187
|
|
|
196
|
-
|
|
197
188
|
/**
|
|
198
189
|
* Converts a value from its JSON representation according to the WebDriver wire
|
|
199
190
|
* protocol. Any JSON object that defines a WebElement ID will be decoded to a
|
|
@@ -206,22 +197,32 @@ async function convertKeys(obj) {
|
|
|
206
197
|
*/
|
|
207
198
|
function fromWireValue(driver, value) {
|
|
208
199
|
if (Array.isArray(value)) {
|
|
209
|
-
value = value.map(v => fromWireValue(driver, v))
|
|
200
|
+
value = value.map((v) => fromWireValue(driver, v))
|
|
210
201
|
} else if (WebElement.isId(value)) {
|
|
211
|
-
let id = WebElement.extractId(value)
|
|
212
|
-
value = new WebElement(driver, id)
|
|
202
|
+
let id = WebElement.extractId(value)
|
|
203
|
+
value = new WebElement(driver, id)
|
|
213
204
|
} else if (value && typeof value === 'object') {
|
|
214
|
-
let result = {}
|
|
205
|
+
let result = {}
|
|
215
206
|
for (let key in value) {
|
|
216
|
-
if (
|
|
217
|
-
result[key] = fromWireValue(driver, value[key])
|
|
207
|
+
if (Object.prototype.hasOwnProperty.call(value, key)) {
|
|
208
|
+
result[key] = fromWireValue(driver, value[key])
|
|
218
209
|
}
|
|
219
210
|
}
|
|
220
|
-
value = result
|
|
211
|
+
value = result
|
|
221
212
|
}
|
|
222
|
-
return value
|
|
213
|
+
return value
|
|
223
214
|
}
|
|
224
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Resolves a wait message from either a function or a string.
|
|
218
|
+
* @param {(string|Function)=} message An optional message to use if the wait times out.
|
|
219
|
+
* @return {string} The resolved message
|
|
220
|
+
*/
|
|
221
|
+
function resolveWaitMessage(message) {
|
|
222
|
+
return message
|
|
223
|
+
? `${typeof message === 'function' ? message() : message}\n`
|
|
224
|
+
: ''
|
|
225
|
+
}
|
|
225
226
|
|
|
226
227
|
/**
|
|
227
228
|
* Structural interface for a WebDriver client.
|
|
@@ -229,7 +230,6 @@ function fromWireValue(driver, value) {
|
|
|
229
230
|
* @record
|
|
230
231
|
*/
|
|
231
232
|
class IWebDriver {
|
|
232
|
-
|
|
233
233
|
/**
|
|
234
234
|
* Executes the provided {@link command.Command} using this driver's
|
|
235
235
|
* {@link command.Executor}.
|
|
@@ -239,14 +239,14 @@ class IWebDriver {
|
|
|
239
239
|
* result.
|
|
240
240
|
* @template T
|
|
241
241
|
*/
|
|
242
|
-
execute(command) {}
|
|
242
|
+
execute(command) {} // eslint-disable-line
|
|
243
243
|
|
|
244
244
|
/**
|
|
245
245
|
* Sets the {@linkplain input.FileDetector file detector} that should be
|
|
246
246
|
* used with this instance.
|
|
247
247
|
* @param {input.FileDetector} detector The detector to use or `null`.
|
|
248
248
|
*/
|
|
249
|
-
setFileDetector(detector) {}
|
|
249
|
+
setFileDetector(detector) {} // eslint-disable-line
|
|
250
250
|
|
|
251
251
|
/**
|
|
252
252
|
* @return {!command.Executor} The command executor used by this instance.
|
|
@@ -285,7 +285,7 @@ class IWebDriver {
|
|
|
285
285
|
* for details).
|
|
286
286
|
* @return {!input.Actions} A new action sequence for this instance.
|
|
287
287
|
*/
|
|
288
|
-
actions(options) {}
|
|
288
|
+
actions(options) {} // eslint-disable-line
|
|
289
289
|
|
|
290
290
|
/**
|
|
291
291
|
* Executes a snippet of JavaScript in the context of the currently selected
|
|
@@ -323,7 +323,7 @@ class IWebDriver {
|
|
|
323
323
|
* scripts return value.
|
|
324
324
|
* @template T
|
|
325
325
|
*/
|
|
326
|
-
executeScript(script, ...args) {}
|
|
326
|
+
executeScript(script, ...args) {} // eslint-disable-line
|
|
327
327
|
|
|
328
328
|
/**
|
|
329
329
|
* Executes a snippet of asynchronous JavaScript in the context of the
|
|
@@ -400,7 +400,7 @@ class IWebDriver {
|
|
|
400
400
|
* value.
|
|
401
401
|
* @template T
|
|
402
402
|
*/
|
|
403
|
-
executeAsyncScript(script, ...args) {}
|
|
403
|
+
executeAsyncScript(script, ...args) {} // eslint-disable-line
|
|
404
404
|
|
|
405
405
|
/**
|
|
406
406
|
* Waits for a condition to evaluate to a "truthy" value. The condition may be
|
|
@@ -435,7 +435,7 @@ class IWebDriver {
|
|
|
435
435
|
* evaluate as a condition.
|
|
436
436
|
* @param {number=} timeout The duration in milliseconds, how long to wait
|
|
437
437
|
* for the condition to be true.
|
|
438
|
-
* @param {string=} message An optional message to use if the wait times out.
|
|
438
|
+
* @param {(string|Function)=} message An optional message to use if the wait times out.
|
|
439
439
|
* @param {number=} pollTimeout The duration in milliseconds, how long to
|
|
440
440
|
* wait between polling the condition.
|
|
441
441
|
* @return {!(IThenable<T>|WebElementPromise)} A promise that will be
|
|
@@ -446,7 +446,12 @@ class IWebDriver {
|
|
|
446
446
|
* @throws {TypeError} if the provided `condition` is not a valid type.
|
|
447
447
|
* @template T
|
|
448
448
|
*/
|
|
449
|
-
wait(
|
|
449
|
+
wait(
|
|
450
|
+
condition, // eslint-disable-line
|
|
451
|
+
timeout = undefined, // eslint-disable-line
|
|
452
|
+
message = undefined, // eslint-disable-line
|
|
453
|
+
pollTimeout = undefined // eslint-disable-line
|
|
454
|
+
) {}
|
|
450
455
|
|
|
451
456
|
/**
|
|
452
457
|
* Makes the driver sleep for the given amount of time.
|
|
@@ -455,7 +460,7 @@ class IWebDriver {
|
|
|
455
460
|
* @return {!Promise<void>} A promise that will be resolved when the sleep has
|
|
456
461
|
* finished.
|
|
457
462
|
*/
|
|
458
|
-
sleep(ms) {}
|
|
463
|
+
sleep(ms) {} // eslint-disable-line
|
|
459
464
|
|
|
460
465
|
/**
|
|
461
466
|
* Retrieves the current window handle.
|
|
@@ -474,7 +479,7 @@ class IWebDriver {
|
|
|
474
479
|
getAllWindowHandles() {}
|
|
475
480
|
|
|
476
481
|
/**
|
|
477
|
-
* Retrieves the current page's source. The returned
|
|
482
|
+
* Retrieves the current page's source. The returned source is a representation
|
|
478
483
|
* of the underlying DOM: do not expect it to be formatted or escaped in the
|
|
479
484
|
* same way as the raw response sent from the web server.
|
|
480
485
|
*
|
|
@@ -498,7 +503,7 @@ class IWebDriver {
|
|
|
498
503
|
* @return {!Promise<void>} A promise that will be resolved when the document
|
|
499
504
|
* has finished loading.
|
|
500
505
|
*/
|
|
501
|
-
get(url) {}
|
|
506
|
+
get(url) {} // eslint-disable-line
|
|
502
507
|
|
|
503
508
|
/**
|
|
504
509
|
* Retrieves the URL for the current page.
|
|
@@ -518,7 +523,7 @@ class IWebDriver {
|
|
|
518
523
|
|
|
519
524
|
/**
|
|
520
525
|
* Locates an element on the page. If the element cannot be found, a
|
|
521
|
-
* {@link error.
|
|
526
|
+
* {@link error.NoSuchElementError} will be returned by the driver.
|
|
522
527
|
*
|
|
523
528
|
* This function should not be used to test whether an element is present on
|
|
524
529
|
* the page. Rather, you should use {@link #findElements}:
|
|
@@ -554,7 +559,7 @@ class IWebDriver {
|
|
|
554
559
|
* commands against the located element. If the element is not found, the
|
|
555
560
|
* element will be invalidated and all scheduled commands aborted.
|
|
556
561
|
*/
|
|
557
|
-
findElement(locator) {}
|
|
562
|
+
findElement(locator) {} // eslint-disable-line
|
|
558
563
|
|
|
559
564
|
/**
|
|
560
565
|
* Search for multiple elements on the page. Refer to the documentation on
|
|
@@ -564,7 +569,7 @@ class IWebDriver {
|
|
|
564
569
|
* @return {!Promise<!Array<!WebElement>>} A promise that will resolve to an
|
|
565
570
|
* array of WebElements.
|
|
566
571
|
*/
|
|
567
|
-
findElements(locator) {}
|
|
572
|
+
findElements(locator) {} // eslint-disable-line
|
|
568
573
|
|
|
569
574
|
/**
|
|
570
575
|
* Takes a screenshot of the current page. The driver makes a best effort to
|
|
@@ -595,8 +600,26 @@ class IWebDriver {
|
|
|
595
600
|
* instance.
|
|
596
601
|
*/
|
|
597
602
|
switchTo() {}
|
|
598
|
-
}
|
|
599
603
|
|
|
604
|
+
/**
|
|
605
|
+
*
|
|
606
|
+
* Takes a PDF of the current page. The driver makes a best effort to
|
|
607
|
+
* return a PDF based on the provided parameters.
|
|
608
|
+
*
|
|
609
|
+
* @param {{orientation: (string|undefined),
|
|
610
|
+
* scale: (number|undefined),
|
|
611
|
+
* background: (boolean|undefined)
|
|
612
|
+
* width: (number|undefined)
|
|
613
|
+
* height: (number|undefined)
|
|
614
|
+
* top: (number|undefined)
|
|
615
|
+
* bottom: (number|undefined)
|
|
616
|
+
* left: (number|undefined)
|
|
617
|
+
* right: (number|undefined)
|
|
618
|
+
* shrinkToFit: (boolean|undefined)
|
|
619
|
+
* pageRanges: (<Array>|undefined)}} options.
|
|
620
|
+
*/
|
|
621
|
+
printPage(options) {} // eslint-disable-line
|
|
622
|
+
}
|
|
600
623
|
|
|
601
624
|
/**
|
|
602
625
|
* @param {!Capabilities} capabilities A capabilities object.
|
|
@@ -604,17 +627,16 @@ class IWebDriver {
|
|
|
604
627
|
* capability names that are not valid W3C names.
|
|
605
628
|
*/
|
|
606
629
|
function filterNonW3CCaps(capabilities) {
|
|
607
|
-
let newCaps = new Capabilities(capabilities)
|
|
630
|
+
let newCaps = new Capabilities(capabilities)
|
|
608
631
|
for (let k of newCaps.keys()) {
|
|
609
632
|
// Any key containing a colon is a vendor-prefixed capability.
|
|
610
633
|
if (!(W3C_CAPABILITY_NAMES.has(k) || k.indexOf(':') >= 0)) {
|
|
611
|
-
newCaps.delete(k)
|
|
634
|
+
newCaps.delete(k)
|
|
612
635
|
}
|
|
613
636
|
}
|
|
614
|
-
return newCaps
|
|
637
|
+
return newCaps
|
|
615
638
|
}
|
|
616
639
|
|
|
617
|
-
|
|
618
640
|
/**
|
|
619
641
|
* Each WebDriver instance provides automated control over a browser session.
|
|
620
642
|
*
|
|
@@ -631,21 +653,21 @@ class WebDriver {
|
|
|
631
653
|
*/
|
|
632
654
|
constructor(session, executor, onQuit = undefined) {
|
|
633
655
|
/** @private {!Promise<!Session>} */
|
|
634
|
-
this.session_ = Promise.resolve(session)
|
|
656
|
+
this.session_ = Promise.resolve(session)
|
|
635
657
|
|
|
636
658
|
// If session is a rejected promise, add a no-op rejection handler.
|
|
637
659
|
// This effectively hides setup errors until users attempt to interact
|
|
638
660
|
// with the session.
|
|
639
|
-
this.session_.catch(function() {})
|
|
661
|
+
this.session_.catch(function () {})
|
|
640
662
|
|
|
641
663
|
/** @private {!command.Executor} */
|
|
642
|
-
this.executor_ = executor
|
|
664
|
+
this.executor_ = executor
|
|
643
665
|
|
|
644
666
|
/** @private {input.FileDetector} */
|
|
645
|
-
this.fileDetector_ = null
|
|
667
|
+
this.fileDetector_ = null
|
|
646
668
|
|
|
647
669
|
/** @private @const {(function(this: void): ?|undefined)} */
|
|
648
|
-
this.onQuit_ = onQuit
|
|
670
|
+
this.onQuit_ = onQuit
|
|
649
671
|
}
|
|
650
672
|
|
|
651
673
|
/**
|
|
@@ -674,251 +696,288 @@ class WebDriver {
|
|
|
674
696
|
* @return {!WebDriver} The driver for the newly created session.
|
|
675
697
|
*/
|
|
676
698
|
static createSession(executor, capabilities, onQuit = undefined) {
|
|
677
|
-
let cmd = new command.Command(command.Name.NEW_SESSION)
|
|
699
|
+
let cmd = new command.Command(command.Name.NEW_SESSION)
|
|
678
700
|
|
|
679
701
|
// For OSS remote ends.
|
|
680
|
-
cmd.setParameter('desiredCapabilities', capabilities)
|
|
702
|
+
cmd.setParameter('desiredCapabilities', capabilities)
|
|
681
703
|
// For W3C remote ends.
|
|
682
704
|
cmd.setParameter('capabilities', {
|
|
683
705
|
alwaysMatch: filterNonW3CCaps(capabilities),
|
|
684
|
-
})
|
|
706
|
+
})
|
|
685
707
|
|
|
686
|
-
let session = executeCommand(executor, cmd)
|
|
708
|
+
let session = executeCommand(executor, cmd)
|
|
687
709
|
if (typeof onQuit === 'function') {
|
|
688
|
-
session = session.catch(err => {
|
|
689
|
-
return Promise.resolve(onQuit.call(void 0)).then(_ => {
|
|
690
|
-
|
|
710
|
+
session = session.catch((err) => {
|
|
711
|
+
return Promise.resolve(onQuit.call(void 0)).then((_) => {
|
|
712
|
+
throw err
|
|
713
|
+
})
|
|
714
|
+
})
|
|
691
715
|
}
|
|
692
|
-
return new this(session, executor, onQuit)
|
|
716
|
+
return new this(session, executor, onQuit)
|
|
693
717
|
}
|
|
694
718
|
|
|
695
719
|
/** @override */
|
|
696
720
|
async execute(command) {
|
|
697
|
-
command.setParameter('sessionId', this.session_)
|
|
698
|
-
let parameters = await toWireValue(command.getParameters())
|
|
699
|
-
command.setParameters(parameters)
|
|
700
|
-
let value = await this.executor_.execute(command)
|
|
701
|
-
return fromWireValue(this, value)
|
|
721
|
+
command.setParameter('sessionId', this.session_)
|
|
722
|
+
let parameters = await toWireValue(command.getParameters())
|
|
723
|
+
command.setParameters(parameters)
|
|
724
|
+
let value = await this.executor_.execute(command)
|
|
725
|
+
return fromWireValue(this, value)
|
|
702
726
|
}
|
|
703
727
|
|
|
704
728
|
/** @override */
|
|
705
729
|
setFileDetector(detector) {
|
|
706
|
-
this.fileDetector_ = detector
|
|
730
|
+
this.fileDetector_ = detector
|
|
707
731
|
}
|
|
708
732
|
|
|
709
733
|
/** @override */
|
|
710
734
|
getExecutor() {
|
|
711
|
-
return this.executor_
|
|
735
|
+
return this.executor_
|
|
712
736
|
}
|
|
713
737
|
|
|
714
738
|
/** @override */
|
|
715
739
|
getSession() {
|
|
716
|
-
return this.session_
|
|
740
|
+
return this.session_
|
|
717
741
|
}
|
|
718
742
|
|
|
719
743
|
/** @override */
|
|
720
744
|
getCapabilities() {
|
|
721
|
-
return this.session_.then(s => s.getCapabilities())
|
|
745
|
+
return this.session_.then((s) => s.getCapabilities())
|
|
722
746
|
}
|
|
723
747
|
|
|
724
748
|
/** @override */
|
|
725
749
|
quit() {
|
|
726
|
-
let result = this.execute(new command.Command(command.Name.QUIT))
|
|
750
|
+
let result = this.execute(new command.Command(command.Name.QUIT))
|
|
727
751
|
// Delete our session ID when the quit command finishes; this will allow us
|
|
728
752
|
// to throw an error when attempting to use a driver post-quit.
|
|
729
753
|
return promise.finally(result, () => {
|
|
730
|
-
this.session_ = Promise.reject(
|
|
731
|
-
|
|
732
|
-
|
|
754
|
+
this.session_ = Promise.reject(
|
|
755
|
+
new error.NoSuchSessionError(
|
|
756
|
+
'This driver instance does not have a valid session ID ' +
|
|
757
|
+
'(did you call WebDriver.quit()?) and may no longer be used.'
|
|
758
|
+
)
|
|
759
|
+
)
|
|
733
760
|
|
|
734
761
|
// Only want the session rejection to bubble if accessed.
|
|
735
|
-
this.session_.catch(function() {})
|
|
762
|
+
this.session_.catch(function () {})
|
|
736
763
|
|
|
737
764
|
if (this.onQuit_) {
|
|
738
|
-
return this.onQuit_.call(void 0)
|
|
765
|
+
return this.onQuit_.call(void 0)
|
|
739
766
|
}
|
|
740
|
-
})
|
|
767
|
+
})
|
|
741
768
|
}
|
|
742
769
|
|
|
743
770
|
/** @override */
|
|
744
771
|
actions(options) {
|
|
745
|
-
return new input.Actions(this, options || undefined)
|
|
772
|
+
return new input.Actions(this, options || undefined)
|
|
746
773
|
}
|
|
747
774
|
|
|
748
775
|
/** @override */
|
|
749
776
|
executeScript(script, ...args) {
|
|
750
777
|
if (typeof script === 'function') {
|
|
751
|
-
script = 'return (' + script + ').apply(null, arguments);'
|
|
778
|
+
script = 'return (' + script + ').apply(null, arguments);'
|
|
752
779
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
780
|
+
return this.execute(
|
|
781
|
+
new command.Command(command.Name.EXECUTE_SCRIPT)
|
|
782
|
+
.setParameter('script', script)
|
|
783
|
+
.setParameter('args', args)
|
|
784
|
+
)
|
|
757
785
|
}
|
|
758
786
|
|
|
759
787
|
/** @override */
|
|
760
788
|
executeAsyncScript(script, ...args) {
|
|
761
789
|
if (typeof script === 'function') {
|
|
762
|
-
script = 'return (' + script + ').apply(null, arguments);'
|
|
790
|
+
script = 'return (' + script + ').apply(null, arguments);'
|
|
763
791
|
}
|
|
764
792
|
return this.execute(
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
793
|
+
new command.Command(command.Name.EXECUTE_ASYNC_SCRIPT)
|
|
794
|
+
.setParameter('script', script)
|
|
795
|
+
.setParameter('args', args)
|
|
796
|
+
)
|
|
768
797
|
}
|
|
769
798
|
|
|
770
799
|
/** @override */
|
|
771
800
|
wait(condition, timeout = 0, message = undefined, pollTimeout = 200) {
|
|
772
801
|
if (typeof timeout !== 'number' || timeout < 0) {
|
|
773
|
-
throw TypeError('timeout must be a number >= 0: ' + timeout)
|
|
802
|
+
throw TypeError('timeout must be a number >= 0: ' + timeout)
|
|
774
803
|
}
|
|
775
804
|
|
|
776
805
|
if (typeof pollTimeout !== 'number' || pollTimeout < 0) {
|
|
777
|
-
throw TypeError('pollTimeout must be a number >= 0: ' + pollTimeout)
|
|
806
|
+
throw TypeError('pollTimeout must be a number >= 0: ' + pollTimeout)
|
|
778
807
|
}
|
|
779
808
|
|
|
780
809
|
if (promise.isPromise(condition)) {
|
|
781
810
|
return new Promise((resolve, reject) => {
|
|
782
811
|
if (!timeout) {
|
|
783
|
-
resolve(condition)
|
|
784
|
-
return
|
|
812
|
+
resolve(condition)
|
|
813
|
+
return
|
|
785
814
|
}
|
|
786
815
|
|
|
787
|
-
let start = Date.now()
|
|
788
|
-
let timer = setTimeout(function() {
|
|
789
|
-
timer = null
|
|
790
|
-
|
|
816
|
+
let start = Date.now()
|
|
817
|
+
let timer = setTimeout(function () {
|
|
818
|
+
timer = null
|
|
819
|
+
try {
|
|
820
|
+
let timeoutMessage = resolveWaitMessage(message)
|
|
821
|
+
reject(
|
|
822
|
+
new error.TimeoutError(
|
|
823
|
+
`${timeoutMessage}Timed out waiting for promise to resolve after ${
|
|
824
|
+
Date.now() - start
|
|
825
|
+
}ms`
|
|
826
|
+
)
|
|
827
|
+
)
|
|
828
|
+
} catch (ex) {
|
|
829
|
+
reject(
|
|
791
830
|
new error.TimeoutError(
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
831
|
+
`${
|
|
832
|
+
ex.message
|
|
833
|
+
}\nTimed out waiting for promise to resolve after ${
|
|
834
|
+
Date.now() - start
|
|
835
|
+
}ms`
|
|
836
|
+
)
|
|
837
|
+
)
|
|
838
|
+
}
|
|
839
|
+
}, timeout)
|
|
840
|
+
const clearTimer = () => timer && clearTimeout(timer)
|
|
841
|
+
|
|
842
|
+
/** @type {!IThenable} */ condition.then(
|
|
843
|
+
function (value) {
|
|
844
|
+
clearTimer()
|
|
845
|
+
resolve(value)
|
|
846
|
+
},
|
|
847
|
+
function (error) {
|
|
848
|
+
clearTimer()
|
|
849
|
+
reject(error)
|
|
850
|
+
}
|
|
851
|
+
)
|
|
852
|
+
})
|
|
808
853
|
}
|
|
809
854
|
|
|
810
|
-
let fn = /** @type {!Function} */(condition)
|
|
855
|
+
let fn = /** @type {!Function} */ (condition)
|
|
811
856
|
if (condition instanceof Condition) {
|
|
812
|
-
message = message || condition.description()
|
|
813
|
-
fn = condition.fn
|
|
857
|
+
message = message || condition.description()
|
|
858
|
+
fn = condition.fn
|
|
814
859
|
}
|
|
815
860
|
|
|
816
861
|
if (typeof fn !== 'function') {
|
|
817
862
|
throw TypeError(
|
|
818
|
-
|
|
819
|
-
|
|
863
|
+
'Wait condition must be a promise-like object, function, or a ' +
|
|
864
|
+
'Condition object'
|
|
865
|
+
)
|
|
820
866
|
}
|
|
821
867
|
|
|
822
|
-
const driver = this
|
|
868
|
+
const driver = this
|
|
823
869
|
function evaluateCondition() {
|
|
824
870
|
return new Promise((resolve, reject) => {
|
|
825
871
|
try {
|
|
826
|
-
resolve(fn(driver))
|
|
872
|
+
resolve(fn(driver))
|
|
827
873
|
} catch (ex) {
|
|
828
|
-
reject(ex)
|
|
874
|
+
reject(ex)
|
|
829
875
|
}
|
|
830
|
-
})
|
|
876
|
+
})
|
|
831
877
|
}
|
|
832
878
|
|
|
833
879
|
let result = new Promise((resolve, reject) => {
|
|
834
|
-
const startTime = Date.now()
|
|
880
|
+
const startTime = Date.now()
|
|
835
881
|
const pollCondition = async () => {
|
|
836
|
-
evaluateCondition().then(function(value) {
|
|
837
|
-
const elapsed = Date.now() - startTime
|
|
838
|
-
if (
|
|
839
|
-
resolve(value)
|
|
882
|
+
evaluateCondition().then(function (value) {
|
|
883
|
+
const elapsed = Date.now() - startTime
|
|
884
|
+
if (value) {
|
|
885
|
+
resolve(value)
|
|
840
886
|
} else if (timeout && elapsed >= timeout) {
|
|
841
|
-
|
|
887
|
+
try {
|
|
888
|
+
let timeoutMessage = resolveWaitMessage(message)
|
|
889
|
+
reject(
|
|
890
|
+
new error.TimeoutError(
|
|
891
|
+
`${timeoutMessage}Wait timed out after ${elapsed}ms`
|
|
892
|
+
)
|
|
893
|
+
)
|
|
894
|
+
} catch (ex) {
|
|
895
|
+
reject(
|
|
842
896
|
new error.TimeoutError(
|
|
843
|
-
|
|
844
|
-
|
|
897
|
+
`${ex.message}\nWait timed out after ${elapsed}ms`
|
|
898
|
+
)
|
|
899
|
+
)
|
|
900
|
+
}
|
|
845
901
|
} else {
|
|
846
|
-
setTimeout(pollCondition, pollTimeout)
|
|
902
|
+
setTimeout(pollCondition, pollTimeout)
|
|
847
903
|
}
|
|
848
|
-
}, reject)
|
|
849
|
-
}
|
|
850
|
-
pollCondition()
|
|
851
|
-
})
|
|
904
|
+
}, reject)
|
|
905
|
+
}
|
|
906
|
+
pollCondition()
|
|
907
|
+
})
|
|
852
908
|
|
|
853
909
|
if (condition instanceof WebElementCondition) {
|
|
854
|
-
result = new WebElementPromise(
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
910
|
+
result = new WebElementPromise(
|
|
911
|
+
this,
|
|
912
|
+
result.then(function (value) {
|
|
913
|
+
if (!(value instanceof WebElement)) {
|
|
914
|
+
throw TypeError(
|
|
915
|
+
'WebElementCondition did not resolve to a WebElement: ' +
|
|
916
|
+
Object.prototype.toString.call(value)
|
|
917
|
+
)
|
|
918
|
+
}
|
|
919
|
+
return value
|
|
920
|
+
})
|
|
921
|
+
)
|
|
862
922
|
}
|
|
863
|
-
return result
|
|
923
|
+
return result
|
|
864
924
|
}
|
|
865
925
|
|
|
866
926
|
/** @override */
|
|
867
927
|
sleep(ms) {
|
|
868
|
-
return new Promise(resolve => setTimeout(() => resolve(), ms))
|
|
928
|
+
return new Promise((resolve) => setTimeout(() => resolve(), ms))
|
|
869
929
|
}
|
|
870
930
|
|
|
871
931
|
/** @override */
|
|
872
932
|
getWindowHandle() {
|
|
873
933
|
return this.execute(
|
|
874
|
-
|
|
934
|
+
new command.Command(command.Name.GET_CURRENT_WINDOW_HANDLE)
|
|
935
|
+
)
|
|
875
936
|
}
|
|
876
937
|
|
|
877
938
|
/** @override */
|
|
878
939
|
getAllWindowHandles() {
|
|
879
|
-
return this.execute(
|
|
880
|
-
new command.Command(command.Name.GET_WINDOW_HANDLES));
|
|
940
|
+
return this.execute(new command.Command(command.Name.GET_WINDOW_HANDLES))
|
|
881
941
|
}
|
|
882
942
|
|
|
883
943
|
/** @override */
|
|
884
944
|
getPageSource() {
|
|
885
|
-
return this.execute(
|
|
886
|
-
new command.Command(command.Name.GET_PAGE_SOURCE));
|
|
945
|
+
return this.execute(new command.Command(command.Name.GET_PAGE_SOURCE))
|
|
887
946
|
}
|
|
888
947
|
|
|
889
948
|
/** @override */
|
|
890
949
|
close() {
|
|
891
|
-
return this.execute(new command.Command(command.Name.CLOSE))
|
|
950
|
+
return this.execute(new command.Command(command.Name.CLOSE))
|
|
892
951
|
}
|
|
893
952
|
|
|
894
953
|
/** @override */
|
|
895
954
|
get(url) {
|
|
896
|
-
return this.navigate().to(url)
|
|
955
|
+
return this.navigate().to(url)
|
|
897
956
|
}
|
|
898
957
|
|
|
899
958
|
/** @override */
|
|
900
959
|
getCurrentUrl() {
|
|
901
|
-
return this.execute(new command.Command(command.Name.GET_CURRENT_URL))
|
|
960
|
+
return this.execute(new command.Command(command.Name.GET_CURRENT_URL))
|
|
902
961
|
}
|
|
903
962
|
|
|
904
963
|
/** @override */
|
|
905
964
|
getTitle() {
|
|
906
|
-
return this.execute(new command.Command(command.Name.GET_TITLE))
|
|
965
|
+
return this.execute(new command.Command(command.Name.GET_TITLE))
|
|
907
966
|
}
|
|
908
967
|
|
|
909
968
|
/** @override */
|
|
910
969
|
findElement(locator) {
|
|
911
|
-
let id
|
|
912
|
-
locator = by.checkedLocator(locator)
|
|
970
|
+
let id
|
|
971
|
+
locator = by.checkedLocator(locator)
|
|
913
972
|
if (typeof locator === 'function') {
|
|
914
|
-
id = this.findElementInternal_(locator, this)
|
|
973
|
+
id = this.findElementInternal_(locator, this)
|
|
915
974
|
} else {
|
|
916
|
-
let cmd = new command.Command(command.Name.FIND_ELEMENT)
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
id = this.execute(cmd)
|
|
975
|
+
let cmd = new command.Command(command.Name.FIND_ELEMENT)
|
|
976
|
+
.setParameter('using', locator.using)
|
|
977
|
+
.setParameter('value', locator.value)
|
|
978
|
+
id = this.execute(cmd)
|
|
920
979
|
}
|
|
921
|
-
return new WebElementPromise(this, id)
|
|
980
|
+
return new WebElementPromise(this, id)
|
|
922
981
|
}
|
|
923
982
|
|
|
924
983
|
/**
|
|
@@ -929,34 +988,42 @@ class WebDriver {
|
|
|
929
988
|
* @private
|
|
930
989
|
*/
|
|
931
990
|
async findElementInternal_(locatorFn, context) {
|
|
932
|
-
let result = await locatorFn(context)
|
|
991
|
+
let result = await locatorFn(context)
|
|
933
992
|
if (Array.isArray(result)) {
|
|
934
|
-
result = result[0]
|
|
993
|
+
result = result[0]
|
|
935
994
|
}
|
|
936
995
|
if (!(result instanceof WebElement)) {
|
|
937
|
-
throw new TypeError('Custom locator did not return a WebElement')
|
|
996
|
+
throw new TypeError('Custom locator did not return a WebElement')
|
|
938
997
|
}
|
|
939
|
-
return result
|
|
998
|
+
return result
|
|
940
999
|
}
|
|
941
1000
|
|
|
942
1001
|
/** @override */
|
|
943
1002
|
async findElements(locator) {
|
|
944
|
-
|
|
945
|
-
if (
|
|
946
|
-
|
|
1003
|
+
let cmd = null
|
|
1004
|
+
if (locator instanceof RelativeBy) {
|
|
1005
|
+
cmd = new command.Command(
|
|
1006
|
+
command.Name.FIND_ELEMENTS_RELATIVE
|
|
1007
|
+
).setParameter('args', locator.marshall())
|
|
947
1008
|
} else {
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1009
|
+
locator = by.checkedLocator(locator)
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
if (typeof locator === 'function') {
|
|
1013
|
+
return this.findElementsInternal_(locator, this)
|
|
1014
|
+
} else if (cmd === null) {
|
|
1015
|
+
cmd = new command.Command(command.Name.FIND_ELEMENTS)
|
|
1016
|
+
.setParameter('using', locator.using)
|
|
1017
|
+
.setParameter('value', locator.value)
|
|
1018
|
+
}
|
|
1019
|
+
try {
|
|
1020
|
+
let res = await this.execute(cmd)
|
|
1021
|
+
return Array.isArray(res) ? res : []
|
|
1022
|
+
} catch (ex) {
|
|
1023
|
+
if (ex instanceof error.NoSuchElementError) {
|
|
1024
|
+
return []
|
|
959
1025
|
}
|
|
1026
|
+
throw ex
|
|
960
1027
|
}
|
|
961
1028
|
}
|
|
962
1029
|
|
|
@@ -968,41 +1035,122 @@ class WebDriver {
|
|
|
968
1035
|
* @private
|
|
969
1036
|
*/
|
|
970
1037
|
async findElementsInternal_(locatorFn, context) {
|
|
971
|
-
const result = await locatorFn(context)
|
|
1038
|
+
const result = await locatorFn(context)
|
|
972
1039
|
if (result instanceof WebElement) {
|
|
973
|
-
return [result]
|
|
1040
|
+
return [result]
|
|
974
1041
|
}
|
|
975
1042
|
|
|
976
1043
|
if (!Array.isArray(result)) {
|
|
977
|
-
return []
|
|
1044
|
+
return []
|
|
978
1045
|
}
|
|
979
1046
|
|
|
980
|
-
return result.filter(function(item) {
|
|
981
|
-
return item instanceof WebElement
|
|
982
|
-
})
|
|
1047
|
+
return result.filter(function (item) {
|
|
1048
|
+
return item instanceof WebElement
|
|
1049
|
+
})
|
|
983
1050
|
}
|
|
984
1051
|
|
|
985
1052
|
/** @override */
|
|
986
1053
|
takeScreenshot() {
|
|
987
|
-
return this.execute(new command.Command(command.Name.SCREENSHOT))
|
|
1054
|
+
return this.execute(new command.Command(command.Name.SCREENSHOT))
|
|
988
1055
|
}
|
|
989
1056
|
|
|
990
1057
|
/** @override */
|
|
991
1058
|
manage() {
|
|
992
|
-
return new Options(this)
|
|
1059
|
+
return new Options(this)
|
|
993
1060
|
}
|
|
994
1061
|
|
|
995
1062
|
/** @override */
|
|
996
1063
|
navigate() {
|
|
997
|
-
return new Navigation(this)
|
|
1064
|
+
return new Navigation(this)
|
|
998
1065
|
}
|
|
999
1066
|
|
|
1000
1067
|
/** @override */
|
|
1001
1068
|
switchTo() {
|
|
1002
|
-
return new TargetLocator(this)
|
|
1069
|
+
return new TargetLocator(this)
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
validatePrintPageParams(keys, object) {
|
|
1073
|
+
let page = {}
|
|
1074
|
+
let margin = {}
|
|
1075
|
+
let data
|
|
1076
|
+
Object.keys(keys).forEach(function (key) {
|
|
1077
|
+
data = keys[key]
|
|
1078
|
+
let obj = {
|
|
1079
|
+
orientation: function () {
|
|
1080
|
+
object.orientation = data
|
|
1081
|
+
},
|
|
1082
|
+
|
|
1083
|
+
scale: function () {
|
|
1084
|
+
object.scale = data
|
|
1085
|
+
},
|
|
1086
|
+
|
|
1087
|
+
background: function () {
|
|
1088
|
+
object.background = data
|
|
1089
|
+
},
|
|
1090
|
+
|
|
1091
|
+
width: function () {
|
|
1092
|
+
page.width = data
|
|
1093
|
+
object.page = page
|
|
1094
|
+
},
|
|
1095
|
+
|
|
1096
|
+
height: function () {
|
|
1097
|
+
page.height = data
|
|
1098
|
+
object.page = page
|
|
1099
|
+
},
|
|
1100
|
+
|
|
1101
|
+
top: function () {
|
|
1102
|
+
margin.top = data
|
|
1103
|
+
object.margin = margin
|
|
1104
|
+
},
|
|
1105
|
+
|
|
1106
|
+
left: function () {
|
|
1107
|
+
margin.left = data
|
|
1108
|
+
object.margin = margin
|
|
1109
|
+
},
|
|
1110
|
+
|
|
1111
|
+
bottom: function () {
|
|
1112
|
+
margin.bottom = data
|
|
1113
|
+
object.margin = margin
|
|
1114
|
+
},
|
|
1115
|
+
|
|
1116
|
+
right: function () {
|
|
1117
|
+
margin.right = data
|
|
1118
|
+
object.margin = margin
|
|
1119
|
+
},
|
|
1120
|
+
|
|
1121
|
+
shrinkToFit: function () {
|
|
1122
|
+
object.shrinkToFit = data
|
|
1123
|
+
},
|
|
1124
|
+
|
|
1125
|
+
pageRanges: function () {
|
|
1126
|
+
object.pageRanges = data
|
|
1127
|
+
},
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
1131
|
+
throw new error.InvalidArgumentError(`Invalid Argument '${key}'`)
|
|
1132
|
+
} else {
|
|
1133
|
+
obj[key]()
|
|
1134
|
+
}
|
|
1135
|
+
})
|
|
1136
|
+
|
|
1137
|
+
return object
|
|
1003
1138
|
}
|
|
1004
|
-
}
|
|
1005
1139
|
|
|
1140
|
+
/** @override */
|
|
1141
|
+
printPage(options = {}) {
|
|
1142
|
+
let keys = options
|
|
1143
|
+
let params = {}
|
|
1144
|
+
let resultObj
|
|
1145
|
+
|
|
1146
|
+
let self = this
|
|
1147
|
+
resultObj = self.validatePrintPageParams(keys, params)
|
|
1148
|
+
|
|
1149
|
+
return this.execute(
|
|
1150
|
+
new command.Command(command.Name.PRINT_PAGE).setParameters(resultObj)
|
|
1151
|
+
)
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1006
1154
|
|
|
1007
1155
|
/**
|
|
1008
1156
|
* Interface for navigating back and forth in the browser history.
|
|
@@ -1021,7 +1169,7 @@ class Navigation {
|
|
|
1021
1169
|
*/
|
|
1022
1170
|
constructor(driver) {
|
|
1023
1171
|
/** @private {!WebDriver} */
|
|
1024
|
-
this.driver_ = driver
|
|
1172
|
+
this.driver_ = driver
|
|
1025
1173
|
}
|
|
1026
1174
|
|
|
1027
1175
|
/**
|
|
@@ -1033,8 +1181,8 @@ class Navigation {
|
|
|
1033
1181
|
*/
|
|
1034
1182
|
to(url) {
|
|
1035
1183
|
return this.driver_.execute(
|
|
1036
|
-
|
|
1037
|
-
|
|
1184
|
+
new command.Command(command.Name.GET).setParameter('url', url)
|
|
1185
|
+
)
|
|
1038
1186
|
}
|
|
1039
1187
|
|
|
1040
1188
|
/**
|
|
@@ -1044,7 +1192,7 @@ class Navigation {
|
|
|
1044
1192
|
* navigation event has completed.
|
|
1045
1193
|
*/
|
|
1046
1194
|
back() {
|
|
1047
|
-
return this.driver_.execute(new command.Command(command.Name.GO_BACK))
|
|
1195
|
+
return this.driver_.execute(new command.Command(command.Name.GO_BACK))
|
|
1048
1196
|
}
|
|
1049
1197
|
|
|
1050
1198
|
/**
|
|
@@ -1054,7 +1202,7 @@ class Navigation {
|
|
|
1054
1202
|
* navigation event has completed.
|
|
1055
1203
|
*/
|
|
1056
1204
|
forward() {
|
|
1057
|
-
return this.driver_.execute(new command.Command(command.Name.GO_FORWARD))
|
|
1205
|
+
return this.driver_.execute(new command.Command(command.Name.GO_FORWARD))
|
|
1058
1206
|
}
|
|
1059
1207
|
|
|
1060
1208
|
/**
|
|
@@ -1064,11 +1212,10 @@ class Navigation {
|
|
|
1064
1212
|
* navigation event has completed.
|
|
1065
1213
|
*/
|
|
1066
1214
|
refresh() {
|
|
1067
|
-
return this.driver_.execute(new command.Command(command.Name.REFRESH))
|
|
1215
|
+
return this.driver_.execute(new command.Command(command.Name.REFRESH))
|
|
1068
1216
|
}
|
|
1069
1217
|
}
|
|
1070
1218
|
|
|
1071
|
-
|
|
1072
1219
|
/**
|
|
1073
1220
|
* Provides methods for managing browser and driver state.
|
|
1074
1221
|
*
|
|
@@ -1082,7 +1229,7 @@ class Options {
|
|
|
1082
1229
|
*/
|
|
1083
1230
|
constructor(driver) {
|
|
1084
1231
|
/** @private {!WebDriver} */
|
|
1085
|
-
this.driver_ = driver
|
|
1232
|
+
this.driver_ = driver
|
|
1086
1233
|
}
|
|
1087
1234
|
|
|
1088
1235
|
/**
|
|
@@ -1111,43 +1258,50 @@ class Options {
|
|
|
1111
1258
|
* invalid.
|
|
1112
1259
|
* @throws {TypeError} if `spec` is not a cookie object.
|
|
1113
1260
|
*/
|
|
1114
|
-
addCookie({name, value, path, domain, secure, httpOnly, expiry, sameSite}) {
|
|
1261
|
+
addCookie({ name, value, path, domain, secure, httpOnly, expiry, sameSite }) {
|
|
1115
1262
|
// We do not allow '=' or ';' in the name.
|
|
1116
1263
|
if (/[;=]/.test(name)) {
|
|
1117
|
-
throw new error.InvalidArgumentError(
|
|
1118
|
-
'Invalid cookie name "' + name + '"');
|
|
1264
|
+
throw new error.InvalidArgumentError('Invalid cookie name "' + name + '"')
|
|
1119
1265
|
}
|
|
1120
1266
|
|
|
1121
1267
|
// We do not allow ';' in value.
|
|
1122
1268
|
if (/;/.test(value)) {
|
|
1123
1269
|
throw new error.InvalidArgumentError(
|
|
1124
|
-
|
|
1270
|
+
'Invalid cookie value "' + value + '"'
|
|
1271
|
+
)
|
|
1125
1272
|
}
|
|
1126
1273
|
|
|
1127
1274
|
if (typeof expiry === 'number') {
|
|
1128
|
-
expiry = Math.floor(expiry)
|
|
1275
|
+
expiry = Math.floor(expiry)
|
|
1129
1276
|
} else if (expiry instanceof Date) {
|
|
1130
|
-
let date = /** @type {!Date} */(expiry)
|
|
1131
|
-
expiry = Math.floor(date.getTime() / 1000)
|
|
1277
|
+
let date = /** @type {!Date} */ (expiry)
|
|
1278
|
+
expiry = Math.floor(date.getTime() / 1000)
|
|
1132
1279
|
}
|
|
1133
1280
|
|
|
1134
|
-
if(sameSite &&
|
|
1281
|
+
if (sameSite && !['Strict', 'Lax', 'None'].includes(sameSite)) {
|
|
1135
1282
|
throw new error.InvalidArgumentError(
|
|
1136
|
-
|
|
1283
|
+
`Invalid sameSite cookie value '${sameSite}'. It should be one of "Lax", "Strict" or "None"`
|
|
1284
|
+
)
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
if (sameSite === 'None' && !secure) {
|
|
1288
|
+
throw new error.InvalidArgumentError(
|
|
1289
|
+
'Invalid cookie configuration: SameSite=None must be Secure'
|
|
1290
|
+
)
|
|
1137
1291
|
}
|
|
1138
1292
|
|
|
1139
1293
|
return this.driver_.execute(
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1294
|
+
new command.Command(command.Name.ADD_COOKIE).setParameter('cookie', {
|
|
1295
|
+
name: name,
|
|
1296
|
+
value: value,
|
|
1297
|
+
path: path,
|
|
1298
|
+
domain: domain,
|
|
1299
|
+
secure: !!secure,
|
|
1300
|
+
httpOnly: !!httpOnly,
|
|
1301
|
+
expiry: expiry,
|
|
1302
|
+
sameSite: sameSite,
|
|
1303
|
+
})
|
|
1304
|
+
)
|
|
1151
1305
|
}
|
|
1152
1306
|
|
|
1153
1307
|
/**
|
|
@@ -1158,7 +1312,8 @@ class Options {
|
|
|
1158
1312
|
*/
|
|
1159
1313
|
deleteAllCookies() {
|
|
1160
1314
|
return this.driver_.execute(
|
|
1161
|
-
|
|
1315
|
+
new command.Command(command.Name.DELETE_ALL_COOKIES)
|
|
1316
|
+
)
|
|
1162
1317
|
}
|
|
1163
1318
|
|
|
1164
1319
|
/**
|
|
@@ -1171,8 +1326,8 @@ class Options {
|
|
|
1171
1326
|
*/
|
|
1172
1327
|
deleteCookie(name) {
|
|
1173
1328
|
return this.driver_.execute(
|
|
1174
|
-
|
|
1175
|
-
|
|
1329
|
+
new command.Command(command.Name.DELETE_COOKIE).setParameter('name', name)
|
|
1330
|
+
)
|
|
1176
1331
|
}
|
|
1177
1332
|
|
|
1178
1333
|
/**
|
|
@@ -1184,7 +1339,8 @@ class Options {
|
|
|
1184
1339
|
*/
|
|
1185
1340
|
getCookies() {
|
|
1186
1341
|
return this.driver_.execute(
|
|
1187
|
-
|
|
1342
|
+
new command.Command(command.Name.GET_ALL_COOKIES)
|
|
1343
|
+
)
|
|
1188
1344
|
}
|
|
1189
1345
|
|
|
1190
1346
|
/**
|
|
@@ -1199,24 +1355,25 @@ class Options {
|
|
|
1199
1355
|
*/
|
|
1200
1356
|
async getCookie(name) {
|
|
1201
1357
|
try {
|
|
1202
|
-
const cookie =
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
return cookie;
|
|
1358
|
+
const cookie = await this.driver_.execute(
|
|
1359
|
+
new command.Command(command.Name.GET_COOKIE).setParameter('name', name)
|
|
1360
|
+
)
|
|
1361
|
+
return cookie
|
|
1207
1362
|
} catch (err) {
|
|
1208
|
-
if (
|
|
1209
|
-
|
|
1210
|
-
|
|
1363
|
+
if (
|
|
1364
|
+
!(err instanceof error.UnknownCommandError) &&
|
|
1365
|
+
!(err instanceof error.UnsupportedOperationError)
|
|
1366
|
+
) {
|
|
1367
|
+
throw err
|
|
1211
1368
|
}
|
|
1212
1369
|
|
|
1213
|
-
const cookies = await this.getCookies()
|
|
1370
|
+
const cookies = await this.getCookies()
|
|
1214
1371
|
for (let cookie of cookies) {
|
|
1215
1372
|
if (cookie && cookie['name'] === name) {
|
|
1216
|
-
return cookie
|
|
1373
|
+
return cookie
|
|
1217
1374
|
}
|
|
1218
1375
|
}
|
|
1219
|
-
return null
|
|
1376
|
+
return null
|
|
1220
1377
|
}
|
|
1221
1378
|
}
|
|
1222
1379
|
|
|
@@ -1231,7 +1388,7 @@ class Options {
|
|
|
1231
1388
|
* @see #setTimeouts()
|
|
1232
1389
|
*/
|
|
1233
1390
|
getTimeouts() {
|
|
1234
|
-
return this.driver_.execute(new command.Command(command.Name.GET_TIMEOUT))
|
|
1391
|
+
return this.driver_.execute(new command.Command(command.Name.GET_TIMEOUT))
|
|
1235
1392
|
}
|
|
1236
1393
|
|
|
1237
1394
|
/**
|
|
@@ -1263,60 +1420,59 @@ class Options {
|
|
|
1263
1420
|
* @see #getTimeouts()
|
|
1264
1421
|
* @see <https://w3c.github.io/webdriver/webdriver-spec.html#dfn-set-timeouts>
|
|
1265
1422
|
*/
|
|
1266
|
-
setTimeouts({script, pageLoad, implicit} = {}) {
|
|
1267
|
-
let cmd = new command.Command(command.Name.SET_TIMEOUT)
|
|
1423
|
+
setTimeouts({ script, pageLoad, implicit } = {}) {
|
|
1424
|
+
let cmd = new command.Command(command.Name.SET_TIMEOUT)
|
|
1268
1425
|
|
|
1269
|
-
let valid = false
|
|
1426
|
+
let valid = false
|
|
1270
1427
|
function setParam(key, value) {
|
|
1271
1428
|
if (value === null || typeof value === 'number') {
|
|
1272
|
-
valid = true
|
|
1273
|
-
cmd.setParameter(key, value)
|
|
1429
|
+
valid = true
|
|
1430
|
+
cmd.setParameter(key, value)
|
|
1274
1431
|
} else if (typeof value !== 'undefined') {
|
|
1275
1432
|
throw TypeError(
|
|
1276
|
-
|
|
1277
|
-
|
|
1433
|
+
'invalid timeouts configuration:' +
|
|
1434
|
+
` expected "${key}" to be a number, got ${typeof value}`
|
|
1435
|
+
)
|
|
1278
1436
|
}
|
|
1279
1437
|
}
|
|
1280
|
-
setParam('implicit', implicit)
|
|
1281
|
-
setParam('pageLoad', pageLoad)
|
|
1282
|
-
setParam('script', script)
|
|
1438
|
+
setParam('implicit', implicit)
|
|
1439
|
+
setParam('pageLoad', pageLoad)
|
|
1440
|
+
setParam('script', script)
|
|
1283
1441
|
|
|
1284
1442
|
if (valid) {
|
|
1285
|
-
return this.driver_.execute(cmd)
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
});
|
|
1443
|
+
return this.driver_.execute(cmd).catch(() => {
|
|
1444
|
+
// Fallback to the legacy method.
|
|
1445
|
+
let cmds = []
|
|
1446
|
+
if (typeof script === 'number') {
|
|
1447
|
+
cmds.push(legacyTimeout(this.driver_, 'script', script))
|
|
1448
|
+
}
|
|
1449
|
+
if (typeof implicit === 'number') {
|
|
1450
|
+
cmds.push(legacyTimeout(this.driver_, 'implicit', implicit))
|
|
1451
|
+
}
|
|
1452
|
+
if (typeof pageLoad === 'number') {
|
|
1453
|
+
cmds.push(legacyTimeout(this.driver_, 'page load', pageLoad))
|
|
1454
|
+
}
|
|
1455
|
+
return Promise.all(cmds)
|
|
1456
|
+
})
|
|
1300
1457
|
}
|
|
1301
|
-
throw TypeError('no timeouts specified')
|
|
1458
|
+
throw TypeError('no timeouts specified')
|
|
1302
1459
|
}
|
|
1303
1460
|
|
|
1304
1461
|
/**
|
|
1305
1462
|
* @return {!Logs} The interface for managing driver logs.
|
|
1306
1463
|
*/
|
|
1307
1464
|
logs() {
|
|
1308
|
-
return new Logs(this.driver_)
|
|
1465
|
+
return new Logs(this.driver_)
|
|
1309
1466
|
}
|
|
1310
1467
|
|
|
1311
1468
|
/**
|
|
1312
1469
|
* @return {!Window} The interface for managing the current window.
|
|
1313
1470
|
*/
|
|
1314
1471
|
window() {
|
|
1315
|
-
return new Window(this.driver_)
|
|
1472
|
+
return new Window(this.driver_)
|
|
1316
1473
|
}
|
|
1317
1474
|
}
|
|
1318
1475
|
|
|
1319
|
-
|
|
1320
1476
|
/**
|
|
1321
1477
|
* @param {!WebDriver} driver
|
|
1322
1478
|
* @param {string} type
|
|
@@ -1325,44 +1481,39 @@ class Options {
|
|
|
1325
1481
|
*/
|
|
1326
1482
|
function legacyTimeout(driver, type, ms) {
|
|
1327
1483
|
return driver.execute(
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1484
|
+
new command.Command(command.Name.SET_TIMEOUT)
|
|
1485
|
+
.setParameter('type', type)
|
|
1486
|
+
.setParameter('ms', ms)
|
|
1487
|
+
)
|
|
1331
1488
|
}
|
|
1332
1489
|
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
1490
|
/**
|
|
1336
1491
|
* A record object describing a browser cookie.
|
|
1337
1492
|
*
|
|
1338
1493
|
* @record
|
|
1339
1494
|
*/
|
|
1340
|
-
Options.Cookie = function() {}
|
|
1341
|
-
|
|
1495
|
+
Options.Cookie = function () {}
|
|
1342
1496
|
|
|
1343
1497
|
/**
|
|
1344
1498
|
* The name of the cookie.
|
|
1345
1499
|
*
|
|
1346
1500
|
* @type {string}
|
|
1347
1501
|
*/
|
|
1348
|
-
Options.Cookie.prototype.name
|
|
1349
|
-
|
|
1502
|
+
Options.Cookie.prototype.name
|
|
1350
1503
|
|
|
1351
1504
|
/**
|
|
1352
1505
|
* The cookie value.
|
|
1353
1506
|
*
|
|
1354
1507
|
* @type {string}
|
|
1355
1508
|
*/
|
|
1356
|
-
Options.Cookie.prototype.value
|
|
1357
|
-
|
|
1509
|
+
Options.Cookie.prototype.value
|
|
1358
1510
|
|
|
1359
1511
|
/**
|
|
1360
1512
|
* The cookie path. Defaults to "/" when adding a cookie.
|
|
1361
1513
|
*
|
|
1362
1514
|
* @type {(string|undefined)}
|
|
1363
1515
|
*/
|
|
1364
|
-
Options.Cookie.prototype.path
|
|
1365
|
-
|
|
1516
|
+
Options.Cookie.prototype.path
|
|
1366
1517
|
|
|
1367
1518
|
/**
|
|
1368
1519
|
* The domain the cookie is visible to. Defaults to the current browsing
|
|
@@ -1370,8 +1521,7 @@ Options.Cookie.prototype.path;
|
|
|
1370
1521
|
*
|
|
1371
1522
|
* @type {(string|undefined)}
|
|
1372
1523
|
*/
|
|
1373
|
-
Options.Cookie.prototype.domain
|
|
1374
|
-
|
|
1524
|
+
Options.Cookie.prototype.domain
|
|
1375
1525
|
|
|
1376
1526
|
/**
|
|
1377
1527
|
* Whether the cookie is a secure cookie. Defaults to false when adding a new
|
|
@@ -1379,8 +1529,7 @@ Options.Cookie.prototype.domain;
|
|
|
1379
1529
|
*
|
|
1380
1530
|
* @type {(boolean|undefined)}
|
|
1381
1531
|
*/
|
|
1382
|
-
Options.Cookie.prototype.secure
|
|
1383
|
-
|
|
1532
|
+
Options.Cookie.prototype.secure
|
|
1384
1533
|
|
|
1385
1534
|
/**
|
|
1386
1535
|
* Whether the cookie is an HTTP only cookie. Defaults to false when adding a
|
|
@@ -1388,8 +1537,7 @@ Options.Cookie.prototype.secure;
|
|
|
1388
1537
|
*
|
|
1389
1538
|
* @type {(boolean|undefined)}
|
|
1390
1539
|
*/
|
|
1391
|
-
Options.Cookie.prototype.httpOnly
|
|
1392
|
-
|
|
1540
|
+
Options.Cookie.prototype.httpOnly
|
|
1393
1541
|
|
|
1394
1542
|
/**
|
|
1395
1543
|
* When the cookie expires.
|
|
@@ -1402,19 +1550,18 @@ Options.Cookie.prototype.httpOnly;
|
|
|
1402
1550
|
*
|
|
1403
1551
|
* @type {(!Date|number|undefined)}
|
|
1404
1552
|
*/
|
|
1405
|
-
Options.Cookie.prototype.expiry
|
|
1406
|
-
|
|
1553
|
+
Options.Cookie.prototype.expiry
|
|
1407
1554
|
|
|
1408
1555
|
/**
|
|
1409
1556
|
* When the cookie applies to a SameSite policy.
|
|
1410
1557
|
*
|
|
1411
1558
|
* When {@linkplain Options#addCookie() adding a cookie}, this may be specified
|
|
1412
|
-
* as a {@link string} object which is
|
|
1559
|
+
* as a {@link string} object which is one of 'Lax', 'Strict' or 'None'.
|
|
1413
1560
|
*
|
|
1414
1561
|
*
|
|
1415
|
-
* @type {(
|
|
1562
|
+
* @type {(string|undefined)}
|
|
1416
1563
|
*/
|
|
1417
|
-
Options.Cookie.prototype.sameSite
|
|
1564
|
+
Options.Cookie.prototype.sameSite
|
|
1418
1565
|
|
|
1419
1566
|
/**
|
|
1420
1567
|
* An interface for managing the current window.
|
|
@@ -1434,7 +1581,7 @@ class Window {
|
|
|
1434
1581
|
*/
|
|
1435
1582
|
constructor(driver) {
|
|
1436
1583
|
/** @private {!WebDriver} */
|
|
1437
|
-
this.driver_ = driver
|
|
1584
|
+
this.driver_ = driver
|
|
1438
1585
|
}
|
|
1439
1586
|
|
|
1440
1587
|
/**
|
|
@@ -1447,20 +1594,25 @@ class Window {
|
|
|
1447
1594
|
async getRect() {
|
|
1448
1595
|
try {
|
|
1449
1596
|
return await this.driver_.execute(
|
|
1450
|
-
|
|
1597
|
+
new command.Command(command.Name.GET_WINDOW_RECT)
|
|
1598
|
+
)
|
|
1451
1599
|
} catch (ex) {
|
|
1452
1600
|
if (ex instanceof error.UnknownCommandError) {
|
|
1453
|
-
let {width, height} =
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1601
|
+
let { width, height } = await this.driver_.execute(
|
|
1602
|
+
new command.Command(command.Name.GET_WINDOW_SIZE).setParameter(
|
|
1603
|
+
'windowHandle',
|
|
1604
|
+
'current'
|
|
1605
|
+
)
|
|
1606
|
+
)
|
|
1607
|
+
let { x, y } = await this.driver_.execute(
|
|
1608
|
+
new command.Command(command.Name.GET_WINDOW_POSITION).setParameter(
|
|
1609
|
+
'windowHandle',
|
|
1610
|
+
'current'
|
|
1611
|
+
)
|
|
1612
|
+
)
|
|
1613
|
+
return { x, y, width, height }
|
|
1462
1614
|
}
|
|
1463
|
-
throw ex
|
|
1615
|
+
throw ex
|
|
1464
1616
|
}
|
|
1465
1617
|
}
|
|
1466
1618
|
|
|
@@ -1475,34 +1627,41 @@ class Window {
|
|
|
1475
1627
|
* height: (number|undefined)}} options
|
|
1476
1628
|
* The desired window size and position.
|
|
1477
1629
|
* @return {!Promise<{x: number, y: number, width: number, height: number}>}
|
|
1478
|
-
* A promise that will resolve to the current
|
|
1630
|
+
* A promise that will resolve to the current window's updated window
|
|
1479
1631
|
* rect.
|
|
1480
1632
|
*/
|
|
1481
|
-
async setRect({x, y, width, height}) {
|
|
1633
|
+
async setRect({ x, y, width, height }) {
|
|
1482
1634
|
try {
|
|
1483
1635
|
return await this.driver_.execute(
|
|
1484
|
-
|
|
1485
|
-
|
|
1636
|
+
new command.Command(command.Name.SET_WINDOW_RECT).setParameters({
|
|
1637
|
+
x,
|
|
1638
|
+
y,
|
|
1639
|
+
width,
|
|
1640
|
+
height,
|
|
1641
|
+
})
|
|
1642
|
+
)
|
|
1486
1643
|
} catch (ex) {
|
|
1487
1644
|
if (ex instanceof error.UnknownCommandError) {
|
|
1488
1645
|
if (typeof x === 'number' && typeof y === 'number') {
|
|
1489
1646
|
await this.driver_.execute(
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1647
|
+
new command.Command(command.Name.SET_WINDOW_POSITION)
|
|
1648
|
+
.setParameter('windowHandle', 'current')
|
|
1649
|
+
.setParameter('x', x)
|
|
1650
|
+
.setParameter('y', y)
|
|
1651
|
+
)
|
|
1494
1652
|
}
|
|
1495
1653
|
|
|
1496
|
-
if (typeof
|
|
1654
|
+
if (typeof width === 'number' && typeof height === 'number') {
|
|
1497
1655
|
await this.driver_.execute(
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1656
|
+
new command.Command(command.Name.SET_WINDOW_SIZE)
|
|
1657
|
+
.setParameter('windowHandle', 'current')
|
|
1658
|
+
.setParameter('width', width)
|
|
1659
|
+
.setParameter('height', height)
|
|
1660
|
+
)
|
|
1502
1661
|
}
|
|
1503
|
-
return this.getRect()
|
|
1662
|
+
return this.getRect()
|
|
1504
1663
|
}
|
|
1505
|
-
throw ex
|
|
1664
|
+
throw ex
|
|
1506
1665
|
}
|
|
1507
1666
|
}
|
|
1508
1667
|
|
|
@@ -1516,13 +1675,16 @@ class Window {
|
|
|
1516
1675
|
*/
|
|
1517
1676
|
maximize() {
|
|
1518
1677
|
return this.driver_.execute(
|
|
1519
|
-
|
|
1520
|
-
|
|
1678
|
+
new command.Command(command.Name.MAXIMIZE_WINDOW).setParameter(
|
|
1679
|
+
'windowHandle',
|
|
1680
|
+
'current'
|
|
1681
|
+
)
|
|
1682
|
+
)
|
|
1521
1683
|
}
|
|
1522
1684
|
|
|
1523
1685
|
/**
|
|
1524
1686
|
* Minimizes the current window. The exact behavior of this command is
|
|
1525
|
-
* specific to individual window managers, but
|
|
1687
|
+
* specific to individual window managers, but typically involves hiding
|
|
1526
1688
|
* the window in the system tray.
|
|
1527
1689
|
*
|
|
1528
1690
|
* @return {!Promise<void>} A promise that will be resolved when the command
|
|
@@ -1530,7 +1692,8 @@ class Window {
|
|
|
1530
1692
|
*/
|
|
1531
1693
|
minimize() {
|
|
1532
1694
|
return this.driver_.execute(
|
|
1533
|
-
|
|
1695
|
+
new command.Command(command.Name.MINIMIZE_WINDOW)
|
|
1696
|
+
)
|
|
1534
1697
|
}
|
|
1535
1698
|
|
|
1536
1699
|
/**
|
|
@@ -1545,11 +1708,11 @@ class Window {
|
|
|
1545
1708
|
*/
|
|
1546
1709
|
fullscreen() {
|
|
1547
1710
|
return this.driver_.execute(
|
|
1548
|
-
|
|
1711
|
+
new command.Command(command.Name.FULLSCREEN_WINDOW)
|
|
1712
|
+
)
|
|
1549
1713
|
}
|
|
1550
1714
|
}
|
|
1551
1715
|
|
|
1552
|
-
|
|
1553
1716
|
/**
|
|
1554
1717
|
* Interface for managing WebDriver log records.
|
|
1555
1718
|
*
|
|
@@ -1568,7 +1731,7 @@ class Logs {
|
|
|
1568
1731
|
*/
|
|
1569
1732
|
constructor(driver) {
|
|
1570
1733
|
/** @private {!WebDriver} */
|
|
1571
|
-
this.driver_ = driver
|
|
1734
|
+
this.driver_ = driver
|
|
1572
1735
|
}
|
|
1573
1736
|
|
|
1574
1737
|
/**
|
|
@@ -1585,19 +1748,23 @@ class Logs {
|
|
|
1585
1748
|
* type.
|
|
1586
1749
|
*/
|
|
1587
1750
|
get(type) {
|
|
1588
|
-
let cmd = new command.Command(command.Name.GET_LOG).
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1751
|
+
let cmd = new command.Command(command.Name.GET_LOG).setParameter(
|
|
1752
|
+
'type',
|
|
1753
|
+
type
|
|
1754
|
+
)
|
|
1755
|
+
return this.driver_.execute(cmd).then(function (entries) {
|
|
1756
|
+
return entries.map(function (entry) {
|
|
1757
|
+
if (!(entry instanceof logging.Entry)) {
|
|
1758
|
+
return new logging.Entry(
|
|
1759
|
+
entry['level'],
|
|
1760
|
+
entry['message'],
|
|
1761
|
+
entry['timestamp'],
|
|
1762
|
+
entry['type']
|
|
1763
|
+
)
|
|
1764
|
+
}
|
|
1765
|
+
return entry
|
|
1766
|
+
})
|
|
1767
|
+
})
|
|
1601
1768
|
}
|
|
1602
1769
|
|
|
1603
1770
|
/**
|
|
@@ -1607,11 +1774,11 @@ class Logs {
|
|
|
1607
1774
|
*/
|
|
1608
1775
|
getAvailableLogTypes() {
|
|
1609
1776
|
return this.driver_.execute(
|
|
1610
|
-
|
|
1777
|
+
new command.Command(command.Name.GET_AVAILABLE_LOG_TYPES)
|
|
1778
|
+
)
|
|
1611
1779
|
}
|
|
1612
1780
|
}
|
|
1613
1781
|
|
|
1614
|
-
|
|
1615
1782
|
/**
|
|
1616
1783
|
* An interface for changing the focus of the driver to another frame or window.
|
|
1617
1784
|
*
|
|
@@ -1629,7 +1796,7 @@ class TargetLocator {
|
|
|
1629
1796
|
*/
|
|
1630
1797
|
constructor(driver) {
|
|
1631
1798
|
/** @private {!WebDriver} */
|
|
1632
|
-
this.driver_ = driver
|
|
1799
|
+
this.driver_ = driver
|
|
1633
1800
|
}
|
|
1634
1801
|
|
|
1635
1802
|
/**
|
|
@@ -1641,8 +1808,9 @@ class TargetLocator {
|
|
|
1641
1808
|
*/
|
|
1642
1809
|
activeElement() {
|
|
1643
1810
|
var id = this.driver_.execute(
|
|
1644
|
-
|
|
1645
|
-
|
|
1811
|
+
new command.Command(command.Name.GET_ACTIVE_ELEMENT)
|
|
1812
|
+
)
|
|
1813
|
+
return new WebElementPromise(this.driver_, id)
|
|
1646
1814
|
}
|
|
1647
1815
|
|
|
1648
1816
|
/**
|
|
@@ -1654,8 +1822,8 @@ class TargetLocator {
|
|
|
1654
1822
|
*/
|
|
1655
1823
|
defaultContent() {
|
|
1656
1824
|
return this.driver_.execute(
|
|
1657
|
-
|
|
1658
|
-
|
|
1825
|
+
new command.Command(command.Name.SWITCH_TO_FRAME).setParameter('id', null)
|
|
1826
|
+
)
|
|
1659
1827
|
}
|
|
1660
1828
|
|
|
1661
1829
|
/**
|
|
@@ -1678,8 +1846,8 @@ class TargetLocator {
|
|
|
1678
1846
|
*/
|
|
1679
1847
|
frame(id) {
|
|
1680
1848
|
return this.driver_.execute(
|
|
1681
|
-
|
|
1682
|
-
|
|
1849
|
+
new command.Command(command.Name.SWITCH_TO_FRAME).setParameter('id', id)
|
|
1850
|
+
)
|
|
1683
1851
|
}
|
|
1684
1852
|
|
|
1685
1853
|
/**
|
|
@@ -1692,7 +1860,8 @@ class TargetLocator {
|
|
|
1692
1860
|
*/
|
|
1693
1861
|
parentFrame() {
|
|
1694
1862
|
return this.driver_.execute(
|
|
1695
|
-
|
|
1863
|
+
new command.Command(command.Name.SWITCH_TO_FRAME_PARENT)
|
|
1864
|
+
)
|
|
1696
1865
|
}
|
|
1697
1866
|
|
|
1698
1867
|
/**
|
|
@@ -1710,11 +1879,12 @@ class TargetLocator {
|
|
|
1710
1879
|
*/
|
|
1711
1880
|
window(nameOrHandle) {
|
|
1712
1881
|
return this.driver_.execute(
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1882
|
+
new command.Command(command.Name.SWITCH_TO_WINDOW)
|
|
1883
|
+
// "name" supports the legacy drivers. "handle" is the W3C
|
|
1884
|
+
// compliant parameter.
|
|
1885
|
+
.setParameter('name', nameOrHandle)
|
|
1886
|
+
.setParameter('handle', nameOrHandle)
|
|
1887
|
+
)
|
|
1718
1888
|
}
|
|
1719
1889
|
|
|
1720
1890
|
/**
|
|
@@ -1730,12 +1900,16 @@ class TargetLocator {
|
|
|
1730
1900
|
*/
|
|
1731
1901
|
newWindow(typeHint) {
|
|
1732
1902
|
var driver = this.driver_
|
|
1733
|
-
return this.driver_
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1903
|
+
return this.driver_
|
|
1904
|
+
.execute(
|
|
1905
|
+
new command.Command(command.Name.SWITCH_TO_NEW_WINDOW).setParameter(
|
|
1906
|
+
'type',
|
|
1907
|
+
typeHint
|
|
1908
|
+
)
|
|
1909
|
+
)
|
|
1910
|
+
.then(function (response) {
|
|
1911
|
+
return driver.switchTo().window(response.handle)
|
|
1912
|
+
})
|
|
1739
1913
|
}
|
|
1740
1914
|
|
|
1741
1915
|
/**
|
|
@@ -1748,25 +1922,26 @@ class TargetLocator {
|
|
|
1748
1922
|
*/
|
|
1749
1923
|
alert() {
|
|
1750
1924
|
var text = this.driver_.execute(
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1925
|
+
new command.Command(command.Name.GET_ALERT_TEXT)
|
|
1926
|
+
)
|
|
1927
|
+
var driver = this.driver_
|
|
1928
|
+
return new AlertPromise(
|
|
1929
|
+
driver,
|
|
1930
|
+
text.then(function (text) {
|
|
1931
|
+
return new Alert(driver, text)
|
|
1932
|
+
})
|
|
1933
|
+
)
|
|
1756
1934
|
}
|
|
1757
1935
|
}
|
|
1758
1936
|
|
|
1759
|
-
|
|
1760
1937
|
//////////////////////////////////////////////////////////////////////////////
|
|
1761
1938
|
//
|
|
1762
1939
|
// WebElement
|
|
1763
1940
|
//
|
|
1764
1941
|
//////////////////////////////////////////////////////////////////////////////
|
|
1765
1942
|
|
|
1766
|
-
|
|
1767
|
-
const
|
|
1768
|
-
const ELEMENT_ID_KEY = 'element-6066-11e4-a52e-4f735466cecf';
|
|
1769
|
-
|
|
1943
|
+
const LEGACY_ELEMENT_ID_KEY = 'ELEMENT'
|
|
1944
|
+
const ELEMENT_ID_KEY = 'element-6066-11e4-a52e-4f735466cecf'
|
|
1770
1945
|
|
|
1771
1946
|
/**
|
|
1772
1947
|
* Represents a DOM element. WebElements can be found by searching from the
|
|
@@ -1786,10 +1961,10 @@ class WebElement {
|
|
|
1786
1961
|
*/
|
|
1787
1962
|
constructor(driver, id) {
|
|
1788
1963
|
/** @private {!WebDriver} */
|
|
1789
|
-
this.driver_ = driver
|
|
1964
|
+
this.driver_ = driver
|
|
1790
1965
|
|
|
1791
1966
|
/** @private {!Promise<string>} */
|
|
1792
|
-
this.id_ = Promise.resolve(id)
|
|
1967
|
+
this.id_ = Promise.resolve(id)
|
|
1793
1968
|
}
|
|
1794
1969
|
|
|
1795
1970
|
/**
|
|
@@ -1799,8 +1974,8 @@ class WebElement {
|
|
|
1799
1974
|
*/
|
|
1800
1975
|
static buildId(id, noLegacy = false) {
|
|
1801
1976
|
return noLegacy
|
|
1802
|
-
|
|
1803
|
-
|
|
1977
|
+
? { [ELEMENT_ID_KEY]: id }
|
|
1978
|
+
: { [ELEMENT_ID_KEY]: id, [LEGACY_ELEMENT_ID_KEY]: id }
|
|
1804
1979
|
}
|
|
1805
1980
|
|
|
1806
1981
|
/**
|
|
@@ -1813,12 +1988,12 @@ class WebElement {
|
|
|
1813
1988
|
static extractId(obj) {
|
|
1814
1989
|
if (obj && typeof obj === 'object') {
|
|
1815
1990
|
if (typeof obj[ELEMENT_ID_KEY] === 'string') {
|
|
1816
|
-
return obj[ELEMENT_ID_KEY]
|
|
1991
|
+
return obj[ELEMENT_ID_KEY]
|
|
1817
1992
|
} else if (typeof obj[LEGACY_ELEMENT_ID_KEY] === 'string') {
|
|
1818
|
-
return obj[LEGACY_ELEMENT_ID_KEY]
|
|
1993
|
+
return obj[LEGACY_ELEMENT_ID_KEY]
|
|
1819
1994
|
}
|
|
1820
1995
|
}
|
|
1821
|
-
throw new TypeError('object is not a WebElement ID')
|
|
1996
|
+
throw new TypeError('object is not a WebElement ID')
|
|
1822
1997
|
}
|
|
1823
1998
|
|
|
1824
1999
|
/**
|
|
@@ -1826,9 +2001,12 @@ class WebElement {
|
|
|
1826
2001
|
* @return {boolean} whether the object is a valid encoded WebElement ID.
|
|
1827
2002
|
*/
|
|
1828
2003
|
static isId(obj) {
|
|
1829
|
-
return
|
|
1830
|
-
|
|
1831
|
-
|
|
2004
|
+
return (
|
|
2005
|
+
obj &&
|
|
2006
|
+
typeof obj === 'object' &&
|
|
2007
|
+
(typeof obj[ELEMENT_ID_KEY] === 'string' ||
|
|
2008
|
+
typeof obj[LEGACY_ELEMENT_ID_KEY] === 'string')
|
|
2009
|
+
)
|
|
1832
2010
|
}
|
|
1833
2011
|
|
|
1834
2012
|
/**
|
|
@@ -1841,15 +2019,14 @@ class WebElement {
|
|
|
1841
2019
|
*/
|
|
1842
2020
|
static async equals(a, b) {
|
|
1843
2021
|
if (a === b) {
|
|
1844
|
-
return true
|
|
2022
|
+
return true
|
|
1845
2023
|
}
|
|
1846
|
-
return a.driver_.executeScript(
|
|
1847
|
-
'return arguments[0] === arguments[1]', a, b);
|
|
2024
|
+
return a.driver_.executeScript('return arguments[0] === arguments[1]', a, b)
|
|
1848
2025
|
}
|
|
1849
2026
|
|
|
1850
2027
|
/** @return {!WebDriver} The parent driver for this instance. */
|
|
1851
2028
|
getDriver() {
|
|
1852
|
-
return this.driver_
|
|
2029
|
+
return this.driver_
|
|
1853
2030
|
}
|
|
1854
2031
|
|
|
1855
2032
|
/**
|
|
@@ -1857,14 +2034,14 @@ class WebElement {
|
|
|
1857
2034
|
* the server-assigned opaque ID assigned to this element.
|
|
1858
2035
|
*/
|
|
1859
2036
|
getId() {
|
|
1860
|
-
return this.id_
|
|
2037
|
+
return this.id_
|
|
1861
2038
|
}
|
|
1862
2039
|
|
|
1863
2040
|
/**
|
|
1864
2041
|
* @return {!Object} Returns the serialized representation of this WebElement.
|
|
1865
2042
|
*/
|
|
1866
2043
|
[Symbols.serialize]() {
|
|
1867
|
-
return this.getId().then(WebElement.buildId)
|
|
2044
|
+
return this.getId().then(WebElement.buildId)
|
|
1868
2045
|
}
|
|
1869
2046
|
|
|
1870
2047
|
/**
|
|
@@ -1879,8 +2056,8 @@ class WebElement {
|
|
|
1879
2056
|
* @private
|
|
1880
2057
|
*/
|
|
1881
2058
|
execute_(command) {
|
|
1882
|
-
command.setParameter('id', this)
|
|
1883
|
-
return this.driver_.execute(command)
|
|
2059
|
+
command.setParameter('id', this)
|
|
2060
|
+
return this.driver_.execute(command)
|
|
1884
2061
|
}
|
|
1885
2062
|
|
|
1886
2063
|
/**
|
|
@@ -1918,18 +2095,17 @@ class WebElement {
|
|
|
1918
2095
|
* element will be invalidated and all scheduled commands aborted.
|
|
1919
2096
|
*/
|
|
1920
2097
|
findElement(locator) {
|
|
1921
|
-
locator = by.checkedLocator(locator)
|
|
1922
|
-
let id
|
|
2098
|
+
locator = by.checkedLocator(locator)
|
|
2099
|
+
let id
|
|
1923
2100
|
if (typeof locator === 'function') {
|
|
1924
|
-
id = this.driver_.findElementInternal_(locator, this)
|
|
2101
|
+
id = this.driver_.findElementInternal_(locator, this)
|
|
1925
2102
|
} else {
|
|
1926
|
-
let cmd = new command.Command(
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
id = this.execute_(cmd);
|
|
2103
|
+
let cmd = new command.Command(command.Name.FIND_CHILD_ELEMENT)
|
|
2104
|
+
.setParameter('using', locator.using)
|
|
2105
|
+
.setParameter('value', locator.value)
|
|
2106
|
+
id = this.execute_(cmd)
|
|
1931
2107
|
}
|
|
1932
|
-
return new WebElementPromise(this.driver_, id)
|
|
2108
|
+
return new WebElementPromise(this.driver_, id)
|
|
1933
2109
|
}
|
|
1934
2110
|
|
|
1935
2111
|
/**
|
|
@@ -1942,16 +2118,15 @@ class WebElement {
|
|
|
1942
2118
|
* array of WebElements.
|
|
1943
2119
|
*/
|
|
1944
2120
|
async findElements(locator) {
|
|
1945
|
-
locator = by.checkedLocator(locator)
|
|
1946
|
-
let id;
|
|
2121
|
+
locator = by.checkedLocator(locator)
|
|
1947
2122
|
if (typeof locator === 'function') {
|
|
1948
|
-
return this.driver_.findElementsInternal_(locator, this)
|
|
2123
|
+
return this.driver_.findElementsInternal_(locator, this)
|
|
1949
2124
|
} else {
|
|
1950
2125
|
let cmd = new command.Command(command.Name.FIND_CHILD_ELEMENTS)
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
let result = await this.execute_(cmd)
|
|
1954
|
-
return Array.isArray(result) ? result : []
|
|
2126
|
+
.setParameter('using', locator.using)
|
|
2127
|
+
.setParameter('value', locator.value)
|
|
2128
|
+
let result = await this.execute_(cmd)
|
|
2129
|
+
return Array.isArray(result) ? result : []
|
|
1955
2130
|
}
|
|
1956
2131
|
}
|
|
1957
2132
|
|
|
@@ -1962,7 +2137,7 @@ class WebElement {
|
|
|
1962
2137
|
* command has completed.
|
|
1963
2138
|
*/
|
|
1964
2139
|
click() {
|
|
1965
|
-
return this.execute_(new command.Command(command.Name.CLICK_ELEMENT))
|
|
2140
|
+
return this.execute_(new command.Command(command.Name.CLICK_ELEMENT))
|
|
1966
2141
|
}
|
|
1967
2142
|
|
|
1968
2143
|
/**
|
|
@@ -2021,34 +2196,37 @@ class WebElement {
|
|
|
2021
2196
|
* have been typed.
|
|
2022
2197
|
*/
|
|
2023
2198
|
async sendKeys(...args) {
|
|
2024
|
-
let keys = []
|
|
2025
|
-
(await Promise.all(args)).forEach(key => {
|
|
2026
|
-
let type = typeof key
|
|
2199
|
+
let keys = []
|
|
2200
|
+
;(await Promise.all(args)).forEach((key) => {
|
|
2201
|
+
let type = typeof key
|
|
2027
2202
|
if (type === 'number') {
|
|
2028
|
-
key = String(key)
|
|
2203
|
+
key = String(key)
|
|
2029
2204
|
} else if (type !== 'string') {
|
|
2030
|
-
throw TypeError('each key must be a number of string; got ' + type)
|
|
2205
|
+
throw TypeError('each key must be a number of string; got ' + type)
|
|
2031
2206
|
}
|
|
2032
2207
|
|
|
2033
2208
|
// The W3C protocol requires keys to be specified as an array where
|
|
2034
2209
|
// each element is a single key.
|
|
2035
|
-
keys.push(...key.split(''))
|
|
2036
|
-
})
|
|
2210
|
+
keys.push(...key.split(''))
|
|
2211
|
+
})
|
|
2037
2212
|
|
|
2038
2213
|
if (!this.driver_.fileDetector_) {
|
|
2039
2214
|
return this.execute_(
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2215
|
+
new command.Command(command.Name.SEND_KEYS_TO_ELEMENT)
|
|
2216
|
+
.setParameter('text', keys.join(''))
|
|
2217
|
+
.setParameter('value', keys)
|
|
2218
|
+
)
|
|
2043
2219
|
}
|
|
2044
2220
|
|
|
2045
|
-
keys =
|
|
2046
|
-
|
|
2047
|
-
|
|
2221
|
+
keys = await this.driver_.fileDetector_.handleFile(
|
|
2222
|
+
this.driver_,
|
|
2223
|
+
keys.join('')
|
|
2224
|
+
)
|
|
2048
2225
|
return this.execute_(
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2226
|
+
new command.Command(command.Name.SEND_KEYS_TO_ELEMENT)
|
|
2227
|
+
.setParameter('text', keys)
|
|
2228
|
+
.setParameter('value', keys.split(''))
|
|
2229
|
+
)
|
|
2052
2230
|
}
|
|
2053
2231
|
|
|
2054
2232
|
/**
|
|
@@ -2058,8 +2236,7 @@ class WebElement {
|
|
|
2058
2236
|
* element's tag name.
|
|
2059
2237
|
*/
|
|
2060
2238
|
getTagName() {
|
|
2061
|
-
return this.execute_(
|
|
2062
|
-
new command.Command(command.Name.GET_ELEMENT_TAG_NAME));
|
|
2239
|
+
return this.execute_(new command.Command(command.Name.GET_ELEMENT_TAG_NAME))
|
|
2063
2240
|
}
|
|
2064
2241
|
|
|
2065
2242
|
/**
|
|
@@ -2077,10 +2254,10 @@ class WebElement {
|
|
|
2077
2254
|
* requested CSS value.
|
|
2078
2255
|
*/
|
|
2079
2256
|
getCssValue(cssStyleProperty) {
|
|
2080
|
-
var name = command.Name.GET_ELEMENT_VALUE_OF_CSS_PROPERTY
|
|
2257
|
+
var name = command.Name.GET_ELEMENT_VALUE_OF_CSS_PROPERTY
|
|
2081
2258
|
return this.execute_(
|
|
2082
|
-
|
|
2083
|
-
|
|
2259
|
+
new command.Command(name).setParameter('propertyName', cssStyleProperty)
|
|
2260
|
+
)
|
|
2084
2261
|
}
|
|
2085
2262
|
|
|
2086
2263
|
/**
|
|
@@ -2114,8 +2291,11 @@ class WebElement {
|
|
|
2114
2291
|
*/
|
|
2115
2292
|
getAttribute(attributeName) {
|
|
2116
2293
|
return this.execute_(
|
|
2117
|
-
|
|
2118
|
-
|
|
2294
|
+
new command.Command(command.Name.GET_ELEMENT_ATTRIBUTE).setParameter(
|
|
2295
|
+
'name',
|
|
2296
|
+
attributeName
|
|
2297
|
+
)
|
|
2298
|
+
)
|
|
2119
2299
|
}
|
|
2120
2300
|
|
|
2121
2301
|
/**
|
|
@@ -2126,7 +2306,11 @@ class WebElement {
|
|
|
2126
2306
|
*/
|
|
2127
2307
|
getProperty(propertyName) {
|
|
2128
2308
|
return this.execute_(
|
|
2129
|
-
|
|
2309
|
+
new command.Command(command.Name.GET_ELEMENT_PROPERTY).setParameter(
|
|
2310
|
+
'name',
|
|
2311
|
+
propertyName
|
|
2312
|
+
)
|
|
2313
|
+
)
|
|
2130
2314
|
}
|
|
2131
2315
|
|
|
2132
2316
|
/**
|
|
@@ -2137,7 +2321,7 @@ class WebElement {
|
|
|
2137
2321
|
* resolved with the element's visible text.
|
|
2138
2322
|
*/
|
|
2139
2323
|
getText() {
|
|
2140
|
-
return this.execute_(new command.Command(command.Name.GET_ELEMENT_TEXT))
|
|
2324
|
+
return this.execute_(new command.Command(command.Name.GET_ELEMENT_TEXT))
|
|
2141
2325
|
}
|
|
2142
2326
|
|
|
2143
2327
|
/**
|
|
@@ -2150,16 +2334,17 @@ class WebElement {
|
|
|
2150
2334
|
async getRect() {
|
|
2151
2335
|
try {
|
|
2152
2336
|
return await this.execute_(
|
|
2153
|
-
|
|
2337
|
+
new command.Command(command.Name.GET_ELEMENT_RECT)
|
|
2338
|
+
)
|
|
2154
2339
|
} catch (err) {
|
|
2155
2340
|
if (err instanceof error.UnknownCommandError) {
|
|
2156
|
-
const {width, height} =
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
const {x, y} =
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
return {x, y, width, height}
|
|
2341
|
+
const { width, height } = await this.execute_(
|
|
2342
|
+
new command.Command(command.Name.GET_ELEMENT_SIZE)
|
|
2343
|
+
)
|
|
2344
|
+
const { x, y } = await this.execute_(
|
|
2345
|
+
new command.Command(command.Name.GET_ELEMENT_LOCATION)
|
|
2346
|
+
)
|
|
2347
|
+
return { x, y, width, height }
|
|
2163
2348
|
}
|
|
2164
2349
|
}
|
|
2165
2350
|
}
|
|
@@ -2172,7 +2357,7 @@ class WebElement {
|
|
|
2172
2357
|
* resolved with whether this element is currently enabled.
|
|
2173
2358
|
*/
|
|
2174
2359
|
isEnabled() {
|
|
2175
|
-
return this.execute_(new command.Command(command.Name.IS_ELEMENT_ENABLED))
|
|
2360
|
+
return this.execute_(new command.Command(command.Name.IS_ELEMENT_ENABLED))
|
|
2176
2361
|
}
|
|
2177
2362
|
|
|
2178
2363
|
/**
|
|
@@ -2182,8 +2367,7 @@ class WebElement {
|
|
|
2182
2367
|
* resolved with whether this element is currently selected.
|
|
2183
2368
|
*/
|
|
2184
2369
|
isSelected() {
|
|
2185
|
-
return this.execute_(
|
|
2186
|
-
new command.Command(command.Name.IS_ELEMENT_SELECTED));
|
|
2370
|
+
return this.execute_(new command.Command(command.Name.IS_ELEMENT_SELECTED))
|
|
2187
2371
|
}
|
|
2188
2372
|
|
|
2189
2373
|
/**
|
|
@@ -2195,7 +2379,7 @@ class WebElement {
|
|
|
2195
2379
|
* when the form has been submitted.
|
|
2196
2380
|
*/
|
|
2197
2381
|
submit() {
|
|
2198
|
-
return this.execute_(new command.Command(command.Name.SUBMIT_ELEMENT))
|
|
2382
|
+
return this.execute_(new command.Command(command.Name.SUBMIT_ELEMENT))
|
|
2199
2383
|
}
|
|
2200
2384
|
|
|
2201
2385
|
/**
|
|
@@ -2207,7 +2391,7 @@ class WebElement {
|
|
|
2207
2391
|
* when the element has been cleared.
|
|
2208
2392
|
*/
|
|
2209
2393
|
clear() {
|
|
2210
|
-
return this.execute_(new command.Command(command.Name.CLEAR_ELEMENT))
|
|
2394
|
+
return this.execute_(new command.Command(command.Name.CLEAR_ELEMENT))
|
|
2211
2395
|
}
|
|
2212
2396
|
|
|
2213
2397
|
/**
|
|
@@ -2217,8 +2401,7 @@ class WebElement {
|
|
|
2217
2401
|
* resolved with whether this element is currently visible on the page.
|
|
2218
2402
|
*/
|
|
2219
2403
|
isDisplayed() {
|
|
2220
|
-
return this.execute_(
|
|
2221
|
-
new command.Command(command.Name.IS_ELEMENT_DISPLAYED));
|
|
2404
|
+
return this.execute_(new command.Command(command.Name.IS_ELEMENT_DISPLAYED))
|
|
2222
2405
|
}
|
|
2223
2406
|
|
|
2224
2407
|
/**
|
|
@@ -2233,12 +2416,14 @@ class WebElement {
|
|
|
2233
2416
|
*/
|
|
2234
2417
|
takeScreenshot(scroll = false) {
|
|
2235
2418
|
return this.execute_(
|
|
2236
|
-
|
|
2237
|
-
|
|
2419
|
+
new command.Command(command.Name.TAKE_ELEMENT_SCREENSHOT).setParameter(
|
|
2420
|
+
'scroll',
|
|
2421
|
+
scroll
|
|
2422
|
+
)
|
|
2423
|
+
)
|
|
2238
2424
|
}
|
|
2239
2425
|
}
|
|
2240
2426
|
|
|
2241
|
-
|
|
2242
2427
|
/**
|
|
2243
2428
|
* WebElementPromise is a promise that will be fulfilled with a WebElement.
|
|
2244
2429
|
* This serves as a forward proxy on WebElement, allowing calls to be
|
|
@@ -2262,35 +2447,33 @@ class WebElementPromise extends WebElement {
|
|
|
2262
2447
|
* that will resolve to the promised element.
|
|
2263
2448
|
*/
|
|
2264
2449
|
constructor(driver, el) {
|
|
2265
|
-
super(driver, 'unused')
|
|
2450
|
+
super(driver, 'unused')
|
|
2266
2451
|
|
|
2267
2452
|
/** @override */
|
|
2268
|
-
this.then = el.then.bind(el)
|
|
2453
|
+
this.then = el.then.bind(el)
|
|
2269
2454
|
|
|
2270
2455
|
/** @override */
|
|
2271
|
-
this.catch = el.catch.bind(el)
|
|
2456
|
+
this.catch = el.catch.bind(el)
|
|
2272
2457
|
|
|
2273
2458
|
/**
|
|
2274
2459
|
* Defers returning the element ID until the wrapped WebElement has been
|
|
2275
2460
|
* resolved.
|
|
2276
2461
|
* @override
|
|
2277
2462
|
*/
|
|
2278
|
-
this.getId = function() {
|
|
2279
|
-
return el.then(function(el) {
|
|
2280
|
-
return el.getId()
|
|
2281
|
-
})
|
|
2282
|
-
}
|
|
2463
|
+
this.getId = function () {
|
|
2464
|
+
return el.then(function (el) {
|
|
2465
|
+
return el.getId()
|
|
2466
|
+
})
|
|
2467
|
+
}
|
|
2283
2468
|
}
|
|
2284
2469
|
}
|
|
2285
2470
|
|
|
2286
|
-
|
|
2287
2471
|
//////////////////////////////////////////////////////////////////////////////
|
|
2288
2472
|
//
|
|
2289
2473
|
// Alert
|
|
2290
2474
|
//
|
|
2291
2475
|
//////////////////////////////////////////////////////////////////////////////
|
|
2292
2476
|
|
|
2293
|
-
|
|
2294
2477
|
/**
|
|
2295
2478
|
* Represents a modal dialog such as {@code alert}, {@code confirm}, or
|
|
2296
2479
|
* {@code prompt}. Provides functions to retrieve the message displayed with
|
|
@@ -2305,10 +2488,10 @@ class Alert {
|
|
|
2305
2488
|
*/
|
|
2306
2489
|
constructor(driver, text) {
|
|
2307
2490
|
/** @private {!WebDriver} */
|
|
2308
|
-
this.driver_ = driver
|
|
2491
|
+
this.driver_ = driver
|
|
2309
2492
|
|
|
2310
2493
|
/** @private {!Promise<string>} */
|
|
2311
|
-
this.text_ = Promise.resolve(text)
|
|
2494
|
+
this.text_ = Promise.resolve(text)
|
|
2312
2495
|
}
|
|
2313
2496
|
|
|
2314
2497
|
/**
|
|
@@ -2319,7 +2502,7 @@ class Alert {
|
|
|
2319
2502
|
* resolved to the text displayed with this alert.
|
|
2320
2503
|
*/
|
|
2321
2504
|
getText() {
|
|
2322
|
-
return this.text_
|
|
2505
|
+
return this.text_
|
|
2323
2506
|
}
|
|
2324
2507
|
|
|
2325
2508
|
/**
|
|
@@ -2329,8 +2512,7 @@ class Alert {
|
|
|
2329
2512
|
* when this command has completed.
|
|
2330
2513
|
*/
|
|
2331
2514
|
accept() {
|
|
2332
|
-
return this.driver_.execute(
|
|
2333
|
-
new command.Command(command.Name.ACCEPT_ALERT));
|
|
2515
|
+
return this.driver_.execute(new command.Command(command.Name.ACCEPT_ALERT))
|
|
2334
2516
|
}
|
|
2335
2517
|
|
|
2336
2518
|
/**
|
|
@@ -2340,8 +2522,7 @@ class Alert {
|
|
|
2340
2522
|
* when this command has completed.
|
|
2341
2523
|
*/
|
|
2342
2524
|
dismiss() {
|
|
2343
|
-
return this.driver_.execute(
|
|
2344
|
-
new command.Command(command.Name.DISMISS_ALERT));
|
|
2525
|
+
return this.driver_.execute(new command.Command(command.Name.DISMISS_ALERT))
|
|
2345
2526
|
}
|
|
2346
2527
|
|
|
2347
2528
|
/**
|
|
@@ -2355,12 +2536,14 @@ class Alert {
|
|
|
2355
2536
|
*/
|
|
2356
2537
|
sendKeys(text) {
|
|
2357
2538
|
return this.driver_.execute(
|
|
2358
|
-
|
|
2359
|
-
|
|
2539
|
+
new command.Command(command.Name.SET_ALERT_TEXT).setParameter(
|
|
2540
|
+
'text',
|
|
2541
|
+
text
|
|
2542
|
+
)
|
|
2543
|
+
)
|
|
2360
2544
|
}
|
|
2361
2545
|
}
|
|
2362
2546
|
|
|
2363
|
-
|
|
2364
2547
|
/**
|
|
2365
2548
|
* AlertPromise is a promise that will be fulfilled with an Alert. This promise
|
|
2366
2549
|
* serves as a forward proxy on an Alert, allowing calls to be scheduled
|
|
@@ -2383,60 +2566,58 @@ class AlertPromise extends Alert {
|
|
|
2383
2566
|
* that will be fulfilled with the promised alert.
|
|
2384
2567
|
*/
|
|
2385
2568
|
constructor(driver, alert) {
|
|
2386
|
-
super(driver, 'unused')
|
|
2569
|
+
super(driver, 'unused')
|
|
2387
2570
|
|
|
2388
2571
|
/** @override */
|
|
2389
|
-
this.then = alert.then.bind(alert)
|
|
2572
|
+
this.then = alert.then.bind(alert)
|
|
2390
2573
|
|
|
2391
2574
|
/** @override */
|
|
2392
|
-
this.catch = alert.catch.bind(alert)
|
|
2575
|
+
this.catch = alert.catch.bind(alert)
|
|
2393
2576
|
|
|
2394
2577
|
/**
|
|
2395
2578
|
* Defer returning text until the promised alert has been resolved.
|
|
2396
2579
|
* @override
|
|
2397
2580
|
*/
|
|
2398
|
-
this.getText = function() {
|
|
2399
|
-
return alert.then(function(alert) {
|
|
2400
|
-
return alert.getText()
|
|
2401
|
-
})
|
|
2402
|
-
}
|
|
2581
|
+
this.getText = function () {
|
|
2582
|
+
return alert.then(function (alert) {
|
|
2583
|
+
return alert.getText()
|
|
2584
|
+
})
|
|
2585
|
+
}
|
|
2403
2586
|
|
|
2404
2587
|
/**
|
|
2405
2588
|
* Defers action until the alert has been located.
|
|
2406
2589
|
* @override
|
|
2407
2590
|
*/
|
|
2408
|
-
this.accept = function() {
|
|
2409
|
-
return alert.then(function(alert) {
|
|
2410
|
-
return alert.accept()
|
|
2411
|
-
})
|
|
2412
|
-
}
|
|
2591
|
+
this.accept = function () {
|
|
2592
|
+
return alert.then(function (alert) {
|
|
2593
|
+
return alert.accept()
|
|
2594
|
+
})
|
|
2595
|
+
}
|
|
2413
2596
|
|
|
2414
2597
|
/**
|
|
2415
2598
|
* Defers action until the alert has been located.
|
|
2416
2599
|
* @override
|
|
2417
2600
|
*/
|
|
2418
|
-
this.dismiss = function() {
|
|
2419
|
-
return alert.then(function(alert) {
|
|
2420
|
-
return alert.dismiss()
|
|
2421
|
-
})
|
|
2422
|
-
}
|
|
2601
|
+
this.dismiss = function () {
|
|
2602
|
+
return alert.then(function (alert) {
|
|
2603
|
+
return alert.dismiss()
|
|
2604
|
+
})
|
|
2605
|
+
}
|
|
2423
2606
|
|
|
2424
2607
|
/**
|
|
2425
2608
|
* Defers action until the alert has been located.
|
|
2426
2609
|
* @override
|
|
2427
2610
|
*/
|
|
2428
|
-
this.sendKeys = function(text) {
|
|
2429
|
-
return alert.then(function(alert) {
|
|
2430
|
-
return alert.sendKeys(text)
|
|
2431
|
-
})
|
|
2432
|
-
}
|
|
2611
|
+
this.sendKeys = function (text) {
|
|
2612
|
+
return alert.then(function (alert) {
|
|
2613
|
+
return alert.sendKeys(text)
|
|
2614
|
+
})
|
|
2615
|
+
}
|
|
2433
2616
|
}
|
|
2434
2617
|
}
|
|
2435
2618
|
|
|
2436
|
-
|
|
2437
2619
|
// PUBLIC API
|
|
2438
2620
|
|
|
2439
|
-
|
|
2440
2621
|
module.exports = {
|
|
2441
2622
|
Alert,
|
|
2442
2623
|
AlertPromise,
|
|
@@ -2450,5 +2631,5 @@ module.exports = {
|
|
|
2450
2631
|
WebElement,
|
|
2451
2632
|
WebElementCondition,
|
|
2452
2633
|
WebElementPromise,
|
|
2453
|
-
Window
|
|
2454
|
-
}
|
|
2634
|
+
Window,
|
|
2635
|
+
}
|