# 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 |
18 | goog.provide('webdriver.TouchSequence');
19 |
20 | goog.require('goog.array');
21 | goog.require('webdriver.Command');
22 | goog.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 | */
41 | webdriver.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 | */
58 | webdriver.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 | */
71 | webdriver.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 | */
91 | webdriver.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 | */
106 | webdriver.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 | */
121 | webdriver.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 | */
136 | webdriver.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 | */
152 | webdriver.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 | */
168 | webdriver.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 | */
184 | webdriver.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 | */
202 | webdriver.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 | */
220 | webdriver.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 | */
238 | webdriver.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 |