selenium-webdriver 4.1.2 → 4.2.0

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 CHANGED
@@ -1,3 +1,13 @@
1
+ ## v4.2.0
2
+
3
+ * Delete old android-driver
4
+ * Remove Opera support from JS bindings #10379
5
+ * Handle a breaking changes in os.networkInterfaces (#10611)
6
+ * Add support to switch frame by id
7
+ * Add support to switch frame by name (#10670)
8
+ * [cdp] add support Chrome 102 and remove for Chrome 98
9
+ * Update implementation for submitting forms
10
+
1
11
  ## v4.1.2
2
12
 
3
13
  * chore/connect to CDP based on ENV selenium address var (#10255)
@@ -106,7 +116,7 @@
106
116
  ## v4.0.0-beta.1
107
117
 
108
118
  * JS Binding support for WebDriver Bidi in Firefox
109
- - This requires Firefox 87 and Geckodriver 0.29 to be able to work
119
+ - This requires Firefox 87 and Geckodriver 0.29 to be able to work
110
120
  * Update the supported CDP versions
111
121
  * Update tmp package version (#9155)
112
122
  * Adding support for /computedlabel (getAccessibleName) (#9073)
@@ -120,11 +130,11 @@
120
130
 
121
131
  * Rolling back native support for Opera Browser
122
132
  * Added new ieOptions capabilities:
123
- - fileUploadDialogTimeout
124
- - setEdgePath
125
- - setEdgeChromium
126
- - setScrollBehavior
127
- - For consistent naming, deprecating `addArguments(...args)` in favor of `addBrowserCommandSwitches(...args)`
133
+ - fileUploadDialogTimeout
134
+ - setEdgePath
135
+ - setEdgeChromium
136
+ - setScrollBehavior
137
+ - For consistent naming, deprecating `addArguments(...args)` in favor of `addBrowserCommandSwitches(...args)`
128
138
 
129
139
  * Added relative locators
130
140
  * Added Chrome DevTools Protocol (CDP) support
@@ -180,32 +190,28 @@ mode (see `example/headless.js`)
180
190
  ### Changes for W3C WebDriver Spec Compliance
181
191
 
182
192
  * Revamped the actions API to conform with the WebDriver Spec:
183
- <https://www.w3.org/TR/webdriver/#actions>. For details, refer to the JS doc on
184
- the `lib/input.Actions` class.
193
+ <https://www.w3.org/TR/webdriver/#actions>. For details, refer to the JS doc on the `lib/input.Actions` class.
185
194
 
186
195
  As of January, 2018, only Firefox natively supports this new API. You can put the `Actions` class
187
196
  into "bridge mode" and it will attempt to translate mouse and keyboard actions to the legacy API (
188
- see class docs). Alternatively, you may continue to use the legacy API directly via
189
- the `lib/actions` module.
197
+ see class docs). Alternatively, you may continue to use the legacy API directly via the `lib/actions` module.
190
198
  __NOTE:__ The legacy API is considered strongly deprecated and will be removed in a minor release
191
199
  once Google's Chrome and Microsoft's Edge browsers support the new API.
192
200
 
193
201
  * All window manipulation commands are now supported.
194
202
  * Added `driver.switchTo().parentFrame()`
195
- * When a named cookie is requested, attempt to fetch it directly using the W3C
196
- endpoint, `GET /session/{session id}/cookie/{name}`. If this command is not recognized by the
203
+ * When a named cookie is requested, attempt to fetch it directly using the W3C endpoint, `GET /session/{session id}/cookie/{name}`. If this command is not recognized by the
197
204
  remote end, fallback to fetching all cookies and then searching for the desired name.
198
- * Replaced `WebElement.getSize()` and `WebElement.getLocation()` with a single
199
- method, `WebElement.getRect()`.
205
+ * Replaced `WebElement.getSize()` and `WebElement.getLocation()` with a single method, `WebElement.getRect()`.
200
206
 
201
207
  ### API Changes
202
208
 
203
209
  * The core WebDriver API no longer uses promise manager
204
- - Removed `index.Builder#setControlFlow()`
205
- - The following thenable types no longer have a `cancel()` method:
206
- - The dynamically generated thenable WebDrivers created by `index.Builder`
207
- - `lib/webdriver.AlertPromise`
208
- - `lib/webdriver.WebElementPromise`
210
+ - Removed `index.Builder#setControlFlow()`
211
+ - The following thenable types no longer have a `cancel()` method:
212
+ - The dynamically generated thenable WebDrivers created by `index.Builder`
213
+ - `lib/webdriver.AlertPromise`
214
+ - `lib/webdriver.WebElementPromise`
209
215
  * Removed `remote/index.DriverService.prototype.stop()` (use `#kill()` instead)
210
216
  * Removed the `lib/actions` module
211
217
  * Removed the `lib/events` module
@@ -213,127 +219,124 @@ mode (see `example/headless.js`)
213
219
  * Removed the 'opera' module
214
220
  * Removed the promise manager from `lib/promise`, which includes the removal of the following
215
221
  exported names (replacements, if any, in parentheses):
216
- - CancellableThenable
217
- - CancellationError
218
- - ControlFlow
219
- - Deferred
220
- - LONG_STACK_TRACES
221
- - MultipleUnhandledRejectionError
222
- - Promise (use native Promises)
223
- - Resolver
224
- - Scheduler
225
- - Thenable
226
- - USE_PROMISE_MANAGER
227
- - all (use Promise.all)
228
- - asap (use Promise.resolve)
229
- - captureStackTrace (use Error.captureStackTrace)
230
- - consume (use async functions)
231
- - controlFlow
232
- - createPromise (use new Promise)
233
- - defer
234
- - fulfilled (use Promise.resolve)
235
- - isGenerator
236
- - rejected (use Promise.reject)
237
- - setDefaultFlow
238
- - when (use Promise.resolve)
222
+ - CancellableThenable
223
+ - CancellationError
224
+ - ControlFlow
225
+ - Deferred
226
+ - LONG_STACK_TRACES
227
+ - MultipleUnhandledRejectionError
228
+ - Promise (use native Promises)
229
+ - Resolver
230
+ - Scheduler
231
+ - Thenable
232
+ - USE_PROMISE_MANAGER
233
+ - all (use Promise.all)
234
+ - asap (use Promise.resolve)
235
+ - captureStackTrace (use Error.captureStackTrace)
236
+ - consume (use async functions)
237
+ - controlFlow
238
+ - createPromise (use new Promise)
239
+ - defer
240
+ - fulfilled (use Promise.resolve)
241
+ - isGenerator
242
+ - rejected (use Promise.reject)
243
+ - setDefaultFlow
244
+ - when (use Promise.resolve)
239
245
  * Changes to the `Builder` class:
240
- - Added setChromeService, setEdgeService, & setFirefoxService
241
- - Removed setEnableNativeEvents
242
- - Removed setScrollBehavior
246
+ - Added setChromeService, setEdgeService, & setFirefoxService
247
+ - Removed setEnableNativeEvents
248
+ - Removed setScrollBehavior
243
249
  * Changes to `chrome.Driver`
244
- - Added sendDevToolsCommand
245
- - Added setDownloadPath
250
+ - Added sendDevToolsCommand
251
+ - Added setDownloadPath
246
252
  * Changes to `chrome.Options`
247
- - Now extends the `Capabilities` class
248
- - Removed from/toCapabilities
253
+ - Now extends the `Capabilities` class
254
+ - Removed from/toCapabilities
249
255
  * Changes to `edge.Options`
250
- - Now extends the `Capabilities` class
251
- - Removed from/toCapabilities
256
+ - Now extends the `Capabilities` class
257
+ - Removed from/toCapabilities
252
258
  * Changes to `ie.Options`
253
- - Now extends the `Capabilities` class
254
- - Removed from/toCapabilities
255
- * Removed the `firefox.Binary` class. Custom binaries can still be selected
256
- using `firefox.Options#setBinary()`. Likewise, custom binary arguments can be specified
259
+ - Now extends the `Capabilities` class
260
+ - Removed from/toCapabilities
261
+ * Removed the `firefox.Binary` class. Custom binaries can still be selected using `firefox.Options#setBinary()`. Likewise, custom binary arguments can be specified
257
262
  with `firefox.Options#addArguments()`.
258
263
  * Changes to `firefox.Driver`
259
- - Added installAddon(path)
260
- - Added uninstallAddon(id)
264
+ - Added installAddon(path)
265
+ - Added uninstallAddon(id)
261
266
  * Changes to `firefox.Options`
262
- - Now extends the `Capabilities` class
263
- - Removed from/toCapabilities
264
- - Removed setLoggingPreferences (was a no-op)
265
- - setProfile now only accepts a path to an existing profile
266
- - Added addExtensions
267
- - Added setPreference
268
- * Removed the `firefox.Profile` class. All of its functionality is now provided directly
269
- by `firefox.Options`
267
+ - Now extends the `Capabilities` class
268
+ - Removed from/toCapabilities
269
+ - Removed setLoggingPreferences (was a no-op)
270
+ - setProfile now only accepts a path to an existing profile
271
+ - Added addExtensions
272
+ - Added setPreference
273
+ * Removed the `firefox.Profile` class. All of its functionality is now provided directly by `firefox.Options`
270
274
  * Removed the `firefox/binary` module
271
275
  * Removed the `firefox/profile` module
272
276
  * Changes to `safari.Options`
273
- - Now extends the `Capabilities` class
274
- - Removed from/toCapabilities
275
- - Removed setCleanSession (was a no-op)
277
+ - Now extends the `Capabilities` class
278
+ - Removed from/toCapabilities
279
+ - Removed setCleanSession (was a no-op)
276
280
  * Changes to `lib/capabilities.Browser`:
277
- - Removed several enum values.
278
- - ANDROID (use Chrome for Android; see docs on the chrome module)
279
- - IPAD (no support available)
280
- - IPHONE (no support available)
281
- - OPERA (use Chrome)
282
- - PHANTOM_JS (use Chrome or Firefox in headless mode)
283
- - HTMLUNIT (use Chrome or Firefox in headless mode)
281
+ - Removed several enum values.
282
+ - ANDROID (use Chrome for Android; see docs on the chrome module)
283
+ - IPAD (no support available)
284
+ - IPHONE (no support available)
285
+ - OPERA (use Chrome)
286
+ - PHANTOM_JS (use Chrome or Firefox in headless mode)
287
+ - HTMLUNIT (use Chrome or Firefox in headless mode)
284
288
  * Changes to `lib/capabilities.Capabilities`:
285
- - Removed static factory methods android(), ipad(), iphone(), opera(), phantomjs(), htmlunit(),
286
- and htmlunitwithjs(). Users can still manually configure capabilities for these, but their use
287
- is not recommended and they will no longer be surfaced in the API.
289
+ - Removed static factory methods android(), ipad(), iphone(), opera(), phantomjs(), htmlunit(),
290
+ and htmlunitwithjs(). Users can still manually configure capabilities for these, but their use
291
+ is not recommended and they will no longer be surfaced in the API.
288
292
  * Changes to `lib/error`:
289
- - Added
290
- - ElementClickInterceptedError
291
- - InsecureCertificateError
292
- - InvalidCoordinatesError
293
- - NoSuchCookieError
294
- - Removed
295
- - ElementNotVisibleError
296
- - InvalidElementCoordinatesError
293
+ - Added
294
+ - ElementClickInterceptedError
295
+ - InsecureCertificateError
296
+ - InvalidCoordinatesError
297
+ - NoSuchCookieError
298
+ - Removed
299
+ - ElementNotVisibleError
300
+ - InvalidElementCoordinatesError
297
301
  * Changes to `lib/webdriver.WebDriver`:
298
- - Dropped support for "requiredCapabilities" from WebDriver.createSession
299
- - actions() now returns the new `lib/input.Actions` class
300
- - Removed touchActions
301
- - Renamed schedule to execute
302
- - Removed the `WebDriver.attachToSession()` factory method. Users can just the `WebDriver`
303
- constructor directly instead.
304
- - Removed the `call()` method. This was used to inject custom function calls into the control
305
- flow. Now that the promise manager is no longer used, this method is no longer necessary.
306
- Users are now responsible for coordinating actions (ideally with async functions) and can just
307
- call functions directly instead of through `driver.call()`.
302
+ - Dropped support for "requiredCapabilities" from WebDriver.createSession
303
+ - actions() now returns the new `lib/input.Actions` class
304
+ - Removed touchActions
305
+ - Renamed schedule to execute
306
+ - Removed the `WebDriver.attachToSession()` factory method. Users can just the `WebDriver`
307
+ constructor directly instead.
308
+ - Removed the `call()` method. This was used to inject custom function calls into the control
309
+ flow. Now that the promise manager is no longer used, this method is no longer necessary. Users are now responsible for coordinating actions (ideally with async functions) and can just
310
+ call functions directly instead of through `driver.call()`.
308
311
  * Changes to `lib/webdriver.WebElement`:
309
- - Replaced getSize & getLocation with getRect
312
+ - Replaced getSize & getLocation with getRect
310
313
  * Changes to `lib/webdriver.Alert`:
311
- - Removed authenticateAs
314
+ - Removed authenticateAs
312
315
  * Changes to `lib/webdriver.Options` (`driver.manage()`):
313
- - Removed timeouts (use get/setTimeouts)
316
+ - Removed timeouts (use get/setTimeouts)
314
317
  * Changes to `lib/webdriver.Window` (`driver.manage().window()`):
315
- - Added
316
- - getRect
317
- - setRect
318
- - fullscreen
319
- - minimize
320
- - Removed (use the getRect/setRect methods)
321
- - getPosition
322
- - setPosition
323
- - getSize
324
- - setSize
318
+ - Added
319
+ - getRect
320
+ - setRect
321
+ - fullscreen
322
+ - minimize
323
+ - Removed (use the getRect/setRect methods)
324
+ - getPosition
325
+ - setPosition
326
+ - getSize
327
+ - setSize
325
328
  * Removed the `testing/assert` module
326
329
  * Changes to `testing/index`
327
- - Since the promise manager has been removed, it is no longer necessary to wrap the Mocha test
328
- hooks; instead, users can simply use async functions. The following have all been removed:
329
- - describe
330
- - before
331
- - beforeEach
332
- - after
333
- - afterEach
334
- - it
335
- - Added the `suite` function. For details, refer to the jsdoc or
336
- `example/google_search_test.js`
330
+ - Since the promise manager has been removed, it is no longer necessary to wrap the Mocha test
331
+ hooks; instead, users can simply use async functions. The following have all been removed:
332
+ - describe
333
+ - before
334
+ - beforeEach
335
+ - after
336
+ - afterEach
337
+ - it
338
+ - Added the `suite` function. For details, refer to the jsdoc or
339
+ `example/google_search_test.js`
337
340
 
338
341
  ## v3.6.0
339
342
 
@@ -349,18 +352,18 @@ mode (see `example/headless.js`)
349
352
  ### API Changes
350
353
 
351
354
  * Added new methods to `selenium-webdriver/firefox.Options`:
352
- - addArguments()
353
- - headless()
354
- - windowSize()
355
+ - addArguments()
356
+ - headless()
357
+ - windowSize()
355
358
  * Deprecated `selenium-webdriver/firefox/binary.Binary`
356
359
  * Removed `selenium-webdriver/firefox.Options#useGeckoDriver()`
357
360
  * Removed the unused `selenium-webdriver/firefox/profile.decode()`
358
361
  * Removed methods from `selenium-webdriver/firefox/profile.Profile` that had no effect since support
359
362
  for the legacy FirefoxDriver was dropped in 3.5.0:
360
- - setNativeEventsEnabled
361
- - nativeEventsEnabled
362
- - getPort
363
- - setPort
363
+ - setNativeEventsEnabled
364
+ - nativeEventsEnabled
365
+ - getPort
366
+ - setPort
364
367
  * Removed `selenium-webdriver/firefox.ServiceBuilder#setFirefoxBinary()`; custom binaries should be
365
368
  configured through the `firefox.Options` class.
366
369
  * Removed `selenium-webdriver/firefox.Capability`. These hold overs from the legacy FirefoxDriver
@@ -382,12 +385,11 @@ to a remote Selenium server that supports Firefox 45.
382
385
  ### Changes
383
386
 
384
387
  * Removed native support for Firefox 46 and older.
385
- - The `SELENIUM_MARIONETTE` enviornment variable no longer has an effect.
386
- - `selenium-webdriver/firefox.Capability.MARIONETTE` is deprecated.
387
- - `selenium-webdriver/firefox.Options#useGeckoDriver()` is deprecated and now a no-op.
388
+ - The `SELENIUM_MARIONETTE` enviornment variable no longer has an effect.
389
+ - `selenium-webdriver/firefox.Capability.MARIONETTE` is deprecated.
390
+ - `selenium-webdriver/firefox.Options#useGeckoDriver()` is deprecated and now a no-op.
388
391
  * `firefox.Options` will no longer discard the `"moz:firefoxOptions"` set in user provided
389
- capabilities (via `Builder.withCapabilities({})`). When both are used, the settings
390
- in `firefox.Options` will be applied _last_.
392
+ capabilities (via `Builder.withCapabilities({})`). When both are used, the settings in `firefox.Options` will be applied _last_.
391
393
  * Added `chrome.Options#headless()` and `chrome.Options#windowSize()`, which may be used to start
392
394
  Chrome in headless mode (requires Chrome 59+) and to set the initial window size, respectively.
393
395
 
@@ -439,8 +441,7 @@ This release requires [geckodriver 0.15.0](https://github.com/mozilla/geckodrive
439
441
  ## v3.1.0
440
442
 
441
443
  * The `lib` package is once again platform agnostic (excluding `lib/devmode`).
442
- * Deprecated `promise.when(value, callback, errback)`.
443
- Use `promise.fulfilled(value).then(callback, errback)`
444
+ * Deprecated `promise.when(value, callback, errback)`. Use `promise.fulfilled(value).then(callback, errback)`
444
445
  * Changed `promise.fulfilled(value)`, `promise.rejected(reason)` and
445
446
  `promise.defer()` to all use native promises when the promise manager is disabled.
446
447
  * Properly handle W3C error responses to new session commands.
@@ -457,10 +458,9 @@ This release requires [geckodriver 0.15.0](https://github.com/mozilla/geckodrive
457
458
  ## v3.0.1
458
459
 
459
460
  * More API adjustments to align with native Promises
460
- - Deprecated `promise.fulfilled(value)`, use `promise.Promise#resolve(value)`
461
- - Deprecated `promise.rejected(reason)`, use `promise.Promise#reject(reason)`
462
- * When a `wait()` condition times out, the returned promise will now be rejected with
463
- an `error.TimeoutError` instead of a generic `Error` object.
461
+ - Deprecated `promise.fulfilled(value)`, use `promise.Promise#resolve(value)`
462
+ - Deprecated `promise.rejected(reason)`, use `promise.Promise#reject(reason)`
463
+ * When a `wait()` condition times out, the returned promise will now be rejected with an `error.TimeoutError` instead of a generic `Error` object.
464
464
  * `WebDriver#wait()` will now throw a TypeError if an invalid wait condition is provided.
465
465
  * Properly catch unhandled promise rejections with an action sequence (only impacts when the promise
466
466
  manager is disabled).
@@ -487,19 +487,17 @@ This release requires [geckodriver 0.15.0](https://github.com/mozilla/geckodrive
487
487
  `SELENIUM_PROMISE_MANAGER=0`. This is part of a larger plan to remove the promise manager, as
488
488
  documented at
489
489
  <https://github.com/SeleniumHQ/selenium/issues/2969>
490
- * When communicating with a W3C-compliant remote end, use the atoms library for
491
- the `WebElement.getAttribute()` and `WebElement.isDisplayed()` commands. This behavior is
490
+ * When communicating with a W3C-compliant remote end, use the atoms library for the `WebElement.getAttribute()` and `WebElement.isDisplayed()` commands. This behavior is
492
491
  consistent with the java, .net, python, and ruby clients.
493
492
 
494
493
  ### API Changes
495
494
 
496
495
  * Removed `safari.Options#useLegacyDriver()`
497
496
  * Reduced the API on `promise.Thenable` for compatibility with native promises:
498
- - Removed `#isPending()`
499
- - Removed `#cancel()`
500
- - Removed `#finally()`
501
- * Changed all subclasses of `webdriver.WebDriver` to overload the static
502
- function `WebDriver.createSession()` instead of doing work in the constructor. All constructors
497
+ - Removed `#isPending()`
498
+ - Removed `#cancel()`
499
+ - Removed `#finally()`
500
+ * Changed all subclasses of `webdriver.WebDriver` to overload the static function `WebDriver.createSession()` instead of doing work in the constructor. All constructors
503
501
  now inherit the base class' function signature. Users are still encouraged to use the `Builder`
504
502
  class instead of creating drivers directly.
505
503
  * `Builder#build()` now returns a "thenable" WebDriver instance, allowing users to immediately
@@ -512,10 +510,8 @@ This release requires [geckodriver 0.15.0](https://github.com/mozilla/geckodrive
512
510
 
513
511
  * Fixed a bug where the promise manager would silently drop callbacks after recovering from an
514
512
  unhandled promise rejection.
515
- * Added the `firefox.ServiceBuilder` class, which may be used to customize the geckodriver used
516
- for `firefox.Driver` instances.
517
- * Added support for Safari 10 safaridriver. safaridriver may be disabled via tha
518
- API, `safari.Options#useLegacyDriver`, to use the safari extension driver.
513
+ * Added the `firefox.ServiceBuilder` class, which may be used to customize the geckodriver used for `firefox.Driver` instances.
514
+ * Added support for Safari 10 safaridriver. safaridriver may be disabled via tha API, `safari.Options#useLegacyDriver`, to use the safari extension driver.
519
515
  * Updated the `lib/proxy` module to support configuring a SOCKS proxy.
520
516
  * For the `promise.ControlFlow`, fire the "uncaughtException" event in a new turn of the JS event
521
517
  loop. As a result of this change, any errors thrown by an event listener will propagate to the
@@ -566,8 +562,7 @@ This release requires [geckodriver 0.15.0](https://github.com/mozilla/geckodrive
566
562
  * Properly configure proxies when using the geckodriver
567
563
  * `http.Executor` now accepts a promised client. The `builder.Builder` class will now use this
568
564
  instead of a `command.DeferredExecutor` when creating WebDriver instances.
569
- * For Chrome and Firefox, the `builder.Builder` class will always return an
570
- instanceof `chrome.Driver` and `firefox.Driver`, respectively, even when configured to use a
565
+ * For Chrome and Firefox, the `builder.Builder` class will always return an instanceof `chrome.Driver` and `firefox.Driver`, respectively, even when configured to use a
571
566
  remote server (from `builder.Builder#usingServer(url)`,
572
567
  `SELENIUM_REMOTE_URL`, etc).
573
568
 
@@ -580,32 +575,32 @@ This release requires [geckodriver 0.15.0](https://github.com/mozilla/geckodrive
580
575
  _seconds_ since epoch. When retrieving cookies, the expiration is always returned in seconds.
581
576
  * Renamed `firefox.Options#useMarionette` to `firefox.Options#useGeckoDriver`
582
577
  * Removed deprecated modules:
583
- - `selenium-webdriver/error` (use `selenium-webdriver/lib/error`,\
584
- or the `error` property exported by `selenium-webdriver`)
585
- - `selenium-webdriver/executors` — this was not previously deprecated, but is no longer used.
578
+ - `selenium-webdriver/error` (use `selenium-webdriver/lib/error`,\
579
+ or the `error` property exported by `selenium-webdriver`)
580
+ - `selenium-webdriver/executors` — this was not previously deprecated, but is no longer used.
586
581
  * Removed deprecated types:
587
- - `command.DeferredExecutor` — this was not previously deprecated, but is no longer used. It can
588
- be trivially implemented by clients should it be needed.
589
- - `error.InvalidSessionIdError` (use `error.NoSuchSessionError`)
590
- - `executors.DeferredExecutor`
591
- - `until.Condition` (use `webdriver.Condition`)
592
- - `until.WebElementCondition` (use `webdriver.WebElementCondition`)
593
- - `webdriver.UnhandledAlertError` (use `error.UnexpectedAlertOpenError`)
582
+ - `command.DeferredExecutor` — this was not previously deprecated, but is no longer used. It can
583
+ be trivially implemented by clients should it be needed.
584
+ - `error.InvalidSessionIdError` (use `error.NoSuchSessionError`)
585
+ - `executors.DeferredExecutor`
586
+ - `until.Condition` (use `webdriver.Condition`)
587
+ - `until.WebElementCondition` (use `webdriver.WebElementCondition`)
588
+ - `webdriver.UnhandledAlertError` (use `error.UnexpectedAlertOpenError`)
594
589
  * Removed deprecated functions:
595
- - `Deferred#cancel()`
596
- - `Deferred#catch()`
597
- - `Deferred#finally()`
598
- - `Deferred#isPending()`
599
- - `Deferred#then()`
600
- - `Promise#thenCatch()`
601
- - `Promise#thenFinally()`
602
- - `WebDriver#isElementPresent()`
603
- - `WebElement#getInnerHtml()`
604
- - `WebElement#getOuterHtml()`
605
- - `WebElement#getRawId()`
606
- - `WebElement#isElementPresent()`
590
+ - `Deferred#cancel()`
591
+ - `Deferred#catch()`
592
+ - `Deferred#finally()`
593
+ - `Deferred#isPending()`
594
+ - `Deferred#then()`
595
+ - `Promise#thenCatch()`
596
+ - `Promise#thenFinally()`
597
+ - `WebDriver#isElementPresent()`
598
+ - `WebElement#getInnerHtml()`
599
+ - `WebElement#getOuterHtml()`
600
+ - `WebElement#getRawId()`
601
+ - `WebElement#isElementPresent()`
607
602
  * Removed deprecated properties:
608
- - `WebDriverError#code`
603
+ - `WebDriverError#code`
609
604
 
610
605
  ## v2.53.2
611
606
 
@@ -629,8 +624,7 @@ This release requires [geckodriver 0.15.0](https://github.com/mozilla/geckodrive
629
624
  Marionette may be enabled via the API,
630
625
  `firefox.Options#useMarionette`, or by setting the `SELENIUM_MARIONETTE`
631
626
  environment variable.
632
- * Moved all logic for parsing and interpreting responses from the remote end into the
633
- individual `command.Executor` implementations.
627
+ * Moved all logic for parsing and interpreting responses from the remote end into the individual `command.Executor` implementations.
634
628
  * For consistency with the other Selenium language bindings,
635
629
  `WebDriver#isElementPresent()` and `WebElement#isElementPresent()` have been deprecated. These
636
630
  methods will be removed in v3.0. Use the findElements command to test for the presence of an
@@ -652,8 +646,7 @@ This release requires [geckodriver 0.15.0](https://github.com/mozilla/geckodrive
652
646
  * FIXED: `io.findInPath()` will no longer match against directories that have the same basename as
653
647
  the target file.
654
648
  * FIXED: `phantomjs.Driver` now takes a third argument that defines the path to a log file to use
655
- for the phantomjs executable's output. This may be quickly set at runtime with
656
- the `SELENIUM_PHANTOMJS_LOG` environment variable.
649
+ for the phantomjs executable's output. This may be quickly set at runtime with the `SELENIUM_PHANTOMJS_LOG` environment variable.
657
650
 
658
651
  ### Changes for W3C WebDriver Spec Compliance
659
652
 
@@ -691,10 +684,8 @@ the selenium-webdriver package README.
691
684
  (Map semantics). To check whether the value is true, use `get(key)`.
692
685
  * Deprecated `executors.DeferredExecutor` in favor of
693
686
  `lib/command.DeferredExecutor`.
694
- * API documentation is no longer distributed with the npm package, but remains available
695
- at <http://seleniumhq.github.io/selenium/docs/api/javascript/>
696
- * Rewrote the `error` module to export an Error subtype for each type of error defined in
697
- the [W3C WebDriver spec](https://w3c.github.io/webdriver/webdriver-spec.html#handling-errors).
687
+ * API documentation is no longer distributed with the npm package, but remains available at <http://seleniumhq.github.io/selenium/docs/api/javascript/>
688
+ * Rewrote the `error` module to export an Error subtype for each type of error defined in the [W3C WebDriver spec](https://w3c.github.io/webdriver/webdriver-spec.html#handling-errors).
698
689
  * Changed the `http.Request` and `http.Response` classes to store headers in maps instead of object
699
690
  literals.
700
691
  * Updated `ws` dependency to version `1.0.1`.
@@ -707,8 +698,7 @@ the selenium-webdriver package README.
707
698
 
708
699
  ### Changes for W3C WebDriver Spec Compliance
709
700
 
710
- * Updated the `By` locators that are not in the W3C spec to delegated to using CSS
711
- selectors: `By.className`, `By.id`, `By.name`, and `By.tagName`.
701
+ * Updated the `By` locators that are not in the W3C spec to delegated to using CSS selectors: `By.className`, `By.id`, `By.name`, and `By.tagName`.
712
702
 
713
703
  ## v2.49-51
714
704
 
@@ -732,8 +722,7 @@ the selenium-webdriver package README.
732
722
  version
733
723
  `2.1.1`.
734
724
  * FIXED: the `webdriver.promise.ControlFlow` now has a consistent execution order for
735
- tasks/callbacks scheduled in different turns of the JS event loop. Refer to
736
- the `webdriver.promise` documentation for more details.
725
+ tasks/callbacks scheduled in different turns of the JS event loop. Refer to the `webdriver.promise` documentation for more details.
737
726
  * FIXED: do not drop user auth from the WebDriver server URL.
738
727
  * FIXED: a single `firefox.Binary` instance may be used to configure and launch multiple
739
728
  FirefoxDriver sessions.
@@ -763,7 +752,7 @@ continue to be supported, but will require setting the `--harmony` flag.
763
752
  ### Change Summary
764
753
 
765
754
  * Add support for [Node v4.0.0](https://nodejs.org/en/blog/release/v4.0.0/)
766
- * Updated `ws` dependency from `0.7.1` to `0.8.0`
755
+ * Updated `ws` dependency from `0.7.1` to `0.8.0`
767
756
  * Bumped the minimum supported version of Node from `0.10.x` to `0.12.x`. This is in accordance with
768
757
  the Node support policy established in `v2.45.0`.
769
758
 
@@ -780,14 +769,14 @@ continue to be supported, but will require setting the `--harmony` flag.
780
769
  * Added support for using a proxy server for WebDriver commands. See `Builder#usingWebDriverProxy()`
781
770
  for more info.
782
771
  * Removed deprecated functions:
783
- * Capabilities#toJSON()
784
- * UnhandledAlertError#getAlert()
785
- * chrome.createDriver()
786
- * phantomjs.createDriver()
787
- * promise.ControlFlow#annotateError()
788
- * promise.ControlFlow#await()
789
- * promise.ControlFlow#clearHistory()
790
- * promise.ControlFlow#getHistory()
772
+ * Capabilities#toJSON()
773
+ * UnhandledAlertError#getAlert()
774
+ * chrome.createDriver()
775
+ * phantomjs.createDriver()
776
+ * promise.ControlFlow#annotateError()
777
+ * promise.ControlFlow#await()
778
+ * promise.ControlFlow#clearHistory()
779
+ * promise.ControlFlow#getHistory()
791
780
  * Removed deprecated enum values: `ErrorCode.NO_MODAL_DIALOG_OPEN` and
792
781
  `ErrorCode.MODAL_DIALOG_OPENED`. Use `ErrorCode.NO_SUCH_ALERT` and
793
782
  `ErrorCode.UNEXPECTED_ALERT_OPEN`, respectively.
@@ -811,8 +800,7 @@ continue to be supported, but will require setting the `--harmony` flag.
811
800
  * FIXED: 8548: Task callbacks are once again dropped if the task was cancelled due to a previously
812
801
  uncaught error within the frame.
813
802
  * FIXED: 8496: Extended the `chrome.Options` API to cover all configuration options (e.g. mobile
814
- emulation and performance logging) documented on the
815
- ChromeDriver [project site](https://chromedriver.chromium.org/capabilities).
803
+ emulation and performance logging) documented on the ChromeDriver [project site](https://chromedriver.chromium.org/capabilities).
816
804
 
817
805
  ## v2.45.0
818
806
 
@@ -887,8 +875,7 @@ major version release (i.e. 1.0.0).
887
875
  * Expanded the interactions API to include touch actions. See `WebDriver.touchActions()`.
888
876
  * FIXED: 8380: `firefox.Driver` will delete its temporary profile on `quit`.
889
877
  * FIXED: 8306: Stack overflow in promise callbacks eliminated.
890
- * FIXED: 8221: Added support for defining custom command mappings. Includes support for
891
- PhantomJS's `executePhantomJS` (requires PhantomJS 1.9.7 or GhostDriver 1.1.0).
878
+ * FIXED: 8221: Added support for defining custom command mappings. Includes support for PhantomJS's `executePhantomJS` (requires PhantomJS 1.9.7 or GhostDriver 1.1.0).
892
879
  * FIXED: 8128: When the FirefoxDriver marshals an object to the page for
893
880
  `executeScript`, it defines additional properties (required by the driver's implementation). These
894
881
  properties will no longer be enumerable and should be omitted (i.e. they won't show up in
@@ -1091,14 +1078,14 @@ major version release (i.e. 1.0.0).
1091
1078
  * For Promises/A+ compatibility, backing out the change in 2.30.0 that ensured rejections were
1092
1079
  always Error objects. Rejection reasons are now left as is.
1093
1080
  * Removed deprecated functions originally scheduled for removal in 2.31.0
1094
- * promise.Application.getInstance()
1095
- * promise.ControlFlow#schedule()
1096
- * promise.ControlFlow#scheduleTimeout()
1097
- * promise.ControlFlow#scheduleWait()
1081
+ * promise.Application.getInstance()
1082
+ * promise.ControlFlow#schedule()
1083
+ * promise.ControlFlow#scheduleTimeout()
1084
+ * promise.ControlFlow#scheduleWait()
1098
1085
  * Renamed some functions for consistency with Promises/A+ terminology. The original functions have
1099
1086
  been deprecated and will be removed in 2.34.0:
1100
- * promise.resolved() -> promise.fulfilled()
1101
- * promise.Deferred#resolve() -> promise.Deferred#fulfill()
1087
+ * promise.resolved() -> promise.fulfilled()
1088
+ * promise.Deferred#resolve() -> promise.Deferred#fulfill()
1102
1089
  * FIXED: remote.SeleniumServer#stop now shuts down within the active control flow, allowing scripts
1103
1090
  to finish. Use #kill to shutdown immediately.
1104
1091
  * FIXED: 5321: cookie deletion commands
package/index.js CHANGED
@@ -38,7 +38,6 @@ const safari = require('./safari')
38
38
  const session = require('./lib/session')
39
39
  const until = require('./lib/until')
40
40
  const webdriver = require('./lib/webdriver')
41
- const opera = require('./opera')
42
41
 
43
42
  const Browser = capabilities.Browser
44
43
  const Capabilities = capabilities.Capabilities
@@ -232,12 +231,6 @@ class Builder {
232
231
 
233
232
  /** @private {http.Agent} */
234
233
  this.agent_ = null
235
-
236
- /** @private {opera.Options} */
237
- this.operaOptions_ = null
238
-
239
- /** @private {remote.DriverService.Builder} */
240
- this.operaService_ = null
241
234
  }
242
235
 
243
236
  /**
@@ -432,20 +425,6 @@ class Builder {
432
425
  return this
433
426
  }
434
427
 
435
- /**
436
- * Sets Opera specific {@linkplain opera.Options options} for drivers
437
- * created by this builder. Any logging or proxy settings defined on the given
438
- * options will take precedence over those set through
439
- * {@link #setLoggingPrefs} and {@link #setProxy}, respectively.
440
- *
441
- * @param {!opera.Options} options The OperaDriver options to use.
442
- * @return {!Builder} A self reference.
443
- */
444
- setOperaOptions(options) {
445
- this.operaOptions_ = options
446
- return this
447
- }
448
-
449
428
  /**
450
429
  * @return {chrome.Options} the Chrome specific options currently configured
451
430
  * for this builder.
@@ -560,21 +539,6 @@ class Builder {
560
539
  return this
561
540
  }
562
541
 
563
- /**
564
- * Sets the {@link opera.ServiceBuilder} to use to manage the
565
- * operaDriver child process when creating sessions locally.
566
- *
567
- * @param {opera.ServiceBuilder} service the service to use.
568
- * @return {!Builder} a self reference.
569
- */
570
- setOperaService(service) {
571
- if (service && !(service instanceof opera.ServiceBuilder)) {
572
- throw TypeError('not a opera.ServiceBuilder object')
573
- }
574
- this.operaService_ = service
575
- return this
576
- }
577
-
578
542
  /**
579
543
  * Sets Safari specific {@linkplain safari.Options options} for drivers
580
544
  * created by this builder. Any logging settings defined on the given options
@@ -648,8 +612,6 @@ class Builder {
648
612
  capabilities.merge(this.safariOptions_)
649
613
  } else if (browser === Browser.EDGE && this.edgeOptions_) {
650
614
  capabilities.merge(this.edgeOptions_)
651
- } else if (browser === Browser.OPERA && this.operaOptions_) {
652
- capabilities.merge(this.operaOptions_)
653
615
  }
654
616
 
655
617
  checkOptions(
@@ -736,14 +698,6 @@ class Builder {
736
698
  return createDriver(edge.Driver, capabilities, service)
737
699
  }
738
700
 
739
- case Browser.OPERA: {
740
- let service = null
741
- if (this.operaService_) {
742
- service = this.operaService_.build()
743
- }
744
- return createDriver(opera.Driver, capabilities, service)
745
- }
746
-
747
701
  case Browser.SAFARI:
748
702
  return createDriver(safari.Driver, capabilities)
749
703
 
@@ -34,7 +34,6 @@ const Browser = {
34
34
  FIREFOX: 'firefox',
35
35
  INTERNET_EXPLORER: 'internet explorer',
36
36
  SAFARI: 'safari',
37
- OPERA: 'opera',
38
37
  }
39
38
 
40
39
  /**
@@ -282,13 +281,6 @@ class Capabilities {
282
281
  return new Capabilities().setBrowserName(Browser.SAFARI)
283
282
  }
284
283
 
285
- /**
286
- * @return {!Capabilities} A basic set of capabilities for Opera
287
- */
288
- static opera() {
289
- return new Capabilities().setBrowserName(Browser.OPERA)
290
- }
291
-
292
284
  /**
293
285
  * @return {!Object<string, ?>} The JSON representation of this instance.
294
286
  * Note, the returned object may contain nested promised values.
package/lib/webdriver.js CHANGED
@@ -2162,13 +2162,23 @@ class TargetLocator {
2162
2162
  * If the specified frame can not be found, the returned promise will be
2163
2163
  * rejected with a {@linkplain error.NoSuchFrameError}.
2164
2164
  *
2165
- * @param {(number|WebElement|null)} id The frame locator.
2165
+ * @param {(number|string|WebElement|null)} id The frame locator.
2166
2166
  * @return {!Promise<void>} A promise that will be resolved
2167
2167
  * when the driver has changed focus to the specified frame.
2168
2168
  */
2169
2169
  frame(id) {
2170
+ let frameReference = id
2171
+ if (typeof id === 'string') {
2172
+ frameReference = this.driver_
2173
+ .findElement({ id })
2174
+ .catch((_) => this.driver_.findElement({ name: id }))
2175
+ }
2176
+
2170
2177
  return this.driver_.execute(
2171
- new command.Command(command.Name.SWITCH_TO_FRAME).setParameter('id', id)
2178
+ new command.Command(command.Name.SWITCH_TO_FRAME).setParameter(
2179
+ 'id',
2180
+ frameReference
2181
+ )
2172
2182
  )
2173
2183
  }
2174
2184
 
@@ -2755,13 +2765,17 @@ class WebElement {
2755
2765
  * when the form has been submitted.
2756
2766
  */
2757
2767
  submit() {
2758
- const form = this.findElement({ xpath: './ancestor-or-self::form' })
2759
- this.driver_.executeScript(
2760
- "var e = arguments[0].ownerDocument.createEvent('Event');" +
2761
- "e.initEvent('submit', true, true);" +
2762
- 'if (arguments[0].dispatchEvent(e)) { arguments[0].submit() }',
2763
- form
2764
- )
2768
+ const script = "var form = arguments[0];\n" +
2769
+ "while (form.nodeName != \"FORM\" && form.parentNode) {\n" +
2770
+ " form = form.parentNode;\n" +
2771
+ "}\n" +
2772
+ "if (!form) { throw Error('Unable to find containing form element'); }\n" +
2773
+ "if (!form.ownerDocument) { throw Error('Unable to find owning document'); }\n" +
2774
+ "var e = form.ownerDocument.createEvent('Event');\n" +
2775
+ "e.initEvent('submit', true, true);\n" +
2776
+ "if (form.dispatchEvent(e)) { HTMLFormElement.prototype.submit.call(form) }\n";
2777
+
2778
+ this.driver_.executeScript(script, this);
2765
2779
  }
2766
2780
 
2767
2781
  /**
package/net/index.js CHANGED
@@ -48,7 +48,7 @@ function getIPAddress(loopback, family) {
48
48
  }
49
49
 
50
50
  for (let ipAddress of interfaces[key]) {
51
- if (ipAddress.family === family && ipAddress.internal === loopback) {
51
+ if ((ipAddress.family === family || `IPv${ipAddress.family}` === family) && ipAddress.internal === loopback) {
52
52
  return ipAddress.address
53
53
  }
54
54
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selenium-webdriver",
3
- "version": "4.1.2",
3
+ "version": "4.2.0",
4
4
  "description": "The official WebDriver JavaScript bindings from the Selenium project",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
package/testing/index.js CHANGED
@@ -39,7 +39,6 @@ const firefox = require('../firefox')
39
39
  const ie = require('../ie')
40
40
  const remote = require('../remote')
41
41
  const safari = require('../safari')
42
- const opera = require('../opera')
43
42
  const { Browser, Capabilities } = require('../lib/capabilities')
44
43
  const { Builder } = require('../index')
45
44
 
@@ -47,7 +46,7 @@ const { Builder } = require('../index')
47
46
  * Describes a browser targeted by a {@linkplain suite test suite}.
48
47
  * @record
49
48
  */
50
- function TargetBrowser() {}
49
+ function TargetBrowser() { }
51
50
 
52
51
  /**
53
52
  * The {@linkplain Browser name} of the targeted browser.
@@ -123,7 +122,6 @@ function getAvailableBrowsers() {
123
122
  [firefox.locateSynchronously, Browser.FIREFOX],
124
123
  [ie.locateSynchronously, Browser.INTERNET_EXPLORER],
125
124
  [safari.locateSynchronously, Browser.SAFARI],
126
- [opera.locateSynchronously, Browser.OPERA],
127
125
  ]
128
126
 
129
127
  let availableBrowsers = []
@@ -210,7 +208,7 @@ function init(force = false) {
210
208
  if (seleniumJar && seleniumUrl) {
211
209
  throw Error(
212
210
  'Ambiguous test configuration: both SELENIUM_REMOTE_URL' +
213
- ' && SELENIUM_SERVER_JAR environment variables are set'
211
+ ' && SELENIUM_SERVER_JAR environment variables are set'
214
212
  )
215
213
  }
216
214
 
@@ -218,8 +216,8 @@ function init(force = false) {
218
216
  if ((seleniumJar || seleniumUrl) && envBrowsers.length === 0) {
219
217
  throw Error(
220
218
  'Ambiguous test configuration: when either the SELENIUM_REMOTE_URL or' +
221
- ' SELENIUM_SERVER_JAR environment variable is set, the' +
222
- ' SELENIUM_BROWSER variable must also be set.'
219
+ ' SELENIUM_SERVER_JAR environment variable is set, the' +
220
+ ' SELENIUM_BROWSER variable must also be set.'
223
221
  )
224
222
  }
225
223
 
@@ -297,7 +295,7 @@ class Environment {
297
295
  builder.getCapabilities().merge(browser.capabilities);
298
296
  }
299
297
 
300
- if(browser.name === 'firefox') {
298
+ if (browser.name === 'firefox') {
301
299
  builder.setCapability('moz:debuggerAddress', true);
302
300
  }
303
301
 
@@ -317,7 +315,7 @@ class Environment {
317
315
  * Configuration options for a {@linkplain ./index.suite test suite}.
318
316
  * @record
319
317
  */
320
- function SuiteOptions() {}
318
+ function SuiteOptions() { }
321
319
 
322
320
  /**
323
321
  * The browsers to run the test suite against.
@@ -492,8 +490,8 @@ function getTestHook(name) {
492
490
  if (type !== 'function') {
493
491
  throw TypeError(
494
492
  `Expected global.${name} to be a function, but is ${type}.` +
495
- ' This can happen if you try using this module when running with' +
496
- ' node directly instead of using jasmine or mocha'
493
+ ' This can happen if you try using this module when running with' +
494
+ ' node directly instead of using jasmine or mocha'
497
495
  )
498
496
  }
499
497
  return fn
package/opera.js DELETED
@@ -1,403 +0,0 @@
1
- // Licensed to the Software Freedom Conservancy (SFC) under one
2
- // or more contributor license agreements. See the NOTICE file
3
- // distributed with this work for additional information
4
- // regarding copyright ownership. The SFC licenses this file
5
- // to you under the Apache License, Version 2.0 (the
6
- // "License"); you may not use this file except in compliance
7
- // with the License. You may obtain a copy of the License at
8
- //
9
- // http://www.apache.org/licenses/LICENSE-2.0
10
- //
11
- // Unless required by applicable law or agreed to in writing,
12
- // software distributed under the License is distributed on an
13
- // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
- // KIND, either express or implied. See the License for the
15
- // specific language governing permissions and limitations
16
- // under the License.
17
-
18
- /**
19
- * @fileoverview Defines a {@linkplain Driver WebDriver} client for the
20
- * Opera web browser (v26+). Before using this module, you must download the
21
- * latest OperaDriver
22
- * [release](https://github.com/operasoftware/operachromiumdriver/releases) and
23
- * ensure it can be found on your system
24
- * [PATH](http://en.wikipedia.org/wiki/PATH_%28variable%29).
25
- *
26
- * There are three primary classes exported by this module:
27
- *
28
- * 1. {@linkplain ServiceBuilder}: configures the
29
- * {@link ./remote.DriverService remote.DriverService}
30
- * that manages the
31
- * [OperaDriver](https://github.com/operasoftware/operachromiumdriver)
32
- * child process.
33
- *
34
- * 2. {@linkplain Options}: defines configuration options for each new Opera
35
- * session, such as which {@linkplain Options#setProxy proxy} to use,
36
- * what {@linkplain Options#addExtensions extensions} to install, or
37
- * what {@linkplain Options#addArguments command-line switches} to use when
38
- * starting the browser.Service
39
- *
40
- * 3. {@linkplain Driver}: the WebDriver client; each new instance will control
41
- * a unique browser session with a clean user profile (unless otherwise
42
- * configured through the {@link Options} class).
43
- *
44
- * By default, every Opera session will use a single driver service, which is
45
- * started the first time a {@link Driver} instance is created and terminated
46
- * when this process exits. The default service will inherit its environment
47
- * from the current process and direct all output to /dev/null. You may obtain
48
- * a handle to this default service using
49
- * {@link #getDefaultService getDefaultService()} and change its configuration
50
- * with {@link #setDefaultService setDefaultService()}.
51
- *
52
- * You may also create a {@link Driver} with its own driver service. This is
53
- * useful if you need to capture the server's log output for a specific session:
54
- *
55
- * var opera = require('selenium-webdriver/opera');
56
- *
57
- * var service = new opera.ServiceBuilder()
58
- * .loggingTo('/my/log/file.txt')
59
- * .enableVerboseLogging()
60
- * .build();
61
- *
62
- * var options = new opera.Options();
63
- * // configure browser options ...
64
- *
65
- * var driver = opera.Driver.createSession(options, service);
66
- *
67
- * Users should only instantiate the {@link Driver} class directly when they
68
- * need a custom driver service configuration (as shown above). For normal
69
- * operation, users should start Opera using the
70
- * {@link ./builder.Builder selenium-webdriver.Builder}.
71
- */
72
-
73
- 'use strict'
74
-
75
- const http = require('./http')
76
- const io = require('./io')
77
- const capabilities = require('./lib/capabilities')
78
- const Symbols = require('./lib/symbols')
79
- const webdriver = require('./lib/webdriver')
80
- const remote = require('./remote')
81
-
82
- /**
83
- * Name of the OperaDriver executable.
84
- * @type {string}
85
- * @const
86
- */
87
- const OPERADRIVER_EXE =
88
- process.platform === 'win32' ? 'operadriver.exe' : 'operadriver'
89
-
90
- /**
91
- * _Synchronously_ attempts to locate the operadriver executable on the current
92
- * system.
93
- *
94
- * @return {?string} the located executable, or `null`.
95
- */
96
- function locateSynchronously() {
97
- return io.findInPath(OPERADRIVER_EXE, true)
98
- }
99
-
100
- /**
101
- * Creates {@link remote.DriverService} instances that manages an
102
- * [OperaDriver](https://github.com/operasoftware/operachromiumdriver)
103
- * server in a child process.
104
- */
105
- class ServiceBuilder extends remote.DriverService.Builder {
106
- /**
107
- * @param {string=} opt_exe Path to the server executable to use. If omitted,
108
- * the builder will attempt to locate the operadriver on the current
109
- * PATH.
110
- * @throws {Error} If provided executable does not exist, or the operadriver
111
- * cannot be found on the PATH.
112
- */
113
- constructor(opt_exe) {
114
- let exe = opt_exe || locateSynchronously()
115
- if (!exe) {
116
- throw Error(
117
- 'The OperaDriver could not be found on the current PATH. Please ' +
118
- 'download the latest version of the OperaDriver from ' +
119
- 'https://github.com/operasoftware/operachromiumdriver/releases and ' +
120
- 'ensure it can be found on your PATH.'
121
- )
122
- }
123
-
124
- super(exe)
125
- this.setLoopback(true)
126
- }
127
-
128
- /**
129
- * Sets the path of the log file the driver should log to. If a log file is
130
- * not specified, the driver will log to stderr.
131
- * @param {string} path Path of the log file to use.
132
- * @return {!ServiceBuilder} A self reference.
133
- */
134
- loggingTo(path) {
135
- return this.addArguments('--log-path=' + path)
136
- }
137
-
138
- /**
139
- * Enables verbose logging.
140
- * @return {!ServiceBuilder} A self reference.
141
- */
142
- enableVerboseLogging() {
143
- return this.addArguments('--verbose')
144
- }
145
-
146
- /**
147
- * Silence sthe drivers output.
148
- * @return {!ServiceBuilder} A self reference.
149
- */
150
- silent() {
151
- return this.addArguments('--silent')
152
- }
153
- }
154
-
155
- /** @type {remote.DriverService} */
156
- let defaultService = null
157
-
158
- /**
159
- * Sets the default service to use for new OperaDriver instances.
160
- * @param {!remote.DriverService} service The service to use.
161
- * @throws {Error} If the default service is currently running.
162
- */
163
- function setDefaultService(service) {
164
- if (defaultService && defaultService.isRunning()) {
165
- throw Error(
166
- 'The previously configured OperaDriver service is still running. ' +
167
- 'You must shut it down before you may adjust its configuration.'
168
- )
169
- }
170
- defaultService = service
171
- }
172
-
173
- /**
174
- * Returns the default OperaDriver service. If such a service has not been
175
- * configured, one will be constructed using the default configuration for
176
- * a OperaDriver executable found on the system PATH.
177
- * @return {!remote.DriverService} The default OperaDriver service.
178
- */
179
- function getDefaultService() {
180
- if (!defaultService) {
181
- defaultService = new ServiceBuilder().build()
182
- }
183
- return defaultService
184
- }
185
-
186
- /**
187
- * @type {string}
188
- * @const
189
- */
190
- const OPTIONS_CAPABILITY_KEY = 'chromeOptions'
191
-
192
- /**
193
- * Class for managing {@linkplain Driver OperaDriver} specific options.
194
- */
195
- class Options {
196
- constructor() {
197
- /** @private {!Array.<string>} */
198
- this.args_ = []
199
-
200
- /** @private {?string} */
201
- this.binary_ = null
202
-
203
- /** @private {!Array.<(string|!Buffer)>} */
204
- this.extensions_ = []
205
-
206
- /** @private {./lib/logging.Preferences} */
207
- this.logPrefs_ = null
208
-
209
- /** @private {?capabilities.ProxyConfig} */
210
- this.proxy_ = null
211
- }
212
-
213
- /**
214
- * Extracts the OperaDriver specific options from the given capabilities
215
- * object.
216
- * @param {!capabilities.Capabilities} caps The capabilities object.
217
- * @return {!Options} The OperaDriver options.
218
- */
219
- static fromCapabilities(caps) {
220
- let options
221
- const o = caps.get(OPTIONS_CAPABILITY_KEY)
222
- if (o instanceof Options) {
223
- options = o
224
- } else if (o) {
225
- options = new Options()
226
- .addArguments(o.args || [])
227
- .addExtensions(o.extensions || [])
228
- .setOperaBinaryPath(o.binary)
229
- } else {
230
- options = new Options()
231
- }
232
-
233
- if (caps.has(capabilities.Capability.PROXY)) {
234
- options.setProxy(caps.get(capabilities.Capability.PROXY))
235
- }
236
-
237
- if (caps.has(capabilities.Capability.LOGGING_PREFS)) {
238
- options.setLoggingPrefs(caps.get(capabilities.Capability.LOGGING_PREFS))
239
- }
240
-
241
- return options
242
- }
243
-
244
- /**
245
- * Add additional command line arguments to use when launching the Opera
246
- * browser. Each argument may be specified with or without the "--" prefix
247
- * (e.g. "--foo" and "foo"). Arguments with an associated value should be
248
- * delimited by an "=": "foo=bar".
249
- * @param {...(string|!Array.<string>)} var_args The arguments to add.
250
- * @return {!Options} A self reference.
251
- */
252
- addArguments(...var_args) {
253
- this.args_ = this.args_.concat.apply(this.args_, var_args)
254
- return this
255
- }
256
-
257
- /**
258
- * Add additional extensions to install when launching Opera. Each extension
259
- * should be specified as the path to the packed CRX file, or a Buffer for an
260
- * extension.
261
- * @param {...(string|!Buffer|!Array.<(string|!Buffer)>)} var_args The
262
- * extensions to add.
263
- * @return {!Options} A self reference.
264
- */
265
- addExtensions(...var_args) {
266
- this.extensions_ = this.extensions_.concat.apply(this.extensions_, var_args)
267
- return this
268
- }
269
-
270
- /**
271
- * Sets the path to the Opera binary to use. On Mac OS X, this path should
272
- * reference the actual Opera executable, not just the application binary. The
273
- * binary path be absolute or relative to the operadriver server executable, but
274
- * it must exist on the machine that will launch Opera.
275
- *
276
- * @param {string} path The path to the Opera binary to use.
277
- * @return {!Options} A self reference.
278
- */
279
- setOperaBinaryPath(path) {
280
- this.binary_ = path
281
- return this
282
- }
283
-
284
- /**
285
- * Sets the logging preferences for the new session.
286
- * @param {!./lib/logging.Preferences} prefs The logging preferences.
287
- * @return {!Options} A self reference.
288
- */
289
- setLoggingPrefs(prefs) {
290
- this.logPrefs_ = prefs
291
- return this
292
- }
293
-
294
- /**
295
- * Sets the proxy settings for the new session.
296
- * @param {capabilities.ProxyConfig} proxy The proxy configuration to use.
297
- * @return {!Options} A self reference.
298
- */
299
- setProxy(proxy) {
300
- this.proxy_ = proxy
301
- return this
302
- }
303
-
304
- /**
305
- * Converts this options instance to a {@link capabilities.Capabilities}
306
- * object.
307
- * @param {capabilities.Capabilities=} opt_capabilities The capabilities to
308
- * merge these options into, if any.
309
- * @return {!capabilities.Capabilities} The capabilities.
310
- */
311
- toCapabilities(opt_capabilities) {
312
- var caps = opt_capabilities || capabilities.Capabilities.opera()
313
- caps
314
- .set(capabilities.Capability.PROXY, this.proxy_)
315
- .set(capabilities.Capability.LOGGING_PREFS, this.logPrefs_)
316
- .set(OPTIONS_CAPABILITY_KEY, this)
317
- return caps
318
- }
319
-
320
- /**
321
- * Converts this instance to its JSON wire protocol representation. Note this
322
- * function is an implementation not intended for general use.
323
- * @return {!Object} The JSON wire protocol representation of this instance.
324
- */
325
- [Symbols.serialize]() {
326
- var json = {
327
- args: this.args_,
328
- extensions: this.extensions_.map(function (extension) {
329
- if (Buffer.isBuffer(extension)) {
330
- return extension.toString('base64')
331
- }
332
- return io
333
- .read(/** @type {string} */ (extension))
334
- .then((buffer) => buffer.toString('base64'))
335
- }),
336
- }
337
- if (this.binary_) {
338
- json.binary = this.binary_
339
- }
340
- return json
341
- }
342
- }
343
-
344
- /**
345
- * Creates a new WebDriver client for Opera.
346
- */
347
- class Driver extends webdriver.WebDriver {
348
- /**
349
- * Creates a new session for Opera.
350
- *
351
- * @param {(Capabilities|Options)=} opt_config The configuration
352
- * options.
353
- * @param {remote.DriverService=} opt_service The session to use; will use
354
- * the {@link getDefaultService default service} by default.
355
- * @return {!Driver} A new driver instance.
356
- */
357
- static createSession(opt_config, opt_service) {
358
- const service = opt_service || getDefaultService()
359
- const client = service.start().then((url) => new http.HttpClient(url))
360
- const executor = new http.Executor(client)
361
-
362
- let caps =
363
- opt_config instanceof Options
364
- ? opt_config.toCapabilities()
365
- : opt_config || capabilities.Capabilities.opera()
366
-
367
- // On Linux, the OperaDriver does not look for Opera on the PATH, so we
368
- // must explicitly find it. See: operachromiumdriver #9.
369
- if (process.platform === 'linux') {
370
- const options = Options.fromCapabilities(caps)
371
- if (!options.binary_) {
372
- let exe = io.findInPath('opera', true)
373
- if (!exe) {
374
- throw Error(
375
- 'The opera executable could not be found on the current PATH'
376
- )
377
- }
378
- options.setOperaBinaryPath(exe)
379
- }
380
- caps = options.toCapabilities(caps)
381
- }
382
-
383
- return /** @type {!Driver} */ (
384
- super.createSession(executor, caps, () => service.kill())
385
- )
386
- }
387
-
388
- /**
389
- * This function is a no-op as file detectors are not supported by this
390
- * implementation.
391
- * @override
392
- */
393
- setFileDetector() {}
394
- }
395
-
396
- // PUBLIC API
397
-
398
- exports.Driver = Driver
399
- exports.Options = Options
400
- exports.ServiceBuilder = ServiceBuilder
401
- exports.getDefaultService = getDefaultService
402
- exports.setDefaultService = setDefaultService
403
- exports.locateSynchronously = locateSynchronously