on xenial help sign in
Squash race conditions everywhere

I searched the entire codebase for compare() entries and evaluated all of them for how appropriate they are compared to tryCompare() or another alternative. I found that there were many cases where compare() depended on delays that came before it to get the correct value, causing race conditions that we haven't even hit yet. In a proactive measure, this commit: * Replaces compare() with tryCompare() where appropriate * Replaces tryCompareFunction() with tryVerify() where appropriate * Uses SignalSpy.wait() where appropriate * Generally lints and pays back technical debt when I found the opportunity

commit2d12d493543fe284a626b40f72775d59dec29c4c authorDalton Durst <dalton@ubports.com> dateMon 27 May 2019, 15:22 (7 years ago) parenta9ffaee
25 files changed+217−238
tests/qmltests/Components/tst_DraggingArea.qml+6−6 tests/qmltests/Components/tst_Lockscreen.qml+6−6 tests/qmltests/Components/tst_MediaServices.qml+5−4 tests/qmltests/Components/tst_Rating.qml+1−1 tests/qmltests/Components/tst_SharingPicker.qml+3−3 tests/qmltests/Greeter/tst_Greeter.qml+19−18 tests/qmltests/Greeter/tst_NarrowView.qml+2−2 tests/qmltests/Notifications/tst_Notifications.qml+12−7 tests/qmltests/Notifications/tst_OptionToggle.qml+12−6 tests/qmltests/Notifications/tst_SwipeToAct.qml+6−2 tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+3−3 tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml+33−79 tests/qmltests/Panel/tst_ActiveCallHint.qml+8−6 tests/qmltests/Panel/tst_MenuContent.qml+2−2 tests/qmltests/Panel/tst_Panel.qml+25−22 tests/qmltests/Panel/tst_PanelItemRow.qml+2−2 tests/qmltests/Panel/tst_PanelMenu.qml+1−1 tests/qmltests/Stage/tst_DesktopStage.qml+3−3 tests/qmltests/Stage/tst_PhoneStage.qml+9−9 tests/qmltests/Stage/tst_SurfaceContainer.qml+7−7 tests/qmltests/Stage/tst_WindowDecoration.qml+3−3 tests/qmltests/Stage/tst_WindowResizeArea.qml+2−2 tests/qmltests/Wizard/tst_Wizard.qml+8−10 tests/qmltests/tst_OrientedShell.qml+4−5 tests/qmltests/tst_Shell.qml+35−29
tests/qmltests/Components/tst_DraggingArea.qml+6−6
@@ -129,8 +129,8 @@ Item {
129129 -100, 25,
130130 0, Qt.LeftButton);
131131
132− compare(draggingArea.dragging, true);
133− compare(draggingArea.dragValue, -125);
132+ tryCompare(draggingArea, "dragging", true);
133+ tryCompare(draggingArea, "dragValue", -125);
134134 compare(dragStartCount, 1);
135135 compare(dragEndCount, 0);
136136
@@ -139,7 +139,7 @@ Item {
139139 -100, 25,
140140 Qt.LeftButton, Qt.NoModifier, 0);
141141
142− compare(draggingArea.dragging, false);
142+ tryCompare(draggingArea, "dragging", false);
143143 compare(dragStartCount, 1);
144144 compare(dragEndCount, 1);
145145 }
@@ -166,8 +166,8 @@ Item {
166166 25, 125,
167167 0, Qt.LeftButton);
168168
169− compare(draggingArea.dragging, true);
170− compare(draggingArea.dragValue, 100);
169+ tryCompare(draggingArea, "dragging", true);
170+ tryCompare(draggingArea, "dragValue", 100);
171171 compare(dragStartCount, 1);
172172 compare(dragEndCount, 0);
173173
@@ -176,7 +176,7 @@ Item {
176176 25, 125,
177177 Qt.LeftButton, Qt.NoModifier, 0);
178178
179− compare(draggingArea.dragging, false);
179+ tryCompare(draggingArea, "dragging", false);
180180 compare(dragStartCount, 1);
181181 compare(dragEndCount, 1);
182182 }
tests/qmltests/Components/tst_Lockscreen.qml+6−6
@@ -184,10 +184,11 @@ Rectangle {
184184 function test_loading(data) {
185185 pinPadCheckBox.checked = data.alphanumeric
186186 waitForLockscreenReady();
187+ var button8 = findChild(lockscreen, "pinPadButton8");
187188 if (data.pinPadAvailable) {
188− compare(findChild(lockscreen, "pinPadButton8").text, "8", "Could not find number 8 on PinPad")
189+ compare(button8.text, "8", "Could not find number 8 on PinPad");
189190 } else {
190− compare(findChild(lockscreen, "pinPadButton8"), null, "Could find number 8 on PinPad even though it should be only OSK")
191+ compare(button8, null, "Could find number 8 on PinPad even though it should be only OSK");
191192 }
192193 }
193194
@@ -292,8 +293,7 @@ Rectangle {
292293 lockscreen.clear(data.animation)
293294 tryCompare(inputField, "text", "")
294295
295− wait(0) // Trigger event loop to make sure the animation would start running
296− compare(animation.running, data.animation)
296+ tryCompare(animation, "running", data.animation)
297297 if (data.animation) {
298298 if (!data.alphanumeric) {
299299 var label = findChild(lockscreen, "wrongNoticeLabel");
@@ -326,12 +326,12 @@ Rectangle {
326326
327327 var pinPadButton5 = findChild(lockscreen, "pinPadButton5");
328328 mouseClick(pinPadButton5, units.gu(1), units.gu(1));
329− compare(pinEntryField.text, "5");
329+ tryCompare(pinEntryField, "text", "5");
330330
331331 tryCompare(backspaceIcon, "opacity", 1);
332332
333333 mouseClick(backspaceIcon, units.gu(1), units.gu(1));
334− compare(pinEntryField.text, "");
334+ tryCompare(pinEntryField, "text", "");
335335
336336 tryCompare(backspaceIcon, "opacity", 0);
337337 }
tests/qmltests/Components/tst_MediaServices.qml+5−4
@@ -151,10 +151,10 @@ Rectangle {
151151
152152 var mediaPlayer = findInvisibleChild(services, "mediaPlayer");
153153 verify(mediaPlayer !== null);
154− compare(mediaPlayer.playbackState, MediaPlayer.PlayingState, "Media player should be playing");
154+ tryCompare(mediaPlayer, "playbackState", MediaPlayer.PlayingState, 5000, "Media player should be playing");
155155
156156 tap(videoPlayer, videoPlayer.width/2, videoPlayer.height/2);
157− compare(mediaPlayer.playbackState, MediaPlayer.PausedState, "Media player should be playing");
157+ tryCompare(mediaPlayer, "playbackState", MediaPlayer.PausedState, 5000, "Media player should be paused");
158158 }
159159
160160 function test_fullscreenSwitch() {
@@ -167,7 +167,7 @@ Rectangle {
167167 verify(button !== null);
168168 tap(button);
169169
170− compare(services.fullscreen, true, "Should have switched to fullscreen mode.");
170+ tryCompare(services, "fullscreen", true, 5000, "Should have switched to fullscreen mode.");
171171 }
172172
173173 function test_HeaderVisibleOnlyWhenFullscreen() {
@@ -200,6 +200,7 @@ Rectangle {
200200 var mediaPlayer = findInvisibleChild(services, "mediaPlayer");
201201 mediaPlayer.play();
202202 mediaPlayer.pause();
203+ // Purposefully wait for when controls would normally time out
203204 wait(300);
204205
205206 compare(services.header.visible, true, "Header should still be visible");
@@ -217,7 +218,7 @@ Rectangle {
217218 verify(navigationButton !== null);
218219
219220 tap(navigationButton);
220− compare(serviceCloseSpy.count, 1, "close was not called");
221+ serviceCloseSpy.wait();
221222 }
222223
223224 function test_maximumVideoSize() {
tests/qmltests/Components/tst_Rating.qml+1−1
@@ -62,7 +62,7 @@ Rectangle {
6262
6363 var averageIconWidth = rating.width / rating.size;
6464 mouseClick(rating, averageIconWidth * data.index + averageIconWidth / 2, rating.height / 2);
65− compare(rating.value, data.value);
65+ tryCompare(rating, "value", data.value);
6666
6767 rating.interactive = false;
6868 }
tests/qmltests/Components/tst_SharingPicker.qml+3−3
@@ -58,16 +58,16 @@ Rectangle {
5858
5959 function test_open_picker() {
6060 sharingPicker.showPeerPicker();
61− compare(peerPicker.visible, true);
61+ tryCompare(peerPicker, "visible", true);
6262 }
6363
6464 function test_createExportedItems() {
6565 var exportedItems = sharingPicker.createExportedItems(shareData["uri"]);
6666 for (var i = 0; i < exportedItems.length; i++) {
67− compare(exportedItems[i].url, shareData["uri"][i]);
67+ tryCompare(exportedItems[i], "url", shareData["uri"][i]);
6868 }
6969 exportedItems = sharingPicker.createExportedItems(shareDataString["uri"]);
70− compare(exportedItems[0].url, shareDataString["uri"]);
70+ tryCompare(exportedItems[0], "url", shareDataString["uri"]);
7171 }
7272 }
7373}
tests/qmltests/Greeter/tst_Greeter.qml+19−18
@@ -185,7 +185,7 @@ Item {
185185
186186 function verifySelected(name) {
187187 var i = getIndexOf(name);
188− compare(view.currentIndex, i);
188+ tryCompare(view, "currentIndex", i);
189189 compare(AccountsService.user, name);
190190 if (name[0] === "*") // custom rows have no authenticationUser set
191191 compare(LightDM.Greeter.authenticationUser, "");
@@ -284,19 +284,19 @@ Item {
284284 function test_fullyShown() {
285285 compare(greeter.fullyShown, true);
286286 view.hide();
287− compare(greeter.fullyShown, false);
287+ tryCompare(greeter, "fullyShown", false);
288288 }
289289
290290 function test_alphanumeric() {
291291 selectUser("has-password");
292− compare(view.alphanumeric, true);
292+ tryCompare(view, "alphanumeric", true);
293293 selectUser("has-pin");
294− compare(view.alphanumeric, false);
294+ tryCompare(view, "alphanumeric", false);
295295 }
296296
297297 function test_background() {
298298 greeter.background = "testing";
299− compare(view.background, Qt.resolvedUrl("testing"));
299+ tryCompare(view, "background", Qt.resolvedUrl("testing"));
300300 }
301301
302302 function test_hasCustomBackground() {
@@ -307,12 +307,12 @@ Item {
307307
308308 function test_notifyAboutToFocusApp() {
309309 greeter.notifyUserRequestedApp("fake-app");
310− compare(viewTryToUnlockSpy.count, 1);
310+ viewTryToUnlockSpy.wait();
311311 compare(viewTryToUnlockSpy.signalArguments[0][0], false);
312312 }
313313
314314 function test_notifyShowingDashFromDrag() {
315− compare(greeter.notifyShowingDashFromDrag("fake-app"), true);
315+ verify(greeter.notifyShowingDashFromDrag("fake-app"));
316316 compare(viewTryToUnlockSpy.count, 1);
317317 compare(viewTryToUnlockSpy.signalArguments[0][0], true);
318318 }
@@ -456,16 +456,16 @@ Item {
456456 function test_dbusHideGreeter() {
457457 compare(view.required, true);
458458 LightDM.Greeter.hideGreeter();
459− compare(view.required, false);
459+ tryCompare(view, "required", false);
460460 compare(greeter.required, false);
461461 }
462462
463463 function test_dbusShowGreeterFromHiddenState() {
464464 greeter.hide();
465− compare(greeter.required, false);
465+ tryCompare(greeter, "required", false);
466466
467467 LightDM.Greeter.showGreeter();
468− compare(greeter.required, true);
468+ tryCompare(greeter, "required", true);
469469 compare(greeter.fullyShown, true);
470470 view = findChild(greeter, "testView");
471471 compare(view.required, true);
@@ -480,7 +480,7 @@ Item {
480480
481481 compare(viewForceShowSpy.count, 0);
482482 LightDM.Greeter.showGreeter();
483− compare(viewForceShowSpy.count, 1);
483+ viewForceShowSpy.wait();
484484 }
485485
486486 function test_selectUserHint() {
@@ -554,7 +554,7 @@ Item {
554554 verify(biometryd.operation.running);
555555
556556 biometryd.operation.mockSuccess(LightDM.Users.data(index, LightDM.UserRoles.UidRole));
557− compare(viewTryToUnlockSpy.count, 1);
557+ viewTryToUnlockSpy.wait();
558558 verify(greeter.locked);
559559 }
560560
@@ -579,7 +579,7 @@ Item {
579579 verify(biometryd.operation.running);
580580
581581 biometryd.operation.mockFailure("error");
582− compare(viewShowErrorMessageSpy.count, 1);
582+ viewShowErrorMessageSpy.wait();
583583 compare(viewShowErrorMessageSpy.signalArguments[0][0], i18n.tr("Try again"));
584584 }
585585
@@ -593,16 +593,17 @@ Item {
593593 compare(viewTryToUnlockSpy.count, 0);
594594
595595 biometryd.operation.mockFailure("error");
596− compare(viewTryToUnlockSpy.count, 1);
596+ viewTryToUnlockSpy.wait();
597+ viewTryToUnlockSpy.clear();
597598
598599 // Confirm that we are stuck in this mode until next login
599600 biometryd.operation.mockSuccess(LightDM.Users.data(index, LightDM.UserRoles.UidRole));
600− compare(viewTryToUnlockSpy.count, 2);
601+ viewTryToUnlockSpy.wait();
601602
602603 unlockAndShowGreeter();
603604
604605 biometryd.operation.mockSuccess(LightDM.Users.data(index, LightDM.UserRoles.UidRole));
605− verify(!greeter.active);
606+ tryCompare(greeter, "active", false);
606607 }
607608
608609 function test_fingerprintFailureCountReset() {
@@ -620,7 +621,7 @@ Item {
620621 compare(viewTryToUnlockSpy.count, 0);
621622
622623 biometryd.operation.mockFailure("error");
623− compare(viewTryToUnlockSpy.count, 1);
624+ viewTryToUnlockSpy.wait();
624625 }
625626
626627 function test_fingerprintWrongUid() {
@@ -631,7 +632,7 @@ Item {
631632 biometryd.operation.mockSuccess(0);
632633
633634 verify(greeter.active);
634− compare(viewShowErrorMessageSpy.count, 1);
635+ viewShowErrorMessageSpy.wait();
635636 compare(viewShowErrorMessageSpy.signalArguments[0][0], i18n.tr("Try again"));
636637 }
637638
tests/qmltests/Greeter/tst_NarrowView.qml+2−2
@@ -319,7 +319,7 @@ Item {
319319 function test_tease(data) {
320320 view.dragHandleLeftMargin = data.offset;
321321 tap(view, data.x, 0);
322− compare(teaseSpy.count, data.count);
322+ tryCompare(teaseSpy, "count", data.count);
323323 }
324324
325325 function test_customBackground() {
@@ -340,7 +340,7 @@ Item {
340340 view.alphanumeric = false;
341341 swipeAwayCover();
342342 typeString("1234");
343− compare(respondedSpy.count, 1);
343+ respondedSpy.wait();
344344 compare(respondedSpy.signalArguments[0][0], "1234");
345345 }
346346
tests/qmltests/Notifications/tst_Notifications.qml+12−7
@@ -648,7 +648,8 @@ Item {
648648
649649 // only test the left/cancel-button if two actions have been passed in
650650 if (data.n.actions.count === 2) {
651− tryCompareFunction(function() { mouseClick(buttonCancel); return actionSpy.signalArguments.length > 0; }, true);
651+ mouseClick(buttonCancel);
652+ actionSpy.wait();
652653 compare(actionSpy.signalArguments[0][0], data.n.actions.data(1, ActionModel.RoleActionId), "got wrong id for negative action")
653654 actionSpy.clear()
654655 }
@@ -657,7 +658,8 @@ Item {
657658 verify(buttonAccept.color === data.buttonTinted ? "#3fb24f" : "#dddddd", "button has the wrong color-tint")
658659
659660 // click the positive/right button
660− tryCompareFunction(function() { mouseClick(buttonAccept); return actionSpy.signalArguments.length > 0; }, true);
661+ mouseClick(buttonAccept);
662+ actionSpy.wait();
661663 compare(actionSpy.signalArguments[0][0], data.n.actions.data(0, ActionModel.RoleActionId), "got wrong id positive action")
662664 actionSpy.clear()
663665
@@ -671,17 +673,20 @@ Item {
671673
672674 // try clicking on choices in expanded comboList
673675 var choiceButton1 = findChild(notification, "notify_button3")
674− tryCompareFunction(function() { mouseClick(choiceButton1); return actionSpy.signalArguments.length > 0; }, true);
676+ mouseClick(choiceButton1);
677+ actionSpy.wait();
675678 compare(actionSpy.signalArguments[0][0], data.n.actions.data(3, ActionModel.RoleActionId), "got wrong id choice action 1")
676679 actionSpy.clear()
677680
678681 var choiceButton2 = findChild(notification, "notify_button4")
679− tryCompareFunction(function() { mouseClick(choiceButton2); return actionSpy.signalArguments.length > 0; }, true);
682+ mouseClick(choiceButton2);
683+ actionSpy.wait();
680684 compare(actionSpy.signalArguments[0][0], data.n.actions.data(4, ActionModel.RoleActionId), "got wrong id choice action 2")
681685 actionSpy.clear()
682686
683687 // click to collapse
684− tryCompareFunction(function() { mouseClick(comboButton, comboButton.width / 2, comboButton.height / 2); return !comboButton.expanded; }, true);
688+ mouseClick(comboButton);
689+ tryCompare(comboButton, "expanded", false);
685690 } else {
686691 tryCompareFunction(function() { mouseClick(buttonCancel); return actionSpy.signalArguments.length > 0; }, true);
687692 compare(actionSpy.signalArguments[0][0], data.n.actions.data(1, ActionModel.RoleActionId), "got wrong id for negative action");
@@ -816,8 +821,8 @@ Item {
816821 var dragY = notification2.height / 2;
817822 touchFlick(notification2, dragStart, dragY, dragEnd, dragY);
818823 waitForRendering(notifications);
819− tryCompareFunction(function() { return notification1.expanded; }, true);
820− tryCompareFunction(function() { return notification2.expanded; }, undefined);
824+ tryCompare(notification1, "expanded", true);
825+ tryCompare(notification2, "expanded", undefined);
821826 }
822827
823828 function topmostIsFullscreen_data() {
tests/qmltests/Notifications/tst_OptionToggle.qml+12−6
@@ -242,7 +242,8 @@ Row {
242242
243243 // only test the left/cancel-button if two actions have been passed in
244244 if (data.actions.length == 2) {
245− tryCompareFunction(function() { mouseClick(buttonCancel); return actionSpy.signalArguments.length > 0; }, true);
245+ mouseClick(buttonCancel);
246+ actionSpy.wait();
246247 compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
247248 actionSpy.clear()
248249 }
@@ -251,7 +252,8 @@ Row {
251252 verify(buttonAccept.color === data.buttonTinted ? "#3fb24f" : "#dddddd", "button has the wrong color-tint")
252253
253254 // click the positive/right button
254− tryCompareFunction(function() { mouseClick(buttonAccept); return actionSpy.signalArguments.length > 0; }, true);
255+ mouseClick(buttonAccept);
256+ actionSpy.wait();
255257 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id positive action")
256258 actionSpy.clear()
257259 waitForRendering(notification)
@@ -259,23 +261,27 @@ Row {
259261 // check if there's a OptionToggle created due to more actions being passed
260262 if (data.actions.length > 2) {
261263 var optionToggle = findChild(notification, "notify_button2")
262− tryCompareFunction(function() { return optionToggle.expanded == false; }, true);
264+ tryCompare(optionToggle, "expanded", false);
263265
264266 // click to expand
265− tryCompareFunction(function() { mouseClick(optionToggle); return optionToggle.expanded == true; }, true);
267+ mouseClick(optionToggle);
268+ tryCompare(optionToggle, "expanded", true);
266269
267270 // try clicking on choices in expanded comboList
268271 var choiceButton1 = findChild(notification, "notify_button3")
269− tryCompareFunction(function() { mouseClick(choiceButton1); return actionSpy.signalArguments.length > 0; }, true);
272+ mouseClick(choiceButton1);
273+ actionSpy.wait();
270274 compare(actionSpy.signalArguments[0][0], data.actions[3]["id"], "got wrong id choice action 1")
271275 actionSpy.clear()
272276
273277 var choiceButton2 = findChild(notification, "notify_button4")
274− tryCompareFunction(function() { mouseClick(choiceButton2); return actionSpy.signalArguments.length > 0; }, true);
278+ mouseClick(choiceButton2);
279+ actionSpy.wait();
275280 compare(actionSpy.signalArguments[0][0], data.actions[4]["id"], "got wrong id choice action 2")
276281 actionSpy.clear()
277282 } else {
278283 mouseClick(buttonCancel)
284+ actionSpy.wait();
279285 compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
280286 }
281287 }
tests/qmltests/Notifications/tst_SwipeToAct.qml+6−2
@@ -283,12 +283,14 @@ Item {
283283 var y = swipeMouseArea.height / 2
284284
285285 if(data.checkSwipeToActAccept) {
286− tryCompareFunction(function() { mouseDrag(slider, x, y, (swipeMouseArea.width / 2) - slider.width, 0); return actionSpy.signalArguments.length > 0; }, true);
286+ mouseDrag(slider, x, y, (swipeMouseArea.width / 2) - slider.width, 0);
287+ actionSpy.wait();
287288 compare(actionSpy.signalArguments[0][0], data.actions.data(0, ActionModel.RoleActionId), "got wrong id for positive action");
288289 actionSpy.clear();
289290 }
290291 if(data.checkSwipeToActReject) {
291− tryCompareFunction(function() { mouseDrag(slider, x, y, -(swipeMouseArea.width / 2), 0); return actionSpy.signalArguments.length > 0; }, true);
292+ mouseDrag(slider, x, y, -(swipeMouseArea.width / 2), 0);
293+ actionSpy.wait();
292294 compare(actionSpy.signalArguments[0][0], data.actions.data(1, ActionModel.RoleActionId), "got wrong id for negative action");
293295 actionSpy.clear();
294296 }
@@ -302,12 +304,14 @@ Item {
302304
303305 if(data.checkSwipeToActAccept) {
304306 mouseClick(rightButton);
307+ actionSpy.wait();
305308 compare(actionSpy.signalArguments[0][0], data.actions.data(0, ActionModel.RoleActionId), "got wrong id for positive action");
306309 actionSpy.clear();
307310 }
308311
309312 if(data.checkSwipeToActReject) {
310313 mouseClick(leftButton);
314+ actionSpy.wait();
311315 compare(actionSpy.signalArguments[0][0], data.actions.data(1, ActionModel.RoleActionId), "got wrong id for negative action");
312316 actionSpy.clear();
313317 }
tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+3−3
@@ -210,9 +210,9 @@ Row {
210210 mouseClick(snap_decision[index])
211211 for (var kindex = 0; kindex < snap_decision.length; kindex++) {
212212 if (kindex == index) {
213− compare(snap_decision[kindex].expanded, true, "state of "+ kindex + ".snap-decision is not expanded");
213+ tryCompare(snap_decision[kindex], "expanded", true, 5000, "state of "+ kindex + ".snap-decision is not expanded");
214214 } else {
215− compare(snap_decision[kindex].expanded, false, "state of "+ kindex + ".snap-decision is not contracted");
215+ tryCompare(snap_decision[kindex], "expanded", false, 5000, "state of "+ kindex + ".snap-decision is not contracted");
216216 }
217217 }
218218 }
@@ -225,7 +225,7 @@ Row {
225225
226226 for (var index = 1; index < snap_decision.length; index++) {
227227 removeTopMostNotification();
228− compare(snap_decision[index].expanded, true, "state of " + index + ". snap-decision is not expanded");
228+ tryCompare(snap_decision[index], "expanded", true, 5000, "state of " + index + ". snap-decision is not expanded");
229229 }
230230 }
231231 }
tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml+33−79
@@ -89,6 +89,12 @@ Item {
8989 verify(loader.item == null);
9090 }
9191
92+ function loadData(menuData) {
93+ loader.data = menuData;
94+ loader.sourceComponent = factory.load(menuData);
95+ tryVerify(function() { return loader.item; });
96+ }
97+
9298 function test_createTypes_data() {
9399 return [
94100 { tag: 'volume', type: "unity.widgets.systemsettings.tablet.volumecontrol", objectName: "sliderMenu" },
@@ -127,9 +133,7 @@ Item {
127133 function test_createTypes(data) {
128134 menuData.type = data.type;
129135
130− loader.data = menuData;
131− loader.sourceComponent = factory.load(menuData);
132− tryCompareFunction(function() { return loader.item != undefined; }, true);
136+ loadData(menuData);
133137 compare(loader.item.objectName, data.objectName, "Created object name does not match intended object (" + loader.item.objectName + " != " + data.objectName + ")");
134138 }
135139
@@ -137,27 +141,21 @@ Item {
137141 var tmpData = menuData;
138142 tmpData.isCheck = true;
139143
140− loader.data = tmpData;
141− loader.sourceComponent = factory.load(tmpData);
142− tryCompareFunction(function() { return loader.item != undefined; }, true);
144+ loadData(tmpData);
143145 compare(loader.item.objectName, "checkableMenu", "Should have created a checkable menu");
144146 }
145147
146148 function test_create_radio() {
147149 menuData.isRadio = true;
148150
149− loader.data = menuData;
150− loader.sourceComponent = factory.load(menuData);
151− tryCompareFunction(function() { return loader.item != undefined; }, true);
151+ loadData(menuData);
152152 compare(loader.item.objectName, "radioMenu", "Should have created a radio menu");
153153 }
154154
155155 function test_create_separator() {
156156 menuData.isSeparator = true;
157157
158− loader.data = menuData;
159− loader.sourceComponent = factory.load(menuData);
160− tryCompareFunction(function() { return loader.item != undefined; }, true);
158+ loadData(menuData);
161159 compare(loader.item.objectName, "separatorMenu", "Should have created a separator menu");
162160 }
163161
@@ -180,9 +178,7 @@ Item {
180178 };
181179 menuData.actionState = data.value1;
182180
183− loader.data = menuData;
184− loader.sourceComponent = factory.load(menuData);
185− tryCompareFunction(function() { return loader.item != undefined; }, true);
181+ loadData(menuData);
186182 compare(loader.item.objectName, "sliderMenu", "Should have created a slider menu");
187183
188184 compare(loader.item.text, data.tag, "Label does not match data");
@@ -217,9 +213,7 @@ Item {
217213 };
218214 menuData.actionState = data.value1;
219215
220− loader.data = menuData;
221− loader.sourceComponent = factory.load(menuData);
222− tryCompareFunction(function() { return loader.item != undefined; }, true);
216+ loadData(menuData);
223217 compare(loader.item.value, data.value1, "Value does not match data");
224218
225219 var slider = findChild(loader.item, "slider");
@@ -247,9 +241,7 @@ Item {
247241 menuData.label = data.label;
248242 menuData.sensitive = data.enabled;
249243
250− loader.data = menuData;
251− loader.sourceComponent = factory.load(menuData);
252− tryCompareFunction(function() { return loader.item != undefined; }, true);
244+ loadData(menuData);
253245 compare(loader.item.objectName, "buttonMenu", "Should have created a button menu");
254246
255247 compare(loader.item.buttonText, data.label, "Label does not match data");
@@ -267,9 +259,7 @@ Item {
267259 menuData.type = "com.canonical.indicator.section"
268260 menuData.label = data.label;
269261
270− loader.data = menuData;
271− loader.sourceComponent = factory.load(menuData);
272− tryCompareFunction(function() { return loader.item != undefined; }, true);
262+ loadData(menuData);
273263 compare(loader.item.objectName, "sectionMenu", "Should have created a section menu");
274264
275265 compare(loader.item.text, data.label, "Label does not match data");
@@ -287,9 +277,7 @@ Item {
287277 menuData.label = data.label;
288278 menuData.actionState = data.value;
289279
290− loader.data = menuData;
291− loader.sourceComponent = factory.load(menuData);
292− tryCompareFunction(function() { return loader.item != undefined; }, true);
280+ loadData(menuData);
293281 compare(loader.item.objectName, "progressMenu", "Should have created a progress menu");
294282
295283 compare(loader.item.text, data.label, "Label does not match data");
@@ -309,9 +297,7 @@ Item {
309297 menuData.sensitive = data.enabled;
310298 menuData.icon = data.icon;
311299
312− loader.data = menuData;
313− loader.sourceComponent = factory.load(menuData);
314− tryCompareFunction(function() { return loader.item != undefined; }, true);
300+ loadData(menuData);
315301 compare(loader.item.objectName, "standardMenu", "Should have created a standard menu");
316302
317303 compare(loader.item.text, data.label, "Label does not match data");
@@ -333,9 +319,7 @@ Item {
333319 menuData.isCheck = true;
334320 menuData.isToggled = data.checked;
335321
336− loader.data = menuData;
337− loader.sourceComponent = factory.load(menuData);
338− tryCompareFunction(function() { return loader.item != undefined; }, true);
322+ loadData(menuData);
339323 compare(loader.item.objectName, "checkableMenu", "Should have created a checkable menu");
340324
341325 compare(loader.item.text, data.label, "Label does not match data");
@@ -357,9 +341,7 @@ Item {
357341 menuData.isRadio = true;
358342 menuData.isToggled = data.checked;
359343
360− loader.data = menuData;
361− loader.sourceComponent = factory.load(menuData);
362− tryCompareFunction(function() { return loader.item != undefined; }, true);
344+ loadData(menuData);
363345 compare(loader.item.objectName, "radioMenu", "Should have created a radio menu");
364346
365347 compare(loader.item.text, data.label, "Label does not match data");
@@ -385,9 +367,7 @@ Item {
385367 'xCanonicalSubtitleAction': data.subtitleAction,
386368 };
387369
388− loader.data = menuData;
389− loader.sourceComponent = factory.load(menuData);
390− tryCompareFunction(function() { return loader.item != undefined; }, true);
370+ loadData(menuData);
391371 compare(loader.item.objectName, "switchMenu", "Should have created a switch menu");
392372
393373 compare(loader.item.text, data.label, "Label does not match data");
@@ -415,9 +395,7 @@ Item {
415395 'xCanonicalTime': data.time.getTime() / 1000 // expected in seconds
416396 };
417397
418− loader.data = menuData;
419− loader.sourceComponent = factory.load(menuData);
420− tryCompareFunction(function() { return loader.item != undefined; }, true);
398+ loadData(menuData);
421399 compare(loader.item.objectName, "alarmMenu", "Should have created a alarm menu");
422400
423401 compare(loader.item.text, data.label, "Label does not match data");
@@ -445,9 +423,7 @@ Item {
445423 'xCanonicalTime': data.time.getTime() / 1000 // expected in seconds
446424 };
447425
448− loader.data = menuData;
449− loader.sourceComponent = factory.load(menuData);
450− tryCompareFunction(function() { return loader.item != undefined; }, true);
426+ loadData(menuData);
451427 compare(loader.item.objectName, "appointmentMenu", "Should have created a appointment menu");
452428
453429 compare(loader.item.text, data.label, "Label does not match data");
@@ -527,9 +503,7 @@ Item {
527503 'xCanonicalUid': data.tag
528504 };
529505
530− loader.data = menuData;
531− loader.sourceComponent = factory.load(menuData);
532− tryCompareFunction(function() { return loader.item != undefined; }, true);
506+ loadData(menuData);
533507 compare(loader.item.objectName, "transferMenu", "Should have created a transfer menu");
534508
535509 compare(loader.item.text, data.label, "Label does not match data");
@@ -556,9 +530,7 @@ Item {
556530 'xCanonicalExtraLabel': data.buttonText
557531 };
558532
559− loader.data = menuData;
560− loader.sourceComponent = factory.load(menuData);
561− tryCompareFunction(function() { return loader.item != undefined; }, true);
533+ loadData(menuData);
562534 compare(loader.item.objectName, "buttonSectionMenu", "Should have created a transfer menu");
563535
564536 compare(loader.item.text, data.label, "Label does not match data");
@@ -580,9 +552,7 @@ Item {
580552 menuData.label = data.label;
581553 menuData.ext = { 'xCanonicalBusyAction': data.busy }
582554
583− loader.data = menuData;
584− loader.sourceComponent = factory.load(menuData);
585− tryCompareFunction(function() { return loader.item != undefined; }, true);
555+ loadData(menuData);
586556 compare(loader.item.objectName, "wifiSection", "Should have created a wifi section menu");
587557
588558 compare(loader.item.text, data.label, "Label does not match data");
@@ -607,9 +577,7 @@ Item {
607577 'xCanonicalWifiApIsAdhoc': data.adHoc,
608578 };
609579
610− loader.data = menuData;
611− loader.sourceComponent = factory.load(menuData);
612− tryCompareFunction(function() { return loader.item != undefined; }, true);
580+ loadData(menuData);
613581 compare(loader.item.objectName, "accessPoint", "Should have created a access point menu");
614582
615583 compare(loader.item.text, data.label, "Label does not match data");
@@ -647,9 +615,7 @@ Item {
647615 'xCanonicalModemLockedAction': data.unlockAction,
648616 };
649617
650− loader.data = menuData;
651− loader.sourceComponent = factory.load(menuData);
652− tryCompareFunction(function() { return loader.item != undefined; }, true);
618+ loadData(menuData);
653619 compare(loader.item.objectName, "modemInfoItem", "Should have created a modem info item.");
654620
655621 compare(loader.item.statusLabelAction.name, data.statusLabelAction, "StatusLabel action incorrect");
@@ -664,9 +630,7 @@ Item {
664630 function test_create_messageItem() {
665631 menuData.type = "com.canonical.indicator.messages.messageitem";
666632
667− loader.data = menuData;
668− loader.sourceComponent = factory.load(menuData);
669− tryCompareFunction(function() { return loader.item != undefined; }, true);
633+ loadData(menuData);
670634 compare(loader.item.objectName, "messageItem", "Should have created a message menu");
671635 }
672636
@@ -686,9 +650,7 @@ Item {
686650 menuData.actionState = [data.count];
687651 menuData.isToggled = true;
688652
689− loader.data = menuData;
690− loader.sourceComponent = factory.load(menuData);
691− tryCompareFunction(function() { return loader.item != undefined; }, true);
653+ loadData(menuData);
692654 compare(loader.item.objectName, "groupedMessage", "Should have created a group message menu");
693655
694656 compare(loader.item.text, data.label, "Label does not match data");
@@ -749,9 +711,7 @@ Item {
749711 'state': data.state,
750712 };
751713
752− loader.data = menuData;
753− loader.sourceComponent = factory.load(menuData);
754− tryCompareFunction(function() { return loader.item != undefined; }, true);
714+ loadData(menuData);
755715 compare(loader.item.objectName, "mediaPayerMenu", "Should have created a media player menu");
756716
757717 compare(loader.item.playerIcon, data.icon, "Album art does not match data");
@@ -789,9 +749,7 @@ Item {
789749 'xCanonicalPreviousAction': data.previousAction
790750 };
791751
792− loader.data = menuData;
793− loader.sourceComponent = factory.load(menuData);
794− tryCompareFunction(function() { return loader.item != undefined; }, true);
752+ loadData(menuData);
795753 compare(loader.item.objectName, "playbackItemMenu", "Should have created a playback menu");
796754
797755 compare(loader.item.playing, false, "Playing does not match data");
@@ -809,8 +767,7 @@ Item {
809767 menuData.sensitive = true;
810768 menuData.isToggled = false;
811769
812− loader.data = menuData;
813− loader.sourceComponent = factory.load(menuData);
770+ loadData(menuData);
814771
815772 compare(loader.item.checked, false, "Loader did not load check state");
816773 mouseClick(loader.item,
@@ -829,8 +786,7 @@ Item {
829786 menuData.sensitive = true;
830787 menuData.isToggled = false;
831788
832− loader.data = menuData;
833− loader.sourceComponent = factory.load(menuData);
789+ loadData(menuData);
834790
835791 var sync = findInvisibleChild(loader.item, "sync");
836792 verify(sync);
@@ -859,9 +815,7 @@ Item {
859815 "appointment-days": data.eventDays
860816 }
861817
862− loader.data = menuData;
863− loader.sourceComponent = factory.load(menuData);
864− tryCompareFunction(function() { return loader.item != undefined; }, true);
818+ loadData(menuData);
865819 compare(loader.item.objectName, "calendarMenu", "Should have created a calendar menu")
866820
867821 compare(loader.item.currentDate.getFullYear(), data.calendarDay.getFullYear(), "Calendar year does not match data")
tests/qmltests/Panel/tst_ActiveCallHint.qml+8−6
@@ -113,7 +113,7 @@ Item {
113113 callManager.foregroundCall = data.call;
114114 callManager.callIndicatorVisible = data.visible;
115115
116− compare(callHint.active, data.expected, "Call hint should be active when callIndicatorVisible=true");
116+ tryCompare(callHint, "active", data.expected, 5000, "Call hint should be active when callIndicatorVisible=true");
117117
118118 if (data.dialer) {
119119 // clean up
@@ -137,7 +137,7 @@ Item {
137137 callManager.backgroundCall = data.background;
138138
139139 var contactLabel = findChild(callHint, "contactLabel");
140− verify(contactLabel !== null);
140+ verify(contactLabel);
141141
142142 compare(contactLabel.text, data.label, "Contact label does not match call");
143143 }
@@ -146,7 +146,7 @@ Item {
146146 callManager.backgroundCall = call3;
147147
148148 var contactLabel = findChild(callHint, "contactLabel");
149− verify(contactLabel !== null);
149+ verify(contactLabel);
150150
151151 contactWactherData.contactData = { "+447812221113": { "alias": "Bob's Uncle" } };
152152 compare(contactLabel.text, "Bob's Uncle", "Contact label does not match call");
@@ -171,22 +171,24 @@ Item {
171171 call1.elapsedTime = data.elpasedTime;
172172
173173 var timeLabel = findChild(callHint, "timeLabel");
174− verify(timeLabel !== null);
174+ verify(timeLabel);
175175
176176 compare(timeLabel.text, data.initial);
177177 call1.elapsedTime = call1.elapsedTime + 1;
178− compare(timeLabel.text, data.expected);
178+ tryCompare(timeLabel, "text", data.expected);
179179 }
180180
181181 function test_displayedLabelChangesOverTime() {
182182 callManager.backgroundCall = call3;
183183
184184 var labelPathView = findChild(callHint, "labelPathView");
185− verify(labelPathView !== null);
185+ verify(labelPathView);
186186
187187 var currentOffset = labelPathView.offset
188+ wait(1100);
188189 tryCompareFunction(function() { return labelPathView.offset !== currentOffset }, true);
189190 currentOffset = labelPathView.offset
191+ wait(1100);
190192 tryCompareFunction(function() { return labelPathView.offset !== currentOffset }, true);
191193 }
192194 }
tests/qmltests/Panel/tst_MenuContent.qml+2−2
@@ -124,7 +124,7 @@ PanelTest {
124124
125125 activate_content(menuIndex);
126126 testItemObjectName = indicatorsModel.data(menuIndex, Indicators.IndicatorsModelRole.Identifier);
127− compare(listView.currentIndex, menuIndex, "Current tab index does not match selected tab index");
127+ tryCompare(listView, "currentIndex", menuIndex, 5000, "Current tab index does not match selected tab index");
128128 tryCompareFunction(current_item_equals_test_item, true);
129129 }
130130 }
@@ -136,7 +136,7 @@ PanelTest {
136136
137137 for (var i = 0; i < 100; i++) {
138138 activate_content(i % menuCount);
139− compare(menuContent.currentMenuIndex, i%menuCount);
139+ tryCompare(menuContent, "currentMenuIndex", i%menuCount);
140140 }
141141 }
142142 }
tests/qmltests/Panel/tst_Panel.qml+25−22
@@ -265,7 +265,7 @@ PanelTest {
265265
266266 // Put the mouse somewhere neutral so it doesn't hover over things
267267 // and mess up the test
268− mouseMove(root, 0, 100);
268+ mouseMove(root, 0, 0);
269269
270270 // Wait for the indicators to get into position.
271271 // (switches between normal and fullscreen modes are animated)
@@ -285,11 +285,13 @@ PanelTest {
285285 panel.indicators.hide();
286286 panel.applicationMenus.hide();
287287 waitForAllAnimationToComplete("initial");
288+ tryCompare(panel.indicators, "fullyClosed", true);
289+ tryCompare(panel.applicationMenus, "fullyClosed", true);
288290 }
289291
290292 function get_indicator_item(index) {
291293 var indicatorItem = findChild(panel, root.originalModelData[index]["identifier"]+"-panelItem");
292− verify(indicatorItem !== null);
294+ verify(indicatorItem);
293295
294296 return indicatorItem;
295297 }
@@ -305,7 +307,7 @@ PanelTest {
305307 var indicatorItem = get_indicator_item(i);
306308
307309 var itemState = findInvisibleChild(indicatorItem, "indicatorItemState");
308− verify(itemState !== null);
310+ verify(itemState);
309311
310312 waitUntilTransitionsEnd(itemState);
311313 }
@@ -357,13 +359,13 @@ PanelTest {
357359 callManager.foregroundCall = data.call;
358360
359361 var panelRow = findChild(panel.indicators, "panelItemRow");
360− verify(panelRow !== null);
362+ verify(panelRow);
361363
362364 var menuContent = findChild(panel.indicators, "menuContent");
363− verify(menuContent !== null);
365+ verify(menuContent);
364366
365367 var panelArea = findChild(panel, "panelArea");
366− verify(panelArea !== null);
368+ verify(panelArea);
367369
368370 // Wait for the indicators to get into position.
369371 // (switches between normal and fullscreen modes are animated)
@@ -417,10 +419,10 @@ PanelTest {
417419 callManager.foregroundCall = data.call;
418420
419421 var panelRow = findChild(data.section, "panelItemRow");
420− verify(panelRow !== null);
422+ verify(panelRow);
421423
422424 var panelArea = findChild(panel, "panelArea");
423− verify(panelArea !== null);
425+ verify(panelArea);
424426
425427 // Wait for the indicators to get into position.
426428 // (switches between normal and fullscreen modes are animated)
@@ -480,7 +482,7 @@ PanelTest {
480482 var hintingAnimation = findInvisibleChild(showDragHandle, "hintingAnimation");
481483 verify(hintingAnimation);
482484
483− compare(hintingAnimation.running, data.hintExpected)
485+ tryCompare(hintingAnimation, "running", data.hintExpected);
484486 tryCompare(hintingAnimation, "running", false); // wait till animation completes
485487
486488 // no hint animation when fullscreen
@@ -507,13 +509,13 @@ PanelTest {
507509 callManager.foregroundCall = data.call;
508510
509511 var panelRow = findChild(panel.indicators, "panelItemRow");
510− verify(panelRow !== null);
512+ verify(panelRow);
511513
512514 var menuContent = findChild(panel.indicators, "menuContent");
513− verify(menuContent !== null);
515+ verify(menuContent);
514516
515517 var panelArea = findChild(panel, "panelArea");
516− verify(panelArea !== null);
518+ verify(panelArea);
517519
518520 // Wait for the indicators to get into position.
519521 // (switches between normal and fullscreen modes are animated)
@@ -528,7 +530,8 @@ PanelTest {
528530 // They should be at least half-way through the screen
529531 tryCompareFunction(
530532 function() {return panel.applicationMenus.height >= panel.height * 0.5},
531− true);
533+ true
534+ );
532535
533536 touchRelease(panel, units.gu(1), panel.height);
534537
@@ -562,7 +565,7 @@ PanelTest {
562565 tryCompare(panel.indicators, "fullyClosed", true);
563566 compare(backgroundPressedSpy.count, 0);
564567 tap(panel, touchPosX, touchPosY);
565− compare(backgroundPressedSpy.count, 2);
568+ tryCompare(backgroundPressedSpy, "count", 2);
566569
567570 pullDownIndicatorsMenu();
568571
@@ -589,7 +592,7 @@ PanelTest {
589592 // Now that's fully closed, input should go through again
590593 backgroundPressedSpy.clear();
591594 tap(panel, touchPosX, touchPosY);
592− compare(backgroundPressedSpy.count, 2);
595+ tryCompare(backgroundPressedSpy, "count", 2);
593596 }
594597
595598 function test_darkenedAreaEatsAllApplicationMenuEvents() {
@@ -605,7 +608,7 @@ PanelTest {
605608 tryCompare(panel.applicationMenus, "fullyClosed", true);
606609 compare(backgroundPressedSpy.count, 0);
607610 tap(panel, touchPosX, touchPosY);
608− compare(backgroundPressedSpy.count, 2);
611+ tryCompare(backgroundPressedSpy, "count", 2);
609612
610613 pullDownApplicationsMenu();
611614
@@ -632,7 +635,7 @@ PanelTest {
632635 // Now that's fully closed, input should go through again
633636 backgroundPressedSpy.clear();
634637 tap(panel, touchPosX, touchPosY);
635− compare(backgroundPressedSpy.count, 2);
638+ tryCompare(backgroundPressedSpy, "count", 2);
636639 }
637640
638641
@@ -696,7 +699,7 @@ PanelTest {
696699 panel.indicators.width / 2,
697700 panel.minimizedPanelHeight / 2);
698701
699− compare(panel.indicators.shown, true);
702+ tryCompare(panel.indicators, "shown", true);
700703 tryCompare(panel.indicators, "fullyOpened", true);
701704
702705 var handle = findChild(panel.indicators, "handle");
@@ -704,7 +707,7 @@ PanelTest {
704707
705708 mouseClick(handle);
706709
707− compare(panel.indicators.shown, false);
710+ tryCompare(panel.indicators, "shown", false);
708711 tryCompare(panel.indicators, "fullyClosed", true);
709712 }
710713
@@ -718,7 +721,7 @@ PanelTest {
718721 // click in very topleft corner and verify the close button got clicked too
719722 mouseMove(panel, 0, 0);
720723 mouseClick(panel, 0, 0, undefined /*button*/, undefined /*modifiers*/, 100 /*short delay*/);
721− compare(windowControlButtonsSpy.count, 1);
724+ windowControlButtonsSpy.wait();
722725 }
723726
724727 function test_hidingKeyboardIndicator_data() {
@@ -848,7 +851,7 @@ PanelTest {
848851
849852 keyClick(Qt.Key_Right);
850853 tryCompare(indicatorsBar, "currentItemIndex", 1);
851− compare(aboutToShowCalledSpy.count, 2);
854+ tryCompare(aboutToShowCalledSpy, "count", 2);
852855
853856 compare(aboutToShowCalledSpy.signalArguments[0][0], 0);
854857 compare(aboutToShowCalledSpy.signalArguments[1][0], 1);
@@ -860,7 +863,7 @@ PanelTest {
860863 aboutToShowCalledSpy.clear();
861864
862865 keyClick(Qt.Key_Enter);
863− compare(aboutToShowCalledSpy.count, 1);
866+ aboutToShowCalledSpy.wait();
864867 }
865868
866869 function test_disabledTopLevel() {
tests/qmltests/Panel/tst_PanelItemRow.qml+2−2
@@ -255,13 +255,13 @@ PanelTest {
255255 var toPosition = indicatorsRow.mapFromItem(toItem, toItem.width/2, toItem.height/2);
256256
257257 mousePress(indicatorsRow, fromPosition.x, fromPosition.y);
258− compare(indicatorsRow.currentItem, fromItem, "Initial item not selected");
258+ tryCompare(indicatorsRow, "currentItem", fromItem, 5000, "Initial item not selected");
259259
260260 // this uses the MouseArea above to change the indicatorRow lateralPosition
261261 mouseFlick(indicatorsRow, fromPosition.x, fromPosition.y, toPosition.x, toPosition.y, false, false, units.gu(5), 30);
262262
263263 mouseRelease(indicatorsRow, fromPosition.x, fromPosition.y);
264− compare(indicatorsRow.currentItem, toItem, "Current item did not change to expected item");
264+ tryCompare(indicatorsRow, "currentItem", toItem, 5000, "Current item did not change to expected item");
265265 }
266266
267267 // testing that positive changes to the lateral position offset shifts the highlight offset to the right
tests/qmltests/Panel/tst_PanelMenu.qml+1−1
@@ -179,7 +179,7 @@ PanelTest {
179179 touchPress(indicatorsMenu, firstItemMappedPosition.x, indicatorsMenu.minimizedPanelHeight / 2);
180180
181181 indicatorsMenu.height = indicatorsMenu.openedHeight / 2;
182− compare(indicatorsMenu.state, "reveal", "Indicators should be revealing when partially opened.");
182+ tryCompare(indicatorsMenu, "state", "reveal", 5000, "Indicators should be revealing when partially opened.");
183183
184184 indicatorsMenu.height = indicatorsMenu.openedHeight;
185185 compare(indicatorsMenu.state, "reveal", "Indicators should still be revealing when fully opened.");
tests/qmltests/Stage/tst_DesktopStage.qml+3−3
@@ -264,13 +264,13 @@ Item {
264264 var fromAppWindow = findChild(fromDelegate, "appWindow");
265265 verify(fromAppWindow);
266266 tap(fromAppWindow);
267− compare(fromDelegate.surface.activeFocus, true);
267+ tryCompare(fromDelegate.surface, "activeFocus", true);
268268 compare(topSurfaceList.focusedWindow, fromDelegate.window);
269269
270270 var toAppWindow = findChild(toDelegate, "appWindow");
271271 verify(toAppWindow);
272272 tap(toAppWindow);
273− compare(toDelegate.surface.activeFocus, true);
273+ tryCompare(toDelegate.surface, "activeFocus", true);
274274 compare(topSurfaceList.focusedWindow, toDelegate.window);
275275 }
276276
@@ -591,7 +591,7 @@ Item {
591591 var dialerDelegate = startApplication("dialer-app");
592592 verify(dialerDelegate);
593593
594− compare(dialerDelegate.visible, true, "Dialer should be visible");
594+ tryCompare(dialerDelegate, "visible", true, 5000, "Dialer should be visible");
595595 compare(dashDelegate.visible, true, "Dash should still be visible");
596596 }
597597
tests/qmltests/Stage/tst_PhoneStage.qml+9−9
@@ -359,10 +359,10 @@ Item {
359359 verify(delegateB);
360360
361361 // A is focused and running, B is unfocused and suspended
362− compare(delegateA.focus, true);
363− compare(delegateA.application.requestedState, ApplicationInfoInterface.RequestedRunning);
364− compare(delegateB.focus, false);
365− compare(delegateB.application.requestedState, ApplicationInfoInterface.RequestedSuspended);
362+ tryCompare(delegateA, "focus", true);
363+ tryCompare(delegateA.application, "requestedState", ApplicationInfoInterface.RequestedRunning);
364+ tryCompare(delegateB, "focus", false);
365+ tryCompare(delegateB.application, "requestedState", ApplicationInfoInterface.RequestedSuspended);
366366
367367 // Switch foreground/focused appp from A to B
368368 performEdgeSwipeToShowAppSpread();
@@ -382,8 +382,8 @@ Item {
382382 var delegate = findChild(stage, "appDelegate_" + topLevelSurfaceList.idAt(0));
383383 verify(delegate);
384384
385− compare(delegate.focus, true);
386− compare(delegate.application.requestedState, ApplicationInfoInterface.RequestedRunning);
385+ tryCompare(delegate, "focus", true);
386+ tryCompare(delegate.application, "requestedState", ApplicationInfoInterface.RequestedRunning);
387387
388388 stage.suspended = true;
389389
@@ -398,9 +398,9 @@ Item {
398398 addApps(1);
399399 // When progress goes to 1 it should switch to spread, but stay there even if progress goes back
400400 stage.rightEdgePushProgress = 1;
401− compare(stage.state, "spread");
401+ tryCompare(stage, "state", "spread");
402402 stage.rightEdgePushProgress = 0;
403− compare(stage.state, "spread");
403+ tryCompare(stage, "state", "spread");
404404 }
405405
406406 function test_closeSurfaceOfMultiSurfaceApp() {
@@ -494,7 +494,7 @@ Item {
494494 tryCompareFunction(function(){return topLevelSurfaceList.idAt(0);}, webbrowserSurfaceId);
495495
496496 // and it should eventually get a new surface and get resumed
497− tryCompareFunction(function(){return topLevelSurfaceList.surfaceAt(0) !== null;}, true);
497+ tryVerify(function(){return topLevelSurfaceList.surfaceAt(0)});
498498 compare(topLevelSurfaceList.count, 2); // still two top-level items
499499 tryCompare(webbrowserApp, "state", ApplicationInfoInterface.Running);
500500 compare(webbrowserApp.surfaceList.count, 1);
tests/qmltests/Stage/tst_SurfaceContainer.qml+7−7
@@ -214,15 +214,15 @@ Rectangle {
214214 tap(surfaceContainer);
215215
216216 // surface got touches as the surfaceContainer is interactive
217− compare(surfaceItem.touchPressCount, 1)
218− compare(surfaceItem.touchReleaseCount, 1);
217+ tryCompare(surfaceItem, "touchPressCount", 1);
218+ tryCompare(surfaceItem, "touchPressCount", 1);
219219
220220 interactiveCheckbox.checked = false;
221221 tap(surfaceContainer);
222222
223223 // surface shouldn't get the touches from the second tap as the surfaceContainer
224224 // was *not* interactive when it happened.
225− compare(surfaceItem.touchPressCount, 1)
225+ compare(surfaceItem.touchPressCount, 1);
226226 compare(surfaceItem.touchReleaseCount, 1);
227227 }
228228
@@ -235,9 +235,9 @@ Rectangle {
235235
236236 surfaceContainer.focus = false;
237237
238− compare(surfaceItem.activeFocus, false);
238+ tryCompare(surfaceItem, "activeFocus", false);
239239 mouseClick(surfaceContainer);
240− compare(surfaceItem.activeFocus, true);
240+ tryCompare(surfaceItem, "activeFocus", true);
241241 }
242242
243243 function test_surfaceItemGetsActiveFocusOnTap() {
@@ -249,9 +249,9 @@ Rectangle {
249249
250250 surfaceContainer.focus = false;
251251
252− compare(surfaceItem.activeFocus, false);
252+ tryCompare(surfaceItem, "activeFocus", false);
253253 tap(surfaceContainer);
254− compare(surfaceItem.activeFocus, true);
254+ tryCompare(surfaceItem, "activeFocus", true);
255255 }
256256 }
257257}
tests/qmltests/Stage/tst_WindowDecoration.qml+3−3
@@ -163,7 +163,7 @@ Item {
163163 verify(controlButton !== null);
164164
165165 mouseClick(controlButton, controlButton.width/2, controlButton.height/2);
166− compare(signalSpy.count, 1);
166+ signalSpy.wait();
167167 }
168168
169169 function test_titleRemainsWhenHoveringOnTitleBarWithNoMenu() {
@@ -177,8 +177,8 @@ Item {
177177 var titleLabel = findChild(decoration, "windowDecorationTitle");
178178 verify(menuLoader);
179179
180− compare(menuLoader.opacity, 0, "Menu should not show when present")
181− compare(titleLabel.opacity, 1, "Title should always show when app menu not present")
180+ tryCompare(menuLoader, "opacity", 0, 5000, "Menu should not show when present")
181+ tryCompare(titleLabel, "opacity", 1, 5000, "Title should always show when app menu not present")
182182 }
183183
184184 function test_menuShowsWhenHoveringOnTitleBar() {
tests/qmltests/Stage/tst_WindowResizeArea.qml+2−2
@@ -397,9 +397,9 @@ Item {
397397
398398 mouseFlick(root, startDragX, startDragY, startDragX + deltaX, startDragY + deltaY);
399399
400− compare(windowRequestedWidthSpy.count, 1);
400+ windowRequestedWidthSpy.wait();
401401 compare(fakeWindow.width, initialWindowWidth + fakeWindow.widthIncrement);
402− compare(windowRequestedHeightSpy.count, 1);
402+ windowRequestedHeightSpy.wait();
403403 compare(fakeWindow.height, initialWindowHeight + fakeWindow.heightIncrement);
404404 }
405405
tests/qmltests/Wizard/tst_Wizard.qml+8−10
@@ -311,7 +311,7 @@ Item {
311311 var pages = findChild(wizard, "wizardPages");
312312 var security = findInvisibleChild(pages, "securityPrivacy");
313313 security.setSecurity("", "", UbuntuSecurityPrivacyPanel.Passphrase);
314− compare(security.securityType, UbuntuSecurityPrivacyPanel.Passphrase);
314+ tryCompare(security, "securityType", UbuntuSecurityPrivacyPanel.Passphrase);
315315
316316 // Make sure that moving from sim page lands on wifi page
317317 tap(findChild(page, "forwardButton"));
@@ -346,7 +346,7 @@ Item {
346346
347347 enterPasscode("1112");
348348 var error = findChild(page, "wrongNoticeLabel");
349− tryCompareFunction(function() { return error.text !== ""; }, true);
349+ tryVerify(function() { return error.text !== ""; });
350350
351351 enterPasscode("1111");
352352
@@ -355,7 +355,7 @@ Item {
355355 waitUntilTransitionsEnd(page);
356356 tap(findChild(page, "finishButton"));
357357
358− tryCompare(setSecuritySpy, "count", 1);
358+ setSecuritySpy.wait();
359359 compare(setSecuritySpy.signalArguments[0][0], "");
360360 compare(setSecuritySpy.signalArguments[0][1], "1111");
361361 compare(setSecuritySpy.signalArguments[0][2], UbuntuSecurityPrivacyPanel.Passcode);
@@ -393,7 +393,7 @@ Item {
393393 waitUntilTransitionsEnd(page);
394394 tap(findChild(page, "finishButton"));
395395
396− tryCompare(setSecuritySpy, "count", 1);
396+ setSecuritySpy.wait();
397397 compare(setSecuritySpy.signalArguments[0][0], "");
398398 compare(setSecuritySpy.signalArguments[0][1], "12345678");
399399 compare(setSecuritySpy.signalArguments[0][2], UbuntuSecurityPrivacyPanel.Passphrase);
@@ -433,7 +433,7 @@ Item {
433433
434434 // go next and verify the (mock) signal got fired
435435 tap(findChild(page, "forwardButton"));
436− tryCompare(timezoneSpy, "count", 1);
436+ timezoneSpy.wait();
437437 compare(timezoneSpy.signalArguments[0][0], "Europe/London");
438438 compare(timezoneSpy.signalArguments[0][1], "Belfast");
439439 }
@@ -444,7 +444,7 @@ Item {
444444 SystemImage.updateAvailable = true;
445445 SystemImage.targetBuildNumber = 42;
446446 SystemImage.updateDownloaded();
447− compare(updateDownloadedSpy.count, 1);
447+ updateDownloadedSpy.wait();
448448
449449 var page = goToPage("systemUpdatePage");
450450 var updateButton = findChild(page, "installButton");
@@ -452,8 +452,8 @@ Item {
452452 compare(skipUntilFinishedSpy.count, 0);
453453 compare(applyUpdateSpy.count, 0);
454454 tap(updateButton);
455− compare(skipUntilFinishedSpy.count, 1);
456− compare(applyUpdateSpy.count, 1);
455+ skipUntilFinishedSpy.wait();
456+ applyUpdateSpy.wait();
457457 }
458458
459459 function test_accountPage() {
@@ -472,14 +472,12 @@ Item {
472472 var langSelector = findChild(page, "langSelector");
473473 verify(langSelector);
474474 langSelector.selectedIndex = 1; // should be fr_FR
475− print("Selected language:", page.selectedLanguage);
476475
477476 // pick some layout
478477 var kbdDelegate = findChild(page, "kbdDelegate1");
479478 verify(kbdDelegate);
480479 mouseClick(kbdDelegate);
481480 verify(kbdDelegate.isCurrent);
482− print("Selected keymap:", page.selectedKeymap);
483481
484482 // verify the keymapsChanged signal got fired
485483 tap(findChild(page, "forwardButton"));
tests/qmltests/tst_OrientedShell.qml+4−5
@@ -525,7 +525,7 @@ Rectangle {
525525 compare(primaryApp.rotatesWindowContents, false);
526526 compare(primaryApp.supportedOrientations, Qt.PrimaryOrientation);
527527
528− tryCompareFunction(function(){return primaryDelegate.surface != null;}, true);
528+ tryVerify(function(){return primaryDelegate.surface});
529529 verify(checkAppSurfaceOrientation(primaryAppWindow, primaryApp, root.primaryOrientationAngle));
530530
531531 compare(shell.transformRotationAngle, root.primaryOrientationAngle);
@@ -958,7 +958,7 @@ Rectangle {
958958 // app must have portrait aspect ratio
959959 verify(decoratedWindow.width < decoratedWindow.height);
960960
961− // shell should remain in its primery orientation as the app in the main stage
961+ // shell should remain in its primary orientation as the app in the main stage
962962 // is the one that dictates its orientation. In this case it's unity8-dash
963963 // which supports only primary orientation
964964 compare(shell.orientation, orientedShell.orientations.primary);
@@ -1508,7 +1508,6 @@ Rectangle {
15081508 }
15091509 var point = surfaceItem.mapToItem(orientedShell, 0, 0);
15101510
1511− print("exptectedAngle", expectedAngle, point.x, point.y)
15121511 switch (expectedAngle) {
15131512 case 0:
15141513 return point.x === 0 && point.y === PanelState.panelHeight;
@@ -1625,7 +1624,7 @@ Rectangle {
16251624 testCase.showPowerDialog();
16261625
16271626 var dialogLoader = findChild(orientedShell, "dialogLoader");
1628− tryCompareFunction(function() { return dialogLoader.item !== null }, true);
1627+ tryVerify(function() { return dialogLoader.item !== null });
16291628
16301629 keyClick(Qt.Key_Escape);
16311630
@@ -1635,7 +1634,7 @@ Rectangle {
16351634 // Do it twice, our previous solution failed the second time ^_^
16361635 testCase.showPowerDialog();
16371636
1638− tryCompareFunction(function() { return dialogLoader.item !== null }, true);
1637+ tryVerify(function() { return dialogLoader.item !== null });
16391638
16401639 keyClick(Qt.Key_Escape);
16411640
tests/qmltests/tst_Shell.qml+35−29
@@ -977,13 +977,13 @@ Rectangle {
977977
978978 var loginList = findChild(view, "loginList");
979979
980− compare(view.sessionToStart, greeter.sessionToStart());
980+ tryCompare(view, "sessionToStart", greeter.sessionToStart());
981981
982982 // Ensure another session can actually be selected
983983 compare(LightDMController.numSessions > 1, true);
984984 loginList.currentSession = LightDM.Sessions.data(1, LightDM.SessionRoles.KeyRole);
985985
986− compare(view.sessionToStart, greeter.sessionToStart());
986+ tryCompare(view, "sessionToStart", greeter.sessionToStart());
987987
988988 }
989989
@@ -1158,7 +1158,7 @@ Rectangle {
11581158 compare(sessionSpy.count, 0);
11591159
11601160 swipeAwayGreeter();
1161− compare(sessionSpy.count, 1);
1161+ sessionSpy.wait();
11621162 }
11631163
11641164 function test_fullscreen() {
@@ -1194,6 +1194,7 @@ Rectangle {
11941194
11951195 touchFlick(shell, touchStartX, touchStartY, units.gu(2), touchStartY, true, false);
11961196
1197+ // We did NOT leave fullscreen
11971198 compare(panel.fullscreenMode, true);
11981199
11991200 touchFlick(shell, units.gu(2), touchStartY, shell.width * 0.5, touchStartY, false, false);
@@ -1235,7 +1236,7 @@ Rectangle {
12351236 wizard.hide();
12361237 tryCompare(wizard, "active", false);
12371238 compare(Wizard.System.wizardEnabled, false);
1238− compare(unlockAllModemsSpy.count, 1);
1239+ unlockAllModemsSpy.wait();
12391240 }
12401241
12411242 function test_wizardEarlyExit() {
@@ -1509,7 +1510,7 @@ Rectangle {
15091510 shell.usageScenario = data.usageScenario;
15101511
15111512 var launcher = findChild(shell, "launcher");
1512− compare(launcher.inverted, data.launcherInverted);
1513+ tryCompare(launcher, "inverted", data.launcherInverted);
15131514 }
15141515
15151516 function test_unfocusedAppsGetSuspendedAfterEnteringStagedMode() {
@@ -1750,6 +1751,7 @@ Rectangle {
17501751
17511752 // Close the app using the close button
17521753 // The button doesn't appear until the mouse is over the surface
1754+ mouseMove(closeMouseArea, closeMouseArea.width / 2 + 1, closeMouseArea.height / 2, 10);
17531755 mouseMove(closeMouseArea, closeMouseArea.width / 2, closeMouseArea.height / 2, 10);
17541756 tryCompare(closeMouseArea, "visible", true);
17551757 mouseClick(closeMouseArea, closeMouseArea.width / 2, closeMouseArea.height / 2);
@@ -1819,7 +1821,7 @@ Rectangle {
18191821 var spreadFlickable = findChild(shell, "spreadFlickable");
18201822 waitForRendering(spreadFlickable);
18211823
1822− compare(spreadFlickable.contentX, 0);
1824+ tryCompare(spreadFlickable, "contentX", 0);
18231825
18241826 // Move the mouse to the right and make sure it scrolls the Flickable
18251827 var shellLeft = launcherPanel.width + 5;
@@ -1977,7 +1979,7 @@ Rectangle {
19771979 mousePress(appDelegate, appDelegate.width / 2, units.gu(1))
19781980 mouseMove(appDelegate, appDelegate.width / 2, -units.gu(100))
19791981
1980− compare(appDelegate.y >= PanelState.panelHeight, true);
1982+ tryVerify(function() {return (appDelegate.y >= PanelState.panelHeight)});
19811983 }
19821984
19831985 function test_cantResizeWindowUnderPanel() {
@@ -2005,7 +2007,7 @@ Rectangle {
20052007 mouseMove(decoration, decoration.width/2, -units.gu(100));
20062008
20072009 // verify we don't go past the panel
2008− compare(appDelegate.y >= PanelState.panelHeight, true);
2010+ tryVerify(function() {return (appDelegate.y >= PanelState.panelHeight)});
20092011 }
20102012
20112013 function test_restoreWindowStateFixesIfUnderPanel() {
@@ -2029,7 +2031,7 @@ Rectangle {
20292031 tryCompareFunction(function () { return topLevelSurfaceList.applicationAt(0).appId; }, application.appId);
20302032
20312033 appDelegate = appRepeater.itemAt(0);
2032− compare(appDelegate.y >= PanelState.panelHeight, true);
2034+ tryVerify(function() {return (appDelegate.y >= PanelState.panelHeight)});
20332035 }
20342036
20352037 function test_lifecyclePolicyForNonTouchApp_data() {
@@ -2151,7 +2153,11 @@ Rectangle {
21512153
21522154 // The popup must appear now, unless in "tablet" mode
21532155 popup = findChild(root, "modeSwitchWarningDialog");
2154− compare(popup !== null, !data.tabletMode);
2156+ if (data.tabletMode) {
2157+ verify(!popup);
2158+ } else {
2159+ verify(popup);
2160+ }
21552161
21562162 if (data.replug || data.tabletMode) {
21572163 shell.usageScenario = "desktop"
@@ -2168,10 +2174,10 @@ Rectangle {
21682174
21692175 if (data.replug || data.tabletMode) {
21702176 // Libreoffice must still be running
2171− compare(ApplicationManager.findApplication("libreoffice") !== null, true);
2177+ tryVerify(function() {return ApplicationManager.findApplication("libreoffice")});
21722178 } else {
21732179 // Libreoffice must be gone now (or soon at least)
2174− tryCompareFunction(function() { return ApplicationManager.findApplication("libreoffice") === null}, true);
2180+ tryVerify(function() {return !ApplicationManager.findApplication("libreoffice")});
21752181 }
21762182 }
21772183
@@ -2193,7 +2199,7 @@ Rectangle {
21932199 var launcher = findChild(shell, "launcher");
21942200 var launcherPanel = findChild(launcher, "launcherPanel");
21952201 var firstAppInLauncher = LauncherModel.get(0).appId;
2196− compare(launcher.state, data.launcherLocked ? "visible": "");
2202+ tryCompare(launcher, "state", data.launcherLocked ? "visible": "");
21972203 compare(launcherPanel.highlightIndex, -2);
21982204
21992205 // Use Super + Tab Tab to cycle to the first entry in the launcher
@@ -2354,20 +2360,20 @@ Rectangle {
23542360 verify(topmostSurfaceItem);
23552361
23562362 mouseClick(shell, 1, shell.height / 2);
2357− compare(topmostSurfaceItem.mousePressCount, 1);
2358− compare(topmostSurfaceItem.mouseReleaseCount, 1);
2363+ tryCompare(topmostSurfaceItem, "mousePressCount", 1);
2364+ tryCompare(topmostSurfaceItem, "mouseReleaseCount", 1);
23592365
23602366 mouseClick(shell, shell.width - 1, shell.height / 2);
2361− compare(topmostSurfaceItem.mousePressCount, 2);
2362− compare(topmostSurfaceItem.mouseReleaseCount, 2);
2367+ tryCompare(topmostSurfaceItem, "mousePressCount", 2);
2368+ tryCompare(topmostSurfaceItem, "mouseReleaseCount", 2);
23632369
23642370 tap(shell, 1, shell.height / 2);
2365− compare(topmostSurfaceItem.touchPressCount, 1);
2366− compare(topmostSurfaceItem.touchReleaseCount, 1);
2371+ tryCompare(topmostSurfaceItem, "touchPressCount", 1);
2372+ tryCompare(topmostSurfaceItem, "touchReleaseCount", 1);
23672373
23682374 tap(shell, shell.width - 1, shell.height / 2);
2369− compare(topmostSurfaceItem.touchPressCount, 2);
2370− compare(topmostSurfaceItem.touchReleaseCount, 2);
2375+ tryCompare(topmostSurfaceItem, "touchPressCount", 2);
2376+ tryCompare(topmostSurfaceItem, "touchReleaseCount", 2);
23712377 }
23722378
23732379 function test_background_data() {
@@ -2434,7 +2440,7 @@ Rectangle {
24342440 var appIcon = findChild(shell, "launcherDelegate0")
24352441 tap(appIcon);
24362442
2437− tryCompare(broadcastUrlSpy, "count", 1);
2443+ broadcastUrlSpy.wait();
24382444 compare(broadcastUrlSpy.signalArguments[0][0], "application:///" + appIcon.appId + ".desktop");
24392445 compare(ApplicationManager.count, 0); // confirm no app is open, we didn't start new app
24402446
@@ -2457,7 +2463,7 @@ Rectangle {
24572463 dragLauncherIntoView();
24582464 tap(findChild(shell, "buttonShowDashHome"));
24592465
2460− tryCompare(broadcastHomeSpy, "count", 1);
2466+ broadcastHomeSpy.wait();
24612467 compare(topLevelSurfaceList.applicationAt(0).appId, "gallery-app"); // confirm we didn't raise dash
24622468
24632469 var coverPage = findChild(shell, "coverPage");
@@ -2475,7 +2481,7 @@ Rectangle {
24752481 verify(urlDispatcher.active);
24762482 urlDispatcher.urlRequested("test:"); // force signal emission
24772483
2478− tryCompare(broadcastUrlSpy, "count", 1);
2484+ broadcastUrlSpy.wait();
24792485 compare(broadcastUrlSpy.signalArguments[0][0], "test:");
24802486 compare(ApplicationManager.count, 0); // confirm no app is open, we didn't start new app
24812487
@@ -2772,7 +2778,7 @@ Rectangle {
27722778 GSettingsController.setEnableLauncher(data.enabled);
27732779
27742780 var launcher = findChild(shell, "launcher");
2775− compare(launcher.available, data.enabled);
2781+ tryCompare(launcher, "available", data.enabled);
27762782
27772783 GSettingsController.setEnableLauncher(true);
27782784 }
@@ -2790,7 +2796,7 @@ Rectangle {
27902796 GSettingsController.setEnableIndicatorMenu(data.enabled);
27912797
27922798 var panel = findChild(shell, "panel");
2793− compare(panel.indicators.available, data.enabled);
2799+ tryCompare(panel.indicators, "available", data.enabled);
27942800
27952801 GSettingsController.setEnableIndicatorMenu(true);
27962802 }
@@ -2910,7 +2916,7 @@ Rectangle {
29102916
29112917 var panel = findChild(shell, "panel"); verify(panel);
29122918 var panelTitle = findChild(panel, "panelTitle"); verify(panelTitle);
2913− compare(panelTitle.visible, false, "Panel title should not be visible when greeter is shown");
2919+ tryCompare(panelTitle, "visible", false, 5000, "Panel title should not be visible when greeter is shown");
29142920
29152921 swipeAwayGreeter();
29162922
@@ -3097,9 +3103,9 @@ Rectangle {
30973103 var launcher = testCase.findChild(shell, "launcher");
30983104 launcher.lockedVisible = data.lockLauncher;
30993105 if (data.lockLauncher) {
3100− compare(panel.applicationMenus.x, launcher.panelWidth);
3106+ tryCompare(panel.applicationMenus, "x", launcher.panelWidth);
31013107 } else {
3102− compare(panel.applicationMenus.x, 0);
3108+ tryCompare(panel.applicationMenus, "x", 0);
31033109 }
31043110 }
31053111