selenium-webdriver 4.0.0-beta.4 → 4.0.0-rc-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 +19 -0
- package/README.md +4 -2
- package/chrome.js +3 -4
- package/chromium.js +26 -6
- package/edge.js +14 -20
- package/firefox.js +18 -1
- package/http/index.js +25 -3
- package/ie.js +8 -8
- package/index.js +11 -8
- package/io/exec.js +2 -1
- package/lib/by.js +39 -20
- package/lib/capabilities.js +10 -1
- package/lib/http.js +2 -1
- package/lib/input.js +4 -15
- package/lib/until.js +14 -16
- package/lib/webdriver.js +38 -47
- package/opera.js +3 -3
- package/package.json +2 -2
- package/remote/index.js +2 -2
- package/safari.js +3 -3
- package/testing/index.js +12 -12
package/CHANGES.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
## v4.0.0-rc-1
|
|
2
|
+
|
|
3
|
+
* Deprecates withCapabilities method and removes tests (#9701)
|
|
4
|
+
* expose `withLocator` method at the top level
|
|
5
|
+
* Enables Mobile feature for Firefox (Still need to expand this to chromium based browsers)
|
|
6
|
+
|
|
7
|
+
* Add the ability to do Relative Locators with all By types. Fixes #9559
|
|
8
|
+
* Add default Opera capabilities. Fixes #9654
|
|
9
|
+
* Add support for ChromeDriver `--enable-chrome-logs` (#9575) [Author: Mark Stacey]
|
|
10
|
+
|
|
11
|
+
The `--enable-chrome-logs` ChromeDriver option can now be enabled using
|
|
12
|
+
the Chromium (or Chrome) ServiceBuilder, similarly to the other options
|
|
13
|
+
provided by ChromeDriver.
|
|
14
|
+
|
|
15
|
+
* Add the debuggerAddress option to chromium.js (#9561) [Author: Brandon Walderman]
|
|
16
|
+
* Adds http client options (#9638)[Author: Dharin Shah]
|
|
17
|
+
* Updating edge.js to extend chromium.driver (fixes #9626)
|
|
18
|
+
|
|
19
|
+
|
|
1
20
|
## v4.0.0-beta.4
|
|
2
21
|
|
|
3
22
|
* Add windowTypes option support for ChromiumDriver (#7897)
|
package/README.md
CHANGED
|
@@ -223,7 +223,9 @@ under the License.
|
|
|
223
223
|
[edge]: http://go.microsoft.com/fwlink/?LinkId=619687
|
|
224
224
|
[geckodriver]: https://github.com/mozilla/geckodriver/releases/
|
|
225
225
|
[reduction]: http://www.webkit.org/quality/reduction.html
|
|
226
|
-
|
|
226
|
+
|
|
227
|
+
[release]: https://www.selenium.dev/downloads/
|
|
228
|
+
|
|
227
229
|
[users]: https://groups.google.com/forum/#!forum/selenium-users
|
|
228
230
|
[safaridriver]: https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInSafari/Articles/Safari_10_0.html#//apple_ref/doc/uid/TP40014305-CH11-DontLinkElementID_28
|
|
229
|
-
[operadriver]: https://github.com/operasoftware/operachromiumdriver/releases
|
|
231
|
+
[operadriver]: https://github.com/operasoftware/operachromiumdriver/releases
|
package/chrome.js
CHANGED
|
@@ -236,10 +236,9 @@ class Driver extends chromium.Driver {
|
|
|
236
236
|
*/
|
|
237
237
|
static createSession(opt_config, opt_serviceExecutor) {
|
|
238
238
|
let caps = opt_config || new Options()
|
|
239
|
-
return /** @type {!Driver} */ (
|
|
240
|
-
caps,
|
|
241
|
-
|
|
242
|
-
))
|
|
239
|
+
return /** @type {!Driver} */ (
|
|
240
|
+
super.createSession(caps, opt_serviceExecutor)
|
|
241
|
+
)
|
|
243
242
|
}
|
|
244
243
|
}
|
|
245
244
|
|
package/chromium.js
CHANGED
|
@@ -213,6 +213,14 @@ class ServiceBuilder extends remote.DriverService.Builder {
|
|
|
213
213
|
return this.addArguments('--log-path=' + path)
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Enables Chrome logging.
|
|
218
|
+
* @returns {!ServiceBuilder} A self reference.
|
|
219
|
+
*/
|
|
220
|
+
enableChromeLogging() {
|
|
221
|
+
return this.addArguments('--enable-chrome-logs');
|
|
222
|
+
}
|
|
223
|
+
|
|
216
224
|
/**
|
|
217
225
|
* Enables verbose logging.
|
|
218
226
|
* @return {!ServiceBuilder} A self reference.
|
|
@@ -275,6 +283,19 @@ class Options extends Capabilities {
|
|
|
275
283
|
return this
|
|
276
284
|
}
|
|
277
285
|
|
|
286
|
+
/**
|
|
287
|
+
* Sets the address of a Chromium remote debugging server to connect to.
|
|
288
|
+
* Address should be of the form "{hostname|IP address}:port"
|
|
289
|
+
* (e.g. "localhost:9222").
|
|
290
|
+
*
|
|
291
|
+
* @param {string} address The address to connect to.
|
|
292
|
+
* @return {!Options} A self reference.
|
|
293
|
+
*/
|
|
294
|
+
debuggerAddress(address) {
|
|
295
|
+
this.options_.debuggerAddress = address;
|
|
296
|
+
return this
|
|
297
|
+
}
|
|
298
|
+
|
|
278
299
|
/**
|
|
279
300
|
* Configures the driver to start the browser in headless mode.
|
|
280
301
|
*
|
|
@@ -557,14 +578,13 @@ class Options extends Capabilities {
|
|
|
557
578
|
* @return {!Options} A self reference.
|
|
558
579
|
*/
|
|
559
580
|
windowTypes(...args) {
|
|
560
|
-
let windowTypes = (this.options_.windowTypes || []).concat(...args)
|
|
581
|
+
let windowTypes = (this.options_.windowTypes || []).concat(...args)
|
|
561
582
|
if (windowTypes.length) {
|
|
562
|
-
this.options_.windowTypes = windowTypes
|
|
583
|
+
this.options_.windowTypes = windowTypes
|
|
563
584
|
}
|
|
564
|
-
return this
|
|
585
|
+
return this
|
|
565
586
|
}
|
|
566
587
|
|
|
567
|
-
|
|
568
588
|
/**
|
|
569
589
|
* Converts this instance to its JSON wire protocol representation. Note this
|
|
570
590
|
* function is an implementation not intended for general use.
|
|
@@ -581,7 +601,7 @@ class Options extends Capabilities {
|
|
|
581
601
|
return extension.toString('base64')
|
|
582
602
|
}
|
|
583
603
|
return io
|
|
584
|
-
.read(/** @type {string} */(extension))
|
|
604
|
+
.read(/** @type {string} */ (extension))
|
|
585
605
|
.then((buffer) => buffer.toString('base64'))
|
|
586
606
|
})
|
|
587
607
|
}
|
|
@@ -634,7 +654,7 @@ class Driver extends webdriver.WebDriver {
|
|
|
634
654
|
* implementation.
|
|
635
655
|
* @override
|
|
636
656
|
*/
|
|
637
|
-
setFileDetector() {
|
|
657
|
+
setFileDetector() {}
|
|
638
658
|
|
|
639
659
|
/**
|
|
640
660
|
* Schedules a command to launch Chrome App with given ID.
|
package/edge.js
CHANGED
|
@@ -80,8 +80,6 @@
|
|
|
80
80
|
const { Browser } = require('./lib/capabilities')
|
|
81
81
|
const io = require('./io')
|
|
82
82
|
const chromium = require('./chromium')
|
|
83
|
-
const http = require('./http')
|
|
84
|
-
const webdriver = require('./lib/webdriver')
|
|
85
83
|
|
|
86
84
|
/**
|
|
87
85
|
* Name of the EdgeDriver executable.
|
|
@@ -111,10 +109,10 @@ class ServiceBuilder extends chromium.ServiceBuilder {
|
|
|
111
109
|
let exe = opt_exe || locateSynchronously()
|
|
112
110
|
if (!exe) {
|
|
113
111
|
throw Error(
|
|
114
|
-
`The WebDriver for Edge could not be found on the current PATH. Please download the
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
112
|
+
`The WebDriver for Edge could not be found on the current PATH. Please download the ` +
|
|
113
|
+
`latest version of ${EDGEDRIVER_CHROMIUM_EXE} from ` +
|
|
114
|
+
`https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ ` +
|
|
115
|
+
`and ensure it can be found on your PATH.`
|
|
118
116
|
)
|
|
119
117
|
}
|
|
120
118
|
super(exe)
|
|
@@ -143,24 +141,20 @@ class Options extends chromium.Options {
|
|
|
143
141
|
/**
|
|
144
142
|
* Creates a new WebDriver client for Microsoft's Edge.
|
|
145
143
|
*/
|
|
146
|
-
class Driver extends
|
|
144
|
+
class Driver extends chromium.Driver {
|
|
147
145
|
/**
|
|
148
146
|
* Creates a new browser session for Microsoft's Edge browser.
|
|
149
147
|
*
|
|
150
|
-
* @param {(Capabilities|Options)=}
|
|
151
|
-
* @param {remote.DriverService=}
|
|
148
|
+
* @param {(Capabilities|Options)=} opt_config The configuration options.
|
|
149
|
+
* @param {remote.DriverService=} opt_serviceExecutor The service to use; will create
|
|
152
150
|
* a new Legacy or Chromium service based on {@linkplain Options} by default.
|
|
153
151
|
* @return {!Driver} A new driver instance.
|
|
154
152
|
*/
|
|
155
|
-
static createSession(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return /** @type {!Driver} */ (super.createSession(executor, options, () =>
|
|
162
|
-
service.kill()
|
|
163
|
-
))
|
|
153
|
+
static createSession(opt_config, opt_serviceExecutor) {
|
|
154
|
+
let caps = opt_config || new Options()
|
|
155
|
+
return /** @type {!Driver} */ (
|
|
156
|
+
super.createSession(caps, opt_serviceExecutor)
|
|
157
|
+
)
|
|
164
158
|
}
|
|
165
159
|
|
|
166
160
|
/**
|
|
@@ -180,7 +174,7 @@ function setDefaultService(service) {
|
|
|
180
174
|
if (defaultService && defaultService.isRunning()) {
|
|
181
175
|
throw Error(
|
|
182
176
|
'The previously configured EdgeDriver service is still running. ' +
|
|
183
|
-
|
|
177
|
+
'You must shut it down before you may adjust its configuration.'
|
|
184
178
|
)
|
|
185
179
|
}
|
|
186
180
|
defaultService = service
|
|
@@ -199,7 +193,6 @@ function getDefaultService() {
|
|
|
199
193
|
return defaultService
|
|
200
194
|
}
|
|
201
195
|
|
|
202
|
-
|
|
203
196
|
/**
|
|
204
197
|
* _Synchronously_ attempts to locate the chromedriver executable on the current
|
|
205
198
|
* system.
|
|
@@ -213,6 +206,7 @@ function locateSynchronously() {
|
|
|
213
206
|
Options.prototype.BROWSER_NAME_VALUE = Browser.EDGE
|
|
214
207
|
Options.prototype.CAPABILITY_KEY = 'ms:edgeOptions'
|
|
215
208
|
Driver.prototype.VENDOR_CAPABILITY_PREFIX = 'ms'
|
|
209
|
+
Driver.getDefaultService = getDefaultService
|
|
216
210
|
|
|
217
211
|
// PUBLIC API
|
|
218
212
|
|
package/firefox.js
CHANGED
|
@@ -124,7 +124,6 @@ const io = require('./io')
|
|
|
124
124
|
const remote = require('./remote')
|
|
125
125
|
const webdriver = require('./lib/webdriver')
|
|
126
126
|
const zip = require('./io/zip')
|
|
127
|
-
const cdp = require('./devtools/CDPConnection')
|
|
128
127
|
const { Browser, Capabilities } = require('./lib/capabilities')
|
|
129
128
|
const { Zip } = require('./io/zip')
|
|
130
129
|
|
|
@@ -394,6 +393,24 @@ class Options extends Capabilities {
|
|
|
394
393
|
}
|
|
395
394
|
throw TypeError('binary must be a string path or Channel object')
|
|
396
395
|
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Enables Mobile start up features
|
|
399
|
+
*
|
|
400
|
+
* @param {string} androidPackage The package to use
|
|
401
|
+
* @return {!Options} A self reference
|
|
402
|
+
*/
|
|
403
|
+
enableMobile(androidPackage = "org.mozilla.firefox", androidActivity = null, deviceSerial = null) {
|
|
404
|
+
this.firefoxOptions_().androidPackage = androidPackage
|
|
405
|
+
|
|
406
|
+
if (androidActivity) {
|
|
407
|
+
this.firefoxOptions_().androidActivity = androidActivity
|
|
408
|
+
}
|
|
409
|
+
if (deviceSerial) {
|
|
410
|
+
this.firefoxOptions_().deviceSerial = deviceSerial
|
|
411
|
+
}
|
|
412
|
+
return this
|
|
413
|
+
}
|
|
397
414
|
}
|
|
398
415
|
|
|
399
416
|
/**
|
package/http/index.js
CHANGED
|
@@ -77,8 +77,9 @@ class HttpClient {
|
|
|
77
77
|
* Defaults to `http.globalAgent`.
|
|
78
78
|
* @param {?string=} opt_proxy The proxy to use for the connection to the
|
|
79
79
|
* server. Default is to use no proxy.
|
|
80
|
+
* @param {?Object.<string,Object>} client_options
|
|
80
81
|
*/
|
|
81
|
-
constructor(serverUrl, opt_agent, opt_proxy) {
|
|
82
|
+
constructor(serverUrl, opt_agent, opt_proxy, client_options = {}) {
|
|
82
83
|
/** @private {http.Agent} */
|
|
83
84
|
this.agent_ = opt_agent || null
|
|
84
85
|
|
|
@@ -88,12 +89,33 @@ class HttpClient {
|
|
|
88
89
|
*/
|
|
89
90
|
this.options_ = getRequestOptions(serverUrl)
|
|
90
91
|
|
|
92
|
+
/**
|
|
93
|
+
* client options, header overrides
|
|
94
|
+
*/
|
|
95
|
+
this.client_options = client_options
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* sets keep-alive for the agent
|
|
99
|
+
* see https://stackoverflow.com/a/58332910
|
|
100
|
+
*/
|
|
101
|
+
this.keepAlive = this.client_options['keep-alive']
|
|
102
|
+
|
|
91
103
|
/**
|
|
92
104
|
* @private {?RequestOptions}
|
|
93
105
|
*/
|
|
94
106
|
this.proxyOptions_ = opt_proxy ? getRequestOptions(opt_proxy) : null
|
|
95
107
|
}
|
|
96
108
|
|
|
109
|
+
get keepAlive() {
|
|
110
|
+
return this.agent_.keepAlive
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
set keepAlive(value) {
|
|
114
|
+
if (value === 'true' || value === true) {
|
|
115
|
+
this.agent_.keepAlive = true
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
97
119
|
/** @override */
|
|
98
120
|
send(httpRequest) {
|
|
99
121
|
let data
|
|
@@ -106,7 +128,7 @@ class HttpClient {
|
|
|
106
128
|
})
|
|
107
129
|
}
|
|
108
130
|
|
|
109
|
-
headers['User-Agent'] = USER_AGENT
|
|
131
|
+
headers['User-Agent'] = this.client_options['user-agent'] || USER_AGENT
|
|
110
132
|
headers['Content-Length'] = 0
|
|
111
133
|
if (httpRequest.method == 'POST' || httpRequest.method == 'PUT') {
|
|
112
134
|
data = JSON.stringify(httpRequest.data)
|
|
@@ -232,7 +254,7 @@ function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
|
|
|
232
254
|
hash: location.hash,
|
|
233
255
|
headers: {
|
|
234
256
|
Accept: 'application/json; charset=utf-8',
|
|
235
|
-
'User-Agent': USER_AGENT,
|
|
257
|
+
'User-Agent': options.headers['User-Agent'] || USER_AGENT,
|
|
236
258
|
},
|
|
237
259
|
},
|
|
238
260
|
onOk,
|
package/ie.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
/**
|
|
19
19
|
* @fileoverview Defines a {@linkplain Driver WebDriver} client for Microsoft's
|
|
20
20
|
* Internet Explorer. Before using the IEDriver, you must download the latest
|
|
21
|
-
* [IEDriverServer](
|
|
21
|
+
* [IEDriverServer](https://www.selenium.dev/downloads/)
|
|
22
22
|
* and place it on your
|
|
23
23
|
* [PATH](http://en.wikipedia.org/wiki/PATH_%28variable%29). You must also apply
|
|
24
24
|
* the system configuration outlined on the Selenium project
|
|
@@ -370,7 +370,7 @@ class Options extends Capabilities {
|
|
|
370
370
|
behavior !== SCROLL_BEHAVIOUR.TOP &&
|
|
371
371
|
behavior !== SCROLL_BEHAVIOUR.BOTTOM
|
|
372
372
|
) {
|
|
373
|
-
throw new error.InvalidArgumentError(`Element Scroll Behavior out of range.
|
|
373
|
+
throw new error.InvalidArgumentError(`Element Scroll Behavior out of range.
|
|
374
374
|
It should be either ${SCROLL_BEHAVIOUR.TOP} or ${SCROLL_BEHAVIOUR.BOTTOM}`)
|
|
375
375
|
}
|
|
376
376
|
this.options_[Key.ELEMENT_SCROLL_BEHAVIOR] = behavior
|
|
@@ -402,9 +402,9 @@ function createServiceFromCapabilities(capabilities) {
|
|
|
402
402
|
if (!exe || !fs.existsSync(exe)) {
|
|
403
403
|
throw Error(
|
|
404
404
|
`${IEDRIVER_EXE} could not be found on the current PATH. Please ` +
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
405
|
+
`download the latest version of ${IEDRIVER_EXE} from ` +
|
|
406
|
+
'https://www.selenium.dev/downloads/ and ' +
|
|
407
|
+
'ensure it can be found on your system PATH.'
|
|
408
408
|
)
|
|
409
409
|
}
|
|
410
410
|
|
|
@@ -478,9 +478,9 @@ class Driver extends webdriver.WebDriver {
|
|
|
478
478
|
let client = service.start().then((url) => new http.HttpClient(url))
|
|
479
479
|
let executor = new http.Executor(client)
|
|
480
480
|
|
|
481
|
-
return /** @type {!Driver} */ (
|
|
482
|
-
service.kill()
|
|
483
|
-
)
|
|
481
|
+
return /** @type {!Driver} */ (
|
|
482
|
+
super.createSession(executor, options, () => service.kill())
|
|
483
|
+
)
|
|
484
484
|
}
|
|
485
485
|
|
|
486
486
|
/**
|
package/index.js
CHANGED
|
@@ -103,7 +103,7 @@ function ensureFileDetectorsAreEnabled(ctor) {
|
|
|
103
103
|
*/
|
|
104
104
|
class ThenableWebDriver {
|
|
105
105
|
/** @param {...?} args */
|
|
106
|
-
static createSession(...args) {} // eslint-disable-line
|
|
106
|
+
static createSession(...args) { } // eslint-disable-line
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
/**
|
|
@@ -162,7 +162,7 @@ function createDriver(ctor, ...args) {
|
|
|
162
162
|
* option always takes precedence over {@code SELENIUM_SERVER_JAR}.
|
|
163
163
|
*
|
|
164
164
|
* - {@code SELENIUM_SERVER_JAR}: defines the path to the
|
|
165
|
-
* <a href="
|
|
165
|
+
* <a href="https://www.selenium.dev/downloads/">
|
|
166
166
|
* standalone Selenium server</a> jar to use. The server will be started the
|
|
167
167
|
* first time a WebDriver instance and be killed when the process exits.
|
|
168
168
|
*
|
|
@@ -318,6 +318,8 @@ class Builder {
|
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
/**
|
|
321
|
+
* @deprecated Since Selenium 4.0 withCapabilities is deprecated, use set*Options instead where * is the browser(eg setChromeOptions)
|
|
322
|
+
*
|
|
321
323
|
* Sets the desired capabilities when requesting a new session. This will
|
|
322
324
|
* overwrite any previously set capabilities.
|
|
323
325
|
* @param {!(Object|Capabilities)} capabilities The desired capabilities for
|
|
@@ -615,7 +617,7 @@ class Builder {
|
|
|
615
617
|
if (typeof browser !== 'string') {
|
|
616
618
|
throw TypeError(
|
|
617
619
|
`Target browser must be a string, but is <${typeof browser}>;` +
|
|
618
|
-
|
|
620
|
+
' did you forget to call forBrowser()?'
|
|
619
621
|
)
|
|
620
622
|
}
|
|
621
623
|
|
|
@@ -736,8 +738,8 @@ class Builder {
|
|
|
736
738
|
default:
|
|
737
739
|
throw new Error(
|
|
738
740
|
'Do not know how to build driver: ' +
|
|
739
|
-
|
|
740
|
-
|
|
741
|
+
browser +
|
|
742
|
+
'; did you forget to call usingServer(url)?'
|
|
741
743
|
)
|
|
742
744
|
}
|
|
743
745
|
}
|
|
@@ -793,9 +795,9 @@ function checkOptions(caps, key, optionType, setMethod) {
|
|
|
793
795
|
if (val instanceof optionType) {
|
|
794
796
|
throw new error.InvalidArgumentError(
|
|
795
797
|
'Options class extends Capabilities and should not be set as key ' +
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
798
|
+
`"${key}"; set browser-specific options with ` +
|
|
799
|
+
`Builder.${setMethod}(). For more information, see the ` +
|
|
800
|
+
'documentation attached to the function that threw this error'
|
|
799
801
|
)
|
|
800
802
|
}
|
|
801
803
|
}
|
|
@@ -807,6 +809,7 @@ exports.Builder = Builder
|
|
|
807
809
|
exports.Button = input.Button
|
|
808
810
|
exports.By = by.By
|
|
809
811
|
exports.withTagName = by.withTagName
|
|
812
|
+
exports.withLocator = by.withLocator
|
|
810
813
|
exports.Capabilities = capabilities.Capabilities
|
|
811
814
|
exports.Capability = capabilities.Capability
|
|
812
815
|
exports.Condition = webdriver.Condition
|
package/io/exec.js
CHANGED
|
@@ -76,7 +76,8 @@ class Result {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
const COMMAND_RESULT =
|
|
79
|
+
const COMMAND_RESULT =
|
|
80
|
+
/** !WeakMap<!Command, !Promise<!Result>> */ new WeakMap()
|
|
80
81
|
const KILL_HOOK = /** !WeakMap<!Command, function(string)> */ new WeakMap()
|
|
81
82
|
|
|
82
83
|
/**
|
package/lib/by.js
CHANGED
|
@@ -258,8 +258,36 @@ class By {
|
|
|
258
258
|
}
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
+
/**
|
|
262
|
+
* Start Searching for relative objects using the value returned from
|
|
263
|
+
* `By.tagName()`.
|
|
264
|
+
*
|
|
265
|
+
* Note: this method will likely be removed in the future please use
|
|
266
|
+
* `locateWith`.
|
|
267
|
+
* @param {By} The value returned from calling By.tagName()
|
|
268
|
+
* @returns
|
|
269
|
+
*/
|
|
261
270
|
function withTagName(tagName) {
|
|
262
|
-
return new RelativeBy(tagName)
|
|
271
|
+
return new RelativeBy({ 'css selector': tagName })
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Start searching for relative objects using search criteria with By.
|
|
276
|
+
* @param {string} A By map that shows how to find the initial element
|
|
277
|
+
* @returns {RelativeBy}
|
|
278
|
+
*/
|
|
279
|
+
function locateWith(by) {
|
|
280
|
+
return new RelativeBy(getLocator(by));
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function getLocator(locatorOrElement) {
|
|
284
|
+
let toFind
|
|
285
|
+
if (locatorOrElement instanceof By) {
|
|
286
|
+
toFind = locatorOrElement.toObject()
|
|
287
|
+
} else {
|
|
288
|
+
toFind = locatorOrElement
|
|
289
|
+
}
|
|
290
|
+
return toFind
|
|
263
291
|
}
|
|
264
292
|
|
|
265
293
|
/**
|
|
@@ -269,11 +297,11 @@ function withTagName(tagName) {
|
|
|
269
297
|
*/
|
|
270
298
|
class RelativeBy {
|
|
271
299
|
/**
|
|
272
|
-
* @param {
|
|
300
|
+
* @param {By} findDetails
|
|
273
301
|
* @param {Array<Object>} filters
|
|
274
302
|
*/
|
|
275
|
-
constructor(
|
|
276
|
-
this.root =
|
|
303
|
+
constructor(findDetails, filters = null) {
|
|
304
|
+
this.root = findDetails
|
|
277
305
|
this.filters = filters || []
|
|
278
306
|
}
|
|
279
307
|
|
|
@@ -285,7 +313,7 @@ class RelativeBy {
|
|
|
285
313
|
above(locatorOrElement) {
|
|
286
314
|
this.filters.push({
|
|
287
315
|
kind: 'above',
|
|
288
|
-
args: [
|
|
316
|
+
args: [getLocator(locatorOrElement)],
|
|
289
317
|
})
|
|
290
318
|
return this
|
|
291
319
|
}
|
|
@@ -298,7 +326,7 @@ class RelativeBy {
|
|
|
298
326
|
below(locatorOrElement) {
|
|
299
327
|
this.filters.push({
|
|
300
328
|
kind: 'below',
|
|
301
|
-
args: [
|
|
329
|
+
args: [getLocator(locatorOrElement)],
|
|
302
330
|
})
|
|
303
331
|
return this
|
|
304
332
|
}
|
|
@@ -311,7 +339,7 @@ class RelativeBy {
|
|
|
311
339
|
toLeftOf(locatorOrElement) {
|
|
312
340
|
this.filters.push({
|
|
313
341
|
kind: 'left',
|
|
314
|
-
args: [
|
|
342
|
+
args: [getLocator(locatorOrElement)],
|
|
315
343
|
})
|
|
316
344
|
return this
|
|
317
345
|
}
|
|
@@ -324,7 +352,7 @@ class RelativeBy {
|
|
|
324
352
|
toRightOf(locatorOrElement) {
|
|
325
353
|
this.filters.push({
|
|
326
354
|
kind: 'right',
|
|
327
|
-
args: [
|
|
355
|
+
args: [getLocator(locatorOrElement)],
|
|
328
356
|
})
|
|
329
357
|
return this
|
|
330
358
|
}
|
|
@@ -337,7 +365,7 @@ class RelativeBy {
|
|
|
337
365
|
near(locatorOrElement) {
|
|
338
366
|
this.filters.push({
|
|
339
367
|
kind: 'near',
|
|
340
|
-
args: [
|
|
368
|
+
args: [getLocator(locatorOrElement)],
|
|
341
369
|
})
|
|
342
370
|
return this
|
|
343
371
|
}
|
|
@@ -350,22 +378,12 @@ class RelativeBy {
|
|
|
350
378
|
marshall() {
|
|
351
379
|
return {
|
|
352
380
|
relative: {
|
|
353
|
-
root:
|
|
381
|
+
root: this.root,
|
|
354
382
|
filters: this.filters,
|
|
355
383
|
},
|
|
356
384
|
}
|
|
357
385
|
}
|
|
358
386
|
|
|
359
|
-
getLocator(locatorOrElement) {
|
|
360
|
-
let toFind
|
|
361
|
-
if (locatorOrElement instanceof By) {
|
|
362
|
-
toFind = locatorOrElement.toObject()
|
|
363
|
-
} else {
|
|
364
|
-
toFind = locatorOrElement
|
|
365
|
-
}
|
|
366
|
-
return toFind
|
|
367
|
-
}
|
|
368
|
-
|
|
369
387
|
/** @override */
|
|
370
388
|
toString() {
|
|
371
389
|
// The static By.name() overrides this.constructor.name. Shame...
|
|
@@ -411,5 +429,6 @@ module.exports = {
|
|
|
411
429
|
By: By,
|
|
412
430
|
RelativeBy: RelativeBy,
|
|
413
431
|
withTagName: withTagName,
|
|
432
|
+
locateWith: locateWith,
|
|
414
433
|
checkedLocator: check,
|
|
415
434
|
}
|
package/lib/capabilities.js
CHANGED
|
@@ -263,7 +263,9 @@ class Capabilities {
|
|
|
263
263
|
* @return {!Capabilities} A basic set of capabilities for Firefox.
|
|
264
264
|
*/
|
|
265
265
|
static firefox() {
|
|
266
|
-
return new Capabilities()
|
|
266
|
+
return new Capabilities()
|
|
267
|
+
.setBrowserName(Browser.FIREFOX)
|
|
268
|
+
.set('moz:debuggerAddress', true)
|
|
267
269
|
}
|
|
268
270
|
|
|
269
271
|
/**
|
|
@@ -280,6 +282,13 @@ class Capabilities {
|
|
|
280
282
|
return new Capabilities().setBrowserName(Browser.SAFARI)
|
|
281
283
|
}
|
|
282
284
|
|
|
285
|
+
/**
|
|
286
|
+
* @return {!Capabilities} A basic set of capabilities for Opera
|
|
287
|
+
*/
|
|
288
|
+
static opera() {
|
|
289
|
+
return new Capabilities().setBrowserName(Browser.OPERA)
|
|
290
|
+
}
|
|
291
|
+
|
|
283
292
|
/**
|
|
284
293
|
* @return {!Object<string, ?>} The JSON representation of this instance.
|
|
285
294
|
* Note, the returned object may contain nested promised values.
|
package/lib/http.js
CHANGED
|
@@ -490,7 +490,8 @@ function buildRequest(customCommands, w3c, command) {
|
|
|
490
490
|
}
|
|
491
491
|
}
|
|
492
492
|
|
|
493
|
-
const CLIENTS =
|
|
493
|
+
const CLIENTS =
|
|
494
|
+
/** !WeakMap<!Executor, !(Client|IThenable<!Client>)> */ new WeakMap()
|
|
494
495
|
|
|
495
496
|
/**
|
|
496
497
|
* A command executor that communicates with the server using JSON over HTTP.
|
package/lib/input.js
CHANGED
|
@@ -20,14 +20,8 @@
|
|
|
20
20
|
/**
|
|
21
21
|
* @fileoverview Defines types related to user input with the WebDriver API.
|
|
22
22
|
*/
|
|
23
|
-
|
|
24
|
-
const promise = require('./promise')
|
|
25
23
|
const { Command, Name } = require('./command')
|
|
26
|
-
const {
|
|
27
|
-
InvalidArgumentError,
|
|
28
|
-
UnknownCommandError,
|
|
29
|
-
UnsupportedOperationError,
|
|
30
|
-
} = require('./error')
|
|
24
|
+
const { InvalidArgumentError } = require('./error')
|
|
31
25
|
|
|
32
26
|
/**
|
|
33
27
|
* Enumeration of the buttons used in the advanced interactions API.
|
|
@@ -503,7 +497,6 @@ class Actions {
|
|
|
503
497
|
* sequence (see class description for details).
|
|
504
498
|
*/
|
|
505
499
|
constructor(executor, { async = false } = {}) {
|
|
506
|
-
|
|
507
500
|
/** @private @const */
|
|
508
501
|
this.executor_ = executor
|
|
509
502
|
|
|
@@ -882,13 +875,9 @@ class Actions {
|
|
|
882
875
|
return Promise.resolve()
|
|
883
876
|
}
|
|
884
877
|
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
)
|
|
889
|
-
} catch (ex) {
|
|
890
|
-
throw ex
|
|
891
|
-
}
|
|
878
|
+
await this.executor_.execute(
|
|
879
|
+
new Command(Name.ACTIONS).setParameter('actions', _actions)
|
|
880
|
+
)
|
|
892
881
|
}
|
|
893
882
|
}
|
|
894
883
|
|
package/lib/until.js
CHANGED
|
@@ -137,14 +137,13 @@ exports.alertIsPresent = function alertIsPresent() {
|
|
|
137
137
|
* @return {!Condition<boolean>} The new condition.
|
|
138
138
|
*/
|
|
139
139
|
exports.titleIs = function titleIs(title) {
|
|
140
|
-
return new Condition(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
)
|
|
140
|
+
return new Condition('for title to be ' + JSON.stringify(title), function (
|
|
141
|
+
driver
|
|
142
|
+
) {
|
|
143
|
+
return driver.getTitle().then(function (t) {
|
|
144
|
+
return t === title
|
|
145
|
+
})
|
|
146
|
+
})
|
|
148
147
|
}
|
|
149
148
|
|
|
150
149
|
/**
|
|
@@ -189,14 +188,13 @@ exports.titleMatches = function titleMatches(regex) {
|
|
|
189
188
|
* @return {!Condition<boolean>} The new condition.
|
|
190
189
|
*/
|
|
191
190
|
exports.urlIs = function urlIs(url) {
|
|
192
|
-
return new Condition(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
)
|
|
191
|
+
return new Condition('for URL to be ' + JSON.stringify(url), function (
|
|
192
|
+
driver
|
|
193
|
+
) {
|
|
194
|
+
return driver.getCurrentUrl().then(function (u) {
|
|
195
|
+
return u === url
|
|
196
|
+
})
|
|
197
|
+
})
|
|
200
198
|
}
|
|
201
199
|
|
|
202
200
|
/**
|
package/lib/webdriver.js
CHANGED
|
@@ -258,18 +258,18 @@ class IWebDriver {
|
|
|
258
258
|
/**
|
|
259
259
|
* @return {!command.Executor} The command executor used by this instance.
|
|
260
260
|
*/
|
|
261
|
-
getExecutor() {}
|
|
261
|
+
getExecutor() { }
|
|
262
262
|
|
|
263
263
|
/**
|
|
264
264
|
* @return {!Promise<!Session>} A promise for this client's session.
|
|
265
265
|
*/
|
|
266
|
-
getSession() {}
|
|
266
|
+
getSession() { }
|
|
267
267
|
|
|
268
268
|
/**
|
|
269
269
|
* @return {!Promise<!Capabilities>} A promise that will resolve with
|
|
270
270
|
* the this instance's capabilities.
|
|
271
271
|
*/
|
|
272
|
-
getCapabilities() {}
|
|
272
|
+
getCapabilities() { }
|
|
273
273
|
|
|
274
274
|
/**
|
|
275
275
|
* Terminates the browser session. After calling quit, this instance will be
|
|
@@ -279,7 +279,7 @@ class IWebDriver {
|
|
|
279
279
|
* @return {!Promise<void>} A promise that will be resolved when the
|
|
280
280
|
* command has completed.
|
|
281
281
|
*/
|
|
282
|
-
quit() {}
|
|
282
|
+
quit() { }
|
|
283
283
|
|
|
284
284
|
/**
|
|
285
285
|
* Creates a new action sequence using this driver. The sequence will not be
|
|
@@ -458,7 +458,7 @@ class IWebDriver {
|
|
|
458
458
|
timeout = undefined, // eslint-disable-line
|
|
459
459
|
message = undefined, // eslint-disable-line
|
|
460
460
|
pollTimeout = undefined // eslint-disable-line
|
|
461
|
-
) {}
|
|
461
|
+
) { }
|
|
462
462
|
|
|
463
463
|
/**
|
|
464
464
|
* Makes the driver sleep for the given amount of time.
|
|
@@ -475,7 +475,7 @@ class IWebDriver {
|
|
|
475
475
|
* @return {!Promise<string>} A promise that will be resolved with the current
|
|
476
476
|
* window handle.
|
|
477
477
|
*/
|
|
478
|
-
getWindowHandle() {}
|
|
478
|
+
getWindowHandle() { }
|
|
479
479
|
|
|
480
480
|
/**
|
|
481
481
|
* Retrieves a list of all available window handles.
|
|
@@ -483,7 +483,7 @@ class IWebDriver {
|
|
|
483
483
|
* @return {!Promise<!Array<string>>} A promise that will be resolved with an
|
|
484
484
|
* array of window handles.
|
|
485
485
|
*/
|
|
486
|
-
getAllWindowHandles() {}
|
|
486
|
+
getAllWindowHandles() { }
|
|
487
487
|
|
|
488
488
|
/**
|
|
489
489
|
* Retrieves the current page's source. The returned source is a representation
|
|
@@ -493,7 +493,7 @@ class IWebDriver {
|
|
|
493
493
|
* @return {!Promise<string>} A promise that will be resolved with the current
|
|
494
494
|
* page source.
|
|
495
495
|
*/
|
|
496
|
-
getPageSource() {}
|
|
496
|
+
getPageSource() { }
|
|
497
497
|
|
|
498
498
|
/**
|
|
499
499
|
* Closes the current window.
|
|
@@ -501,7 +501,7 @@ class IWebDriver {
|
|
|
501
501
|
* @return {!Promise<void>} A promise that will be resolved when this command
|
|
502
502
|
* has completed.
|
|
503
503
|
*/
|
|
504
|
-
close() {}
|
|
504
|
+
close() { }
|
|
505
505
|
|
|
506
506
|
/**
|
|
507
507
|
* Navigates to the given URL.
|
|
@@ -518,7 +518,7 @@ class IWebDriver {
|
|
|
518
518
|
* @return {!Promise<string>} A promise that will be resolved with the
|
|
519
519
|
* current URL.
|
|
520
520
|
*/
|
|
521
|
-
getCurrentUrl() {}
|
|
521
|
+
getCurrentUrl() { }
|
|
522
522
|
|
|
523
523
|
/**
|
|
524
524
|
* Retrieves the current page title.
|
|
@@ -526,7 +526,7 @@ class IWebDriver {
|
|
|
526
526
|
* @return {!Promise<string>} A promise that will be resolved with the current
|
|
527
527
|
* page's title.
|
|
528
528
|
*/
|
|
529
|
-
getTitle() {}
|
|
529
|
+
getTitle() { }
|
|
530
530
|
|
|
531
531
|
/**
|
|
532
532
|
* Locates an element on the page. If the element cannot be found, a
|
|
@@ -590,23 +590,23 @@ class IWebDriver {
|
|
|
590
590
|
* @return {!Promise<string>} A promise that will be resolved to the
|
|
591
591
|
* screenshot as a base-64 encoded PNG.
|
|
592
592
|
*/
|
|
593
|
-
takeScreenshot() {}
|
|
593
|
+
takeScreenshot() { }
|
|
594
594
|
|
|
595
595
|
/**
|
|
596
596
|
* @return {!Options} The options interface for this instance.
|
|
597
597
|
*/
|
|
598
|
-
manage() {}
|
|
598
|
+
manage() { }
|
|
599
599
|
|
|
600
600
|
/**
|
|
601
601
|
* @return {!Navigation} The navigation interface for this instance.
|
|
602
602
|
*/
|
|
603
|
-
navigate() {}
|
|
603
|
+
navigate() { }
|
|
604
604
|
|
|
605
605
|
/**
|
|
606
606
|
* @return {!TargetLocator} The target locator interface for this
|
|
607
607
|
* instance.
|
|
608
608
|
*/
|
|
609
|
-
switchTo() {}
|
|
609
|
+
switchTo() { }
|
|
610
610
|
|
|
611
611
|
/**
|
|
612
612
|
*
|
|
@@ -665,7 +665,7 @@ class WebDriver {
|
|
|
665
665
|
// If session is a rejected promise, add a no-op rejection handler.
|
|
666
666
|
// This effectively hides setup errors until users attempt to interact
|
|
667
667
|
// with the session.
|
|
668
|
-
this.session_.catch(function () {})
|
|
668
|
+
this.session_.catch(function () { })
|
|
669
669
|
|
|
670
670
|
/** @private {!command.Executor} */
|
|
671
671
|
this.executor_ = executor
|
|
@@ -761,12 +761,12 @@ class WebDriver {
|
|
|
761
761
|
this.session_ = Promise.reject(
|
|
762
762
|
new error.NoSuchSessionError(
|
|
763
763
|
'This driver instance does not have a valid session ID ' +
|
|
764
|
-
|
|
764
|
+
'(did you call WebDriver.quit()?) and may no longer be used.'
|
|
765
765
|
)
|
|
766
766
|
)
|
|
767
767
|
|
|
768
768
|
// Only want the session rejection to bubble if accessed.
|
|
769
|
-
this.session_.catch(function () {})
|
|
769
|
+
this.session_.catch(function () { })
|
|
770
770
|
|
|
771
771
|
if (this.onQuit_) {
|
|
772
772
|
return this.onQuit_.call(void 0)
|
|
@@ -827,18 +827,15 @@ class WebDriver {
|
|
|
827
827
|
let timeoutMessage = resolveWaitMessage(message)
|
|
828
828
|
reject(
|
|
829
829
|
new error.TimeoutError(
|
|
830
|
-
`${timeoutMessage}Timed out waiting for promise to resolve after ${
|
|
831
|
-
Date.now() - start
|
|
830
|
+
`${timeoutMessage}Timed out waiting for promise to resolve after ${Date.now() - start
|
|
832
831
|
}ms`
|
|
833
832
|
)
|
|
834
833
|
)
|
|
835
834
|
} catch (ex) {
|
|
836
835
|
reject(
|
|
837
836
|
new error.TimeoutError(
|
|
838
|
-
`${
|
|
839
|
-
|
|
840
|
-
}\nTimed out waiting for promise to resolve after ${
|
|
841
|
-
Date.now() - start
|
|
837
|
+
`${ex.message
|
|
838
|
+
}\nTimed out waiting for promise to resolve after ${Date.now() - start
|
|
842
839
|
}ms`
|
|
843
840
|
)
|
|
844
841
|
)
|
|
@@ -868,7 +865,7 @@ class WebDriver {
|
|
|
868
865
|
if (typeof fn !== 'function') {
|
|
869
866
|
throw TypeError(
|
|
870
867
|
'Wait condition must be a promise-like object, function, or a ' +
|
|
871
|
-
|
|
868
|
+
'Condition object'
|
|
872
869
|
)
|
|
873
870
|
}
|
|
874
871
|
|
|
@@ -920,7 +917,7 @@ class WebDriver {
|
|
|
920
917
|
if (!(value instanceof WebElement)) {
|
|
921
918
|
throw TypeError(
|
|
922
919
|
'WebElementCondition did not resolve to a WebElement: ' +
|
|
923
|
-
|
|
920
|
+
Object.prototype.toString.call(value)
|
|
924
921
|
)
|
|
925
922
|
}
|
|
926
923
|
return value
|
|
@@ -1732,7 +1729,7 @@ class Options {
|
|
|
1732
1729
|
} else if (typeof value !== 'undefined') {
|
|
1733
1730
|
throw TypeError(
|
|
1734
1731
|
'invalid timeouts configuration:' +
|
|
1735
|
-
|
|
1732
|
+
` expected "${key}" to be a number, got ${typeof value}`
|
|
1736
1733
|
)
|
|
1737
1734
|
}
|
|
1738
1735
|
}
|
|
@@ -1793,7 +1790,7 @@ function legacyTimeout(driver, type, ms) {
|
|
|
1793
1790
|
*
|
|
1794
1791
|
* @record
|
|
1795
1792
|
*/
|
|
1796
|
-
Options.Cookie = function () {}
|
|
1793
|
+
Options.Cookie = function () { }
|
|
1797
1794
|
|
|
1798
1795
|
/**
|
|
1799
1796
|
* The name of the cookie.
|
|
@@ -2498,18 +2495,18 @@ class WebElement {
|
|
|
2498
2495
|
*/
|
|
2499
2496
|
async sendKeys(...args) {
|
|
2500
2497
|
let keys = []
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2498
|
+
; (await Promise.all(args)).forEach((key) => {
|
|
2499
|
+
let type = typeof key
|
|
2500
|
+
if (type === 'number') {
|
|
2501
|
+
key = String(key)
|
|
2502
|
+
} else if (type !== 'string') {
|
|
2503
|
+
throw TypeError('each key must be a number of string; got ' + type)
|
|
2504
|
+
}
|
|
2508
2505
|
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2506
|
+
// The W3C protocol requires keys to be specified as an array where
|
|
2507
|
+
// each element is a single key.
|
|
2508
|
+
keys.push(...key.split(''))
|
|
2509
|
+
})
|
|
2513
2510
|
|
|
2514
2511
|
if (!this.driver_.fileDetector_) {
|
|
2515
2512
|
return this.execute_(
|
|
@@ -2728,18 +2725,12 @@ class WebElement {
|
|
|
2728
2725
|
* Take a screenshot of the visible region encompassed by this element's
|
|
2729
2726
|
* bounding rectangle.
|
|
2730
2727
|
*
|
|
2731
|
-
* @param {boolean=} scroll Optional argument that indicates whether the
|
|
2732
|
-
* element should be scrolled into view before taking a screenshot.
|
|
2733
|
-
* Defaults to false.
|
|
2734
2728
|
* @return {!Promise<string>} A promise that will be
|
|
2735
2729
|
* resolved to the screenshot as a base-64 encoded PNG.
|
|
2736
2730
|
*/
|
|
2737
|
-
takeScreenshot(
|
|
2731
|
+
takeScreenshot() {
|
|
2738
2732
|
return this.execute_(
|
|
2739
|
-
new command.Command(command.Name.TAKE_ELEMENT_SCREENSHOT)
|
|
2740
|
-
'scroll',
|
|
2741
|
-
scroll
|
|
2742
|
-
)
|
|
2733
|
+
new command.Command(command.Name.TAKE_ELEMENT_SCREENSHOT)
|
|
2743
2734
|
)
|
|
2744
2735
|
}
|
|
2745
2736
|
}
|
package/opera.js
CHANGED
|
@@ -383,9 +383,9 @@ class Driver extends webdriver.WebDriver {
|
|
|
383
383
|
caps = options.toCapabilities(caps)
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
-
return /** @type {!Driver} */ (
|
|
387
|
-
service.kill()
|
|
388
|
-
)
|
|
386
|
+
return /** @type {!Driver} */ (
|
|
387
|
+
super.createSession(executor, caps, () => service.kill())
|
|
388
|
+
)
|
|
389
389
|
}
|
|
390
390
|
|
|
391
391
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "selenium-webdriver",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-rc-1",
|
|
4
4
|
"description": "The official WebDriver JavaScript bindings from the Selenium project",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"eslint-plugin-node": "^11.1.0",
|
|
36
36
|
"eslint-plugin-prettier": "^3.4.0",
|
|
37
37
|
"express": "^4.17.1",
|
|
38
|
-
"jasmine": "^3.
|
|
38
|
+
"jasmine": "^3.8.0",
|
|
39
39
|
"mocha": "^8.1.0",
|
|
40
40
|
"multer": "^1.4.2",
|
|
41
41
|
"prettier": "^2.3.0",
|
package/remote/index.js
CHANGED
|
@@ -448,7 +448,7 @@ DriverService.Builder = class {
|
|
|
448
448
|
|
|
449
449
|
/**
|
|
450
450
|
* Manages the life and death of the
|
|
451
|
-
* <a href="
|
|
451
|
+
* <a href="https://www.selenium.dev/downloads/">
|
|
452
452
|
* standalone Selenium server</a>.
|
|
453
453
|
*/
|
|
454
454
|
class SeleniumServer extends DriverService {
|
|
@@ -562,7 +562,7 @@ SeleniumServer.Options = class {
|
|
|
562
562
|
/**
|
|
563
563
|
* A {@link webdriver.FileDetector} that may be used when running
|
|
564
564
|
* against a remote
|
|
565
|
-
* [Selenium server](
|
|
565
|
+
* [Selenium server](https://www.selenium.dev/downloads/).
|
|
566
566
|
*
|
|
567
567
|
* When a file path on the local machine running this script is entered with
|
|
568
568
|
* {@link webdriver.WebElement#sendKeys WebElement#sendKeys}, this file detector
|
package/safari.js
CHANGED
|
@@ -154,9 +154,9 @@ class Driver extends webdriver.WebDriver {
|
|
|
154
154
|
service.start().then((url) => new http.HttpClient(url))
|
|
155
155
|
)
|
|
156
156
|
|
|
157
|
-
return /** @type {!Driver} */ (
|
|
158
|
-
service.kill()
|
|
159
|
-
)
|
|
157
|
+
return /** @type {!Driver} */ (
|
|
158
|
+
super.createSession(executor, caps, () => service.kill())
|
|
159
|
+
)
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
|
package/testing/index.js
CHANGED
|
@@ -47,7 +47,7 @@ const { Builder } = require('../index')
|
|
|
47
47
|
* Describes a browser targeted by a {@linkplain suite test suite}.
|
|
48
48
|
* @record
|
|
49
49
|
*/
|
|
50
|
-
function TargetBrowser() {
|
|
50
|
+
function TargetBrowser() {}
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* The {@linkplain Browser name} of the targeted browser.
|
|
@@ -210,7 +210,7 @@ function init(force = false) {
|
|
|
210
210
|
if (seleniumJar && seleniumUrl) {
|
|
211
211
|
throw Error(
|
|
212
212
|
'Ambiguous test configuration: both SELENIUM_REMOTE_URL' +
|
|
213
|
-
|
|
213
|
+
' && SELENIUM_SERVER_JAR environment variables are set'
|
|
214
214
|
)
|
|
215
215
|
}
|
|
216
216
|
|
|
@@ -218,8 +218,8 @@ function init(force = false) {
|
|
|
218
218
|
if ((seleniumJar || seleniumUrl) && envBrowsers.length === 0) {
|
|
219
219
|
throw Error(
|
|
220
220
|
'Ambiguous test configuration: when either the SELENIUM_REMOTE_URL or' +
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
' SELENIUM_SERVER_JAR environment variable is set, the' +
|
|
222
|
+
' SELENIUM_BROWSER variable must also be set.'
|
|
223
223
|
)
|
|
224
224
|
}
|
|
225
225
|
|
|
@@ -236,7 +236,8 @@ function init(force = false) {
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
const TARGET_MAP = /** !WeakMap<!Environment, !TargetBrowser> */ new WeakMap()
|
|
239
|
-
const URL_MAP =
|
|
239
|
+
const URL_MAP =
|
|
240
|
+
/** !WeakMap<!Environment, ?(string|remote.SeleniumServer)> */ new WeakMap()
|
|
240
241
|
|
|
241
242
|
/**
|
|
242
243
|
* Defines the environment a {@linkplain suite test suite} is running against.
|
|
@@ -249,9 +250,9 @@ class Environment {
|
|
|
249
250
|
* Selenium server to test against.
|
|
250
251
|
*/
|
|
251
252
|
constructor(browser, url = undefined) {
|
|
252
|
-
browser = /** @type {!TargetBrowser} */ (
|
|
253
|
-
Object.assign({}, browser)
|
|
254
|
-
)
|
|
253
|
+
browser = /** @type {!TargetBrowser} */ (
|
|
254
|
+
Object.seal(Object.assign({}, browser))
|
|
255
|
+
)
|
|
255
256
|
|
|
256
257
|
TARGET_MAP.set(this, browser)
|
|
257
258
|
URL_MAP.set(this, url || null)
|
|
@@ -288,7 +289,6 @@ class Environment {
|
|
|
288
289
|
|
|
289
290
|
const realBuild = builder.build
|
|
290
291
|
builder.build = function () {
|
|
291
|
-
|
|
292
292
|
builder.forBrowser(browser.name, browser.version, browser.platform)
|
|
293
293
|
|
|
294
294
|
if (browser.capabilities) {
|
|
@@ -311,7 +311,7 @@ class Environment {
|
|
|
311
311
|
* Configuration options for a {@linkplain ./index.suite test suite}.
|
|
312
312
|
* @record
|
|
313
313
|
*/
|
|
314
|
-
function SuiteOptions() {
|
|
314
|
+
function SuiteOptions() {}
|
|
315
315
|
|
|
316
316
|
/**
|
|
317
317
|
* The browsers to run the test suite against.
|
|
@@ -486,8 +486,8 @@ function getTestHook(name) {
|
|
|
486
486
|
if (type !== 'function') {
|
|
487
487
|
throw TypeError(
|
|
488
488
|
`Expected global.${name} to be a function, but is ${type}.` +
|
|
489
|
-
|
|
490
|
-
|
|
489
|
+
' This can happen if you try using this module when running with' +
|
|
490
|
+
' node directly instead of using jasmine or mocha'
|
|
491
491
|
)
|
|
492
492
|
}
|
|
493
493
|
return fn
|