on cbdd179 help sign in
unity8/tests/utils/modules/Unity/Test/UnityTestCase.qml
325 lines 11 kB history raw
1/*
2 * Copyright 2013 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17import QtTest 1.0
18import Ubuntu.Components 0.1
19import Unity.Test 0.1 as UT
21TestCase {
22 TestUtil {id:util}
24 // Fake implementation to be provided to items under test
25 property var fakeDateTime: new function() {
26 this.currentTimeMs = 0
27 this.getCurrentTimeMs = function() {return this.currentTimeMs}
28 }
30 // Flickable won't recognise a single mouse move as dragging the flickable.
31 // Use 5 steps because it's what
32 // Qt uses in QQuickViewTestUtil::flick
33 // speed is in pixels/second
34 function mouseFlick(item, x, y, toX, toY, pressMouse, releaseMouse,
35 speed, iterations) {
36 pressMouse = ((pressMouse != null) ? pressMouse : true); // Default to true for pressMouse if not present
37 releaseMouse = ((releaseMouse != null) ? releaseMouse : true); // Default to true for releaseMouse if not present
39 // set a default speed if not specified
40 speed = (speed != null) ? speed : units.gu(10);
42 // set a default iterations if not specified
43 iterations = (iterations !== undefined) ? iterations : 5
45 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
46 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
48 var timeStep = totalTime / iterations
49 var diffX = (toX - x) / iterations
50 var diffY = (toY - y) / iterations
51 if (pressMouse) {
52 fakeDateTime.currentTimeMs += timeStep
53 mousePress(item, x, y)
54 }
55 for (var i = 0; i < iterations; ++i) {
56 fakeDateTime.currentTimeMs += timeStep
57 if (i === iterations - 1) {
58 // Avoid any rounding errors by making the last move be at precisely
59 // the point specified
60 mouseMove(item, toX, toY, iterations / speed)
61 } else {
62 mouseMove(item, x + (i + 1) * diffX, y + (i + 1) * diffY, iterations / speed)
63 }
64 }
65 if (releaseMouse) {
66 fakeDateTime.currentTimeMs += timeStep
67 mouseRelease(item, toX, toY)
68 }
69 }
72 // Find an object with the given name in the children tree of "obj"
73 function findChild(obj,objectName) {
74 var childs = new Array(0);
75 childs.push(obj)
76 while (childs.length > 0) {
77 if (childs[0].objectName == objectName) {
78 return childs[0]
79 }
80 for (var i in childs[0].children) {
81 childs.push(childs[0].children[i])
82 }
83 childs.splice(0, 1);
84 }
85 return undefined;
86 }
88 // Find an object with the given name in the children tree of "obj"
89 // Including invisible children like animations, timers etc.
90 // Note: you should use findChild if you're not sure you need this
91 // as this tree is much bigger and might contain stuff that goes
92 // away randomly.
93 function findInvisibleChild(obj,objectName) {
94 var childs = new Array(0);
95 childs.push(obj)
96 while (childs.length > 0) {
97 if (childs[0].objectName == objectName) {
98 return childs[0]
99 }
100 for (var i in childs[0].data) {
101 childs.push(childs[0].data[i])
102 }
103 childs.splice(0, 1);
104 }
105 return undefined;
106 }
108 // Type a full string instead of keyClick letter by letter
109 // TODO: this is not ugly, this is uber-ugly and does not support
110 // any special character. Remove the keyMap once keyClick(obj, char)
111 // has landed in upstream Qt.
112 function typeString(str) {
113 var keyMap = {
114 "a": Qt.Key_A,
115 "b": Qt.Key_B,
116 "c": Qt.Key_C,
117 "d": Qt.Key_D,
118 "e": Qt.Key_E,
119 "f": Qt.Key_F,
120 "g": Qt.Key_G,
121 "h": Qt.Key_H,
122 "i": Qt.Key_I,
123 "j": Qt.Key_J,
124 "k": Qt.Key_K,
125 "l": Qt.Key_L,
126 "m": Qt.Key_M,
127 "n": Qt.Key_N,
128 "o": Qt.Key_O,
129 "p": Qt.Key_P,
130 "q": Qt.Key_Q,
131 "r": Qt.Key_R,
132 "s": Qt.Key_S,
133 "t": Qt.Key_T,
134 "u": Qt.Key_U,
135 "v": Qt.Key_V,
136 "w": Qt.Key_W,
137 "x": Qt.Key_X,
138 "y": Qt.Key_Y,
139 "z": Qt.Key_Z,
140 "A": Qt.Key_A,
141 "B": Qt.Key_B,
142 "C": Qt.Key_C,
143 "D": Qt.Key_D,
144 "E": Qt.Key_E,
145 "F": Qt.Key_F,
146 "G": Qt.Key_G,
147 "H": Qt.Key_H,
148 "I": Qt.Key_I,
149 "J": Qt.Key_J,
150 "K": Qt.Key_K,
151 "L": Qt.Key_L,
152 "M": Qt.Key_M,
153 "N": Qt.Key_N,
154 "O": Qt.Key_O,
155 "P": Qt.Key_P,
156 "Q": Qt.Key_Q,
157 "R": Qt.Key_R,
158 "S": Qt.Key_S,
159 "T": Qt.Key_T,
160 "U": Qt.Key_U,
161 "V": Qt.Key_V,
162 "W": Qt.Key_W,
163 "X": Qt.Key_X,
164 "Y": Qt.Key_Y,
165 "Z": Qt.Key_Z,
166 "0": Qt.Key_0,
167 "1": Qt.Key_1,
168 "2": Qt.Key_2,
169 "3": Qt.Key_3,
170 "4": Qt.Key_4,
171 "5": Qt.Key_5,
172 "6": Qt.Key_6,
173 "7": Qt.Key_7,
174 "8": Qt.Key_8,
175 "9": Qt.Key_9,
176 " ": Qt.Key_Space,
177 }
178 for (var i = 0; i < str.length; i++) {
179 keyClick(keyMap[str[i]])
180 }
181 }
183 // Keeps executing a given parameter-less function until it returns the given
184 // expected result or the timemout is reached (in which case a test failure
185 // is generated)
186 function tryCompareFunction(func, expectedResult) {
187 var timeSpent = 0
188 var timeout = 5000
189 var success = false
190 var actualResult
191 while (timeSpent < timeout && !success) {
192 actualResult = func()
193 success = qtest_compareInternal(actualResult, expectedResult)
194 if (success === false) {
195 wait(50)
196 timeSpent += 50
197 }
198 }
200 var act = qtest_results.stringify(actualResult)
201 var exp = qtest_results.stringify(expectedResult)
202 if (!qtest_results.compare(success,
203 "function returned unexpected result",
204 act, exp,
205 util.callerFile(), util.callerLine())) {
206 throw new Error("QtQuickTest::fail")
207 }
208 }
210 function touchEvent() {
211 return UT.Util.touchEvent()
212 }
214 // speed is in pixels/second
215 function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed, iterations) {
217 // Default to true for beginTouch if not present
218 beginTouch = (beginTouch !== undefined) ? beginTouch : true
220 // Default to true for endTouch if not present
221 endTouch = (endTouch !== undefined) ? endTouch : true
223 // Set a default speed if not specified
224 speed = (speed !== undefined) ? speed : units.gu(10)
226 // Set a default iterations if not specified
227 var iterations = (iterations !== undefined) ? iterations : 5
229 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
230 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
232 var timeStep = totalTime / iterations
233 var diffX = (toX - x) / iterations
234 var diffY = (toY - y) / iterations
235 if (beginTouch) {
236 fakeDateTime.currentTimeMs += timeStep
238 var event = touchEvent()
239 event.press(0 /* touchId */, x, y)
240 event.commit()
241 }
242 for (var i = 0; i < iterations; ++i) {
243 fakeDateTime.currentTimeMs += timeStep
244 if (i === iterations - 1) {
245 // Avoid any rounding errors by making the last move be at precisely
246 // the point specified
247 wait(iterations / speed)
248 var event = touchEvent()
249 event.move(0 /* touchId */, toX, toY)
250 event.commit()
251 } else {
252 wait(iterations / speed)
253 var event = touchEvent()
254 event.move(0 /* touchId */, x + (i + 1) * diffX, y + (i + 1) * diffY)
255 event.commit()
256 }
257 }
258 if (endTouch) {
259 fakeDateTime.currentTimeMs += timeStep
260 var event = touchEvent()
261 event.release(0 /* touchId */, toX, toY)
262 event.commit()
263 }
264 }
266 function fetchRootItem(item) {
267 if (item.parent)
268 return fetchRootItem(item.parent)
269 else
270 return item
271 }
273 function touchPress(item, x, y) {
274 var root = fetchRootItem(item)
275 var rootPoint = item.mapToItem(root, x, y)
277 var event = touchEvent()
278 event.press(0 /* touchId */, rootPoint.x, rootPoint.y)
279 event.commit()
280 }
282 function touchRelease(item, x, y) {
283 var root = fetchRootItem(item)
284 var rootPoint = item.mapToItem(root, x, y)
286 var event = touchEvent()
287 event.release(0 /* touchId */, rootPoint.x, rootPoint.y)
288 event.commit()
289 }
291 function tap(item, x, y) {
292 var event = touchEvent()
293 event.press(0 /* touchId */, x, y)
294 event.commit()
296 event = touchEvent()
297 event.release(0 /* touchId */, x, y)
298 event.commit()
299 }
301 /*
302 In qmltests, sequences of touch events are sent all at once, unlike in "real life".
303 Also qmltests might run really slowly, e.g. when run from inside virtual machines.
304 Thus to remove a variable that qmltests cannot really control, namely time, this
305 function removes all constraints from DirectionalDragAreas that are sensible to
306 elapsed time.
308 This effectively makes DirectionalDragAreas easier to fool.
309 */
310 function removeTimeConstraintsFromDirectionalDragAreas(item) {
312 // use duck-typing to identify a DirectionalDragArea
313 if (item.minSpeed != undefined
314 && item.maxSilenceTime != undefined
315 && item.compositionTime != undefined) {
316 item.minSpeed = 0;
317 item.maxSilenceTime = 60 * 60 * 1000;
318 item.compositionTime = 0;
319 } else {
320 for (var i in item.children) {
321 removeTimeConstraintsFromDirectionalDragAreas(item.children[i]);
322 }
323 }
324 }