@@ -200,6 +200,7 @@ Action.Type = {
200200 POINTER_UP : 'pointerUp' ,
201201 POINTER_MOVE : 'pointerMove' ,
202202 POINTER_CANCEL : 'pointerCancel' ,
203+ SCROLL : 'scroll' ,
203204}
204205
205206/**
@@ -233,6 +234,7 @@ Device.Type = {
233234 KEY : 'key' ,
234235 NONE : 'none' ,
235236 POINTER : 'pointer' ,
237+ WHEEL : 'wheel' ,
236238}
237239
238240/**
@@ -392,6 +394,34 @@ Pointer.Type = {
392394 TOUCH : 'touch' ,
393395}
394396
397+ class Wheel extends Device {
398+ /**
399+ * @param {string } id the device ID.
400+ * @param {Pointer.Type } type the pointer type.
401+ */
402+ constructor ( id , type ) {
403+ super ( Device . Type . WHEEL , id )
404+ }
405+
406+ /**
407+ * Scrolls a page via the coordinates given
408+ * @param {number } x starting x coordinate
409+ * @param {number } y starting y coordinate
410+ * @param {number } deltaX Delta X to scroll to target
411+ * @param {number } deltaY Delta Y to scroll to target
412+ * @param {number } duration duration ratio be the ratio of time delta and duration
413+ * @returns {!Action } An action to scroll with this device.
414+ */
415+ scroll ( x , y , deltaX , deltaY , origin , duration ) {
416+ return {
417+ type : Action . Type . SCROLL ,
418+ duration : duration , x : x , y : y ,
419+ deltaX : deltaX , deltaY : deltaY ,
420+ origin : origin
421+ }
422+ }
423+ }
424+
395425/**
396426 * User facing API for generating complex user gestures. This class should not
397427 * be instantiated directly. Instead, users should create new instances by
@@ -509,10 +539,14 @@ class Actions {
509539 /** @private @const */
510540 this . mouse_ = new Pointer ( 'default mouse' , Pointer . Type . MOUSE )
511541
542+ /** @private @const */
543+ this . wheel_ = new Wheel ( 'default wheel' )
544+
512545 /** @private @const {!Map<!Device, !Array<!Action>>} */
513546 this . sequences_ = new Map ( [
514547 [ this . keyboard_ , [ ] ] ,
515548 [ this . mouse_ , [ ] ] ,
549+ [ this . wheel_ , [ ] ] ,
516550 ] )
517551 }
518552
@@ -526,6 +560,11 @@ class Actions {
526560 return this . mouse_
527561 }
528562
563+ /** @return {!Wheel } the wheel device handle. */
564+ wheel ( ) {
565+ return this . wheel_
566+ }
567+
529568 /**
530569 * @param {!Device } device
531570 * @return {!Array<!Action> }
@@ -736,125 +775,139 @@ class Actions {
736775 }
737776
738777 /**
739- * Inserts an action for moving the mouse `x` and `y` pixels relative to the
740- * specified `origin`. The `origin` may be defined as the mouse's
741- * {@linkplain ./input.Origin.POINTER current position}, the
742- * {@linkplain ./input.Origin.VIEWPORT viewport}, or the center of a specific
743- * {@linkplain ./webdriver.WebElement WebElement}.
744- *
745- * You may adjust how long the remote end should take, in milliseconds, to
746- * perform the move using the `duration` parameter (defaults to 100 ms).
747- * The number of incremental move events generated over this duration is an
748- * implementation detail for the remote end.
749- *
750- * @param {{
751- * x: (number|undefined),
752- * y: (number|undefined),
753- * duration: (number|undefined),
754- * origin: (!Origin|!./webdriver.WebElement|undefined),
755- * }= } options The move options. Defaults to moving the mouse to the top-left
756- * corner of the viewport over 100ms.
757- * @return {!Actions } a self reference.
778+ * scrolls a page via the coordinates given
779+ * @param {number } x starting x coordinate
780+ * @param {number } y starting y coordinate
781+ * @param {number } deltax delta x to scroll to target
782+ * @param {number } deltay delta y to scroll to target
783+ * @param {number } duration duration ratio be the ratio of time delta and duration
784+ * @returns {!Action } An action to scroll with this device.
758785 */
759- move ( { x = 0 , y = 0 , duration = 100 , origin = Origin . VIEWPORT } = { } ) {
760- return this . insert (
761- this . mouse_ ,
762- this . mouse_ . move ( { x, y, duration, origin } )
763- )
764- }
786+ * /
787+ scroll ( x , y , targetDeltaX , targetDeltaY , origin , duration ) {
788+ return this . insert ( this . wheel_ , this . wheel_ . scroll ( x , y , targetDeltaX , targetDeltaY , origin , duration ) )
789+ }
765790
766- /**
767- * Short-hand for performing a simple left-click (down/up) with the mouse.
768- *
769- * @param {./webdriver.WebElement= } element If specified, the mouse will
770- * first be moved to the center of the element before performing the
771- * click.
772- * @return {!Actions } a self reference.
773- */
774- click ( element ) {
775- if ( element ) {
776- this . move ( { origin : element } )
777- }
778- return this . press ( ) . release ( )
779- }
791+ /**
792+ * Inserts an action for moving the mouse `x` and `y` pixels relative to the
793+ * specified `origin`. The `origin` may be defined as the mouse's
794+ * {@linkplain ./input.Origin.POINTER current position}, the
795+ * {@linkplain ./input.Origin.VIEWPORT viewport}, or the center of a specific
796+ * {@linkplain ./webdriver.WebElement WebElement}.
797+ *
798+ * You may adjust how long the remote end should take, in milliseconds, to
799+ * perform the move using the `duration` parameter (defaults to 100 ms).
800+ * The number of incremental move events generated over this duration is an
801+ * implementation detail for the remote end.
802+ *
803+ * @param {{
804+ * x: (number|undefined),
805+ * y: (number|undefined),
806+ * duration: (number|undefined),
807+ * origin: (!Origin|!./webdriver.WebElement|undefined),
808+ * }= } options The move options. Defaults to moving the mouse to the top-left
809+ * corner of the viewport over 100ms.
810+ * @return {!Actions } a self reference.
811+ */
812+ move ( { x = 0 , y = 0 , duration = 100 , origin = Origin . VIEWPORT } = { } ) {
813+ return this . insert (
814+ this . mouse_ ,
815+ this . mouse_ . move ( { x, y, duration, origin } )
816+ )
817+ }
780818
781- /**
782- * Short-hand for performing a simple right-click (down/up) with the mouse.
783- *
784- * @param {./webdriver.WebElement= } element If specified, the mouse will
785- * first be moved to the center of the element before performing the
786- * click.
787- * @return {!Actions } a self reference.
788- */
789- contextClick ( element ) {
790- if ( element ) {
791- this . move ( { origin : element } )
792- }
793- return this . press ( Button . RIGHT ) . release ( Button . RIGHT )
819+ /**
820+ * Short-hand for performing a simple left-click (down/up) with the mouse.
821+ *
822+ * @param {./webdriver.WebElement= } element If specified, the mouse will
823+ * first be moved to the center of the element before performing the
824+ * click.
825+ * @return {!Actions } a self reference.
826+ */
827+ click ( element ) {
828+ if ( element ) {
829+ this . move ( { origin : element } )
794830 }
831+ return this . press ( ) . release ( )
832+ }
795833
796- /**
797- * Short-hand for performing a double left-click with the mouse.
798- *
799- * @param {./webdriver.WebElement= } element If specified, the mouse will
800- * first be moved to the center of the element before performing the
801- * click.
802- * @return {!Actions } a self reference.
803- */
804- doubleClick ( element ) {
805- return this . click ( element ) . press ( ) . release ( )
834+ /**
835+ * Short-hand for performing a simple right-click (down/up) with the mouse.
836+ *
837+ * @param {./webdriver.WebElement= } element If specified, the mouse will
838+ * first be moved to the center of the element before performing the
839+ * click.
840+ * @return {!Actions } a self reference.
841+ */
842+ contextClick ( element ) {
843+ if ( element ) {
844+ this . move ( { origin : element } )
806845 }
846+ return this . press ( Button . RIGHT ) . release ( Button . RIGHT )
847+ }
807848
808- /**
809- * Configures a drag-and-drop action consisting of the following steps:
810- *
811- * 1. Move to the center of the `from` element (element to be dragged).
812- * 2. Press the left mouse button.
813- * 3. If the `to` target is a {@linkplain ./webdriver.WebElement WebElement},
814- * move the mouse to its center. Otherwise, move the mouse by the
815- * specified offset.
816- * 4. Release the left mouse button.
817- *
818- * @param {!./webdriver.WebElement } from The element to press the left mouse
819- * button on to start the drag.
820- * @param {(!./webdriver.WebElement|{x: number, y: number}) } to Either another
821- * element to drag to (will drag to the center of the element), or an
822- * object specifying the offset to drag by, in pixels.
823- * @return {!Actions } a self reference.
824- */
825- dragAndDrop ( from , to ) {
826- // Do not require up top to avoid a cycle that breaks static analysis.
827- const { WebElement } = require ( './webdriver' )
828- if (
829- ! ( to instanceof WebElement ) &&
830- ( ! to || typeof to . x !== 'number' || typeof to . y !== 'number' )
831- ) {
832- throw new InvalidArgumentError (
833- 'Invalid drag target; must specify a WebElement or {x, y} offset'
834- )
835- }
849+ /**
850+ * Short-hand for performing a double left-click with the mouse.
851+ *
852+ * @param {./webdriver.WebElement= } element If specified, the mouse will
853+ * first be moved to the center of the element before performing the
854+ * click.
855+ * @return {!Actions } a self reference.
856+ */
857+ doubleClick ( element ) {
858+ return this . click ( element ) . press ( ) . release ( )
859+ }
836860
837- this . move ( { origin : from } ) . press ( )
838- if ( to instanceof WebElement ) {
839- this . move ( { origin : to } )
840- } else {
841- this . move ( { x : to . x , y : to . y , origin : Origin . POINTER } )
842- }
843- return this . release ( )
861+ /**
862+ * Configures a drag-and-drop action consisting of the following steps:
863+ *
864+ * 1. Move to the center of the `from` element (element to be dragged).
865+ * 2. Press the left mouse button.
866+ * 3. If the `to` target is a {@linkplain ./webdriver.WebElement WebElement},
867+ * move the mouse to its center. Otherwise, move the mouse by the
868+ * specified offset.
869+ * 4. Release the left mouse button.
870+ *
871+ * @param {!./webdriver.WebElement } from The element to press the left mouse
872+ * button on to start the drag.
873+ * @param {(!./webdriver.WebElement|{x: number, y: number}) } to Either another
874+ * element to drag to (will drag to the center of the element), or an
875+ * object specifying the offset to drag by, in pixels.
876+ * @return {!Actions } a self reference.
877+ */
878+ dragAndDrop ( from , to ) {
879+ // Do not require up top to avoid a cycle that breaks static analysis.
880+ const { WebElement } = require ( './webdriver' )
881+ if (
882+ ! ( to instanceof WebElement ) &&
883+ ( ! to || typeof to . x !== 'number' || typeof to . y !== 'number' )
884+ ) {
885+ throw new InvalidArgumentError (
886+ 'Invalid drag target; must specify a WebElement or {x, y} offset'
887+ )
844888 }
845889
846- /**
847- * Releases all keys, pointers, and clears internal state.
848- *
849- * @return {!Promise<void> } a promise that will resolve when finished
850- * clearing all action state.
851- */
852- clear ( ) {
853- for ( const s of this . sequences_ . values ( ) ) {
854- s . length = 0
855- }
856- return this . executor_ . execute ( new Command ( Name . CLEAR_ACTIONS ) )
890+ this . move ( { origin : from } ) . press ( )
891+ if ( to instanceof WebElement ) {
892+ this . move ( { origin : to } )
893+ } else {
894+ this . move ( { x : to . x , y : to . y , origin : Origin . POINTER } )
895+ }
896+ return this . release ( )
897+ }
898+
899+ /**
900+ * Releases all keys, pointers, and clears internal state.
901+ *
902+ * @return {!Promise<void> } a promise that will resolve when finished
903+ * clearing all action state.
904+ */
905+ clear ( ) {
906+ for ( const s of this . sequences_ . values ( ) ) {
907+ s . length = 0
857908 }
909+ return this . executor_ . execute ( new Command ( Name . CLEAR_ACTIONS ) )
910+ }
858911
859912 /**
860913 * Performs the configured action sequence.
@@ -863,22 +916,22 @@ class Actions {
863916 * been completed.
864917 */
865918 async perform ( ) {
866- const _actions = [ ]
867- this . sequences_ . forEach ( ( actions , device ) => {
868- if ( ! isIdle ( actions ) ) {
869- actions = actions . concat ( ) // Defensive copy.
870- _actions . push ( Object . assign ( { actions } , device . toJSON ( ) ) )
871- }
872- } )
873-
874- if ( _actions . length === 0 ) {
875- return Promise . resolve ( )
919+ const _actions = [ ]
920+ this . sequences_ . forEach ( ( actions , device ) => {
921+ if ( ! isIdle ( actions ) ) {
922+ actions = actions . concat ( ) // Defensive copy.
923+ _actions . push ( Object . assign ( { actions } , device . toJSON ( ) ) )
876924 }
925+ } )
877926
878- await this . executor_ . execute (
879- new Command ( Name . ACTIONS ) . setParameter ( 'actions' , _actions )
880- )
927+ if ( _actions . length === 0 ) {
928+ return Promise . resolve ( )
881929 }
930+
931+ await this . executor_ . execute (
932+ new Command ( Name . ACTIONS ) . setParameter ( 'actions' , _actions )
933+ )
934+ }
882935}
883936
884937/**
0 commit comments