selenium-webdriver 4.0.0 → 4.1.2
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 +523 -552
- package/LICENSE +1 -1
- package/NOTICE +1 -1
- package/README.md +4 -4
- package/chrome.js +10 -6
- package/chromium.js +91 -30
- package/devtools/CDPConnection.js +9 -4
- package/devtools/networkinterceptor.js +60 -61
- package/edge.js +10 -8
- package/example/google_search.js +1 -1
- package/firefox.js +32 -17
- package/http/index.js +13 -14
- package/http/util.js +14 -20
- package/index.js +15 -15
- package/io/index.js +58 -55
- package/io/zip.js +1 -3
- package/lib/atoms/find-elements.js +2 -2
- package/lib/by.js +9 -10
- package/lib/capabilities.js +1 -1
- package/lib/command.js +6 -11
- package/lib/error.js +24 -19
- package/lib/http.js +62 -153
- package/lib/input.js +71 -5
- package/lib/promise.js +12 -17
- package/lib/proxy.js +15 -5
- package/lib/session.js +1 -1
- package/lib/webdriver.js +410 -226
- package/net/index.js +14 -7
- package/net/portprober.js +5 -4
- package/opera.js +19 -22
- package/package.json +2 -3
- package/remote/index.js +13 -10
- package/testing/index.js +21 -16
package/http/util.js
CHANGED
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
|
|
22
22
|
'use strict'
|
|
23
23
|
|
|
24
|
-
const Executor = require('./index').Executor
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
const Executor = require('./index').Executor
|
|
25
|
+
const HttpClient = require('./index').HttpClient
|
|
26
|
+
const HttpRequest = require('./index').Request
|
|
27
|
+
const Command = require('../lib/command').Command
|
|
28
|
+
const CommandName = require('../lib/command').Name
|
|
29
|
+
const error = require('../lib/error')
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Queries a WebDriver server for its current status.
|
|
@@ -43,18 +43,6 @@ function getStatus(url) {
|
|
|
43
43
|
|
|
44
44
|
class CancellationError {}
|
|
45
45
|
|
|
46
|
-
// PUBLIC API
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Queries a WebDriver server for its current status.
|
|
50
|
-
* @param {string} url Base URL of the server to query.
|
|
51
|
-
* @return {!Promise<!Object>} A promise that resolves with
|
|
52
|
-
* a hash of the server status.
|
|
53
|
-
*/
|
|
54
|
-
exports.getStatus = getStatus
|
|
55
|
-
|
|
56
|
-
exports.CancellationError = CancellationError
|
|
57
|
-
|
|
58
46
|
/**
|
|
59
47
|
* Waits for a WebDriver server to be healthy and accepting requests.
|
|
60
48
|
* @param {string} url Base URL of the server to query.
|
|
@@ -65,7 +53,7 @@ exports.CancellationError = CancellationError
|
|
|
65
53
|
* @return {!Promise} A promise that will resolve when the server is ready, or
|
|
66
54
|
* if the wait is cancelled.
|
|
67
55
|
*/
|
|
68
|
-
|
|
56
|
+
function waitForServer(url, timeout, opt_cancelToken) {
|
|
69
57
|
return new Promise((onResolve, onReject) => {
|
|
70
58
|
let start = Date.now()
|
|
71
59
|
|
|
@@ -120,7 +108,7 @@ exports.waitForServer = function (url, timeout, opt_cancelToken) {
|
|
|
120
108
|
* @return {!Promise} A promise that will resolve when a 2xx is received from
|
|
121
109
|
* the given URL, or if the wait is cancelled.
|
|
122
110
|
*/
|
|
123
|
-
|
|
111
|
+
function waitForUrl(url, timeout, opt_cancelToken) {
|
|
124
112
|
return new Promise((onResolve, onReject) => {
|
|
125
113
|
let client = new HttpClient(url)
|
|
126
114
|
let request = new HttpRequest('GET', '')
|
|
@@ -170,3 +158,9 @@ exports.waitForUrl = function (url, timeout, opt_cancelToken) {
|
|
|
170
158
|
}
|
|
171
159
|
})
|
|
172
160
|
}
|
|
161
|
+
|
|
162
|
+
// PUBLIC API
|
|
163
|
+
module.exports.getStatus = getStatus
|
|
164
|
+
module.exports.CancellationError = CancellationError
|
|
165
|
+
module.exports.waitForServer = waitForServer
|
|
166
|
+
module.exports.waitForUrl = waitForUrl
|
package/index.js
CHANGED
|
@@ -45,7 +45,7 @@ const Capabilities = capabilities.Capabilities
|
|
|
45
45
|
const Capability = capabilities.Capability
|
|
46
46
|
const WebDriver = webdriver.WebDriver
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
let seleniumServer
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Starts an instance of the Selenium server if not yet running.
|
|
@@ -76,13 +76,12 @@ function startSeleniumServer(jar) {
|
|
|
76
76
|
* @return {function(new: webdriver.WebDriver, ...?)}
|
|
77
77
|
*/
|
|
78
78
|
function ensureFileDetectorsAreEnabled(ctor) {
|
|
79
|
-
|
|
79
|
+
return class extends ctor {
|
|
80
80
|
/** @param {input.FileDetector} detector */
|
|
81
|
-
setFileDetector(detector) {
|
|
81
|
+
setFileDetector (detector) {
|
|
82
82
|
webdriver.WebDriver.prototype.setFileDetector.call(this, detector)
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
return mixin
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
/**
|
|
@@ -103,7 +102,7 @@ function ensureFileDetectorsAreEnabled(ctor) {
|
|
|
103
102
|
*/
|
|
104
103
|
class ThenableWebDriver {
|
|
105
104
|
/** @param {...?} args */
|
|
106
|
-
static createSession(...args) {
|
|
105
|
+
static createSession(...args) {} // eslint-disable-line
|
|
107
106
|
}
|
|
108
107
|
|
|
109
108
|
/**
|
|
@@ -339,10 +338,10 @@ class Builder {
|
|
|
339
338
|
getCapabilities() {
|
|
340
339
|
return this.capabilities_
|
|
341
340
|
}
|
|
342
|
-
|
|
341
|
+
|
|
343
342
|
/**
|
|
344
|
-
* Sets the desired capability when requesting a new session.
|
|
345
|
-
* If there is already a capability named key, its value will be overwritten with value.
|
|
343
|
+
* Sets the desired capability when requesting a new session.
|
|
344
|
+
* If there is already a capability named key, its value will be overwritten with value.
|
|
346
345
|
* This is a convenience wrapper around builder.getCapabilities().set(key, value) to support Builder method chaining.
|
|
347
346
|
* @param {string} key The capability key.
|
|
348
347
|
* @param {*} value The capability value.
|
|
@@ -630,7 +629,7 @@ class Builder {
|
|
|
630
629
|
if (typeof browser !== 'string') {
|
|
631
630
|
throw TypeError(
|
|
632
631
|
`Target browser must be a string, but is <${typeof browser}>;` +
|
|
633
|
-
|
|
632
|
+
' did you forget to call forBrowser()?'
|
|
634
633
|
)
|
|
635
634
|
}
|
|
636
635
|
|
|
@@ -751,8 +750,8 @@ class Builder {
|
|
|
751
750
|
default:
|
|
752
751
|
throw new Error(
|
|
753
752
|
'Do not know how to build driver: ' +
|
|
754
|
-
|
|
755
|
-
|
|
753
|
+
browser +
|
|
754
|
+
'; did you forget to call usingServer(url)?'
|
|
756
755
|
)
|
|
757
756
|
}
|
|
758
757
|
}
|
|
@@ -808,9 +807,9 @@ function checkOptions(caps, key, optionType, setMethod) {
|
|
|
808
807
|
if (val instanceof optionType) {
|
|
809
808
|
throw new error.InvalidArgumentError(
|
|
810
809
|
'Options class extends Capabilities and should not be set as key ' +
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
810
|
+
`"${key}"; set browser-specific options with ` +
|
|
811
|
+
`Builder.${setMethod}(). For more information, see the ` +
|
|
812
|
+
'documentation attached to the function that threw this error'
|
|
814
813
|
)
|
|
815
814
|
}
|
|
816
815
|
}
|
|
@@ -821,8 +820,9 @@ exports.Browser = capabilities.Browser
|
|
|
821
820
|
exports.Builder = Builder
|
|
822
821
|
exports.Button = input.Button
|
|
823
822
|
exports.By = by.By
|
|
823
|
+
exports.RelativeBy = by.RelativeBy
|
|
824
824
|
exports.withTagName = by.withTagName
|
|
825
|
-
exports.
|
|
825
|
+
exports.locateWith = by.locateWith
|
|
826
826
|
exports.Capabilities = capabilities.Capabilities
|
|
827
827
|
exports.Capability = capabilities.Capability
|
|
828
828
|
exports.Condition = webdriver.Condition
|
package/io/index.js
CHANGED
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
|
|
20
20
|
const fs = require('fs')
|
|
21
21
|
const path = require('path')
|
|
22
|
-
const rimraf = require('rimraf')
|
|
23
22
|
const tmp = require('tmp')
|
|
24
23
|
|
|
25
24
|
/**
|
|
@@ -43,8 +42,6 @@ function checkedCall(fn) {
|
|
|
43
42
|
})
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
// PUBLIC API
|
|
47
|
-
|
|
48
45
|
/**
|
|
49
46
|
* Recursively removes a directory and all of its contents. This is equivalent
|
|
50
47
|
* to {@code rm -rf} on a POSIX system.
|
|
@@ -52,24 +49,16 @@ function checkedCall(fn) {
|
|
|
52
49
|
* @return {!Promise} A promise to be resolved when the operation has
|
|
53
50
|
* completed.
|
|
54
51
|
*/
|
|
55
|
-
|
|
52
|
+
function rmDir(dirPath) {
|
|
56
53
|
return new Promise(function (fulfill, reject) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
reject(err)
|
|
68
|
-
} else {
|
|
69
|
-
fulfill()
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
}
|
|
54
|
+
fs.rm(dirPath, { recursive: true, maxRetries: 2 }, function (err) {
|
|
55
|
+
if (err && err.code === 'ENOENT') {
|
|
56
|
+
fulfill()
|
|
57
|
+
} else if (err) {
|
|
58
|
+
reject(err)
|
|
59
|
+
}
|
|
60
|
+
fulfill()
|
|
61
|
+
})
|
|
73
62
|
})
|
|
74
63
|
}
|
|
75
64
|
|
|
@@ -79,12 +68,12 @@ exports.rmDir = function (dirPath) {
|
|
|
79
68
|
* @param {string} dst The destination file.
|
|
80
69
|
* @return {!Promise<string>} A promise for the copied file's path.
|
|
81
70
|
*/
|
|
82
|
-
|
|
71
|
+
function copy(src, dst) {
|
|
83
72
|
return new Promise(function (fulfill, reject) {
|
|
84
|
-
|
|
73
|
+
const rs = fs.createReadStream(src)
|
|
85
74
|
rs.on('error', reject)
|
|
86
75
|
|
|
87
|
-
|
|
76
|
+
const ws = fs.createWriteStream(dst)
|
|
88
77
|
ws.on('error', reject)
|
|
89
78
|
ws.on('close', () => fulfill(dst))
|
|
90
79
|
|
|
@@ -102,20 +91,19 @@ exports.copy = function (src, dst) {
|
|
|
102
91
|
* @return {!Promise<string>} A promise for the destination
|
|
103
92
|
* directory's path once all files have been copied.
|
|
104
93
|
*/
|
|
105
|
-
|
|
106
|
-
|
|
94
|
+
function copyDir(src, dst, opt_exclude) {
|
|
95
|
+
let predicate = opt_exclude
|
|
107
96
|
if (opt_exclude && typeof opt_exclude !== 'function') {
|
|
108
97
|
predicate = function (p) {
|
|
109
98
|
return !opt_exclude.test(p)
|
|
110
99
|
}
|
|
111
100
|
}
|
|
112
101
|
|
|
113
|
-
// TODO(jleyba): Make this function completely async.
|
|
114
102
|
if (!fs.existsSync(dst)) {
|
|
115
103
|
fs.mkdirSync(dst)
|
|
116
104
|
}
|
|
117
105
|
|
|
118
|
-
|
|
106
|
+
let files = fs.readdirSync(src)
|
|
119
107
|
files = files.map(function (file) {
|
|
120
108
|
return path.join(src, file)
|
|
121
109
|
})
|
|
@@ -124,18 +112,18 @@ exports.copyDir = function (src, dst, opt_exclude) {
|
|
|
124
112
|
files = files.filter(/** @type {function(string): boolean} */ (predicate))
|
|
125
113
|
}
|
|
126
114
|
|
|
127
|
-
|
|
115
|
+
const results = []
|
|
128
116
|
files.forEach(function (file) {
|
|
129
|
-
|
|
130
|
-
|
|
117
|
+
const stats = fs.statSync(file)
|
|
118
|
+
const target = path.join(dst, path.basename(file))
|
|
131
119
|
|
|
132
120
|
if (stats.isDirectory()) {
|
|
133
121
|
if (!fs.existsSync(target)) {
|
|
134
122
|
fs.mkdirSync(target, stats.mode)
|
|
135
123
|
}
|
|
136
|
-
results.push(
|
|
124
|
+
results.push(copyDir(file, target, predicate))
|
|
137
125
|
} else {
|
|
138
|
-
results.push(
|
|
126
|
+
results.push(copy(file, target))
|
|
139
127
|
}
|
|
140
128
|
})
|
|
141
129
|
|
|
@@ -147,14 +135,13 @@ exports.copyDir = function (src, dst, opt_exclude) {
|
|
|
147
135
|
* @param {string} aPath The path to test.
|
|
148
136
|
* @return {!Promise<boolean>} A promise for whether the file exists.
|
|
149
137
|
*/
|
|
150
|
-
|
|
138
|
+
function exists(aPath) {
|
|
151
139
|
return new Promise(function (fulfill, reject) {
|
|
152
140
|
let type = typeof aPath
|
|
153
141
|
if (type !== 'string') {
|
|
154
142
|
reject(TypeError(`expected string path, but got ${type}`))
|
|
155
143
|
} else {
|
|
156
|
-
|
|
157
|
-
fs.exists(aPath, fulfill)
|
|
144
|
+
fulfill(fs.existsSync(aPath))
|
|
158
145
|
}
|
|
159
146
|
})
|
|
160
147
|
}
|
|
@@ -164,7 +151,7 @@ exports.exists = function (aPath) {
|
|
|
164
151
|
* @param {string} aPath The path to stat.
|
|
165
152
|
* @return {!Promise<!fs.Stats>} A promise for the file stats.
|
|
166
153
|
*/
|
|
167
|
-
|
|
154
|
+
function stat(aPath) {
|
|
168
155
|
return checkedCall((callback) => fs.stat(aPath, callback))
|
|
169
156
|
}
|
|
170
157
|
|
|
@@ -174,18 +161,16 @@ exports.stat = function stat(aPath) {
|
|
|
174
161
|
* @param {string} aPath The path to remove.
|
|
175
162
|
* @return {!Promise} A promise for when the file has been removed.
|
|
176
163
|
*/
|
|
177
|
-
|
|
164
|
+
function unlink(aPath) {
|
|
178
165
|
return new Promise(function (fulfill, reject) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
})
|
|
166
|
+
const exists = fs.existsSync(aPath)
|
|
167
|
+
if (exists) {
|
|
168
|
+
fs.unlink(aPath, function (err) {
|
|
169
|
+
;(err && reject(err)) || fulfill()
|
|
170
|
+
})
|
|
171
|
+
} else {
|
|
172
|
+
fulfill()
|
|
173
|
+
}
|
|
189
174
|
})
|
|
190
175
|
}
|
|
191
176
|
|
|
@@ -193,7 +178,7 @@ exports.unlink = function (aPath) {
|
|
|
193
178
|
* @return {!Promise<string>} A promise for the path to a temporary directory.
|
|
194
179
|
* @see https://www.npmjs.org/package/tmp
|
|
195
180
|
*/
|
|
196
|
-
|
|
181
|
+
function tmpDir() {
|
|
197
182
|
return checkedCall((callback) => tmp.dir({ unsafeCleanup: true }, callback))
|
|
198
183
|
}
|
|
199
184
|
|
|
@@ -202,7 +187,7 @@ exports.tmpDir = function () {
|
|
|
202
187
|
* @return {!Promise<string>} A promise for the path to a temporary file.
|
|
203
188
|
* @see https://www.npmjs.org/package/tmp
|
|
204
189
|
*/
|
|
205
|
-
|
|
190
|
+
function tmpFile(opt_options) {
|
|
206
191
|
return checkedCall((callback) => {
|
|
207
192
|
/** check fixed in v > 0.2.1 if
|
|
208
193
|
* (typeof options === 'function') {
|
|
@@ -222,7 +207,7 @@ exports.tmpFile = function (opt_options) {
|
|
|
222
207
|
* @return {?string} Path to the located file, or {@code null} if it could
|
|
223
208
|
* not be found.
|
|
224
209
|
*/
|
|
225
|
-
|
|
210
|
+
function findInPath(file, opt_checkCwd) {
|
|
226
211
|
const dirs = []
|
|
227
212
|
if (opt_checkCwd) {
|
|
228
213
|
dirs.push(process.cwd())
|
|
@@ -249,7 +234,7 @@ exports.findInPath = function (file, opt_checkCwd) {
|
|
|
249
234
|
* @return {!Promise<!Buffer>} A promise that will resolve with a buffer of the
|
|
250
235
|
* file contents.
|
|
251
236
|
*/
|
|
252
|
-
|
|
237
|
+
function read(aPath) {
|
|
253
238
|
return checkedCall((callback) => fs.readFile(aPath, callback))
|
|
254
239
|
}
|
|
255
240
|
|
|
@@ -261,7 +246,7 @@ exports.read = function (aPath) {
|
|
|
261
246
|
* @return {!Promise} A promise that will resolve when the operation has
|
|
262
247
|
* completed.
|
|
263
248
|
*/
|
|
264
|
-
|
|
249
|
+
function write(aPath, data) {
|
|
265
250
|
return checkedCall((callback) => fs.writeFile(aPath, data, callback))
|
|
266
251
|
}
|
|
267
252
|
|
|
@@ -272,7 +257,7 @@ exports.write = function (aPath, data) {
|
|
|
272
257
|
* @return {!Promise<string>} A promise that will resolve with the path of the
|
|
273
258
|
* created directory.
|
|
274
259
|
*/
|
|
275
|
-
|
|
260
|
+
function mkdir(aPath) {
|
|
276
261
|
return checkedCall((callback) => {
|
|
277
262
|
fs.mkdir(aPath, undefined, (err) => {
|
|
278
263
|
if (err && err.code !== 'EEXIST') {
|
|
@@ -291,7 +276,7 @@ exports.mkdir = function (aPath) {
|
|
|
291
276
|
* @return {!Promise<string>} A promise that will resolve with the path of the
|
|
292
277
|
* created directory.
|
|
293
278
|
*/
|
|
294
|
-
|
|
279
|
+
function mkdirp(dir) {
|
|
295
280
|
return checkedCall((callback) => {
|
|
296
281
|
fs.mkdir(dir, undefined, (err) => {
|
|
297
282
|
if (!err) {
|
|
@@ -327,7 +312,7 @@ exports.mkdirp = function mkdirp(dir) {
|
|
|
327
312
|
* resolve with a list of entries seen. For each entry, the recorded path
|
|
328
313
|
* will be relative to `rootPath`.
|
|
329
314
|
*/
|
|
330
|
-
|
|
315
|
+
function walkDir(rootPath) {
|
|
331
316
|
const seen = []
|
|
332
317
|
return (function walk(dir) {
|
|
333
318
|
return checkedCall((callback) => fs.readdir(dir, callback)).then((files) =>
|
|
@@ -346,3 +331,21 @@ exports.walkDir = function (rootPath) {
|
|
|
346
331
|
)
|
|
347
332
|
})(rootPath).then(() => seen)
|
|
348
333
|
}
|
|
334
|
+
|
|
335
|
+
// PUBLIC API
|
|
336
|
+
module.exports = {
|
|
337
|
+
walkDir,
|
|
338
|
+
rmDir,
|
|
339
|
+
mkdirp,
|
|
340
|
+
mkdir,
|
|
341
|
+
write,
|
|
342
|
+
read,
|
|
343
|
+
findInPath,
|
|
344
|
+
tmpFile,
|
|
345
|
+
tmpDir,
|
|
346
|
+
unlink,
|
|
347
|
+
copy,
|
|
348
|
+
copyDir,
|
|
349
|
+
exists,
|
|
350
|
+
stat,
|
|
351
|
+
}
|
package/io/zip.js
CHANGED
|
@@ -109,8 +109,8 @@ function gd(a){var b=a.shape.toLowerCase();a=a.coords.split(",");if("rect"==b&&4
|
|
|
109
109
|
function hd(a){return a.replace(/^[^\S\xa0]+|[^\S\xa0]+$/g,"")}function id(a){var b=[];Yc?jd(a,b):kd(a,b);a=qa(b,hd);return hd(a.join("\n")).replace(/\xa0/g," ")}
|
|
110
110
|
function ld(a,b,c){if(S(a,"BR"))b.push("");else{var d=S(a,"TD"),e=V(a,"display"),f=!d&&!(0<=oa(md,e)),g=void 0!==a.previousElementSibling?a.previousElementSibling:gb(a.previousSibling);g=g?V(g,"display"):"";var h=V(a,"float")||V(a,"cssFloat")||V(a,"styleFloat");!f||"run-in"==g&&"none"==h||/^[\s\xa0]*$/.test(b[b.length-1]||"")||b.push("");var n=ed(a),u=null,p=null;n&&(u=V(a,"white-space"),p=V(a,"text-transform"));l(a.childNodes,function(G){c(G,b,n,u,p)});a=b[b.length-1]||"";!d&&"table-cell"!=e||!a||
|
|
111
111
|
za(a)||(b[b.length-1]+=" ");f&&"run-in"!=e&&!/^[\s\xa0]*$/.test(a)&&b.push("")}}function kd(a,b){ld(a,b,function(c,d,e,f,g){3==c.nodeType&&e?nd(c,d,f,g):S(c)&&kd(c,d)})}var md="inline inline-block inline-table none table-cell table-column table-column-group".split(" ");
|
|
112
|
-
function nd(a,b,c,d){a=a.nodeValue.replace(/[\u200b\u200e\u200f]/g,"");a=a.replace(/(\r\n|\r|\n)/g,"\n");if("normal"==c||"nowrap"==c)a=a.replace(/\n/g," ");a="pre"==c||"pre-wrap"==c?a.replace(/[ \f\t\v\u2028\u2029]/g,"\u00a0"):a.replace(/[ \f\t\v\u2028\u2029]+/g," ");"capitalize"==d?a=a.replace(/(^|[^\d\p{L}\p{S}])([\p{Ll}|\p{S}])/gu,function(e,f,g){return f+g.toUpperCase()}):"uppercase"==d?a=a.toUpperCase():"lowercase"==d&&(a=a.toLowerCase());c=b.pop()||"";za(c)&&0==a.lastIndexOf(" ",
|
|
113
|
-
b.push(c+a)}function dd(a){if(Mc){if("relative"==V(a,"position"))return 1;a=V(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return od(a)}function od(a){var b=1,c=V(a,"opacity");c&&(b=Number(c));(a=Zc(a))&&(b*=od(a));return b}
|
|
112
|
+
function nd(a,b,c,d){a=a.nodeValue.replace(/[\u200b\u200e\u200f]/g,"");a=a.replace(/(\r\n|\r|\n)/g,"\n");if("normal"==c||"nowrap"==c)a=a.replace(/\n/g," ");a="pre"==c||"pre-wrap"==c?a.replace(/[ \f\t\v\u2028\u2029]/g,"\u00a0"):a.replace(/[ \f\t\v\u2028\u2029]+/g," ");"capitalize"==d?a=a.replace(t?/(^|\s|\b)(\S)/g:/(^|[^\d\p{L}\p{S}])([\p{Ll}|\p{S}])/gu,function(e,f,g){return f+g.toUpperCase()}):"uppercase"==d?a=a.toUpperCase():"lowercase"==d&&(a=a.toLowerCase());c=b.pop()||"";za(c)&&0==a.lastIndexOf(" ",
|
|
113
|
+
0)&&(a=a.substr(1));b.push(c+a)}function dd(a){if(Mc){if("relative"==V(a,"position"))return 1;a=V(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return od(a)}function od(a){var b=1,c=V(a,"opacity");c&&(b=Number(c));(a=Zc(a))&&(b*=od(a));return b}
|
|
114
114
|
function pd(a,b,c,d,e){if(3==a.nodeType&&c)nd(a,b,d,e);else if(S(a))if(S(a,"CONTENT")||S(a,"SLOT")){for(var f=a;f.parentNode;)f=f.parentNode;f instanceof ShadowRoot?(a=S(a,"CONTENT")?a.getDistributedNodes():a.assignedNodes(),l(a,function(g){pd(g,b,c,d,e)})):jd(a,b)}else if(S(a,"SHADOW")){for(f=a;f.parentNode;)f=f.parentNode;if(f instanceof ShadowRoot&&(a=f))for(a=a.olderShadowRoot;a;)l(a.childNodes,function(g){pd(g,b,c,d,e)}),a=a.olderShadowRoot}else jd(a,b)}
|
|
115
115
|
function jd(a,b){a.shadowRoot&&l(a.shadowRoot.childNodes,function(c){pd(c,b,!0,null,null)});ld(a,b,function(c,d,e,f,g){var h=null;1==c.nodeType?h=c:3==c.nodeType&&(h=c);null!=h&&(null!=h.assignedSlot||h.getDestinationInsertionPoints&&0<h.getDestinationInsertionPoints().length)||pd(c,d,e,f,g)})};var qd={C:function(a,b){return!(!a.querySelectorAll||!a.querySelector)&&!/^\d.*/.test(b)},o:function(a,b){var c=eb(b),d="string"===typeof a?c.a.getElementById(a):a;return d?Uc(d,"id")==a&&b!=d&&hb(b,d)?d:ua(mb(c,"*"),function(e){return Uc(e,"id")==a&&b!=e&&hb(b,e)}):null},j:function(a,b){if(!a)return[];if(qd.C(b,a))try{return b.querySelectorAll("#"+qd.T(a))}catch(c){return[]}b=mb(eb(b),"*",null,b);return pa(b,function(c){return Uc(c,"id")==a})},T:function(a){return a.replace(/([\s'"\\#.:;,!?+<>=~*^$|%&@`{}\-\/\[\]\(\)])/g,
|
|
116
116
|
"\\$1")}};var Y={},rd={};Y.N=function(a,b,c){try{var d=Nc.j("a",b)}catch(e){d=mb(eb(b),"A",null,b)}return ua(d,function(e){e=id(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};Y.K=function(a,b,c){try{var d=Nc.j("a",b)}catch(e){d=mb(eb(b),"A",null,b)}return pa(d,function(e){e=id(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};Y.o=function(a,b){return Y.N(a,b,!1)};Y.j=function(a,b){return Y.K(a,b,!1)};rd.o=function(a,b){return Y.N(a,b,!0)};
|
package/lib/by.js
CHANGED
|
@@ -190,11 +190,9 @@ class By {
|
|
|
190
190
|
* @return {function(!./webdriver.WebDriver): !Promise}
|
|
191
191
|
* A new JavaScript-based locator function.
|
|
192
192
|
*/
|
|
193
|
-
static js(script, var_args) {
|
|
194
|
-
// eslint-disable-line
|
|
195
|
-
let args = Array.prototype.slice.call(arguments, 0)
|
|
193
|
+
static js(script, ...var_args) {
|
|
196
194
|
return function (driver) {
|
|
197
|
-
return driver.executeScript.
|
|
195
|
+
return driver.executeScript.call(driver, script, ...var_args)
|
|
198
196
|
}
|
|
199
197
|
}
|
|
200
198
|
|
|
@@ -227,7 +225,7 @@ class By {
|
|
|
227
225
|
* @return {!By} The new locator.
|
|
228
226
|
*/
|
|
229
227
|
static tagName(name) {
|
|
230
|
-
return By
|
|
228
|
+
return new By('tag name', name)
|
|
231
229
|
}
|
|
232
230
|
|
|
233
231
|
/**
|
|
@@ -277,7 +275,7 @@ function withTagName(tagName) {
|
|
|
277
275
|
* @returns {RelativeBy}
|
|
278
276
|
*/
|
|
279
277
|
function locateWith(by) {
|
|
280
|
-
return new RelativeBy(getLocator(by))
|
|
278
|
+
return new RelativeBy(getLocator(by))
|
|
281
279
|
}
|
|
282
280
|
|
|
283
281
|
function getLocator(locatorOrElement) {
|
|
@@ -426,9 +424,10 @@ function check(locator) {
|
|
|
426
424
|
// PUBLIC API
|
|
427
425
|
|
|
428
426
|
module.exports = {
|
|
429
|
-
By
|
|
430
|
-
RelativeBy
|
|
431
|
-
withTagName
|
|
432
|
-
locateWith
|
|
427
|
+
By,
|
|
428
|
+
RelativeBy,
|
|
429
|
+
withTagName,
|
|
430
|
+
locateWith,
|
|
431
|
+
escapeCss,
|
|
433
432
|
checkedLocator: check,
|
|
434
433
|
}
|
package/lib/capabilities.js
CHANGED
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,
|