2 * Copyright 2013-2016 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 Unity.Application 0.1
20import Ubuntu.Components 1.3
21import Ubuntu.Test 1.0 as UbuntuTest
22import Unity.Test 0.1 as UT
27 property var util: TestUtil {id:util}
29 // This is needed for waitForRendering calls to return
30 // if the watched element already got rendered
35 parent: testCase.parent
36 border { width: units.dp(1); color: "black" }
39 visible: testCase.running
41 RotationAnimation on rotation {
42 running: rotatingRectangle.visible
45 loops: Animation.Infinite
50 // Fake implementation to be provided to items under test
51 property var fakeDateTime: new function() {
52 this.currentTimeMs = 0
53 this.getCurrentTimeMs = function() {return this.currentTimeMs}
56 // TODO This function can be removed altogether once we use Qt 5.7 which has the same feature
57 function mouseClick(item, x, y, button, modifiers, delay) {
59 qtest_fail("no item given", 1);
61 if (button === undefined)
62 button = Qt.LeftButton;
63 if (modifiers === undefined)
64 modifiers = Qt.NoModifier;
65 if (delay === undefined)
71 if (!qtest_events.mouseClick(item, x, y, button, modifiers, delay))
72 qtest_fail("window not shown", 2);
75 // TODO This function can be removed altogether once we use Qt 5.7 which has the same feature
76 function mouseDoubleClick(item, x, y, button, modifiers, delay) {
78 qtest_fail("no item given", 1);
80 if (button === undefined)
81 button = Qt.LeftButton;
82 if (modifiers === undefined)
83 modifiers = Qt.NoModifier;
84 if (delay === undefined)
90 if (!qtest_events.mouseDoubleClick(item, x, y, button, modifiers, delay))
91 qtest_fail("window not shown", 2)
94 // TODO This function can be removed altogether once we use Qt 5.7 which has the same feature
95 function mousePress(item, x, y, button, modifiers, delay) {
97 qtest_fail("no item given", 1);
99 if (button === undefined)
100 button = Qt.LeftButton;
101 if (modifiers === undefined)
102 modifiers = Qt.NoModifier;
103 if (delay === undefined)
109 if (!qtest_events.mousePress(item, x, y, button, modifiers, delay))
110 qtest_fail("window not shown", 2)
113 // TODO This function can be removed altogether once we use Qt 5.7 which has the same feature
114 function mouseRelease(item, x, y, button, modifiers, delay) {
116 qtest_fail("no item given", 1);
118 if (button === undefined)
119 button = Qt.LeftButton;
120 if (modifiers === undefined)
121 modifiers = Qt.NoModifier;
122 if (delay === undefined)
128 if (!qtest_events.mouseRelease(item, x, y, button, modifiers, delay))
129 qtest_fail("window not shown", 2)
133 // Flickable won't recognise a single mouse move as dragging the flickable.
134 // Use 5 steps because it's what
135 // Qt uses in QQuickViewTestUtil::flick
136 // speed is in pixels/second
137 function mouseFlick(item, x, y, toX, toY, pressMouse, releaseMouse,
140 qtest_fail("no item given", 1);
142 pressMouse = ((pressMouse != null) ? pressMouse : true); // Default to true for pressMouse if not present
143 releaseMouse = ((releaseMouse != null) ? releaseMouse : true); // Default to true for releaseMouse if not present
145 // set a default speed if not specified
146 speed = (speed != null) ? speed : units.gu(10);
148 // set a default iterations if not specified
149 iterations = (iterations !== undefined) ? iterations : 5
151 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
152 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
154 var timeStep = totalTime / iterations
155 var diffX = (toX - x) / iterations
156 var diffY = (toY - y) / iterations
158 fakeDateTime.currentTimeMs += timeStep
159 mousePress(item, x, y)
161 for (var i = 0; i < iterations; ++i) {
162 fakeDateTime.currentTimeMs += timeStep
163 if (i === iterations - 1) {
164 // Avoid any rounding errors by making the last move be at precisely
165 // the point specified
166 mouseMove(item, toX, toY, iterations / speed)
168 mouseMove(item, x + (i + 1) * diffX, y + (i + 1) * diffY, iterations / speed)
172 fakeDateTime.currentTimeMs += timeStep
173 mouseRelease(item, toX, toY)
178 // Find an object with the given name in the children tree of "obj"
179 function findChild(obj, objectName) {
181 qtest_fail("no obj given", 1);
183 return findChildIn(obj, "children", objectName);
186 // Find an object with the given name in the children tree of "obj"
187 // Including invisible children like animations, timers etc.
188 // Note: you should use findChild if you're not sure you need this
189 // as this tree is much bigger and might contain stuff that goes
191 function findInvisibleChild(obj, objectName) {
193 qtest_fail("no obj given", 1);
195 return findChildIn(obj, "data", objectName);
198 // Find a child in the named property
199 function findChildIn(obj, prop, objectName) {
201 qtest_fail("no obj given", 1);
203 var childs = new Array(0);
205 while (childs.length > 0) {
206 if (childs[0].objectName == objectName) {
209 for (var i in childs[0][prop]) {
210 childs.push(childs[0][prop][i])
217 function findChildsByType(obj, typeName) {
219 qtest_fail("no obj given", 1);
221 var res = new Array(0);
222 for (var i in obj.children) {
223 var c = obj.children[i];
224 if (UT.Util.isInstanceOf(c, typeName)) {
227 res = res.concat(findChildsByType(c, typeName));
232 // Type a full string instead of keyClick letter by letter
233 function typeString(str) {
234 for (var i = 0; i < str.length; i++) {
239 // Keeps executing a given parameter-less function until it returns the given
240 // expected result or the timemout is reached (in which case a test failure
242 function tryCompareFunction(func, expectedResult, timeout) {
244 if (timeout === undefined)
248 while (timeSpent < timeout && !success) {
249 actualResult = func()
250 success = qtest_compareInternal(actualResult, expectedResult)
251 if (success === false) {
257 var act = qtest_results.stringify(actualResult)
258 var exp = qtest_results.stringify(expectedResult)
259 if (!qtest_results.compare(success,
260 "function returned unexpected result",
262 util.callerFile(), util.callerLine())) {
263 throw new Error("QtQuickTest::fail")
267 function flickToYEnd(item) {
269 qtest_fail("no item given", 1);
272 var x = item.width / 2;
273 var y = item.height - units.gu(1);
274 var toY = units.gu(1);
275 var maxIterations = 5 + item.contentHeight / item.height;
276 while (i < maxIterations && !item.atYEnd) {
277 touchFlick(item, x, y, x, toY);
278 tryCompare(item, "moving", false);
281 tryCompare(item, "atYEnd", true);
284 function touchEvent(item) {
285 return UT.Util.touchEvent(item)
288 // speed is in pixels/second
289 function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed, iterations) {
291 qtest_fail("no item given", 1);
293 // Make sure the item is rendered
294 waitForRendering(item);
296 var root = fetchRootItem(item);
297 var rootFrom = item.mapToItem(root, x, y);
298 var rootTo = item.mapToItem(root, toX, toY);
300 // Default to true for beginTouch if not present
301 beginTouch = (beginTouch !== undefined) ? beginTouch : true
303 // Default to true for endTouch if not present
304 endTouch = (endTouch !== undefined) ? endTouch : true
306 // Set a default speed if not specified
307 speed = (speed !== undefined) ? speed : units.gu(10)
309 // Set a default iterations if not specified
310 var iterations = (iterations !== undefined) ? iterations : 10
312 var distance = Math.sqrt(Math.pow(rootTo.x - rootFrom.x, 2) + Math.pow(rootTo.Y - rootFrom.y, 2))
313 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
315 var timeStep = totalTime / iterations
316 var diffX = (rootTo.x - rootFrom.x) / iterations
317 var diffY = (rootTo.y - rootFrom.y) / iterations
319 fakeDateTime.currentTimeMs += timeStep
321 var event = touchEvent(item)
322 event.press(0 /* touchId */, rootFrom.x, rootFrom.y)
325 for (var i = 0; i < iterations; ++i) {
326 fakeDateTime.currentTimeMs += timeStep
327 if (i === iterations - 1) {
328 // Avoid any rounding errors by making the last move be at precisely
329 // the point specified
330 wait(iterations / speed)
331 var event = touchEvent(item)
332 event.move(0 /* touchId */, rootTo.x, rootTo.y)
335 wait(iterations / speed)
336 var event = touchEvent(item)
337 event.move(0 /* touchId */, rootFrom.x + (i + 1) * diffX, rootFrom.y + (i + 1) * diffY)
342 fakeDateTime.currentTimeMs += timeStep
343 var event = touchEvent(item)
344 event.release(0 /* touchId */, rootTo.x, rootTo.y)
349 // perform a drag in the given direction until the given condition is true
350 // The condition is a function to be evaluated after every step
351 function touchDragUntil(item, startX, startY, stepX, stepY, condition) {
353 qtest_fail("no item given", 1);
355 multiTouchDragUntil([0], item, startX, startY, stepX, stepY, condition);
358 function multiTouchDragUntil(touchIds, item, startX, startY, stepX, stepY, condition) {
360 qtest_fail("no item given", 1);
362 var root = fetchRootItem(item);
363 var pos = item.mapToItem(root, startX, startY);
365 // convert step to scene coords
367 var stepStart = item.mapToItem(root, 0, 0);
368 var stepEnd = item.mapToItem(root, stepX, stepY);
370 stepX = stepEnd.x - stepStart.x;
371 stepY = stepEnd.y - stepStart.y;
373 var event = touchEvent(item)
374 for (var i = 0; i < touchIds.length; i++) {
375 event.press(touchIds[i], pos.x, pos.y)
379 // we have to stop at some point
383 while (!condition() && stepsDone < maxSteps) {
385 fakeDateTime.currentTimeMs += 25;
390 event = touchEvent(item);
391 for (i = 0; i < touchIds.length; i++) {
392 event.move(touchIds[i], pos.x, pos.y);
399 event = touchEvent(item)
400 for (i = 0; i < touchIds.length; i++) {
401 event.release(touchIds[i], pos.x, pos.y)
406 function touchMove(item, tox, toy) {
408 qtest_fail("no item given", 1);
410 multiTouchMove(0, item, tox, toy);
413 function multiTouchMove(touchId, item, tox, toy) {
415 qtest_fail("no item given", 1);
417 if (typeof touchId !== "number") touchId = 0;
418 var root = fetchRootItem(item)
419 var rootPoint = item.mapToItem(root, tox, toy)
421 var event = touchEvent(item);
422 event.move(touchId, rootPoint.x, rootPoint.y);
426 function touchPinch(item, x1Start, y1Start, x1End, y1End, x2Start, y2Start, x2End, y2End) {
428 qtest_fail("no item given", 1);
430 // Make sure the item is rendered
431 waitForRendering(item);
433 var event1 = touchEvent(item);
435 event1.press(0, x1Start, y1Start);
438 event1.move(0, x1Start, y1Start);
439 event1.press(1, x2Start, y2Start);
443 for (var i = 0.0; i < 1.0; i += 0.02) {
444 event1.move(0, x1Start + (x1End - x1Start) * i, y1Start + (y1End - y1Start) * i);
445 event1.move(1, x2Start + (x2End - x2Start) * i, y2Start + (y2End - y2Start) * i);
450 event1.release(0, x1End, y1End);
451 event1.release(1, x2End, y2End);
455 function fetchRootItem(item) {
457 qtest_fail("no item given", 1);
460 return fetchRootItem(item.parent)
465 function touchPress(item, x, y) {
467 qtest_fail("no item given", 1);
469 multiTouchPress(0, item, x, y, []);
472 /*! \brief Release a touch point
474 \param touchId The touchId to be pressed
476 \param x The x coordinate of the press, defaults to horizontal center
477 \param y The y coordinate of the press, defaults to vertical center
478 \param stationaryPoints An array of touchIds which are "already touched"
480 function multiTouchPress(touchId, item, x, y, stationaryPoints) {
482 qtest_fail("no item given", 1);
484 if (typeof touchId !== "number") touchId = 0;
485 if (typeof x !== "number") x = item.width / 2;
486 if (typeof y !== "number") y = item.height / 2;
487 if (typeof stationaryPoints !== "object") stationaryPoints = []
488 var root = fetchRootItem(item)
489 var rootPoint = item.mapToItem(root, x, y)
491 var event = touchEvent(item)
492 event.press(touchId, rootPoint.x, rootPoint.y)
493 for (var i = 0; i < stationaryPoints.length; i++) {
494 event.stationary(stationaryPoints[i]);
499 function touchRelease(item, x, y) {
501 qtest_fail("no item given", 1);
503 multiTouchRelease(0, item, x, y, []);
506 /*! \brief Release a touch point
508 \param touchId The touchId to be released
510 \param x The x coordinate of the release, defaults to horizontal center
511 \param y The y coordinate of the release, defaults to vertical center
512 \param stationaryPoints An array of touchIds which are "still touched"
514 function multiTouchRelease(touchId, item, x, y, stationaryPoints) {
516 qtest_fail("no item given", 1);
518 if (typeof touchId !== "number") touchId = 0;
519 if (typeof x !== "number") x = item.width / 2;
520 if (typeof y !== "number") y = item.height / 2;
521 if (typeof stationaryPoints !== "object") stationaryPoints = []
522 var root = fetchRootItem(item)
523 var rootPoint = item.mapToItem(root, x, y)
525 var event = touchEvent(item)
526 event.release(touchId, rootPoint.x, rootPoint.y)
527 for (var i = 0; i < stationaryPoints.length; i++) {
528 event.stationary(stationaryPoints[i]);
533 /*! \brief Tap the item with a touch event.
535 \param item The item to be tapped
536 \param x The x coordinate of the tap, defaults to horizontal center
537 \param y The y coordinate of the tap, defaults to vertical center
539 function tap(item, x, y) {
541 qtest_fail("no item given", 1);
543 multiTouchTap([0], item, x, y);
546 function multiTouchTap(touchIds, item, x, y) {
548 qtest_fail("no item given", 1);
550 if (typeof touchIds !== "object") touchIds = [0];
551 if (typeof x !== "number") x = item.width / 2;
552 if (typeof y !== "number") y = item.height / 2;
554 var root = fetchRootItem(item)
555 var rootPoint = item.mapToItem(root, x, y)
557 var event = touchEvent(item)
558 for (var i = 0; i < touchIds.length; i++) {
559 event.press(touchIds[i], rootPoint.x, rootPoint.y)
563 event = touchEvent(item)
564 for (i = 0; i < touchIds.length; i++) {
565 event.release(touchIds[i], rootPoint.x, rootPoint.y)
571 Component.onCompleted: {
572 var rootItem = parent;
573 while (rootItem.parent != undefined) {
574 rootItem = rootItem.parent;
576 removeTimeConstraintsFromSwipeAreas(rootItem);
580 In qmltests, sequences of touch events are sent all at once, unlike in "real life".
581 Also qmltests might run really slowly, e.g. when run from inside virtual machines.
582 Thus to remove a variable that qmltests cannot really control, namely time, this
583 function removes all constraints from SwipeAreas that are sensible to
586 This effectively makes SwipeAreas easier to fool.
588 function removeTimeConstraintsFromSwipeAreas(item) {
590 qtest_fail("no item given", 1);
592 if (UT.Util.isInstanceOf(item, "UCSwipeArea")) {
593 UbuntuTest.TestExtras.removeTimeConstraintsFromSwipeArea(item);
595 for (var i in item.children) {
596 removeTimeConstraintsFromSwipeAreas(item.children[i]);
601 // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature
602 function waitForRendering(item, timeout) {
603 if (timeout === undefined)
606 qtest_fail("No item given to waitForRendering", 1);
607 return qtest_results.waitForRendering(item, timeout);
611 Wait until any transition animation has finished for the given StateGroup or Item
613 function waitUntilTransitionsEnd(stateGroup) {
614 var transitions = stateGroup.transitions;
615 for (var i = 0; i < transitions.length; ++i) {
616 var transition = transitions[i];
617 tryCompare(transition, "running", false, 2000);
622 kill all (fake) running apps but unity8-dash, bringing Unity.Application back to its initial state
624 function killApps() {
625 while (ApplicationManager.count > 1) {
626 var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
627 var application = ApplicationManager.get(appIndex);
628 ApplicationManager.stopApplication(application.appId);
629 // wait until all zombie surfaces are gone. As MirSurfaceItems hold references over them.
630 // They won't be gone until those surface items are destroyed.
631 tryCompareFunction(function() { return application.surfaceList.count }, 0);
632 tryCompare(application, "state", ApplicationInfo.Stopped);
634 compare(ApplicationManager.count, 1);
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