@@ -0,0 +1,201 @@
1+/*
2+ * Copyright 2014-2016 Canonical Ltd.
3+ * Copyright 2019 UBports Foundation
4+ *
5+ * This program is free software; you can redistribute it and/or modify
6+ * it under the terms of the GNU General Public License as published by
7+ * the Free Software Foundation; version 3.
8+ *
9+ * This program is distributed in the hope that it will be useful,
10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+ * GNU General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU General Public License
15+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16+ */
17+
18+import QtQuick 2.4
19+import QtTest 1.0
20+import Unity.Test 0.1 as UT
21+import ".."
22+import "../../../qml/Components"
23+import "../../../qml/Stage"
24+import Ubuntu.Components 1.3
25+import Unity.Application 0.1
26+import WindowManager 1.0
27+
28+Item {
29+ id: root
30+ width: units.gu(70)
31+ height: units.gu(70)
32+
33+ property var greeter: { fullyShown: true }
34+
35+ SurfaceManager { id: sMgr }
36+ ApplicationMenuDataLoader {
37+ id: appMenuData
38+ surfaceManager: sMgr
39+ }
40+
41+ Loader {
42+ id: loader
43+ active: true;
44+
45+ sourceComponent: Stage {
46+ id: stage
47+ anchors { fill: parent; rightMargin: units.gu(30) }
48+ focus: true
49+ dragAreaWidth: units.gu(2)
50+ allowInteractivity: true
51+ shellOrientation: Qt.PortraitOrientation
52+ orientations: Orientations {}
53+ applicationManager: ApplicationManager
54+ mode: "staged"
55+ topLevelSurfaceList: TopLevelWindowModel {
56+ id: topLevelWindowModel
57+ applicationManager: ApplicationManager
58+ surfaceManager: sMgr
59+ }
60+ availableDesktopArea: availableDesktopAreaItem
61+ Item {
62+ id: availableDesktopAreaItem
63+ anchors.fill: parent
64+ }
65+ }
66+ }
67+
68+ Flickable {
69+ contentHeight: controlRect.height
70+
71+ anchors.top: root.top
72+ anchors.bottom: root.bottom
73+ anchors.right: root.right
74+ width: units.gu(30)
75+ Rectangle {
76+ id: controlRect
77+ anchors { left: parent.left; right: parent.right }
78+ height: childrenRect.height + units.gu(2)
79+ color: "darkGrey"
80+ Column {
81+ anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
82+ spacing: units.gu(1)
83+ Repeater {
84+ model: ApplicationManager.availableApplications
85+ ApplicationCheckBox { appId: modelData }
86+ }
87+ }
88+ }
89+ }
90+
91+ property alias stage: loader.item
92+ property var tlwm: loader.item.topLevelSurfaceList
93+
94+ UT.UnityTestCase {
95+ id: testCase
96+ name: "PhoneStage"
97+ when: windowShown
98+
99+ function init() {
100+ loader.active = true;
101+ tryCompare(loader, "status", Loader.Ready);
102+ verify(stage);
103+ verify(tlwm);
104+ waitForRendering(stage);
105+ }
106+
107+ function cleanup() {
108+ killApps();
109+ loader.active = false;
110+ }
111+
112+ function findAppWindowForSurfaceId(surfaceId) {
113+ var delegateObjectName = "appDelegate_" + surfaceId;
114+ var spreadDelegate = findChild(stage, delegateObjectName);
115+ if (!spreadDelegate) {
116+ console.warn("Failed to find " + delegateObjectName + " in stage");
117+ return null;
118+ }
119+ var appWindow = findChild(spreadDelegate, "appWindow");
120+ return appWindow;
121+ }
122+
123+ // Waits until ApplicationWindow has moved from showing a splash screen to displaying
124+ // the application surface.
125+ function waitUntilAppSurfaceShowsUp(surfaceId) {
126+ var appWindow = findAppWindowForSurfaceId(surfaceId);
127+ verify(appWindow);
128+ var appWindowStates = findInvisibleChild(appWindow, "applicationWindowStateGroup");
129+ verify(appWindowStates);
130+ tryCompare(appWindowStates, "state", "surface");
131+ }
132+
133+ function addApps(count) {
134+ if (count == undefined) count = 1;
135+ for (var i = 0; i < count; i++) {
136+ var startingAppId = ApplicationManager.availableApplications[ApplicationManager.count];
137+ var appSurfaceId = tlwm.nextId;
138+ var app = ApplicationManager.startApplication(startingAppId)
139+ tryCompare(app, "state", ApplicationInfoInterface.Running)
140+ waitUntilAppSurfaceShowsUp(appSurfaceId);
141+ waitForRendering(stage)
142+ tryCompare(ApplicationManager, "focusedApplicationId", startingAppId)
143+ }
144+ }
145+
146+ /*
147+ Ensure that closing a surface while rootFocus is off focuses the
148+ next available surface when rootFocus is given back.
149+
150+ Regression test for https://github.com/ubports/unity8/issues/234
151+
152+ This cannot be tested in tst_TopLevelWindowModel.cpp, the mocks for
153+ it are not advanced enough.
154+ */
155+ function test_closeLastFocusedApp()
156+ {
157+ var dialerApp = ApplicationManager.startApplication("dialer-app");
158+ var webbrowserSurfaceId = tlwm.nextId;
159+ var webbrowserApp = ApplicationManager.startApplication("morph-browser");
160+ waitUntilAppSurfaceShowsUp(webbrowserSurfaceId);
161+
162+ tlwm.rootFocus = false;
163+
164+ ApplicationManager.stopApplication(webbrowserApp.appId);
165+ // It should be gone soon
166+ tryCompareFunction(function() { return tlwm.indexForId(webbrowserSurfaceId); }, -1);
167+
168+ tlwm.rootFocus = true;
169+ compare(dialerApp.focused, true);
170+ }
171+
172+ /*
173+ Ensure that we can handle issuing windows up to maxWindowId,
174+ including reusing IDs once we're exhausted.
175+ */
176+ function test_issueAllTheIds()
177+ {
178+ tlwm.maxWindowId = 5;
179+
180+ // Start an app ourselves so we can close it
181+ var nextAppId = ApplicationManager.availableApplications[5];
182+ var app = ApplicationManager.startApplication(nextAppId);
183+ var appWindowId = tlwm.idAt(0);
184+
185+ // Add four more apps to bring us to five
186+ addApps(4);
187+
188+ ApplicationManager.stopApplication(app.appId);
189+ // It should be gone soon
190+ tryCompareFunction(function() { return tlwm.indexForId(appWindowId); }, -1);
191+
192+ // And now we can start a new one
193+ var appAgain = ApplicationManager.startApplication(nextAppId);
194+ verify(appAgain);
195+
196+ // The new app should have taken the ID of the closed app since
197+ // we're under contention.
198+ tryCompareFunction(function() { return tlwm.indexForId(appWindowId); }, 0);
199+ }
200+ }
201+}