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 function findChildsByType(obj, typeName) {
174 var res = new Array(0);
175 for (var i in obj.children) {
176 var c = obj.children[i];
177 if (UT.Util.isInstanceOf(c, typeName)) {
180 res = res.concat(findChildsByType(c, typeName));
185 // Type a full string instead of keyClick letter by letter
186 // TODO: this is not ugly, this is uber-ugly and does not support
187 // any special character. Remove the keyMap once keyClick(obj, char)
188 // has landed in upstream Qt.
189 function typeString(str) {
255 for (var i = 0; i < str.length; i++) {
256 keyClick(keyMap[str[i]])
260 // Keeps executing a given parameter-less function until it returns the given
261 // expected result or the timemout is reached (in which case a test failure
263 function tryCompareFunction(func, expectedResult, timeout) {
265 if (timeout === undefined)
269 while (timeSpent < timeout && !success) {
270 actualResult = func()
271 success = qtest_compareInternal(actualResult, expectedResult)
272 if (success === false) {
278 var act = qtest_results.stringify(actualResult)
279 var exp = qtest_results.stringify(expectedResult)
280 if (!qtest_results.compare(success,
281 "function returned unexpected result",
283 util.callerFile(), util.callerLine())) {
284 throw new Error("QtQuickTest::fail")
288 function touchEvent() {
289 return UT.Util.touchEvent()
292 // speed is in pixels/second
293 function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed, iterations) {
294 // Make sure the item is rendered
295 waitForRendering(item);
297 var root = fetchRootItem(item);
298 var rootFrom = item.mapToItem(root, x, y);
299 var rootTo = item.mapToItem(root, toX, toY);
301 // Default to true for beginTouch if not present
302 beginTouch = (beginTouch !== undefined) ? beginTouch : true
304 // Default to true for endTouch if not present
305 endTouch = (endTouch !== undefined) ? endTouch : true
307 // Set a default speed if not specified
308 speed = (speed !== undefined) ? speed : units.gu(10)
310 // Set a default iterations if not specified
311 var iterations = (iterations !== undefined) ? iterations : 5
313 var distance = Math.sqrt(Math.pow(rootTo.x - rootFrom.x, 2) + Math.pow(rootTo.Y - rootFrom.y, 2))
314 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
316 var timeStep = totalTime / iterations
317 var diffX = (rootTo.x - rootFrom.x) / iterations
318 var diffY = (rootTo.y - rootFrom.y) / iterations
320 fakeDateTime.currentTimeMs += timeStep
322 var event = touchEvent()
323 event.press(0 /* touchId */, rootFrom.x, rootFrom.y)
326 for (var i = 0; i < iterations; ++i) {
327 fakeDateTime.currentTimeMs += timeStep
328 if (i === iterations - 1) {
329 // Avoid any rounding errors by making the last move be at precisely
330 // the point specified
331 wait(iterations / speed)
332 var event = touchEvent()
333 event.move(0 /* touchId */, rootTo.x, rootTo.y)
336 wait(iterations / speed)
337 var event = touchEvent()
338 event.move(0 /* touchId */, rootFrom.x + (i + 1) * diffX, rootFrom.y + (i + 1) * diffY)
343 fakeDateTime.currentTimeMs += timeStep
344 var event = touchEvent()
345 event.release(0 /* touchId */, rootTo.x, rootTo.y)
350 function touchPinch(item, x1Start, y1Start, x1End, y1End, x2Start, y2Start, x2End, y2End) {
351 // Make sure the item is rendered
352 waitForRendering(item);
354 var event1 = touchEvent();
356 event1.press(0, x1Start, y1Start);
359 event1.stationary(0);
360 event1.press(1, x2Start, y2Start);
364 for (var i = 0.0; i < 1.0; i += 0.02) {
365 event1.move(0, x1Start + (x1End - x1Start) * i, y1Start + (y1End - y1Start) * i);
366 event1.move(1, x2Start + (x2End - x2Start) * i, y2Start + (y2End - y2Start) * i);
371 event1.release(0, x1End, y1End);
372 event1.release(1, x2End, y2End);
376 function fetchRootItem(item) {
378 return fetchRootItem(item.parent)
383 function touchPress(item, x, y) {
384 var root = fetchRootItem(item)
385 var rootPoint = item.mapToItem(root, x, y)
387 var event = touchEvent()
388 event.press(0 /* touchId */, rootPoint.x, rootPoint.y)
392 function touchRelease(item, x, y) {
393 var root = fetchRootItem(item)
394 var rootPoint = item.mapToItem(root, x, y)
396 var event = touchEvent()
397 event.release(0 /* touchId */, rootPoint.x, rootPoint.y)
401 /*! \brief Tap the item with a touch event.
403 \param item The item to be tapped
404 \param x The x coordinate of the tap, defaults to horizontal center
405 \param y The y coordinate of the tap, defaults to vertical center
407 function tap(item, x, y) {
408 if (typeof x !== "number") x = item.width / 2;
409 if (typeof y !== "number") y = item.height / 2;
411 var root = fetchRootItem(item)
412 var rootPoint = item.mapToItem(root, x, y)
414 var event = touchEvent()
415 event.press(0 /* touchId */, rootPoint.x, rootPoint.y)
419 event.release(0 /* touchId */, rootPoint.x, rootPoint.y)
423 Component.onCompleted: {
424 UT.Util.ensureTouchRegistryInstalled();
426 var rootItem = parent;
427 while (rootItem.parent != undefined) {
428 rootItem = rootItem.parent;
430 removeTimeConstraintsFromDirectionalDragAreas(rootItem);
434 In qmltests, sequences of touch events are sent all at once, unlike in "real life".
435 Also qmltests might run really slowly, e.g. when run from inside virtual machines.
436 Thus to remove a variable that qmltests cannot really control, namely time, this
437 function removes all constraints from DirectionalDragAreas that are sensible to
440 This effectively makes DirectionalDragAreas easier to fool.
442 function removeTimeConstraintsFromDirectionalDragAreas(item) {
444 // use duck-typing to identify a DirectionalDragArea
445 if (item.minSpeed != undefined
446 && item.maxSilenceTime != undefined
447 && item.compositionTime != undefined) {
449 item.maxSilenceTime = 60 * 60 * 1000;
450 item.compositionTime = 0;
452 for (var i in item.children) {
453 removeTimeConstraintsFromDirectionalDragAreas(item.children[i]);
458 // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature
459 function waitForRendering(item, timeout) {
460 if (timeout === undefined)
463 qtest_fail("No item given to waitForRendering", 1);
464 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