selenium-webdriver 4.0.0-alpha.5 → 4.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.md +35 -1
- package/LICENSE +1 -1
- package/NOTICE +1 -1
- package/README.md +4 -4
- package/chrome.js +72 -592
- package/chromium.js +829 -0
- package/devtools/CDPConnection.js +37 -0
- package/edge.js +124 -86
- package/example/chrome_android.js +16 -13
- package/example/chrome_mobile_emulation.js +18 -14
- package/example/firefox_channels.js +35 -28
- package/example/google_search.js +9 -9
- package/example/google_search_test.js +20 -22
- package/example/headless.js +27 -19
- package/example/logging.js +34 -38
- package/firefox.js +200 -200
- package/http/index.js +131 -115
- 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 +142 -152
- package/io/zip.js +75 -65
- package/lib/actions.js +140 -122
- package/lib/atoms/find-elements.js +124 -0
- package/lib/atoms/get-attribute.js +79 -59
- package/lib/atoms/is-displayed.js +72 -73
- package/lib/atoms/mutation-listener.js +38 -0
- package/lib/by.js +192 -65
- package/lib/capabilities.js +82 -78
- package/lib/command.js +20 -20
- package/lib/error.js +134 -168
- package/lib/http.js +337 -230
- package/lib/input.js +325 -302
- package/lib/logging.js +127 -138
- 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 -160
- package/lib/webdriver.js +1024 -541
- package/net/index.js +30 -36
- package/net/portprober.js +31 -144
- package/opera.js +406 -0
- package/package.json +19 -12
- package/proxy.js +2 -2
- package/remote/index.js +190 -187
- package/safari.js +40 -49
- package/testing/index.js +166 -155
package/lib/until.js
CHANGED
|
@@ -39,15 +39,13 @@
|
|
|
39
39
|
* }, 1000);
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
|
-
'use strict'
|
|
42
|
+
'use strict'
|
|
43
43
|
|
|
44
|
-
const by = require('./by')
|
|
45
|
-
const
|
|
46
|
-
const error = require('./error');
|
|
44
|
+
const by = require('./by')
|
|
45
|
+
const error = require('./error')
|
|
47
46
|
const webdriver = require('./webdriver'),
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
Condition = webdriver.Condition,
|
|
48
|
+
WebElementCondition = webdriver.WebElementCondition
|
|
51
49
|
|
|
52
50
|
/**
|
|
53
51
|
* Creates a condition that will wait until the input driver is able to switch
|
|
@@ -70,33 +68,38 @@ const webdriver = require('./webdriver'),
|
|
|
70
68
|
* @return {!Condition<boolean>} A new condition.
|
|
71
69
|
*/
|
|
72
70
|
exports.ableToSwitchToFrame = function ableToSwitchToFrame(frame) {
|
|
73
|
-
|
|
71
|
+
let condition
|
|
74
72
|
if (typeof frame === 'number' || frame instanceof webdriver.WebElement) {
|
|
75
|
-
condition = driver => attemptToSwitchFrames(driver, frame)
|
|
73
|
+
condition = (driver) => attemptToSwitchFrames(driver, frame)
|
|
76
74
|
} else {
|
|
77
|
-
condition = function(driver) {
|
|
78
|
-
let locator = /** @type {!(By|Function)} */(frame)
|
|
79
|
-
return driver.findElements(locator).then(function(els) {
|
|
75
|
+
condition = function (driver) {
|
|
76
|
+
let locator = /** @type {!(By|Function)} */ (frame)
|
|
77
|
+
return driver.findElements(locator).then(function (els) {
|
|
80
78
|
if (els.length) {
|
|
81
|
-
return attemptToSwitchFrames(driver, els[0])
|
|
79
|
+
return attemptToSwitchFrames(driver, els[0])
|
|
82
80
|
}
|
|
83
|
-
})
|
|
84
|
-
}
|
|
81
|
+
})
|
|
82
|
+
}
|
|
85
83
|
}
|
|
86
84
|
|
|
87
|
-
return new Condition('to be able to switch to frame', condition)
|
|
85
|
+
return new Condition('to be able to switch to frame', condition)
|
|
88
86
|
|
|
89
87
|
function attemptToSwitchFrames(driver, frame) {
|
|
90
|
-
return driver
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
return driver
|
|
89
|
+
.switchTo()
|
|
90
|
+
.frame(frame)
|
|
91
|
+
.then(
|
|
92
|
+
function () {
|
|
93
|
+
return true
|
|
94
|
+
},
|
|
95
|
+
function (e) {
|
|
93
96
|
if (!(e instanceof error.NoSuchFrameError)) {
|
|
94
|
-
throw e
|
|
97
|
+
throw e
|
|
95
98
|
}
|
|
96
|
-
}
|
|
99
|
+
}
|
|
100
|
+
)
|
|
97
101
|
}
|
|
98
|
-
}
|
|
99
|
-
|
|
102
|
+
}
|
|
100
103
|
|
|
101
104
|
/**
|
|
102
105
|
* Creates a condition that waits for an alert to be opened. Upon success, the
|
|
@@ -105,21 +108,26 @@ exports.ableToSwitchToFrame = function ableToSwitchToFrame(frame) {
|
|
|
105
108
|
* @return {!Condition<!./webdriver.Alert>} The new condition.
|
|
106
109
|
*/
|
|
107
110
|
exports.alertIsPresent = function alertIsPresent() {
|
|
108
|
-
return new Condition('for alert to be present', function(driver) {
|
|
109
|
-
return driver
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
111
|
+
return new Condition('for alert to be present', function (driver) {
|
|
112
|
+
return driver
|
|
113
|
+
.switchTo()
|
|
114
|
+
.alert()
|
|
115
|
+
.catch(function (e) {
|
|
116
|
+
if (
|
|
117
|
+
!(
|
|
118
|
+
e instanceof error.NoSuchAlertError ||
|
|
119
|
+
// XXX: Workaround for GeckoDriver error `TypeError: can't convert null
|
|
120
|
+
// to object`. For more details, see
|
|
121
|
+
// https://github.com/SeleniumHQ/selenium/pull/2137
|
|
122
|
+
(e instanceof error.WebDriverError &&
|
|
123
|
+
e.message === `can't convert null to object`)
|
|
124
|
+
)
|
|
125
|
+
) {
|
|
126
|
+
throw e
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
}
|
|
123
131
|
|
|
124
132
|
/**
|
|
125
133
|
* Creates a condition that will wait for the current page's title to match the
|
|
@@ -130,14 +138,14 @@ exports.alertIsPresent = function alertIsPresent() {
|
|
|
130
138
|
*/
|
|
131
139
|
exports.titleIs = function titleIs(title) {
|
|
132
140
|
return new Condition(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
+
'for title to be ' + JSON.stringify(title),
|
|
142
|
+
function (driver) {
|
|
143
|
+
return driver.getTitle().then(function (t) {
|
|
144
|
+
return t === title
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
)
|
|
148
|
+
}
|
|
141
149
|
|
|
142
150
|
/**
|
|
143
151
|
* Creates a condition that will wait for the current page's title to contain
|
|
@@ -149,14 +157,14 @@ exports.titleIs = function titleIs(title) {
|
|
|
149
157
|
*/
|
|
150
158
|
exports.titleContains = function titleContains(substr) {
|
|
151
159
|
return new Condition(
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
'for title to contain ' + JSON.stringify(substr),
|
|
161
|
+
function (driver) {
|
|
162
|
+
return driver.getTitle().then(function (title) {
|
|
163
|
+
return title.indexOf(substr) !== -1
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
)
|
|
167
|
+
}
|
|
160
168
|
|
|
161
169
|
/**
|
|
162
170
|
* Creates a condition that will wait for the current page's title to match the
|
|
@@ -166,13 +174,12 @@ exports.titleContains = function titleContains(substr) {
|
|
|
166
174
|
* @return {!Condition<boolean>} The new condition.
|
|
167
175
|
*/
|
|
168
176
|
exports.titleMatches = function titleMatches(regex) {
|
|
169
|
-
return new Condition('for title to match ' + regex, function(driver) {
|
|
170
|
-
return driver.getTitle().then(function(title) {
|
|
171
|
-
return regex.test(title)
|
|
172
|
-
})
|
|
173
|
-
})
|
|
174
|
-
}
|
|
175
|
-
|
|
177
|
+
return new Condition('for title to match ' + regex, function (driver) {
|
|
178
|
+
return driver.getTitle().then(function (title) {
|
|
179
|
+
return regex.test(title)
|
|
180
|
+
})
|
|
181
|
+
})
|
|
182
|
+
}
|
|
176
183
|
|
|
177
184
|
/**
|
|
178
185
|
* Creates a condition that will wait for the current page's url to match the
|
|
@@ -183,14 +190,14 @@ exports.titleMatches = function titleMatches(regex) {
|
|
|
183
190
|
*/
|
|
184
191
|
exports.urlIs = function urlIs(url) {
|
|
185
192
|
return new Condition(
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
193
|
+
'for URL to be ' + JSON.stringify(url),
|
|
194
|
+
function (driver) {
|
|
195
|
+
return driver.getCurrentUrl().then(function (u) {
|
|
196
|
+
return u === url
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
}
|
|
194
201
|
|
|
195
202
|
/**
|
|
196
203
|
* Creates a condition that will wait for the current page's url to contain
|
|
@@ -202,14 +209,14 @@ exports.urlIs = function urlIs(url) {
|
|
|
202
209
|
*/
|
|
203
210
|
exports.urlContains = function urlContains(substrUrl) {
|
|
204
211
|
return new Condition(
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
212
|
+
'for URL to contain ' + JSON.stringify(substrUrl),
|
|
213
|
+
function (driver) {
|
|
214
|
+
return driver.getCurrentUrl().then(function (url) {
|
|
215
|
+
return url && url.indexOf(substrUrl) !== -1
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
}
|
|
213
220
|
|
|
214
221
|
/**
|
|
215
222
|
* Creates a condition that will wait for the current page's url to match the
|
|
@@ -219,13 +226,12 @@ exports.urlContains = function urlContains(substrUrl) {
|
|
|
219
226
|
* @return {!Condition<boolean>} The new condition.
|
|
220
227
|
*/
|
|
221
228
|
exports.urlMatches = function urlMatches(regex) {
|
|
222
|
-
return new Condition('for URL to match ' + regex, function(driver) {
|
|
223
|
-
return driver.getCurrentUrl().then(function(url) {
|
|
224
|
-
return regex.test(url)
|
|
225
|
-
})
|
|
226
|
-
})
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
+
return new Condition('for URL to match ' + regex, function (driver) {
|
|
230
|
+
return driver.getCurrentUrl().then(function (url) {
|
|
231
|
+
return regex.test(url)
|
|
232
|
+
})
|
|
233
|
+
})
|
|
234
|
+
}
|
|
229
235
|
|
|
230
236
|
/**
|
|
231
237
|
* Creates a condition that will loop until an element is
|
|
@@ -235,17 +241,18 @@ exports.urlMatches = function urlMatches(regex) {
|
|
|
235
241
|
* @return {!WebElementCondition} The new condition.
|
|
236
242
|
*/
|
|
237
243
|
exports.elementLocated = function elementLocated(locator) {
|
|
238
|
-
locator = by.checkedLocator(locator)
|
|
244
|
+
locator = by.checkedLocator(locator)
|
|
239
245
|
let locatorStr =
|
|
240
|
-
|
|
241
|
-
return new WebElementCondition(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
})
|
|
247
|
-
}
|
|
248
|
-
|
|
246
|
+
typeof locator === 'function' ? 'by function()' : locator + ''
|
|
247
|
+
return new WebElementCondition(
|
|
248
|
+
'for element to be located ' + locatorStr,
|
|
249
|
+
function (driver) {
|
|
250
|
+
return driver.findElements(locator).then(function (elements) {
|
|
251
|
+
return elements[0]
|
|
252
|
+
})
|
|
253
|
+
}
|
|
254
|
+
)
|
|
255
|
+
}
|
|
249
256
|
|
|
250
257
|
/**
|
|
251
258
|
* Creates a condition that will loop until at least one element is
|
|
@@ -256,18 +263,18 @@ exports.elementLocated = function elementLocated(locator) {
|
|
|
256
263
|
* condition.
|
|
257
264
|
*/
|
|
258
265
|
exports.elementsLocated = function elementsLocated(locator) {
|
|
259
|
-
locator = by.checkedLocator(locator)
|
|
266
|
+
locator = by.checkedLocator(locator)
|
|
260
267
|
let locatorStr =
|
|
261
|
-
|
|
268
|
+
typeof locator === 'function' ? 'by function()' : locator + ''
|
|
262
269
|
return new Condition(
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
270
|
+
'for at least one element to be located ' + locatorStr,
|
|
271
|
+
function (driver) {
|
|
272
|
+
return driver.findElements(locator).then(function (elements) {
|
|
273
|
+
return elements.length > 0 ? elements : null
|
|
274
|
+
})
|
|
275
|
+
}
|
|
276
|
+
)
|
|
277
|
+
}
|
|
271
278
|
|
|
272
279
|
/**
|
|
273
280
|
* Creates a condition that will wait for the given element to become stale. An
|
|
@@ -278,18 +285,20 @@ exports.elementsLocated = function elementsLocated(locator) {
|
|
|
278
285
|
* @return {!Condition<boolean>} The new condition.
|
|
279
286
|
*/
|
|
280
287
|
exports.stalenessOf = function stalenessOf(element) {
|
|
281
|
-
return new Condition('element to become stale', function() {
|
|
288
|
+
return new Condition('element to become stale', function () {
|
|
282
289
|
return element.getTagName().then(
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
290
|
+
function () {
|
|
291
|
+
return false
|
|
292
|
+
},
|
|
293
|
+
function (e) {
|
|
294
|
+
if (e instanceof error.StaleElementReferenceError) {
|
|
295
|
+
return true
|
|
296
|
+
}
|
|
297
|
+
throw e
|
|
298
|
+
}
|
|
299
|
+
)
|
|
300
|
+
})
|
|
301
|
+
}
|
|
293
302
|
|
|
294
303
|
/**
|
|
295
304
|
* Creates a condition that will wait for the given element to become visible.
|
|
@@ -299,11 +308,10 @@ exports.stalenessOf = function stalenessOf(element) {
|
|
|
299
308
|
* @see ./webdriver.WebDriver#isDisplayed
|
|
300
309
|
*/
|
|
301
310
|
exports.elementIsVisible = function elementIsVisible(element) {
|
|
302
|
-
return new WebElementCondition('until element is visible', function() {
|
|
303
|
-
return element.isDisplayed().then(v => v ? element : null)
|
|
304
|
-
})
|
|
305
|
-
}
|
|
306
|
-
|
|
311
|
+
return new WebElementCondition('until element is visible', function () {
|
|
312
|
+
return element.isDisplayed().then((v) => (v ? element : null))
|
|
313
|
+
})
|
|
314
|
+
}
|
|
307
315
|
|
|
308
316
|
/**
|
|
309
317
|
* Creates a condition that will wait for the given element to be in the DOM,
|
|
@@ -314,11 +322,10 @@ exports.elementIsVisible = function elementIsVisible(element) {
|
|
|
314
322
|
* @see ./webdriver.WebDriver#isDisplayed
|
|
315
323
|
*/
|
|
316
324
|
exports.elementIsNotVisible = function elementIsNotVisible(element) {
|
|
317
|
-
return new WebElementCondition('until element is not visible', function() {
|
|
318
|
-
return element.isDisplayed().then(v => v ? null : element)
|
|
319
|
-
})
|
|
320
|
-
}
|
|
321
|
-
|
|
325
|
+
return new WebElementCondition('until element is not visible', function () {
|
|
326
|
+
return element.isDisplayed().then((v) => (v ? null : element))
|
|
327
|
+
})
|
|
328
|
+
}
|
|
322
329
|
|
|
323
330
|
/**
|
|
324
331
|
* Creates a condition that will wait for the given element to be enabled.
|
|
@@ -328,11 +335,10 @@ exports.elementIsNotVisible = function elementIsNotVisible(element) {
|
|
|
328
335
|
* @see webdriver.WebDriver#isEnabled
|
|
329
336
|
*/
|
|
330
337
|
exports.elementIsEnabled = function elementIsEnabled(element) {
|
|
331
|
-
return new WebElementCondition('until element is enabled', function() {
|
|
332
|
-
return element.isEnabled().then(v => v ? element : null)
|
|
333
|
-
})
|
|
334
|
-
}
|
|
335
|
-
|
|
338
|
+
return new WebElementCondition('until element is enabled', function () {
|
|
339
|
+
return element.isEnabled().then((v) => (v ? element : null))
|
|
340
|
+
})
|
|
341
|
+
}
|
|
336
342
|
|
|
337
343
|
/**
|
|
338
344
|
* Creates a condition that will wait for the given element to be disabled.
|
|
@@ -342,11 +348,10 @@ exports.elementIsEnabled = function elementIsEnabled(element) {
|
|
|
342
348
|
* @see webdriver.WebDriver#isEnabled
|
|
343
349
|
*/
|
|
344
350
|
exports.elementIsDisabled = function elementIsDisabled(element) {
|
|
345
|
-
return new WebElementCondition('until element is disabled', function() {
|
|
346
|
-
return element.isEnabled().then(v => v ? null : element)
|
|
347
|
-
})
|
|
348
|
-
}
|
|
349
|
-
|
|
351
|
+
return new WebElementCondition('until element is disabled', function () {
|
|
352
|
+
return element.isEnabled().then((v) => (v ? null : element))
|
|
353
|
+
})
|
|
354
|
+
}
|
|
350
355
|
|
|
351
356
|
/**
|
|
352
357
|
* Creates a condition that will wait for the given element to be selected.
|
|
@@ -355,11 +360,10 @@ exports.elementIsDisabled = function elementIsDisabled(element) {
|
|
|
355
360
|
* @see webdriver.WebDriver#isSelected
|
|
356
361
|
*/
|
|
357
362
|
exports.elementIsSelected = function elementIsSelected(element) {
|
|
358
|
-
return new WebElementCondition('until element is selected', function() {
|
|
359
|
-
return element.isSelected().then(v => v ? element : null)
|
|
360
|
-
})
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
+
return new WebElementCondition('until element is selected', function () {
|
|
364
|
+
return element.isSelected().then((v) => (v ? element : null))
|
|
365
|
+
})
|
|
366
|
+
}
|
|
363
367
|
|
|
364
368
|
/**
|
|
365
369
|
* Creates a condition that will wait for the given element to be deselected.
|
|
@@ -369,11 +373,10 @@ exports.elementIsSelected = function elementIsSelected(element) {
|
|
|
369
373
|
* @see webdriver.WebDriver#isSelected
|
|
370
374
|
*/
|
|
371
375
|
exports.elementIsNotSelected = function elementIsNotSelected(element) {
|
|
372
|
-
return new WebElementCondition('until element is not selected', function() {
|
|
373
|
-
return element.isSelected().then(v => v ? null : element)
|
|
374
|
-
})
|
|
375
|
-
}
|
|
376
|
-
|
|
376
|
+
return new WebElementCondition('until element is not selected', function () {
|
|
377
|
+
return element.isSelected().then((v) => (v ? null : element))
|
|
378
|
+
})
|
|
379
|
+
}
|
|
377
380
|
|
|
378
381
|
/**
|
|
379
382
|
* Creates a condition that will wait for the given element's
|
|
@@ -386,11 +389,10 @@ exports.elementIsNotSelected = function elementIsNotSelected(element) {
|
|
|
386
389
|
* @see webdriver.WebDriver#getText
|
|
387
390
|
*/
|
|
388
391
|
exports.elementTextIs = function elementTextIs(element, text) {
|
|
389
|
-
return new WebElementCondition('until element text is', function() {
|
|
390
|
-
return element.getText().then(t => t === text ? element : null)
|
|
391
|
-
})
|
|
392
|
-
}
|
|
393
|
-
|
|
392
|
+
return new WebElementCondition('until element text is', function () {
|
|
393
|
+
return element.getText().then((t) => (t === text ? element : null))
|
|
394
|
+
})
|
|
395
|
+
}
|
|
394
396
|
|
|
395
397
|
/**
|
|
396
398
|
* Creates a condition that will wait for the given element's
|
|
@@ -403,12 +405,12 @@ exports.elementTextIs = function elementTextIs(element, text) {
|
|
|
403
405
|
* @see webdriver.WebDriver#getText
|
|
404
406
|
*/
|
|
405
407
|
exports.elementTextContains = function elementTextContains(element, substr) {
|
|
406
|
-
return new WebElementCondition('until element text contains', function() {
|
|
407
|
-
return element
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
}
|
|
411
|
-
|
|
408
|
+
return new WebElementCondition('until element text contains', function () {
|
|
409
|
+
return element
|
|
410
|
+
.getText()
|
|
411
|
+
.then((t) => (t.indexOf(substr) != -1 ? element : null))
|
|
412
|
+
})
|
|
413
|
+
}
|
|
412
414
|
|
|
413
415
|
/**
|
|
414
416
|
* Creates a condition that will wait for the given element's
|
|
@@ -421,7 +423,7 @@ exports.elementTextContains = function elementTextContains(element, substr) {
|
|
|
421
423
|
* @see webdriver.WebDriver#getText
|
|
422
424
|
*/
|
|
423
425
|
exports.elementTextMatches = function elementTextMatches(element, regex) {
|
|
424
|
-
return new WebElementCondition('until element text matches', function() {
|
|
425
|
-
return element.getText().then(t => regex.test(t) ? element : null)
|
|
426
|
-
})
|
|
427
|
-
}
|
|
426
|
+
return new WebElementCondition('until element text matches', function () {
|
|
427
|
+
return element.getText().then((t) => (regex.test(t) ? element : null))
|
|
428
|
+
})
|
|
429
|
+
}
|