lib/webdriver/touchsequence.js

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
18goog.provide('webdriver.TouchSequence');
19
20goog.require('goog.array');
21goog.require('webdriver.Command');
22goog.require('webdriver.CommandName');
23
24
25
26/**
27 * Class for defining sequences of user touch interactions. Each sequence
28 * will not be executed until {@link #perform} is called.
29 *
30 * Example:
31 *
32 * new webdriver.TouchSequence(driver).
33 * tapAndHold({x: 0, y: 0}).
34 * move({x: 3, y: 4}).
35 * release({x: 10, y: 10}).
36 * perform();
37 *
38 * @param {!webdriver.WebDriver} driver The driver instance to use.
39 * @constructor
40 */
41webdriver.TouchSequence = function(driver) {
42
43 /** @private {!webdriver.WebDriver} */
44 this.driver_ = driver;
45
46 /** @private {!Array<{description: string, command: !webdriver.Command}>} */
47 this.touchActions_ = [];
48};
49
50
51/**
52 * Schedules an action to be executed each time {@link #perform} is called on
53 * this instance.
54 * @param {string} description A description of the command.
55 * @param {!webdriver.Command} command The command.
56 * @private
57 */
58webdriver.TouchSequence.prototype.schedule_ = function(description, command) {
59 this.touchActions_.push({
60 description: description,
61 command: command
62 });
63};
64
65
66/**
67 * Executes this action sequence.
68 * @return {!webdriver.promise.Promise} A promise that will be resolved once
69 * this sequence has completed.
70 */
71webdriver.TouchSequence.prototype.perform = function() {
72 // Make a protected copy of the scheduled actions. This will protect against
73 // users defining additional commands before this sequence is actually
74 // executed.
75 var actions = goog.array.clone(this.touchActions_);
76 var driver = this.driver_;
77 return driver.controlFlow().execute(function() {
78 goog.array.forEach(actions, function(action) {
79 driver.schedule(action.command, action.description);
80 });
81 }, 'TouchSequence.perform');
82};
83
84
85/**
86 * Taps an element.
87 *
88 * @param {!webdriver.WebElement} elem The element to tap.
89 * @return {!webdriver.TouchSequence} A self reference.
90 */
91webdriver.TouchSequence.prototype.tap = function(elem) {
92 var command = new webdriver.Command(webdriver.CommandName.TOUCH_SINGLE_TAP).
93 setParameter('element', elem.getRawId());
94
95 this.schedule_('tap', command);
96 return this;
97};
98
99
100/**
101 * Double taps an element.
102 *
103 * @param {!webdriver.WebElement} elem The element to double tap.
104 * @return {!webdriver.TouchSequence} A self reference.
105 */
106webdriver.TouchSequence.prototype.doubleTap = function(elem) {
107 var command = new webdriver.Command(webdriver.CommandName.TOUCH_DOUBLE_TAP).
108 setParameter('element', elem.getRawId());
109
110 this.schedule_('doubleTap', command);
111 return this;
112};
113
114
115/**
116 * Long press on an element.
117 *
118 * @param {!webdriver.WebElement} elem The element to long press.
119 * @return {!webdriver.TouchSequence} A self reference.
120 */
121webdriver.TouchSequence.prototype.longPress = function(elem) {
122 var command = new webdriver.Command(webdriver.CommandName.TOUCH_LONG_PRESS).
123 setParameter('element', elem.getRawId());
124
125 this.schedule_('longPress', command);
126 return this;
127};
128
129
130/**
131 * Touch down at the given location.
132 *
133 * @param {{x: number, y: number}} location The location to touch down at.
134 * @return {!webdriver.TouchSequence} A self reference.
135 */
136webdriver.TouchSequence.prototype.tapAndHold = function(location) {
137 var command = new webdriver.Command(webdriver.CommandName.TOUCH_DOWN).
138 setParameter('x', location.x).
139 setParameter('y', location.y);
140
141 this.schedule_('tapAndHold', command);
142 return this;
143};
144
145
146/**
147 * Move a held {@linkplain #tapAndHold touch} to the specified location.
148 *
149 * @param {{x: number, y: number}} location The location to move to.
150 * @return {!webdriver.TouchSequence} A self reference.
151 */
152webdriver.TouchSequence.prototype.move = function(location) {
153 var command = new webdriver.Command(webdriver.CommandName.TOUCH_MOVE).
154 setParameter('x', location.x).
155 setParameter('y', location.y);
156
157 this.schedule_('move', command);
158 return this;
159};
160
161
162/**
163 * Release a held {@linkplain #tapAndHold touch} at the specified location.
164 *
165 * @param {{x: number, y: number}} location The location to release at.
166 * @return {!webdriver.TouchSequence} A self reference.
167 */
168webdriver.TouchSequence.prototype.release = function(location) {
169 var command = new webdriver.Command(webdriver.CommandName.TOUCH_UP).
170 setParameter('x', location.x).
171 setParameter('y', location.y);
172
173 this.schedule_('release', command);
174 return this;
175};
176
177
178/**
179 * Scrolls the touch screen by the given offset.
180 *
181 * @param {{x: number, y: number}} offset The offset to scroll to.
182 * @return {!webdriver.TouchSequence} A self reference.
183 */
184webdriver.TouchSequence.prototype.scroll = function(offset) {
185 var command = new webdriver.Command(webdriver.CommandName.TOUCH_SCROLL).
186 setParameter('xoffset', offset.x).
187 setParameter('yoffset', offset.y);
188
189 this.schedule_('scroll', command);
190 return this;
191};
192
193
194/**
195 * Scrolls the touch screen, starting on `elem` and moving by the specified
196 * offset.
197 *
198 * @param {!webdriver.WebElement} elem The element where scroll starts.
199 * @param {{x: number, y: number}} offset The offset to scroll to.
200 * @return {!webdriver.TouchSequence} A self reference.
201 */
202webdriver.TouchSequence.prototype.scrollFromElement = function(elem, offset) {
203 var command = new webdriver.Command(webdriver.CommandName.TOUCH_SCROLL).
204 setParameter('element', elem.getRawId()).
205 setParameter('xoffset', offset.x).
206 setParameter('yoffset', offset.y);
207
208 this.schedule_('scrollFromElement', command);
209 return this;
210};
211
212
213/**
214 * Flick, starting anywhere on the screen, at speed xspeed and yspeed.
215 *
216 * @param {{xspeed: number, yspeed: number}} speed The speed to flick in each
217 direction, in pixels per second.
218 * @return {!webdriver.TouchSequence} A self reference.
219 */
220webdriver.TouchSequence.prototype.flick = function(speed) {
221 var command = new webdriver.Command(webdriver.CommandName.TOUCH_FLICK).
222 setParameter('xspeed', speed.xspeed).
223 setParameter('yspeed', speed.yspeed);
224
225 this.schedule_('flick', command);
226 return this;
227};
228
229
230/**
231 * Flick starting at elem and moving by x and y at specified speed.
232 *
233 * @param {!webdriver.WebElement} elem The element where flick starts.
234 * @param {{x: number, y: number}} offset The offset to flick to.
235 * @param {number} speed The speed to flick at in pixels per second.
236 * @return {!webdriver.TouchSequence} A self reference.
237 */
238webdriver.TouchSequence.prototype.flickElement = function(elem, offset, speed) {
239 var command = new webdriver.Command(webdriver.CommandName.TOUCH_FLICK).
240 setParameter('element', elem.getRawId()).
241 setParameter('xoffset', offset.x).
242 setParameter('yoffset', offset.y).
243 setParameter('speed', speed);
244
245 this.schedule_('flickElement', command);
246 return this;
247};
248