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 function mouseClick(item, x, y, button, modifiers, delay) {
41 if (button === undefined)
42 button = Qt.LeftButton;
43 if (modifiers === undefined)
44 modifiers = Qt.NoModifier;
45 if (delay === undefined)
51 if (!qtest_events.mouseClick(item, x, y, button, modifiers, delay))
52 qtest_fail("window not shown", 2);
55 function mouseDoubleClick(item, x, y, button, modifiers, delay) {
56 if (button === undefined)
57 button = Qt.LeftButton;
58 if (modifiers === undefined)
59 modifiers = Qt.NoModifier;
60 if (delay === undefined)
66 if (!qtest_events.mouseDoubleClick(item, x, y, button, modifiers, delay))
67 qtest_fail("window not shown", 2)
70 function mousePress(item, x, y, button, modifiers, delay) {
71 if (button === undefined)
72 button = Qt.LeftButton;
73 if (modifiers === undefined)
74 modifiers = Qt.NoModifier;
75 if (delay === undefined)
81 if (!qtest_events.mousePress(item, x, y, button, modifiers, delay))
82 qtest_fail("window not shown", 2)
85 function mouseRelease(item, x, y, button, modifiers, delay) {
86 if (button === undefined)
87 button = Qt.LeftButton;
88 if (modifiers === undefined)
89 modifiers = Qt.NoModifier;
90 if (delay === undefined)
96 if (!qtest_events.mouseRelease(item, x, y, button, modifiers, delay))
97 qtest_fail("window not shown", 2)
101 // Flickable won't recognise a single mouse move as dragging the flickable.
102 // Use 5 steps because it's what
103 // Qt uses in QQuickViewTestUtil::flick
104 // speed is in pixels/second
105 function mouseFlick(item, x, y, toX, toY, pressMouse, releaseMouse,
107 pressMouse = ((pressMouse != null) ? pressMouse : true); // Default to true for pressMouse if not present
108 releaseMouse = ((releaseMouse != null) ? releaseMouse : true); // Default to true for releaseMouse if not present
110 // set a default speed if not specified
111 speed = (speed != null) ? speed : units.gu(10);
113 // set a default iterations if not specified
114 iterations = (iterations !== undefined) ? iterations : 5
116 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
117 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
119 var timeStep = totalTime / iterations
120 var diffX = (toX - x) / iterations
121 var diffY = (toY - y) / iterations
123 fakeDateTime.currentTimeMs += timeStep
124 mousePress(item, x, y)
126 for (var i = 0; i < iterations; ++i) {
127 fakeDateTime.currentTimeMs += timeStep
128 if (i === iterations - 1) {
129 // Avoid any rounding errors by making the last move be at precisely
130 // the point specified
131 mouseMove(item, toX, toY, iterations / speed)
133 mouseMove(item, x + (i + 1) * diffX, y + (i + 1) * diffY, iterations / speed)
137 fakeDateTime.currentTimeMs += timeStep
138 mouseRelease(item, toX, toY)
143 // Find an object with the given name in the children tree of "obj"
144 function findChild(obj, objectName) {
145 return findChildIn(obj, "children", objectName);
148 // Find an object with the given name in the children tree of "obj"
149 // Including invisible children like animations, timers etc.
150 // Note: you should use findChild if you're not sure you need this
151 // as this tree is much bigger and might contain stuff that goes
153 function findInvisibleChild(obj, objectName) {
154 return findChildIn(obj, "data", objectName);
157 // Find a child in the named property
158 function findChildIn(obj, prop, objectName) {
159 var childs = new Array(0);
161 while (childs.length > 0) {
162 if (childs[0].objectName == objectName) {
165 for (var i in childs[0][prop]) {
166 childs.push(childs[0][prop][i])
173 // Type a full string instead of keyClick letter by letter
174 // TODO: this is not ugly, this is uber-ugly and does not support
175 // any special character. Remove the keyMap once keyClick(obj, char)
176 // has landed in upstream Qt.
177 function typeString(str) {
243 for (var i = 0; i < str.length; i++) {
244 keyClick(keyMap[str[i]])
248 // Keeps executing a given parameter-less function until it returns the given
249 // expected result or the timemout is reached (in which case a test failure
251 function tryCompareFunction(func, expectedResult, timeout) {
253 if (timeout === undefined)
257 while (timeSpent < timeout && !success) {
258 actualResult = func()
259 success = qtest_compareInternal(actualResult, expectedResult)
260 if (success === false) {
266 var act = qtest_results.stringify(actualResult)
267 var exp = qtest_results.stringify(expectedResult)
268 if (!qtest_results.compare(success,
269 "function returned unexpected result",
271 util.callerFile(), util.callerLine())) {
272 throw new Error("QtQuickTest::fail")
276 function touchEvent() {
277 return UT.Util.touchEvent()
280 // speed is in pixels/second
281 function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed, iterations) {
282 // Make sure the item is rendered
283 waitForRendering(item);
285 var root = fetchRootItem(item);
286 var rootFrom = item.mapToItem(root, x, y);
287 var rootTo = item.mapToItem(root, toX, toY);
289 // Default to true for beginTouch if not present
290 beginTouch = (beginTouch !== undefined) ? beginTouch : true
292 // Default to true for endTouch if not present
293 endTouch = (endTouch !== undefined) ? endTouch : true
295 // Set a default speed if not specified
296 speed = (speed !== undefined) ? speed : units.gu(10)
298 // Set a default iterations if not specified
299 var iterations = (iterations !== undefined) ? iterations : 5
301 var distance = Math.sqrt(Math.pow(rootTo.x - rootFrom.x, 2) + Math.pow(rootTo.Y - rootFrom.y, 2))
302 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
304 var timeStep = totalTime / iterations
305 var diffX = (rootTo.x - rootFrom.x) / iterations
306 var diffY = (rootTo.y - rootFrom.y) / iterations
308 fakeDateTime.currentTimeMs += timeStep
310 var event = touchEvent()
311 event.press(0 /* touchId */, rootFrom.x, rootFrom.y)
314 for (var i = 0; i < iterations; ++i) {
315 fakeDateTime.currentTimeMs += timeStep
316 if (i === iterations - 1) {
317 // Avoid any rounding errors by making the last move be at precisely
318 // the point specified
319 wait(iterations / speed)
320 var event = touchEvent()
321 event.move(0 /* touchId */, rootTo.x, rootTo.y)
324 wait(iterations / speed)
325 var event = touchEvent()
326 event.move(0 /* touchId */, rootFrom.x + (i + 1) * diffX, rootFrom.y + (i + 1) * diffY)
331 fakeDateTime.currentTimeMs += timeStep
332 var event = touchEvent()
333 event.release(0 /* touchId */, rootTo.x, rootTo.y)
338 function touchPinch(item, x1Start, y1Start, x1End, y1End, x2Start, y2Start, x2End, y2End) {
339 // Make sure the item is rendered
340 waitForRendering(item);
342 var event1 = touchEvent();
344 event1.press(0, x1Start, y1Start);
347 event1.stationary(0);
348 event1.press(1, x2Start, y2Start);
352 for (var i = 0.0; i < 1.0; i += 0.02) {
353 event1.move(0, x1Start + (x1End - x1Start) * i, y1Start + (y1End - y1Start) * i);
354 event1.move(1, x2Start + (x2End - x2Start) * i, y2Start + (y2End - y2Start) * i);
359 event1.release(0, x1End, y1End);
360 event1.release(1, x2End, y2End);
364 function fetchRootItem(item) {
366 return fetchRootItem(item.parent)
371 function touchPress(item, x, y) {
372 var root = fetchRootItem(item)
373 var rootPoint = item.mapToItem(root, x, y)
375 var event = touchEvent()
376 event.press(0 /* touchId */, rootPoint.x, rootPoint.y)
380 function touchRelease(item, x, y) {
381 var root = fetchRootItem(item)
382 var rootPoint = item.mapToItem(root, x, y)
384 var event = touchEvent()
385 event.release(0 /* touchId */, rootPoint.x, rootPoint.y)
389 /*! \brief Tap the item with a touch event.
391 \param item The item to be tapped
392 \param x The x coordinate of the tap, defaults to horizontal center
393 \param y The y coordinate of the tap, defaults to vertical center
395 function tap(item, x, y) {
396 if (typeof x !== "number") x = item.width / 2;
397 if (typeof y !== "number") y = item.height / 2;
399 var root = fetchRootItem(item)
400 var rootPoint = item.mapToItem(root, x, y)
402 var event = touchEvent()
403 event.press(0 /* touchId */, rootPoint.x, rootPoint.y)
407 event.release(0 /* touchId */, rootPoint.x, rootPoint.y)
411 Component.onCompleted: {
412 UT.Util.ensureTouchRegistryInstalled();
414 var rootItem = parent;
415 while (rootItem.parent != undefined) {
416 rootItem = rootItem.parent;
418 removeTimeConstraintsFromDirectionalDragAreas(rootItem);
422 In qmltests, sequences of touch events are sent all at once, unlike in "real life".
423 Also qmltests might run really slowly, e.g. when run from inside virtual machines.
424 Thus to remove a variable that qmltests cannot really control, namely time, this
425 function removes all constraints from DirectionalDragAreas that are sensible to
428 This effectively makes DirectionalDragAreas easier to fool.
430 function removeTimeConstraintsFromDirectionalDragAreas(item) {
432 // use duck-typing to identify a DirectionalDragArea
433 if (item.minSpeed != undefined
434 && item.maxSilenceTime != undefined
435 && item.compositionTime != undefined) {
437 item.maxSilenceTime = 60 * 60 * 1000;
438 item.compositionTime = 0;
440 for (var i in item.children) {
441 removeTimeConstraintsFromDirectionalDragAreas(item.children[i]);
446 // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature
447 function waitForRendering(item, timeout) {
448 if (timeout === undefined)
451 qtest_fail("No item given to waitForRendering", 1);
452 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