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 function findChildsByType(obj, typeName) {
178 var res = new Array(0);
179 for (var i in obj.children) {
180 var c = obj.children[i];
181 if (UT.Util.isInstanceOf(c, typeName)) {
184 res = res.concat(findChildsByType(c, typeName));
189 // Type a full string instead of keyClick letter by letter
190 function typeString(str) {
191 for (var i = 0; i < str.length; i++) {
196 // Keeps executing a given parameter-less function until it returns the given
197 // expected result or the timemout is reached (in which case a test failure
199 function tryCompareFunction(func, expectedResult, timeout) {
201 if (timeout === undefined)
205 while (timeSpent < timeout && !success) {
206 actualResult = func()
207 success = qtest_compareInternal(actualResult, expectedResult)
208 if (success === false) {
214 var act = qtest_results.stringify(actualResult)
215 var exp = qtest_results.stringify(expectedResult)
216 if (!qtest_results.compare(success,
217 "function returned unexpected result",
219 util.callerFile(), util.callerLine())) {
220 throw new Error("QtQuickTest::fail")
224 function touchEvent(item) {
225 return UT.Util.touchEvent(item)
228 // speed is in pixels/second
229 function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed, iterations) {
230 // Make sure the item is rendered
231 waitForRendering(item);
233 var root = fetchRootItem(item);
234 var rootFrom = item.mapToItem(root, x, y);
235 var rootTo = item.mapToItem(root, toX, toY);
237 // Default to true for beginTouch if not present
238 beginTouch = (beginTouch !== undefined) ? beginTouch : true
240 // Default to true for endTouch if not present
241 endTouch = (endTouch !== undefined) ? endTouch : true
243 // Set a default speed if not specified
244 speed = (speed !== undefined) ? speed : units.gu(10)
246 // Set a default iterations if not specified
247 var iterations = (iterations !== undefined) ? iterations : 5
249 var distance = Math.sqrt(Math.pow(rootTo.x - rootFrom.x, 2) + Math.pow(rootTo.Y - rootFrom.y, 2))
250 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
252 var timeStep = totalTime / iterations
253 var diffX = (rootTo.x - rootFrom.x) / iterations
254 var diffY = (rootTo.y - rootFrom.y) / iterations
256 fakeDateTime.currentTimeMs += timeStep
258 var event = touchEvent(item)
259 event.press(0 /* touchId */, rootFrom.x, rootFrom.y)
262 for (var i = 0; i < iterations; ++i) {
263 fakeDateTime.currentTimeMs += timeStep
264 if (i === iterations - 1) {
265 // Avoid any rounding errors by making the last move be at precisely
266 // the point specified
267 wait(iterations / speed)
268 var event = touchEvent(item)
269 event.move(0 /* touchId */, rootTo.x, rootTo.y)
272 wait(iterations / speed)
273 var event = touchEvent(item)
274 event.move(0 /* touchId */, rootFrom.x + (i + 1) * diffX, rootFrom.y + (i + 1) * diffY)
279 fakeDateTime.currentTimeMs += timeStep
280 var event = touchEvent(item)
281 event.release(0 /* touchId */, rootTo.x, rootTo.y)
286 function touchPinch(item, x1Start, y1Start, x1End, y1End, x2Start, y2Start, x2End, y2End) {
287 // Make sure the item is rendered
288 waitForRendering(item);
290 var event1 = touchEvent(item);
292 event1.press(0, x1Start, y1Start);
295 event1.move(0, x1Start, y1Start);
296 event1.press(1, x2Start, y2Start);
299 for (var i = 0.0; i < 1.0; i += 0.02) {
300 event1.move(0, x1Start + (x1End - x1Start) * i, y1Start + (y1End - y1Start) * i);
301 event1.move(1, x2Start + (x2End - x2Start) * i, y2Start + (y2End - y2Start) * i);
306 event1.release(0, x1End, y1End);
307 event1.release(1, x2End, y2End);
311 function fetchRootItem(item) {
313 return fetchRootItem(item.parent)
318 function touchPress(item, x, y) {
319 var root = fetchRootItem(item)
320 var rootPoint = item.mapToItem(root, x, y)
322 var event = touchEvent(item)
323 event.press(0 /* touchId */, rootPoint.x, rootPoint.y)
327 function touchRelease(item, x, y) {
328 var root = fetchRootItem(item)
329 var rootPoint = item.mapToItem(root, x, y)
331 var event = touchEvent(item)
332 event.release(0 /* touchId */, rootPoint.x, rootPoint.y)
336 /*! \brief Tap the item with a touch event.
338 \param item The item to be tapped
339 \param x The x coordinate of the tap, defaults to horizontal center
340 \param y The y coordinate of the tap, defaults to vertical center
342 function tap(item, x, y) {
343 if (typeof x !== "number") x = item.width / 2;
344 if (typeof y !== "number") y = item.height / 2;
346 var root = fetchRootItem(item)
347 var rootPoint = item.mapToItem(root, x, y)
349 var event = touchEvent(item)
350 event.press(0 /* touchId */, rootPoint.x, rootPoint.y)
353 event = touchEvent(item)
354 event.release(0 /* touchId */, rootPoint.x, rootPoint.y)
358 Component.onCompleted: {
359 UT.Util.ensureTouchRegistryInstalled();
361 var rootItem = parent;
362 while (rootItem.parent != undefined) {
363 rootItem = rootItem.parent;
365 removeTimeConstraintsFromDirectionalDragAreas(rootItem);
369 In qmltests, sequences of touch events are sent all at once, unlike in "real life".
370 Also qmltests might run really slowly, e.g. when run from inside virtual machines.
371 Thus to remove a variable that qmltests cannot really control, namely time, this
372 function removes all constraints from DirectionalDragAreas that are sensible to
375 This effectively makes DirectionalDragAreas easier to fool.
377 function removeTimeConstraintsFromDirectionalDragAreas(item) {
379 // use duck-typing to identify a DirectionalDragArea
380 if (item.minSpeed != undefined
381 && item.maxSilenceTime != undefined
382 && item.compositionTime != undefined) {
384 item.maxSilenceTime = 60 * 60 * 1000;
385 item.compositionTime = 0;
387 for (var i in item.children) {
388 removeTimeConstraintsFromDirectionalDragAreas(item.children[i]);
393 // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature
394 function waitForRendering(item, timeout) {
395 if (timeout === undefined)
398 qtest_fail("No item given to waitForRendering", 1);
399 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