on xenial help sign in
Improve tst_Shell

- Ensure a fresh Shell instance before every single test is executed - Improve logic that checks whether the AppWindow of a given Application object is fully loaded (ie, ready for its surface to be interacted with) - Add a button that shows the greeter, for manual testing Approved by: Michael Terry

commit06e0a2e147ada76f8f10f2347d612bdf1fb27c45 authorDaniel d'Andrada <daniel.dandrada@canonical.com> dateThu 18 Sep 2014, 09:43 (12 years ago) parentc43869f9483802
2 files changed+91−22
qml/Stages/SpreadDelegate.qml+1 tests/qmltests/tst_Shell.qml+90−22
qml/Stages/SpreadDelegate.qml+1
@@ -57,6 +57,7 @@ Item {
5757
5858 ApplicationWindow {
5959 id: appWindow
60+ objectName: application ? "appWindow_" + application.appId : "appWindow_null"
6061 anchors {
6162 fill: parent
6263 topMargin: appWindow.fullscreen ? 0 : maximizedAppTopMargin
tests/qmltests/tst_Shell.qml+90−22
@@ -21,6 +21,7 @@ import QtQuick 2.0
2121import QtTest 1.0
2222import GSettings 1.0
2323import LightDM 0.1 as LightDM
24+import Ubuntu.Components 1.1
2425import Ubuntu.Telephony 0.1 as Telephony
2526import Unity.Application 0.1
2627import Unity.Connectivity 0.1
@@ -29,10 +30,9 @@ import Powerd 0.1
2930
3031import "../../qml"
3132
32−Item {
33+Row {
3334 id: root
34− width: shell.width
35− height: shell.height
35+ spacing: 0
3636
3737 QtObject {
3838 id: applicationArguments
@@ -50,13 +50,52 @@ Item {
5050 }
5151 }
5252
53− Shell {
54− id: shell
53+ Loader {
54+ id: shellLoader
55+
56+ // Copied from Shell.qml
57+ property bool tablet: false
58+ width: tablet ? units.gu(160)
59+ : applicationArguments.hasGeometry() ? applicationArguments.width()
60+ : units.gu(40)
61+ height: tablet ? units.gu(100)
62+ : applicationArguments.hasGeometry() ? applicationArguments.height()
63+ : units.gu(71)
64+
65+ property bool itemDestroyed: false
66+ sourceComponent: Component {
67+ Shell {
68+ Component.onDestruction: {
69+ shellLoader.itemDestroyed = true;
70+ }
71+ }
72+ }
5573 }
5674
57− Component {
58− id: shellComponent
59− Shell {}
75+ Rectangle {
76+ color: "white"
77+ width: units.gu(30)
78+ height: shellLoader.height
79+
80+ Column {
81+ anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
82+ spacing: units.gu(1)
83+ Row {
84+ anchors { left: parent.left; right: parent.right }
85+ Button {
86+ text: "Show Greeter"
87+ onClicked: {
88+ if (shellLoader.status !== Loader.Ready)
89+ return;
90+
91+ var greeter = testCase.findChild(shellLoader.item, "greeter");
92+ if (!greeter.shown) {
93+ greeter.show();
94+ }
95+ }
96+ }
97+ }
98+ }
6099 }
61100
62101 SignalSpy {
@@ -81,10 +120,13 @@ Item {
81120 }
82121
83122 UT.UnityTestCase {
123+ id: testCase
84124 name: "Shell"
85125 when: windowShown
86126
87− function initTestCase() {
127+ property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
128+
129+ function init() {
88130 swipeAwayGreeter();
89131
90132 sessionSpy.target = findChild(shell, "greeter")
@@ -92,17 +134,30 @@ Item {
92134 }
93135
94136 function cleanup() {
95− // If a test invoked the greeter, make sure we swipe it away again
96− var greeter = findChild(shell, "greeter");
97− if (greeter.shown) {
98− swipeAwayGreeter();
99− }
137+ shellLoader.itemDestroyed = false;
138+
139+ shellLoader.active = false;
140+
141+ tryCompare(shellLoader, "status", Loader.Null);
142+ tryCompare(shellLoader, "item", null);
143+ // Loader.status might be Loader.Null and Loader.item might be null but the Loader
144+ // item might still be alive. So if we set Loader.active back to true
145+ // again right now we will get the very same Shell instance back. So no reload
146+ // actually took place. Likely because Loader waits until the next event loop
147+ // iteration to do its work. So to ensure the reload, we will wait until the
148+ // Shell instance gets destroyed.
149+ tryCompare(shellLoader, "itemDestroyed", true);
100150
101151 // kill all (fake) running apps
102152 killApps(ApplicationManager);
103153
104− waitForUIToSettle();
105− hideIndicators();
154+ unlockAllModemsSpy.clear()
155+
156+ // reload our test subject to get it in a fresh state once again
157+ shellLoader.active = true;
158+
159+ tryCompare(shellLoader, "status", Loader.Ready);
160+ removeTimeConstraintsFromDirectionalDragAreas(shellLoader.item);
106161 }
107162
108163 function killApps() {
@@ -241,10 +296,27 @@ Item {
241296 tryCompare(item, "visible", false);
242297 }
243298
299+ // wait until any transition animation has finished
300+ function waitUntilTransitionsEnd(stateGroup) {
301+ var transitions = stateGroup.transitions;
302+ for (var i = 0; i < transitions.length; ++i) {
303+ var transition = transitions[i];
304+ tryCompare(transition, "running", false, 2000);
305+ }
306+ }
307+
308+ // Wait until the ApplicationWindow for the given Application object is fully loaded
309+ // (ie, the real surface has replaced the splash screen)
310+ function waitUntilAppWindowIsFullyLoaded(app) {
311+ var appWindow = findChild(shell, "appWindow_" + app.appId);
312+ var appWindowStateGroup = findInvisibleChild(appWindow, "applicationWindowStateGroup");
313+ tryCompareFunction(function() { return appWindowStateGroup.state === "surface" }, true);
314+ waitUntilTransitionsEnd(appWindowStateGroup);
315+ }
316+
244317 function test_surfaceLosesFocusWhilePanelIsOpen() {
245318 var app = ApplicationManager.startApplication("dialer-app");
246− // wait until the app is fully loaded (ie, real surface replaces splash screen)
247− tryCompareFunction(function() { return app.session !== null && app.session.surface !== null }, true);
319+ waitUntilAppWindowIsFullyLoaded(app);
248320
249321 tryCompare(app.session.surface, "focus", true);
250322
@@ -465,13 +537,9 @@ Item {
465537 }
466538
467539 function test_unlockAllModemsOnBoot() {
468− unlockAllModemsSpy.clear()
469− // actually create an object so we notice the onCompleted signal
470− var greeter = shellComponent.createObject(root)
471540 // TODO reenable when service ready (LP: #1361074)
472541 expectFail("", "Unlock on boot temporarily disabled");
473542 tryCompare(unlockAllModemsSpy, "count", 1)
474− greeter.destroy()
475543 }
476544 }
477545}