selenium-webdriver 4.1.1 → 4.3.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/README.md CHANGED
@@ -33,10 +33,10 @@ The sample below and others are included in the `example` directory. You may
33
33
  also find the tests for selenium-webdriver informative.
34
34
 
35
35
  ```javascript
36
- const {Builder, By, Key, until} = require('selenium-webdriver');
36
+ const {Builder, Browser, By, Key, until} = require('selenium-webdriver');
37
37
 
38
38
  (async function example() {
39
- let driver = await new Builder().forBrowser('firefox').build();
39
+ let driver = await new Builder().forBrowser(Browser.FIREFOX).build();
40
40
  try {
41
41
  await driver.get('http://www.google.com/ncr');
42
42
  await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
@@ -60,7 +60,7 @@ const chrome = require('selenium-webdriver/chrome');
60
60
  const firefox = require('selenium-webdriver/firefox');
61
61
 
62
62
  let driver = new webdriver.Builder()
63
- .forBrowser('firefox')
63
+ .forBrowser(webdriver.Browser.FIREFOX)
64
64
  .setChromeOptions(/* ... */)
65
65
  .setFirefoxOptions(/* ... */)
66
66
  .build();
@@ -99,7 +99,7 @@ API:
99
99
 
100
100
  ```javascript
101
101
  let driver = new webdriver.Builder()
102
- .forBrowser('firefox')
102
+ .forBrowser(webdriver.Browser.FIREFOX)
103
103
  .usingServer('http://localhost:4444/wd/hub')
104
104
  .build();
105
105
  ```
package/chrome.js CHANGED
@@ -290,9 +290,8 @@ Driver.prototype.VENDOR_COMMAND_PREFIX = 'goog'
290
290
  module.exports = {
291
291
  Driver: Driver,
292
292
  Options,
293
- ServiceBuilder ,
293
+ ServiceBuilder,
294
294
  getDefaultService,
295
295
  setDefaultService,
296
- locateSynchronously
296
+ locateSynchronously,
297
297
  }
298
-
package/chromium.js CHANGED
@@ -92,6 +92,7 @@ const Command = {
92
92
  LAUNCH_APP: 'launchApp',
93
93
  GET_NETWORK_CONDITIONS: 'getNetworkConditions',
94
94
  SET_NETWORK_CONDITIONS: 'setNetworkConditions',
95
+ DELETE_NETWORK_CONDITIONS: 'deleteNetworkConditions',
95
96
  SEND_DEVTOOLS_COMMAND: 'sendDevToolsCommand',
96
97
  SEND_AND_GET_DEVTOOLS_COMMAND: 'sendAndGetDevToolsCommand',
97
98
  SET_PERMISSION: 'setPermission',
@@ -137,6 +138,11 @@ function configureExecutor(executor, vendorPrefix) {
137
138
  'POST',
138
139
  '/session/:sessionId/chromium/network_conditions'
139
140
  )
141
+ executor.defineCommand(
142
+ Command.DELETE_NETWORK_CONDITIONS,
143
+ 'DELETE',
144
+ '/session/:sessionId/chromium/network_conditions'
145
+ )
140
146
  executor.defineCommand(
141
147
  Command.SEND_DEVTOOLS_COMMAND,
142
148
  'POST',
@@ -655,14 +661,12 @@ class Driver extends webdriver.WebDriver {
655
661
  */
656
662
  static createSession(caps, opt_serviceExecutor) {
657
663
  let executor
658
- let onQuit
659
664
  if (opt_serviceExecutor instanceof http.Executor) {
660
665
  executor = opt_serviceExecutor
661
666
  configureExecutor(executor, this.VENDOR_COMMAND_PREFIX)
662
667
  } else {
663
668
  let service = opt_serviceExecutor || this.getDefaultService()
664
669
  executor = createExecutor(service.start(), this.VENDOR_COMMAND_PREFIX)
665
- onQuit = () => service.kill()
666
670
  }
667
671
 
668
672
  // W3C spec requires noProxy value to be an array of strings, but Chromium
@@ -675,7 +679,7 @@ class Driver extends webdriver.WebDriver {
675
679
  }
676
680
  }
677
681
 
678
- return /** @type {!Driver} */ (super.createSession(executor, caps, onQuit))
682
+ return /** @type {!Driver} */ (super.createSession(executor, caps))
679
683
  }
680
684
 
681
685
  /**
@@ -706,6 +710,15 @@ class Driver extends webdriver.WebDriver {
706
710
  return this.execute(new command.Command(Command.GET_NETWORK_CONDITIONS))
707
711
  }
708
712
 
713
+ /**
714
+ * Schedules a command to delete Chromium network emulation settings.
715
+ * @return {!Promise} A promise that will be resolved when network
716
+ * emulation settings have been deleted.
717
+ */
718
+ deleteNetworkConditions() {
719
+ return this.execute(new command.Command(Command.DELETE_NETWORK_CONDITIONS))
720
+ }
721
+
709
722
  /**
710
723
  * Schedules a command to set Chromium network emulation settings.
711
724
  *
@@ -847,7 +860,7 @@ class Driver extends webdriver.WebDriver {
847
860
  * @return {!promise.Thenable<void>} A promise that will be resolved
848
861
  * when the mirror command has been issued to the device.
849
862
  */
850
- startDesktopMirroring(deviceName) {
863
+ startDesktopMirroring(deviceName) {
851
864
  return this.schedule(
852
865
  new command.Command(Command.START_CAST_DESKTOP_MIRRORING).setParameter(
853
866
  'sinkName',
@@ -19,7 +19,7 @@ class CDPConnection {
19
19
  constructor(wsConnection) {
20
20
  this._wsConnection = wsConnection
21
21
  this.cmd_id = 0
22
- this.targetID = null;
22
+ this.targetID = null
23
23
  this.sessionId = null
24
24
  }
25
25
 
package/edge.js CHANGED
@@ -94,7 +94,7 @@ let defaultService = null
94
94
 
95
95
  /**
96
96
  * Creates {@link selenium-webdriver/remote.DriverService} instances that manage
97
- * a [ChromeDriver](https://chromedriver.chromium.org/)
97
+ * a [MSEdgeDriver](https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/)
98
98
  * server in a child process.
99
99
  */
100
100
  class ServiceBuilder extends chromium.ServiceBuilder {
@@ -130,7 +130,7 @@ class Options extends chromium.Options {
130
130
  * The binary path be absolute or relative to the msedgedriver server
131
131
  * executable, but it must exist on the machine that will launch edge chromium.
132
132
  *
133
- * @param {string} path The path to the edgedriver binary to use.
133
+ * @param {string} path The path to the msedgedriver binary to use.
134
134
  * @return {!Options} A self reference.
135
135
  */
136
136
  setEdgeChromiumBinaryPath(path) {
package/firefox.js CHANGED
@@ -672,7 +672,7 @@ class Driver extends webdriver.WebDriver {
672
672
  */
673
673
  async installAddon(path, temporary = false) {
674
674
  let stats = fs.statSync(path)
675
- let buf;
675
+ let buf
676
676
  if (stats.isDirectory()) {
677
677
  let zip = new Zip()
678
678
  await zip.addDir(path)
package/ie.js CHANGED
@@ -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
- `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.'
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
 
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
@@ -78,7 +77,7 @@ function startSeleniumServer(jar) {
78
77
  function ensureFileDetectorsAreEnabled(ctor) {
79
78
  return class extends ctor {
80
79
  /** @param {input.FileDetector} detector */
81
- setFileDetector (detector) {
80
+ setFileDetector(detector) {
82
81
  webdriver.WebDriver.prototype.setFileDetector.call(this, detector)
83
82
  }
84
83
  }
@@ -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
 
package/lib/by.js CHANGED
@@ -225,7 +225,7 @@ class By {
225
225
  * @return {!By} The new locator.
226
226
  */
227
227
  static tagName(name) {
228
- return By.css(name)
228
+ return new By('tag name', name)
229
229
  }
230
230
 
231
231
  /**
@@ -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/command.js CHANGED
@@ -164,6 +164,15 @@ const Name = {
164
164
  FIND_ELEMENT_FROM_SHADOWROOT: 'findElementFromShadowRoot',
165
165
  FIND_ELEMENTS_FROM_SHADOWROOT: 'findElementsFromShadowRoot',
166
166
 
167
+ // Virtual Authenticator Commands
168
+ ADD_VIRTUAL_AUTHENTICATOR: 'addVirtualAuthenticator',
169
+ REMOVE_VIRTUAL_AUTHENTICATOR: 'removeVirtualAuthenticator',
170
+ ADD_CREDENTIAL: 'addCredential',
171
+ GET_CREDENTIALS: 'getCredentials',
172
+ REMOVE_CREDENTIAL: 'removeCredential',
173
+ REMOVE_ALL_CREDENTIALS: 'removeAllCredentials',
174
+ SET_USER_VERIFIED: 'setUserVerified',
175
+
167
176
  GET_AVAILABLE_LOG_TYPES: 'getAvailableLogTypes',
168
177
  GET_LOG: 'getLog',
169
178
 
package/lib/http.js CHANGED
@@ -63,8 +63,8 @@ function requireAtom(module, bazelTarget) {
63
63
  console.log(ex2)
64
64
  throw Error(
65
65
  `Failed to import atoms module ${module}. If running in dev mode, you` +
66
- ` need to run \`bazel build ${bazelTarget}\` from the project` +
67
- `root: ${ex}`
66
+ ` need to run \`bazel build ${bazelTarget}\` from the project` +
67
+ `root: ${ex}`
68
68
  )
69
69
  }
70
70
  }
@@ -197,7 +197,6 @@ function toExecuteAtomCommand(command, atom, ...params) {
197
197
 
198
198
  /** @const {!Map<string, (CommandSpec|CommandTransformer)>} */
199
199
  const W3C_COMMAND_MAP = new Map([
200
-
201
200
  // Session management.
202
201
  [cmd.Name.NEW_SESSION, post('/session')],
203
202
  [cmd.Name.QUIT, del('/session/:sessionId')],
@@ -245,7 +244,6 @@ const W3C_COMMAND_MAP = new Map([
245
244
  [cmd.Name.CLEAR_ACTIONS, del('/session/:sessionId/actions')],
246
245
  [cmd.Name.PRINT_PAGE, post('/session/:sessionId/print')],
247
246
 
248
-
249
247
  // Locating elements.
250
248
  [cmd.Name.GET_ACTIVE_ELEMENT, get('/session/:sessionId/element/active')],
251
249
  [cmd.Name.FIND_ELEMENT, post('/session/:sessionId/element')],
@@ -266,7 +264,10 @@ const W3C_COMMAND_MAP = new Map([
266
264
  ],
267
265
  // Element interaction.
268
266
  [cmd.Name.GET_ELEMENT_TAG_NAME, get('/session/:sessionId/element/:id/name')],
269
- [cmd.Name.GET_DOM_ATTRIBUTE, get('/session/:sessionId/element/:id/attribute/:name')],
267
+ [
268
+ cmd.Name.GET_DOM_ATTRIBUTE,
269
+ get('/session/:sessionId/element/:id/attribute/:name'),
270
+ ],
270
271
  [
271
272
  cmd.Name.GET_ELEMENT_ATTRIBUTE,
272
273
  (cmd) => {
@@ -346,6 +347,44 @@ const W3C_COMMAND_MAP = new Map([
346
347
 
347
348
  // Server Extensions
348
349
  [cmd.Name.UPLOAD_FILE, post('/session/:sessionId/se/file')],
350
+
351
+ // Virtual Authenticator
352
+ [
353
+ cmd.Name.ADD_VIRTUAL_AUTHENTICATOR,
354
+ post('/session/:sessionId/webauthn/authenticator'),
355
+ ],
356
+ [
357
+ cmd.Name.REMOVE_VIRTUAL_AUTHENTICATOR,
358
+ del('/session/:sessionId/webauthn/authenticator/:authenticatorId'),
359
+ ],
360
+ [
361
+ cmd.Name.ADD_CREDENTIAL,
362
+ post(
363
+ '/session/:sessionId/webauthn/authenticator/:authenticatorId/credential'
364
+ ),
365
+ ],
366
+ [
367
+ cmd.Name.GET_CREDENTIALS,
368
+ get(
369
+ '/session/:sessionId/webauthn/authenticator/:authenticatorId/credentials'
370
+ ),
371
+ ],
372
+ [
373
+ cmd.Name.REMOVE_CREDENTIAL,
374
+ del(
375
+ '/session/:sessionId/webauthn/authenticator/:authenticatorId/credentials/:credentialId'
376
+ ),
377
+ ],
378
+ [
379
+ cmd.Name.REMOVE_ALL_CREDENTIALS,
380
+ del(
381
+ '/session/:sessionId/webauthn/authenticator/:authenticatorId/credentials'
382
+ ),
383
+ ],
384
+ [
385
+ cmd.Name.SET_USER_VERIFIED,
386
+ post('/session/:sessionId/webauthn/authenticator/:authenticatorId/uv'),
387
+ ],
349
388
  ])
350
389
 
351
390
  /**
@@ -363,7 +402,7 @@ class Client {
363
402
  * @return {!Promise<Response>} A promise that will be fulfilled with the
364
403
  * server's response.
365
404
  */
366
- send(httpRequest) { } // eslint-disable-line
405
+ send(httpRequest) {} // eslint-disable-line
367
406
  }
368
407
 
369
408
  /**
@@ -471,6 +510,7 @@ class Executor {
471
510
  this.log_.finer(() => `>>>\n${request}\n<<<\n${response}`)
472
511
 
473
512
  let httpResponse = /** @type {!Response} */ (response)
513
+
474
514
  let { isW3C, value } = parseHttpResponse(command, httpResponse)
475
515
 
476
516
  if (command.getName() === cmd.Name.NEW_SESSION) {
@@ -529,6 +569,7 @@ function parseHttpResponse(command, httpResponse) {
529
569
  }
530
570
 
531
571
  let parsed = tryParse(httpResponse.body)
572
+
532
573
  if (parsed && typeof parsed === 'object') {
533
574
  let value = parsed.value
534
575
  let isW3C =
@@ -609,5 +650,5 @@ module.exports = {
609
650
  Request: Request,
610
651
  Response: Response,
611
652
  // Exported for testing.
612
- buildPath: buildPath
653
+ buildPath: buildPath,
613
654
  }
package/lib/input.js CHANGED
@@ -200,6 +200,7 @@ Action.Type = {
200
200
  POINTER_UP: 'pointerUp',
201
201
  POINTER_MOVE: 'pointerMove',
202
202
  POINTER_CANCEL: 'pointerCancel',
203
+ SCROLL: 'scroll',
203
204
  }
204
205
 
205
206
  /**
@@ -233,6 +234,7 @@ Device.Type = {
233
234
  KEY: 'key',
234
235
  NONE: 'none',
235
236
  POINTER: 'pointer',
237
+ WHEEL: 'wheel',
236
238
  }
237
239
 
238
240
  /**
@@ -344,11 +346,43 @@ class Pointer extends Device {
344
346
 
345
347
  /**
346
348
  * @param {!Button=} button The button to press.
349
+ * @param width
350
+ * @param height
351
+ * @param pressure
352
+ * @param tangentialPressure
353
+ * @param tiltX
354
+ * @param tiltY
355
+ * @param twist
356
+ * @param altitudeAngle
357
+ * @param azimuthAngle
347
358
  * @return {!Action} An action to press the specified button with this device.
348
359
  * @package
349
360
  */
350
- press(button = Button.LEFT) {
351
- return { type: Action.Type.POINTER_DOWN, button }
361
+ press(
362
+ button = Button.LEFT,
363
+ width = 0,
364
+ height = 0,
365
+ pressure = 0,
366
+ tangentialPressure = 0,
367
+ tiltX = 0,
368
+ tiltY = 0,
369
+ twist = 0,
370
+ altitudeAngle = 0,
371
+ azimuthAngle = 0
372
+ ) {
373
+ return {
374
+ type: Action.Type.POINTER_DOWN,
375
+ button,
376
+ width,
377
+ height,
378
+ pressure,
379
+ tangentialPressure,
380
+ tiltX,
381
+ tiltY,
382
+ twist,
383
+ altitudeAngle,
384
+ azimuthAngle,
385
+ }
352
386
  }
353
387
 
354
388
  /**
@@ -377,8 +411,37 @@ class Pointer extends Device {
377
411
  * @return {!Action} The new action.
378
412
  * @package
379
413
  */
380
- move({ x = 0, y = 0, duration = 100, origin = Origin.VIEWPORT }) {
381
- return { type: Action.Type.POINTER_MOVE, origin, duration, x, y }
414
+ move({
415
+ x = 0,
416
+ y = 0,
417
+ duration = 100,
418
+ origin = Origin.VIEWPORT,
419
+ width = 0,
420
+ height = 0,
421
+ pressure = 0,
422
+ tangentialPressure = 0,
423
+ tiltX = 0,
424
+ tiltY = 0,
425
+ twist = 0,
426
+ altitudeAngle = 0,
427
+ azimuthAngle = 0,
428
+ }) {
429
+ return {
430
+ type: Action.Type.POINTER_MOVE,
431
+ origin,
432
+ duration,
433
+ x,
434
+ y,
435
+ width,
436
+ height,
437
+ pressure,
438
+ tangentialPressure,
439
+ tiltX,
440
+ tiltY,
441
+ twist,
442
+ altitudeAngle,
443
+ azimuthAngle,
444
+ }
382
445
  }
383
446
  }
384
447
 
@@ -392,6 +455,37 @@ Pointer.Type = {
392
455
  TOUCH: 'touch',
393
456
  }
394
457
 
458
+ class Wheel extends Device {
459
+ /**
460
+ * @param {string} id the device ID..
461
+ */
462
+ constructor(id) {
463
+ super(Device.Type.WHEEL, id)
464
+ }
465
+
466
+ /**
467
+ * Scrolls a page via the coordinates given
468
+ * @param {number} x starting x coordinate
469
+ * @param {number} y starting y coordinate
470
+ * @param {number} deltaX Delta X to scroll to target
471
+ * @param {number} deltaY Delta Y to scroll to target
472
+ * @param {WebElement} origin element origin
473
+ * @param {number} duration duration ratio be the ratio of time delta and duration
474
+ * @returns {!Action} An action to scroll with this device.
475
+ */
476
+ scroll(x, y, deltaX, deltaY, origin, duration) {
477
+ return {
478
+ type: Action.Type.SCROLL,
479
+ duration: duration,
480
+ x: x,
481
+ y: y,
482
+ deltaX: deltaX,
483
+ deltaY: deltaY,
484
+ origin: origin,
485
+ }
486
+ }
487
+ }
488
+
395
489
  /**
396
490
  * User facing API for generating complex user gestures. This class should not
397
491
  * be instantiated directly. Instead, users should create new instances by
@@ -509,10 +603,14 @@ class Actions {
509
603
  /** @private @const */
510
604
  this.mouse_ = new Pointer('default mouse', Pointer.Type.MOUSE)
511
605
 
606
+ /** @private @const */
607
+ this.wheel_ = new Wheel('default wheel')
608
+
512
609
  /** @private @const {!Map<!Device, !Array<!Action>>} */
513
610
  this.sequences_ = new Map([
514
611
  [this.keyboard_, []],
515
612
  [this.mouse_, []],
613
+ [this.wheel_, []],
516
614
  ])
517
615
  }
518
616
 
@@ -526,6 +624,11 @@ class Actions {
526
624
  return this.mouse_
527
625
  }
528
626
 
627
+ /** @return {!Wheel} the wheel device handle. */
628
+ wheel() {
629
+ return this.wheel_
630
+ }
631
+
529
632
  /**
530
633
  * @param {!Device} device
531
634
  * @return {!Array<!Action>}
@@ -735,6 +838,22 @@ class Actions {
735
838
  return this.insert(this.mouse_, this.mouse_.release(button))
736
839
  }
737
840
 
841
+ /**
842
+ * scrolls a page via the coordinates given
843
+ * @param {number} x starting x coordinate
844
+ * @param {number} y starting y coordinate
845
+ * @param {number} deltax delta x to scroll to target
846
+ * @param {number} deltay delta y to scroll to target
847
+ * @param {number} duration duration ratio be the ratio of time delta and duration
848
+ * @returns {!Actions} An action to scroll with this device.
849
+ */
850
+ scroll(x, y, targetDeltaX, targetDeltaY, origin, duration) {
851
+ return this.insert(
852
+ this.wheel_,
853
+ this.wheel_.scroll(x, y, targetDeltaX, targetDeltaY, origin, duration)
854
+ )
855
+ }
856
+
738
857
  /**
739
858
  * Inserts an action for moving the mouse `x` and `y` pixels relative to the
740
859
  * specified `origin`. The `origin` may be defined as the mouse's