lib/webdriver/touchsequence.js

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