on xenial help sign in
merge dednick's branch
commit22f86a789d39d9a138eb41addc0812c01fb803b5 authorMichael Zanetti <michael.zanetti@canonical.com> dateWed 15 Apr 2015, 18:46 (12 years ago) parent3d59dc60ef484e
11 files changed+303−97
tests/mocks/GSettings.1.0/fake_gsettings.h+2−2 tests/mocks/GSettings.1.0/plugin.cpp+6 tests/mocks/Utils/CMakeLists.txt+2 tests/mocks/Utils/constants.cpp+23 tests/mocks/Utils/constants.h+43 tests/mocks/Utils/plugin.cpp+10−1 tests/qmltests/Stages/ApplicationCheckBox.qml+49−20 tests/qmltests/Stages/tst_DesktopStage.qml+56−67 tests/qmltests/tst_DesktopShell.qml → tests/qmltests/tst_DesktopShell.qml.THIS tests/qmltests/tst_Shell.qml+111−7 tests/utils/modules/Unity/Test/MouseTouchEmulationCheckbox.qml+1
tests/mocks/GSettings.1.0/fake_gsettings.h+2−2
@@ -78,10 +78,10 @@ public:
7878 ~GSettingsControllerQml();
7979
8080 QString pictureUri() const;
81− void setPictureUri(const QString &str);
81+ Q_INVOKABLE void setPictureUri(const QString &str);
8282
8383 QString usageMode() const;
84− void setUsageMode(const QString &usageMode);
84+ Q_INVOKABLE void setUsageMode(const QString &usageMode);
8585
8686Q_SIGNALS:
8787 void pictureUriChanged(const QString&);
tests/mocks/GSettings.1.0/plugin.cpp+6
@@ -19,8 +19,14 @@
1919
2020#include <QtQml/qqml.h>
2121
22+static QObject* controllerProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
23+{
24+ return GSettingsControllerQml::instance();
25+}
26+
2227void FakeGSettingsQmlPlugin::registerTypes(const char *uri)
2328{
29+ qmlRegisterSingletonType<GSettingsControllerQml>(uri, 1, 0, "GSettingsController", controllerProvider);
2430 qmlRegisterType<GSettingsQml>(uri, 1, 0, "GSettings");
2531 qmlRegisterUncreatableType<GSettingsSchemaQml>(uri, 1, 0, "GSettingsSchema",
2632 "GSettingsSchema can only be used inside of a GSettings component");
tests/mocks/Utils/CMakeLists.txt+2
@@ -19,6 +19,8 @@ set(QMLPLUGIN_SRC
1919 ${CMAKE_SOURCE_DIR}/plugins/Utils/easingcurve.cpp
2020 ${CMAKE_SOURCE_DIR}/plugins/Utils/inputwatcher.cpp
2121 ${CMAKE_SOURCE_DIR}/plugins/Utils/spreadflickable.cpp
22+ constants.cpp
23+ plugin.cpp
2224 windowstatestorage.cpp
2325 plugin.cpp
2426 )
tests/mocks/Utils/constants.cppnew file+23
@@ -0,0 +1,23 @@
1+/*
2+ * Copyright 2015 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+*/
16+
17+#include "constants.h"
18+
19+Constants::Constants(QObject *parent)
20+ : QObject(parent)
21+{
22+ m_indicatorValueTimeout = 5000;
23+}
tests/mocks/Utils/constants.hnew file+43
@@ -0,0 +1,43 @@
1+/*
2+ * Copyright 2015 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+*/
16+
17+#ifndef CONSTANTS_H
18+#define CONSTANTS_H
19+
20+#include <QObject>
21+
22+/**
23+ * @brief The Constants class
24+ *
25+ * This singleton class exposes contants to Qml
26+ *
27+ */
28+
29+class Constants: public QObject
30+{
31+ Q_OBJECT
32+ Q_PROPERTY(int indicatorValueTimeout READ indicatorValueTimeout CONSTANT)
33+
34+public:
35+ Constants(QObject *parent = 0);
36+
37+ int indicatorValueTimeout() const { return m_indicatorValueTimeout; }
38+
39+private:
40+ int m_indicatorValueTimeout;
41+};
42+
43+#endif
tests/mocks/Utils/plugin.cpp+10−1
@@ -25,15 +25,16 @@
2525
2626// local
2727#include "inputwatcher.h"
28−#include "easingcurve.h"
2928#include "qlimitproxymodelqml.h"
3029#include "unitysortfilterproxymodelqml.h"
3130#include "relativetimeformatter.h"
3231#include "timeformatter.h"
3332#include "unitymenumodelpaths.h"
3433#include "windowkeysfilter.h"
34+#include "easingcurve.h"
3535#include "windowstatestorage.h"
3636#include "spreadflickable.h"
37+#include "constants.h"
3738
3839static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
3940{
@@ -42,6 +43,13 @@ static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEn
4243 return new WindowStateStorage();
4344}
4445
46+static QObject *createConstants(QQmlEngine *engine, QJSEngine *scriptEngine)
47+{
48+ Q_UNUSED(engine)
49+ Q_UNUSED(scriptEngine)
50+ return new Constants();
51+}
52+
4553void FakeUtilsPlugin::registerTypes(const char *uri)
4654{
4755 Q_ASSERT(uri == QLatin1String("Utils"));
@@ -57,6 +65,7 @@ void FakeUtilsPlugin::registerTypes(const char *uri)
5765 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
5866 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
5967 qmlRegisterType<SpreadFlickable>(uri, 0, 1, "SpreadFlickable");
68+ qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants);
6069}
6170
6271void FakeUtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
tests/qmltests/Stages/ApplicationCheckBox.qml+49−20
@@ -22,27 +22,67 @@ import Unity.Application 0.1
2222RowLayout {
2323 id: root
2424 property string appId
25− property alias checked: checkbox.checked
25+ property bool checked: false
2626
2727 enabled: appId !== "unity8-dash"
2828
29+ onCheckedChanged: {
30+ if (d.bindGuard) { return; }
31+ d.bindGuard = true;
32+
33+ if (checked) {
34+ ApplicationManager.startApplication(root.appId);
35+ } else {
36+ ApplicationManager.stopApplication(root.appId);
37+ }
38+ d.bindGuard = false;
39+ }
40+
41+ QtObject {
42+ id: d
43+ property bool bindGuard: false
44+ property var application: null
45+ Component.onCompleted: {
46+ application = ApplicationManager.findApplication(root.appId);
47+ }
48+ }
49+
50+ Connections {
51+ target: ApplicationManager
52+ onCountChanged: {
53+ d.application = ApplicationManager.findApplication(root.appId);
54+ }
55+ }
56+
2957 Layout.fillWidth: true
3058 CheckBox {
3159 id: checkbox
3260 checked: false
3361 activeFocusOnPress: false
34− property bool noop: false
35− onCheckedChanged: {
36− if (noop) {
37− return;
38− }
62+
63+ onTriggered: {
64+ if (d.bindGuard) { return; }
65+ d.bindGuard = true;
66+
3967 if (checked) {
40− var application = ApplicationManager.startApplication(root.appId);
41− appConnections.target = application;
68+ ApplicationManager.startApplication(root.appId);
4269 } else {
43− appConnections.target = null;
4470 ApplicationManager.stopApplication(root.appId);
4571 }
72+ d.bindGuard = false;
73+ }
74+ onCheckedChanged: {
75+ if (d.bindGuard) { return; }
76+ d.bindGuard = true;
77+
78+ root.checked = checked;
79+
80+ d.bindGuard = false;
81+ }
82+ Binding {
83+ target: checkbox
84+ property: "checked"
85+ value: d.application != null
4686 }
4787 }
4888 Label {
@@ -50,15 +90,4 @@ RowLayout {
5090 color: "white"
5191 anchors.verticalCenter: parent.verticalCenter
5292 }
53−
54− Connections {
55− id: appConnections
56− onStateChanged: {
57− if (target.state == ApplicationInfoInterface.Stopped) {
58− checkbox.noop = true;
59− checkbox.checked = false;
60− checkbox.noop = false;
61− }
62− }
63− }
6493}
tests/qmltests/Stages/tst_DesktopStage.qml+56−67
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2013,2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@ import Ubuntu.Components 1.1
2020import Ubuntu.Components.ListItems 1.0 as ListItem
2121import Unity.Application 0.1
2222import Unity.Test 0.1
23+import Utils 0.1
2324
2425import "../../../qml/Stages"
2526
@@ -29,31 +30,18 @@ Rectangle {
2930 width: desktopStageLoader.width + controls.width
3031 height: desktopStageLoader.height
3132
32− QtObject {
33− id: fakeWindowStateStorage
34−
35− property var storedGeom: [
36− ["unity8-dash", Qt.rect(units.gu(2), units.gu(2), units.gu(50), units.gu(50))],
37− ["webbrowser-app", Qt.rect(units.gu(60), units.gu(2), units.gu(50), units.gu(50))]
38− ]
33+ Binding {
34+ target: MouseTouchAdaptor
35+ property: "enabled"
36+ value: false
37+ }
3938
40− function saveGeometry(windowId, geometry) {
41− for (var i = 0; i < storedGeom.length; ++i) {
42− if (storedGeom[i][0] === windowId) {
43− storedGeom[i][1] = geometry;
44− return;
45− }
46− }
47− // if new
48− storedGeom[storedGeom.length] = [windowId, geometry];
49− }
50− function getGeometry(windowId, defaultGeometry) {
51− for (var i = 0; i < storedGeom.length; ++i) {
52− if (storedGeom[i][0] === windowId) {
53− return storedGeom[i][1];
54− }
55− }
56− return defaultGeometry;
39+ Component.onCompleted: {
40+ // ensures apps which are tested decorations are in view.
41+ WindowStateStorage.geometry = {
42+ 'unity8-dash': Qt.rect(0, units.gu(3), units.gu(50), units.gu(40)),
43+ 'dialer-app': Qt.rect(units.gu(51), units.gu(3), units.gu(50), units.gu(40)),
44+ 'camera-app': Qt.rect(0, units.gu(44), units.gu(50), units.gu(40)),
5745 }
5846 }
5947
@@ -70,7 +58,6 @@ Rectangle {
7058 sourceComponent: Component {
7159 DesktopStage {
7260 anchors.fill: parent
73− windowStateStorage: fakeWindowStateStorage
7461 Component.onDestruction: {
7562 desktopStageLoader.itemDestroyed = true;
7663 }
@@ -145,57 +132,59 @@ Rectangle {
145132 tryCompare(appWindowStates, "state", "surface");
146133 }
147134
148− function rectsIntersect(aLocal, bLocal) {
149−
150− var a = aLocal.mapToItem(null, 0, 0, aLocal.width, aLocal.height);
151− var b = bLocal.mapToItem(null, 0, 0, bLocal.width, bLocal.height);
152−
153− return !((a.y+a.height) < b.y
154− || a.y > (b.y+b.height)
155− || (a.x+a.width) < b.x
156− || a.x > (b.x+b.width));
135+ function startApplication(appId) {
136+ var app = ApplicationManager.findApplication(appId);
137+ if (!app) {
138+ app = ApplicationManager.startApplication(appId);
139+ }
140+ verify(app);
141+ waitUntilAppSurfaceShowsUp(appId);
142+ verify(app.session.surface);
143+ return app;
157144 }
158145
159− function test_tappingOnWindowChangesFocusedApp() {
160− ApplicationManager.startApplication("webbrowser-app");
161− waitUntilAppSurfaceShowsUp("webbrowser-app");
162−
163− var webbrowserWindow = findChild(desktopStage, "appWindow_webbrowser-app");
164− verify(webbrowserWindow);
165− var dashWindow = findChild(desktopStage, "appWindow_unity8-dash");
166− verify(dashWindow);
146+ function test_appFocusSwitch_data() {
147+ return [
148+ {tag: "dash", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 0, focusTo: 1 },
149+ {tag: "dash", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 1, focusTo: 0 },
150+ ]
151+ }
167152
168− // some sanity check
169− compare(rectsIntersect(dashWindow, webbrowserWindow), false);
153+ function test_appFocusSwitch(data) {
154+ var i;
155+ for (i = 0; i < data.apps.length; i++) {
156+ startApplication(data.apps[i]);
157+ }
170158
171− tap(dashWindow);
172− compare(dashWindow.application.session.surface.activeFocus, true);
159+ ApplicationManager.requestFocusApplication(data.apps[data.focusfrom]);
160+ tryCompare(ApplicationManager.findApplication(data.apps[data.focusfrom]).session.surface, "activeFocus", true);
173161
174− tap(webbrowserWindow);
175− compare(webbrowserWindow.application.session.surface.activeFocus, true);
162+ ApplicationManager.requestFocusApplication(data.apps[data.focusTo]);
163+ tryCompare(ApplicationManager.findApplication(data.apps[data.focusTo]).session.surface, "activeFocus", true);
176164 }
177165
178− function test_tappingOnWindowTitleChangesFocusedApp() {
179− ApplicationManager.startApplication("webbrowser-app");
180− waitUntilAppSurfaceShowsUp("webbrowser-app");
181−
182− var webbrowserWindow = findChild(desktopStage, "decoratedWindow_webbrowser-app");
183− verify(webbrowserWindow);
184− var webbrowserWindowTitle = findChild(webbrowserWindow, "windowDecorationTitle");
185− verify(webbrowserWindowTitle);
186− var dashWindow = findChild(desktopStage, "decoratedWindow_unity8-dash");
187− verify(dashWindow);
188− var dashWindowTitle = findChild(dashWindow, "windowDecorationTitle");
189− verify(dashWindowTitle);
166+ function test_decorationPressFocusesApplication_data() {
167+ return [
168+ {tag: "dash", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 0, focusTo: 1 },
169+ {tag: "dash", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 1, focusTo: 0 },
170+ ]
171+ }
190172
191− // some sanity check
192− compare(rectsIntersect(dashWindow, webbrowserWindow), false);
173+ function test_decorationPressFocusesApplication(data) {
174+ var i;
175+ for (i = 0; i < data.apps.length; i++) {
176+ startApplication(data.apps[i]);
177+ }
193178
194− tap(dashWindowTitle);
195− compare(dashWindow.application.session.surface.activeFocus, true);
179+ var fromAppDecoration = findChild(desktopStage, "appWindowDecoration_" + data.apps[data.focusfrom]);
180+ verify(fromAppDecoration);
181+ mouseClick(fromAppDecoration);
182+ tryCompare(ApplicationManager.findApplication(data.apps[data.focusfrom]).session.surface, "activeFocus", true);
196183
197− tap(webbrowserWindowTitle);
198− compare(webbrowserWindow.application.session.surface.activeFocus, true);
184+ var toAppDecoration = findChild(desktopStage, "appWindowDecoration_" + data.apps[data.focusTo]);
185+ verify(toAppDecoration);
186+ mouseClick(toAppDecoration);
187+ tryCompare(ApplicationManager.findApplication(data.apps[data.focusTo]).session.surface, "activeFocus", true);
199188 }
200189 }
201190}
tests/qmltests/tst_DesktopShell.qml → tests/qmltests/tst_DesktopShell.qml.THISrenamed

The content is the same.

tests/qmltests/tst_Shell.qml+111−7
@@ -34,6 +34,7 @@ import Powerd 0.1
3434import Wizard 0.1 as Wizard
3535
3636import "../../qml"
37+import "Stages"
3738
3839Rectangle {
3940 id: root
@@ -65,6 +66,7 @@ Rectangle {
6566 }
6667
6768 Item {
69+ id: shellContainer
6870 anchors.left: root.left
6971 anchors.right: controls.left
7072 anchors.top: root.top
@@ -84,6 +86,11 @@ Rectangle {
8486 width: units.gu(40)
8587 height: units.gu(71)
8688 }
89+ StateChangeScript {
90+ script: {
91+ GSettingsController.setUsageMode("Staged")
92+ }
93+ }
8794 },
8895 State {
8996 name: "tablet"
@@ -92,6 +99,28 @@ Rectangle {
9299 width: units.gu(100)
93100 height: units.gu(71)
94101 }
102+ StateChangeScript {
103+ script: {
104+ GSettingsController.setUsageMode("Staged")
105+ }
106+ }
107+ },
108+ State {
109+ name: "desktop"
110+ PropertyChanges {
111+ target: shellLoader
112+ width: shellContainer.width
113+ height: shellContainer.height
114+ }
115+ PropertyChanges {
116+ target: mouseEmulation
117+ checked: false
118+ }
119+ StateChangeScript {
120+ script: {
121+ GSettingsController.setUsageMode("Windowed")
122+ }
123+ }
95124 }
96125 ]
97126
@@ -121,7 +150,6 @@ Rectangle {
121150 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
122151 spacing: units.gu(1)
123152 Row {
124− anchors { left: parent.left; right: parent.right }
125153 Button {
126154 text: "Show Greeter"
127155 activeFocusOnPress: false
@@ -135,6 +163,19 @@ Rectangle {
135163 }
136164 }
137165 }
166+ Button {
167+ text: "Hide Greeter"
168+ activeFocusOnPress: false
169+ onClicked: {
170+ if (shellLoader.status !== Loader.Ready)
171+ return;
172+
173+ var greeter = testCase.findChild(shellLoader.item, "greeter");
174+ if (greeter.shown) {
175+ greeter.hide()
176+ }
177+ }
178+ }
138179 }
139180 ListItem.ItemSelector {
140181 anchors { left: parent.left; right: parent.right }
@@ -152,13 +193,45 @@ Rectangle {
152193 anchors { left: parent.left; right: parent.right }
153194 activeFocusOnPress: false
154195 text: "Size"
155− model: ["phone", "tablet"]
196+ model: ["phone", "tablet", "desktop"]
156197 onSelectedIndexChanged: {
157198 shellLoader.active = false;
158199 shellLoader.state = model[selectedIndex];
159200 shellLoader.active = true;
160201 }
161− MouseTouchEmulationCheckbox { color: "white" }
202+ }
203+ MouseTouchEmulationCheckbox {
204+ id: mouseEmulation
205+ checked: true
206+ color: "white"
207+ }
208+
209+ Button {
210+ anchors { left: parent.left; right: parent.right }
211+ text: "Start all apps"
212+ onClicked: {
213+ for (var i = 0; i < appRepeater.count; i++) {
214+ var appId = ApplicationManager.availableApplications[i]
215+ if (!ApplicationManager.findApplication(appId)) {
216+ ApplicationManager.startApplication(appId)
217+ }
218+ }
219+ }
220+ }
221+
222+ Column {
223+ anchors { left: parent.left; right: parent.right }
224+ spacing: units.gu(1)
225+
226+ Label { text: "Applications"; font.bold: true }
227+
228+ Repeater {
229+ id: appRepeater
230+ model: ApplicationManager.availableApplications
231+ ApplicationCheckBox {
232+ appId: modelData
233+ }
234+ }
162235 }
163236 }
164237 }
@@ -237,6 +310,7 @@ Rectangle {
237310 }
238311
239312 function cleanup() {
313+ mouseEmulation.checked = true;
240314 tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
241315 tearDown();
242316 }
@@ -685,8 +759,9 @@ Rectangle {
685759
686760 function test_launchedAppHasActiveFocus_data() {
687761 return [
688− {tag:"phone", formFactor:"phone"},
689− {tag:"tablet", formFactor:"tablet"},
762+ {tag: "phone", formFactor: "phone"},
763+ {tag: "tablet", formFactor: "tablet"},
764+ {tag: "desktop", formFactor: "desktop"}
690765 ];
691766 }
692767
@@ -877,6 +952,7 @@ Rectangle {
877952 function test_greeterLoginsAutomaticallyWhenNoPasswordSet() {
878953 loadShell("phone");
879954 swipeAwayGreeter();
955+
880956 sessionSpy.clear();
881957 verify(sessionSpy.valid);
882958
@@ -1125,8 +1201,7 @@ Rectangle {
11251201 loadShell("phone");
11261202 swipeAwayGreeter();
11271203 AccountsService.backgroundFile = data.accounts;
1128− var backgroundSettings = findInvisibleChild(shell, "backgroundSettings");
1129− backgroundSettings.pictureUri = data.gsettings;
1204+ GSettingsController.setPictureUri(data.gsettings);
11301205
11311206 if (data.output === "defaultBackground") {
11321207 tryCompare(shell, "background", shell.defaultBackground);
@@ -1183,5 +1258,34 @@ Rectangle {
11831258 tryCompare(passwordInput, "focus", true)
11841259 }
11851260 }
1261+
1262+ function test_stageLoader_data() {
1263+ return [
1264+ {tag: "phone", source: "Stages/PhoneStage.qml"},
1265+ {tag: "tablet", source: "Stages/TabletStage.qml"},
1266+ {tag: "desktop", source: "Stages/DesktopStage.qml"}
1267+ ]
1268+ }
1269+
1270+ function test_stageLoader(data) {
1271+ loadShell(data.tag);
1272+ var stageLoader = findChild(shell, "applicationsDisplayLoader");
1273+ verify(String(stageLoader.source).indexOf(data.source) >= 0);
1274+ }
1275+
1276+ function test_launcherInverted_data() {
1277+ return [
1278+ {tag: "phone", formFactor: "phone"},
1279+ {tag: "tablet", formFactor: "tablet"},
1280+ {tag: "desktop", formFactor: "desktop"}
1281+ ];
1282+ }
1283+
1284+ function test_launcherInverted(data) {
1285+ loadShell(data.formFactor);
1286+
1287+ var launcher = findChild(shell, "launcher");
1288+ compare(launcher.inverted, data.formFactor !== "desktop");
1289+ }
11861290 }
11871291}
tests/utils/modules/Unity/Test/MouseTouchEmulationCheckbox.qml+1
@@ -22,6 +22,7 @@ import Unity.Test 0.1
2222RowLayout {
2323 id: root
2424 property alias color: label.color
25+ property alias checked: checkbox.checked
2526
2627 Binding {
2728 target: MouseTouchAdaptor