2 * Copyright 2013 Canonical Ltd.
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.
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.
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/>.
19import Ubuntu.Components 0.1
20import Unity.Test 0.1 as UT
27 visible: testCase.running
28 anchors.centerIn: parent
29 Component.onCompleted: parent = testCase.parent
34 // Fake implementation to be provided to items under test
35 property var fakeDateTime: new function() {
36 this.currentTimeMs = 0
37 this.getCurrentTimeMs = function() {return this.currentTimeMs}
40 // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature
41 function mouseClick(item, x, y, button, modifiers, delay) {
42 if (button === undefined)
43 button = Qt.LeftButton;
44 if (modifiers === undefined)
45 modifiers = Qt.NoModifier;
46 if (delay === undefined)
52 if (!qtest_events.mouseClick(item, x, y, button, modifiers, delay))
53 qtest_fail("window not shown", 2);
56 // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature
57 function mouseDoubleClick(item, x, y, button, modifiers, delay) {
58 if (button === undefined)
59 button = Qt.LeftButton;
60 if (modifiers === undefined)
61 modifiers = Qt.NoModifier;
62 if (delay === undefined)
68 if (!qtest_events.mouseDoubleClick(item, x, y, button, modifiers, delay))
69 qtest_fail("window not shown", 2)
72 // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature
73 function mousePress(item, x, y, button, modifiers, delay) {
74 if (button === undefined)
75 button = Qt.LeftButton;
76 if (modifiers === undefined)
77 modifiers = Qt.NoModifier;
78 if (delay === undefined)
84 if (!qtest_events.mousePress(item, x, y, button, modifiers, delay))
85 qtest_fail("window not shown", 2)
88 // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature
89 function mouseRelease(item, x, y, button, modifiers, delay) {
90 if (button === undefined)
91 button = Qt.LeftButton;
92 if (modifiers === undefined)
93 modifiers = Qt.NoModifier;
94 if (delay === undefined)
100 if (!qtest_events.mouseRelease(item, x, y, button, modifiers, delay))
101 qtest_fail("window not shown", 2)
105 // Flickable won't recognise a single mouse move as dragging the flickable.
106 // Use 5 steps because it's what
107 // Qt uses in QQuickViewTestUtil::flick
108 // speed is in pixels/second
109 function mouseFlick(item, x, y, toX, toY, pressMouse, releaseMouse,
111 pressMouse = ((pressMouse != null) ? pressMouse : true); // Default to true for pressMouse if not present
112 releaseMouse = ((releaseMouse != null) ? releaseMouse : true); // Default to true for releaseMouse if not present
114 // set a default speed if not specified
115 speed = (speed != null) ? speed : units.gu(10);
117 // set a default iterations if not specified
118 iterations = (iterations !== undefined) ? iterations : 5
120 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
121 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
123 var timeStep = totalTime / iterations
124 var diffX = (toX - x) / iterations
125 var diffY = (toY - y) / iterations
127 fakeDateTime.currentTimeMs += timeStep
128 mousePress(item, x, y)
130 for (var i = 0; i < iterations; ++i) {
131 fakeDateTime.currentTimeMs += timeStep
132 if (i === iterations - 1) {
133 // Avoid any rounding errors by making the last move be at precisely
134 // the point specified
135 mouseMove(item, toX, toY, iterations / speed)
137 mouseMove(item, x + (i + 1) * diffX, y + (i + 1) * diffY, iterations / speed)
141 fakeDateTime.currentTimeMs += timeStep
142 mouseRelease(item, toX, toY)
147 // Find an object with the given name in the children tree of "obj"
148 function findChild(obj, objectName) {
149 return findChildIn(obj, "children", objectName);
152 // Find an object with the given name in the children tree of "obj"
153 // Including invisible children like animations, timers etc.
154 // Note: you should use findChild if you're not sure you need this
155 // as this tree is much bigger and might contain stuff that goes
157 function findInvisibleChild(obj, objectName) {
158 return findChildIn(obj, "data", objectName);
161 // Find a child in the named property
162 function findChildIn(obj, prop, objectName) {
163 var childs = new Array(0);
165 while (childs.length > 0) {
166 if (childs[0].objectName == objectName) {
169 for (var i in childs[0][prop]) {
170 childs.push(childs[0][prop][i])
177 // Type a full string instead of keyClick letter by letter
178 function typeString(str) {
179 for (var i = 0; i < str.length; i++) {
184 // Keeps executing a given parameter-less function until it returns the given
185 // expected result or the timemout is reached (in which case a test failure
187 function tryCompareFunction(func, expectedResult, timeout) {
189 if (timeout === undefined)
193 while (timeSpent < timeout && !success) {
194 actualResult = func()
195 success = qtest_compareInternal(actualResult, expectedResult)
196 if (success === false) {
202 var act = qtest_results.stringify(actualResult)
203 var exp = qtest_results.stringify(expectedResult)
204 if (!qtest_results.compare(success,
205 "function returned unexpected result",
207 util.callerFile(), util.callerLine())) {
208 throw new Error("QtQuickTest::fail")
212 function touchEvent() {
213 return UT.Util.touchEvent()
216 // speed is in pixels/second
217 function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed, iterations) {
218 // Make sure the item is rendered
219 waitForRendering(item);
221 var root = fetchRootItem(item);
222 var rootFrom = item.mapToItem(root, x, y);
223 var rootTo = item.mapToItem(root, toX, toY);
225 // Default to true for beginTouch if not present
226 beginTouch = (beginTouch !== undefined) ? beginTouch : true
228 // Default to true for endTouch if not present
229 endTouch = (endTouch !== undefined) ? endTouch : true
231 // Set a default speed if not specified
232 speed = (speed !== undefined) ? speed : units.gu(10)
234 // Set a default iterations if not specified
235 var iterations = (iterations !== undefined) ? iterations : 5
237 var distance = Math.sqrt(Math.pow(rootTo.x - rootFrom.x, 2) + Math.pow(rootTo.Y - rootFrom.y, 2))
238 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
240 var timeStep = totalTime / iterations
241 var diffX = (rootTo.x - rootFrom.x) / iterations
242 var diffY = (rootTo.y - rootFrom.y) / iterations
244 fakeDateTime.currentTimeMs += timeStep
246 var event = touchEvent()
247 event.press(0 /* touchId */, rootFrom.x, rootFrom.y)
250 for (var i = 0; i < iterations; ++i) {
251 fakeDateTime.currentTimeMs += timeStep
252 if (i === iterations - 1) {
253 // Avoid any rounding errors by making the last move be at precisely
254 // the point specified
255 wait(iterations / speed)
256 var event = touchEvent()
257 event.move(0 /* touchId */, rootTo.x, rootTo.y)
260 wait(iterations / speed)
261 var event = touchEvent()
262 event.move(0 /* touchId */, rootFrom.x + (i + 1) * diffX, rootFrom.y + (i + 1) * diffY)
267 fakeDateTime.currentTimeMs += timeStep
268 var event = touchEvent()
269 event.release(0 /* touchId */, rootTo.x, rootTo.y)
274 function touchPinch(item, x1Start, y1Start, x1End, y1End, x2Start, y2Start, x2End, y2End) {
275 // Make sure the item is rendered
276 waitForRendering(item);
278 var event1 = touchEvent();
280 event1.press(0, x1Start, y1Start);
283 event1.stationary(0);
284 event1.press(1, x2Start, y2Start);
288 for (var i = 0.0; i < 1.0; i += 0.02) {
289 event1.move(0, x1Start + (x1End - x1Start) * i, y1Start + (y1End - y1Start) * i);
290 event1.move(1, x2Start + (x2End - x2Start) * i, y2Start + (y2End - y2Start) * i);
295 event1.release(0, x1End, y1End);
296 event1.release(1, x2End, y2End);
300 function fetchRootItem(item) {
302 return fetchRootItem(item.parent)
307 function touchPress(item, x, y) {
308 var root = fetchRootItem(item)
309 var rootPoint = item.mapToItem(root, x, y)
311 var event = touchEvent()
312 event.press(0 /* touchId */, rootPoint.x, rootPoint.y)
316 function touchRelease(item, x, y) {
317 var root = fetchRootItem(item)
318 var rootPoint = item.mapToItem(root, x, y)
320 var event = touchEvent()
321 event.release(0 /* touchId */, rootPoint.x, rootPoint.y)
325 /*! \brief Tap the item with a touch event.
327 \param item The item to be tapped
328 \param x The x coordinate of the tap, defaults to horizontal center
329 \param y The y coordinate of the tap, defaults to vertical center
331 function tap(item, x, y) {
332 if (typeof x !== "number") x = item.width / 2;
333 if (typeof y !== "number") y = item.height / 2;
335 var root = fetchRootItem(item)
336 var rootPoint = item.mapToItem(root, x, y)
338 var event = touchEvent()
339 event.press(0 /* touchId */, rootPoint.x, rootPoint.y)
343 event.release(0 /* touchId */, rootPoint.x, rootPoint.y)
347 Component.onCompleted: {
348 UT.Util.ensureTouchRegistryInstalled();
350 var rootItem = parent;
351 while (rootItem.parent != undefined) {
352 rootItem = rootItem.parent;
354 removeTimeConstraintsFromDirectionalDragAreas(rootItem);
358 In qmltests, sequences of touch events are sent all at once, unlike in "real life".
359 Also qmltests might run really slowly, e.g. when run from inside virtual machines.
360 Thus to remove a variable that qmltests cannot really control, namely time, this
361 function removes all constraints from DirectionalDragAreas that are sensible to
364 This effectively makes DirectionalDragAreas easier to fool.
366 function removeTimeConstraintsFromDirectionalDragAreas(item) {
368 // use duck-typing to identify a DirectionalDragArea
369 if (item.minSpeed != undefined
370 && item.maxSilenceTime != undefined
371 && item.compositionTime != undefined) {
373 item.maxSilenceTime = 60 * 60 * 1000;
374 item.compositionTime = 0;
376 for (var i in item.children) {
377 removeTimeConstraintsFromDirectionalDragAreas(item.children[i]);
382 // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature
383 function waitForRendering(item, timeout) {
384 if (timeout === undefined)
387 qtest_fail("No item given to waitForRendering", 1);
388 return qtest_results.waitForRendering(item, timeout);
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list