@@ -19,6 +19,7 @@ import QtTest 1.0
1919import AccountsService 0.1
2020import IntegratedLightDM 0.1 as LightDM
2121import Ubuntu.Components 1.3
22+import Ubuntu.Components.ListItems 1.3
2223import Ubuntu.Telephony 0.1 as Telephony
2324import Unity.Application 0.1
2425import Unity.Test 0.1 as UT
@@ -26,10 +27,11 @@ import Unity.Test 0.1 as UT
2627import "../../../qml"
2728import "../../../qml/Components"
2829
29−Item {
30+Rectangle {
3031 id: root
31− width: shellLoader.width + buttons.width
32− height: shellLoader.height
32+ color: UbuntuColors.lightGrey
33+ width: units.gu(100) + buttons.width
34+ height: units.gu(71)
3335
3436 QtObject {
3537 id: applicationArguments
@@ -59,24 +61,62 @@ Item {
5961 shellLoader.active = true;
6062 }
6163
62− Row {
63− spacing: 0
64− anchors.fill: parent
64+ Item {
65+ id: shellContainer
66+ anchors.left: root.left
67+ anchors.right: buttons.left
68+ anchors.top: root.top
69+ anchors.bottom: root.bottom
6570
6671 Loader {
6772 id: shellLoader
6873
6974 active: false
70− width: units.gu(40)
71− height: units.gu(71)
75+ anchors.horizontalCenter: parent.horizontalCenter
76+ anchors.top: parent.top
77+ anchors.bottom: parent.bottom
78+
79+ property int shellOrientation: Qt.PortraitOrientation
80+ property int nativeOrientation: Qt.PortraitOrientation
81+ property int primaryOrientation: Qt.PortraitOrientation
82+
83+ state: modeSelector.model[modeSelector.selectedIndex]
84+ states: [
85+ State {
86+ name: "phone"
87+ PropertyChanges {
88+ target: shellLoader
89+ width: units.gu(40)
90+ }
91+ },
92+ State {
93+ name: "tablet"
94+ PropertyChanges {
95+ target: shellLoader
96+ width: units.gu(100)
97+ shellOrientation: Qt.LandscapeOrientation
98+ nativeOrientation: Qt.LandscapeOrientation
99+ primaryOrientation: Qt.LandscapeOrientation
100+ }
101+ },
102+ State {
103+ name: "desktop"
104+ PropertyChanges {
105+ target: shellLoader
106+ width: units.gu(100)
107+ }
108+ }
109+ ]
72110
73111 property bool itemDestroyed: false
74112 sourceComponent: Component {
75113 Shell {
114+ usageScenario: shellLoader.state
76115 property string indicatorProfile: "phone"
116+ orientation: shellLoader.shellOrientation
77117 orientations: Orientations {
78− native_: Qt.PortraitOrientation
79− primary: Qt.PortraitOrientation
118+ native_: shellLoader.nativeOrientation
119+ primary: shellLoader.primaryOrientation
80120 }
81121
82122 Component.onDestruction: {
@@ -85,102 +125,92 @@ Item {
85125 }
86126 }
87127 }
128+ }
88129
89− Rectangle {
90− id: buttons
91− color: "black"
92− width: units.gu(30)
93− height: shellLoader.height
94−
95− Column {
96− anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
97− spacing: units.gu(1)
98− Row {
99− anchors { left: parent.left; right: parent.right }
100− Button {
101− text: "Hide Greeter"
102− onClicked: {
103− if (shellLoader.status !== Loader.Ready)
104− return;
105−
106− var greeter = testCase.findChild(shellLoader.item, "greeter");
107− if (greeter.shown) {
108− greeter.hide();
109− }
130+ Rectangle {
131+ id: buttons
132+ color: UbuntuColors.darkGrey
133+ width: units.gu(30)
134+ anchors.top: root.top
135+ anchors.bottom: root.bottom
136+ anchors.right: root.right
137+
138+ Column {
139+ anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
140+ spacing: units.gu(1)
141+ Row {
142+ anchors { left: parent.left; right: parent.right }
143+ Button {
144+ text: "Hide Greeter"
145+ onClicked: {
146+ if (shellLoader.status !== Loader.Ready)
147+ return;
148+
149+ var greeter = testCase.findChild(shellLoader.item, "greeter");
150+ if (greeter.shown) {
151+ greeter.hide();
110152 }
111153 }
112154 }
155+ }
113156
114− Row {
115− anchors { left: parent.left; right: parent.right }
116− Button {
117− text: "Restart Tutorial"
118− onClicked: {
119− if (shellLoader.status !== Loader.Ready)
120− return;
121−
122− AccountsService.demoEdges = false;
123− AccountsService.demoEdgesCompleted = [];
124− AccountsService.demoEdges = true;
125− }
157+ Row {
158+ anchors { left: parent.left; right: parent.right }
159+ Button {
160+ text: "Restart Tutorial"
161+ onClicked: {
162+ if (shellLoader.status !== Loader.Ready)
163+ return;
164+
165+ AccountsService.demoEdges = false;
166+ AccountsService.demoEdgesCompleted = [];
167+ AccountsService.demoEdges = true;
126168 }
127169 }
170+ }
128171
129− Row {
130− anchors { left: parent.left; right: parent.right }
131− CheckBox {
132− onCheckedChanged: {
133− if (checked) {
134− callManager.foregroundCall = phoneCall;
135− } else {
136− callManager.foregroundCall = null;
137− }
172+ Row {
173+ anchors { left: parent.left; right: parent.right }
174+ CheckBox {
175+ onCheckedChanged: {
176+ if (checked) {
177+ callManager.foregroundCall = phoneCall;
178+ } else {
179+ callManager.foregroundCall = null;
138180 }
139181 }
140− Label {
141− text: "Active Call"
142− anchors.verticalCenter: parent.verticalCenter
143− }
144182 }
145−
146− Row {
147− anchors { left: parent.left; right: parent.right }
148− CheckBox {
149− activeFocusOnPress: false
150− onCheckedChanged: {
151− var surface = SurfaceManager.inputMethodSurface();
152− if (checked) {
153− surface.setState(Mir.RestoredState);
154− } else {
155− surface.setState(Mir.MinimizedState);
156− }
157− }
158− }
159− Label {
160− text: "Input Method"
161− anchors.verticalCenter: parent.verticalCenter
162− }
183+ Label {
184+ text: "Active Call"
185+ anchors.verticalCenter: parent.verticalCenter
163186 }
187+ }
164188
165− Row {
166− anchors { left: parent.left; right: parent.right }
167− CheckBox {
168− onCheckedChanged: {
169− if (shellLoader.status !== Loader.Ready)
170− return;
171−
172− if (checked) {
173− shellLoader.item.usageScenario = "desktop";
174− } else {
175− shellLoader.item.usageScenario = "phone";
176− }
189+ Row {
190+ anchors { left: parent.left; right: parent.right }
191+ CheckBox {
192+ activeFocusOnPress: false
193+ onCheckedChanged: {
194+ var surface = SurfaceManager.inputMethodSurface();
195+ if (checked) {
196+ surface.setState(Mir.RestoredState);
197+ } else {
198+ surface.setState(Mir.MinimizedState);
177199 }
178200 }
179− Label {
180− text: "Desktop Mode"
181− anchors.verticalCenter: parent.verticalCenter
182− }
183201 }
202+ Label {
203+ text: "Input Method"
204+ anchors.verticalCenter: parent.verticalCenter
205+ }
206+ }
207+
208+ ItemSelector {
209+ id: modeSelector
210+ anchors { left: parent.left; right: parent.right }
211+ activeFocusOnPress: false
212+ text: "Mode"
213+ model: ["phone", "tablet", "desktop"]
184214 }
185215 }
186216 }
@@ -195,24 +225,21 @@ Item {
195225 property real halfHeight: shell ? shell.height / 2 : 0
196226
197227 function init() {
198− tryCompare(shell, "enabled", true); // enabled by greeter when ready
199−
200− shell.usageScenario = "phone";
201− callManager.foregroundCall = null;
202− AccountsService.demoEdges = false;
203− AccountsService.demoEdgesCompleted = [];
204− AccountsService.demoEdges = true;
205−
206− LightDM.Greeter.hideGreeter();
228+ prepareShell();
207229
208230 var tutorialLeft = findChild(shell, "tutorialLeft");
209231 tryCompare(tutorialLeft, "opacity", 1);
210232 }
211233
212234 function cleanup() {
235+ resetLoader("phone");
236+ }
237+
238+ function resetLoader(state) {
213239 shellLoader.itemDestroyed = false;
214240
215241 shellLoader.active = false;
242+ shellLoader.state = state;
216243
217244 tryCompare(shellLoader, "status", Loader.Null);
218245 tryCompare(shellLoader, "item", null);
@@ -224,9 +251,14 @@ Item {
224251 // Shell instance gets destroyed.
225252 tryCompare(shellLoader, "itemDestroyed", true);
226253
254+ // Reset any futzing our tests may have done with persistent objects
255+ var app = ApplicationManager.findApplication("dialer-app");
256+ if (app) {
257+ app.setStage(ApplicationInfoInterface.SideStage);
258+ }
259+ SurfaceManager.inputMethodSurface().destroy(); // so that InputMethod will notice new one
227260 // kill all (fake) running apps
228261 killApps();
229− SurfaceManager.inputMethodSurface().destroy(); // so that InputMethod will notice new one
230262
231263 // reload our test subject to get it in a fresh state once again
232264 shellLoader.active = true;
@@ -235,6 +267,22 @@ Item {
235267 removeTimeConstraintsFromDirectionalDragAreas(shellLoader.item);
236268 }
237269
270+ function prepareShell() {
271+ tryCompare(shell, "enabled", true); // enabled by greeter when ready
272+
273+ callManager.foregroundCall = null;
274+ AccountsService.demoEdges = false;
275+ AccountsService.demoEdgesCompleted = [];
276+ AccountsService.demoEdges = true;
277+
278+ LightDM.Greeter.hideGreeter();
279+ }
280+
281+ function loadShell(state) {
282+ resetLoader(state);
283+ prepareShell();
284+ }
285+
238286 function killApps() {
239287 while (ApplicationManager.count > 1) {
240288 var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
@@ -273,9 +321,8 @@ Item {
273321 var tutorialRight = findChild(shell, "tutorialRight");
274322
275323 AccountsService.demoEdgesCompleted = ["left", "top"];
276− ApplicationManager.startApplication("dialer-app");
277− ApplicationManager.startApplication("camera-app");
278− ApplicationManager.startApplication("messaging-app");
324+ ApplicationManager.startApplication("gallery-app");
325+ ApplicationManager.startApplication("facebook-webapp");
279326
280327 tryCompare(tutorialLeft, "visible", false);
281328 tryCompare(tutorialRight, "shown", true);
@@ -359,7 +406,7 @@ Item {
359406 // Just confirm that a long drag ("dash" drag) doesn't confuse us
360407
361408 // So that we actually switch to dash and launcher hides
362− ApplicationManager.startApplication("dialer-app");
409+ ApplicationManager.startApplication("gallery-app");
363410
364411 var launcher = findChild(shell, "launcher");
365412 var tutorialLeft = findChild(shell, "tutorialLeft");
@@ -520,7 +567,7 @@ Item {
520567 tryCompare(AccountsService, "demoEdgesCompleted", ["left", "right"]);
521568 }
522569
523− /*function test_tutorialBottomEdges() {
570+ function test_tutorialBottomEdges() {
524571 var tutorial = findChild(shell, "tutorial");
525572 var tutorialBottom = findChild(tutorial, "tutorialBottom");
526573 var launcher = findChild(shell, "launcher");
@@ -537,9 +584,9 @@ Item {
537584 verify(!launcher.available);
538585 verify(!stage.spreadEnabled);
539586 verify(!panel.indicators.available);
540− }*/
587+ }
541588
542− /*function test_tutorialBottomFinish() {
589+ function test_tutorialBottomFinish() {
543590 var tutorial = findChild(shell, "tutorial");
544591 var tutorialBottom = findChild(tutorial, "tutorialBottom");
545592
@@ -549,24 +596,65 @@ Item {
549596 tryCompare(tutorialBottom, "shown", false);
550597 tryCompare(AccountsService, "demoEdgesCompleted", ["left", "top", "right", "bottom"]);
551598 tryCompare(AccountsService, "demoEdges", false);
552− }*/
599+ }
553600
554− /*function test_tutorialBottomDelay() {
555− // Test that if we exit the right tutorial, we don't immediately
556− // jump into bottom tutorial.
601+ function test_tutorialBottomAppearsBeforeRight() {
602+ // Confirm that if bottom edge and right edge would appear on the
603+ // the same app open, bottom edge appears first. (this is a lightly
604+ // edited version of openTutorialRight)
605+ var tutorialLeft = findChild(shell, "tutorialLeft");
606+ var tutorialRight = findChild(shell, "tutorialRight");
557607 var tutorialBottom = findChild(shell, "tutorialBottom");
558− var tutorialBottomTimer = findInvisibleChild(tutorialBottom, "tutorialBottomTimer");
559608
560− tutorialBottomTimer.interval = 1;
561− openTutorialRight();
562− ApplicationManager.requestFocusApplication("dialer-app");
563− tryCompare(ApplicationManager, "focusedApplicationId", "dialer-app");
609+ AccountsService.demoEdgesCompleted = ["left", "top"];
610+ ApplicationManager.startApplication("gallery-app");
611+ ApplicationManager.startApplication("dialer-app");
564612
565− AccountsService.demoEdgesCompleted = ["left", "top", "right"];
566− verify(tutorialBottomTimer.running);
567− verify(!tutorialBottom.shown);
613+ tryCompare(tutorialLeft, "visible", false);
614+ tryCompare(tutorialRight, "visible", false);
568615 tryCompare(tutorialBottom, "shown", true);
569− }*/
616+ tryCompare(tutorialBottom, "opacity", 1);
617+ }
618+
619+ function test_tutorialBottomOnlyCoversSideStageOnTablet() {
620+ loadShell("tablet");
621+
622+ var tutorialBottom = findChild(shell, "tutorialBottom");
623+ var targetHeight = shell.height - units.gu(4);
624+ var mainStageX = units.gu(20);
625+ var sideStageX = shell.width - units.gu(20);
626+
627+ openTutorialBottom();
628+
629+ touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, true, false);
630+ compare(tutorialBottom.opacity, 1);
631+ touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, false, true);
632+
633+ touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, true, false);
634+ verify(tutorialBottom.opacity < 1);
635+ touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, false, true);
636+ }
637+
638+ function test_tutorialBottomOnlyCoversMainStageOnTablet() {
639+ loadShell("tablet");
640+
641+ var tutorialBottom = findChild(shell, "tutorialBottom");
642+ var targetHeight = shell.height - units.gu(4);
643+ var mainStageX = units.gu(20);
644+ var sideStageX = shell.width - units.gu(20);
645+
646+ openTutorialBottom();
647+ var app = ApplicationManager.findApplication("dialer-app");
648+ app.setStage(ApplicationInfoInterface.MainStage);
649+
650+ touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, true, false);
651+ compare(tutorialBottom.opacity, 1);
652+ touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, false, true);
653+
654+ touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, true, false);
655+ verify(tutorialBottom.opacity < 1);
656+ touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, false, true);
657+ }
570658
571659 function test_activeCallInterruptsTutorial() {
572660 var tutorialLeft = findChild(shell, "tutorialLeft");
@@ -622,21 +710,20 @@ Item {
622710 }
623711
624712 function test_desktopOnlyShowsTutorialRight() {
625− shell.usageScenario = "desktop";
713+ loadShell("desktop");
626714
627715 var tutorialLeft = findChild(shell, "tutorialLeft");
628716 var tutorialTop = findChild(shell, "tutorialTop");
629717 var tutorialRight = findChild(shell, "tutorialRight");
630− //var tutorialBottom = findChild(shell, "tutorialBottom");
718+ var tutorialBottom = findChild(shell, "tutorialBottom");
631719 verify(tutorialLeft.skipped);
632720 verify(tutorialTop.skipped);
633721 verify(!tutorialRight.skipped);
634− //verify(tutorialBottom.skipped);
722+ verify(tutorialBottom.skipped);
635723 compare(AccountsService.demoEdgesCompleted, []);
636724
637725 ApplicationManager.startApplication("dialer-app");
638726 ApplicationManager.startApplication("camera-app");
639− ApplicationManager.startApplication("messaging-app");
640727 tryCompare(tutorialRight, "isReady", true);
641728 tryCompare(tutorialRight, "shown", true);
642729 }