on xenial help sign in
Add tests for welcome wizard.
7eb3dd9Michael Terry
debian/control+4
@@ -33,6 +33,7 @@ Build-Depends: cmake,
33 python3-all:any,
33 python3-all:any,
34 python3-setuptools,
34 python3-setuptools,
35 python:any (>= 2.7),
35 python:any (>= 2.7),
36+ qml-module-qt-labs-folderlistmodel,
36 qml-module-qtquick-layouts,
37 qml-module-qtquick-layouts,
37 qml-module-qtquick-xmllistmodel,
38 qml-module-qtquick-xmllistmodel,
38 qml-module-qtquick2,
39 qml-module-qtquick2,
@@ -47,6 +48,7 @@ Build-Depends: cmake,
47 qtdeclarative5-qtmultimedia-plugin,
48 qtdeclarative5-qtmultimedia-plugin,
48 qtdeclarative5-ubuntu-settings-components (>= 0.4),
49 qtdeclarative5-ubuntu-settings-components (>= 0.4),
49 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239),
50 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239),
51+ qtdeclarative5-ubuntu-web-plugin,
50 ttf-ubuntu-font-family,
52 ttf-ubuntu-font-family,
51Standards-Version: 3.9.4
53Standards-Version: 3.9.4
52Homepage: http://launchpad.net/unity
54Homepage: http://launchpad.net/unity
@@ -84,10 +86,12 @@ Depends: gsettings-desktop-schemas,
84 libcap2-bin,
86 libcap2-bin,
85 libglib2.0-bin,
87 libglib2.0-bin,
86 qmenumodel-qml (>= 0.2.8),
88 qmenumodel-qml (>= 0.2.8),
89+ qml-module-qt-labs-folderlistmodel,
87 qml-module-qtquick-xmllistmodel,
90 qml-module-qtquick-xmllistmodel,
88 qtdeclarative5-gsettings1.0,
91 qtdeclarative5-gsettings1.0,
89 qtdeclarative5-qtmir-plugin (>= 0.4.4),
92 qtdeclarative5-qtmir-plugin (>= 0.4.4),
90 qtdeclarative5-ubuntu-telephony0.1,
93 qtdeclarative5-ubuntu-telephony0.1,
94+ qtdeclarative5-ubuntu-web-plugin,
91 ubuntu-system-settings,
95 ubuntu-system-settings,
92 unity-launcher-impl-4,
96 unity-launcher-impl-4,
93 unity8-common (= ${source:Version}),
97 unity8-common (= ${source:Version}),
plugins/Wizard/plugin.cpp+1−8
@@ -20,13 +20,6 @@
20
20
21#include <QtQml/qqml.h>
21#include <QtQml/qqml.h>
22
22
23−static QObject *pagelist_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
24−{
25− Q_UNUSED(engine)
26− Q_UNUSED(scriptEngine)
27− return new PageList();
28−}
29−
30static QObject *system_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
23static QObject *system_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
31{
24{
32 Q_UNUSED(engine)
25 Q_UNUSED(engine)
@@ -37,6 +30,6 @@ static QObject *system_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
37void WizardPlugin::registerTypes(const char *uri)
30void WizardPlugin::registerTypes(const char *uri)
38{
31{
39 Q_ASSERT(uri == QLatin1String("Wizard"));
32 Q_ASSERT(uri == QLatin1String("Wizard"));
40− qmlRegisterSingletonType<PageList>(uri, 0, 1, "PageList", pagelist_provider);
33+ qmlRegisterType<PageList>(uri, 0, 1, "PageList");
41 qmlRegisterSingletonType<System>(uri, 0, 1, "System", system_provider);
34 qmlRegisterSingletonType<System>(uri, 0, 1, "System", system_provider);
42}
35}
qml/Wizard/Page.qml+2
@@ -77,6 +77,7 @@ Item {
77
77
78 StackButton {
78 StackButton {
79 id: backButton
79 id: backButton
80+ objectName: "backButton"
80 width: buttonWidth
81 width: buttonWidth
81 anchors {
82 anchors {
82 left: parent.left
83 left: parent.left
@@ -94,6 +95,7 @@ Item {
94
95
95 Loader {
96 Loader {
96 id: forwardButton
97 id: forwardButton
98+ objectName: "forwardButton"
97 width: buttonWidth
99 width: buttonWidth
98 anchors {
100 anchors {
99 right: parent.right
101 right: parent.right
qml/Wizard/Pages.qml+11−4
@@ -22,6 +22,7 @@ import "../Components"
22
22
23Item {
23Item {
24 id: root
24 id: root
25+ objectName: "wizardPages"
25 focus: true
26 focus: true
26
27
27 // The background wallpaper to use
28 // The background wallpaper to use
@@ -36,6 +37,7 @@ Item {
36
37
37 UbuntuSecurityPrivacyPanel {
38 UbuntuSecurityPrivacyPanel {
38 id: securityPrivacy
39 id: securityPrivacy
40+ objectName: "securityPrivacy"
39 }
41 }
40
42
41 function quitWizard() {
43 function quitWizard() {
@@ -69,21 +71,26 @@ Item {
69 visible: status === Image.Ready
71 visible: status === Image.Ready
70 }
72 }
71
73
74+ PageList {
75+ id: pageList
76+ }
77+
72 PageStack {
78 PageStack {
73 id: pageStack
79 id: pageStack
80+ objectName: "pageStack"
74 anchors.fill: parent
81 anchors.fill: parent
75
82
76 function next() {
83 function next() {
77 // If we've opened any extra (non-main) pages, pop them before
84 // If we've opened any extra (non-main) pages, pop them before
78 // continuing so back button returns to the previous main page.
85 // continuing so back button returns to the previous main page.
79− while (PageList.index < pageStack.depth - 1)
86+ while (pageList.index < pageStack.depth - 1)
80 pop()
87 pop()
81− load(PageList.next())
88+ load(pageList.next())
82 }
89 }
83
90
84 function prev() {
91 function prev() {
85− if (PageList.index >= pageStack.depth - 1)
92+ if (pageList.index >= pageStack.depth - 1)
86− PageList.prev() // update PageList.index, but not for extra pages
93+ pageList.prev() // update pageList.index, but not for extra pages
87 pop()
94 pop()
88 if (!currentPage || currentPage.opacity === 0) { // undo skipped pages
95 if (!currentPage || currentPage.opacity === 0) { // undo skipped pages
89 prev()
96 prev()
qml/Wizard/Pages/10-welcome.qml+4
@@ -22,6 +22,8 @@ import Wizard 0.1
22import ".." as LocalComponents
22import ".." as LocalComponents
23
23
24LocalComponents.Page {
24LocalComponents.Page {
25+ objectName: "languagePage"
26+
25 title: i18n.tr("Hi!")
27 title: i18n.tr("Hi!")
26 forwardButtonSourceComponent: forwardButton
28 forwardButtonSourceComponent: forwardButton
27
29
@@ -57,6 +59,7 @@ LocalComponents.Page {
57
59
58 ComboButton {
60 ComboButton {
59 id: combo
61 id: combo
62+ objectName: "languageCombo"
60 anchors.left: parent.left
63 anchors.left: parent.left
61 anchors.right: parent.right
64 anchors.right: parent.right
62 text: listview.currentItem.text
65 text: listview.currentItem.text
@@ -67,6 +70,7 @@ LocalComponents.Page {
67 model: plugin.languageNames
70 model: plugin.languageNames
68 currentIndex: plugin.currentLanguage
71 currentIndex: plugin.currentLanguage
69 delegate: Standard {
72 delegate: Standard {
73+ objectName: "languageDelegate" + index
70 text: modelData
74 text: modelData
71 onClicked: {
75 onClicked: {
72 listview.currentIndex = index
76 listview.currentIndex = index
qml/Wizard/Pages/20-sim.qml+2
@@ -20,6 +20,8 @@ import Ubuntu.Components 0.1
20import ".." as LocalComponents
20import ".." as LocalComponents
21
21
22LocalComponents.Page {
22LocalComponents.Page {
23+ objectName: "simPage"
24+
23 title: i18n.tr("Add a SIM card and restart your device")
25 title: i18n.tr("Add a SIM card and restart your device")
24 forwardButtonSourceComponent: forwardButton
26 forwardButtonSourceComponent: forwardButton
25
27
qml/Wizard/Pages/30-passwd-type.qml+4
@@ -34,6 +34,8 @@ import ".." as LocalComponents
34
34
35LocalComponents.Page {
35LocalComponents.Page {
36 id: passwdPage
36 id: passwdPage
37+ objectName: "passwdPage"
38+
37 title: i18n.tr("Lock security")
39 title: i18n.tr("Lock security")
38 forwardButtonSourceComponent: forwardButton
40 forwardButtonSourceComponent: forwardButton
39
41
@@ -84,6 +86,8 @@ LocalComponents.Page {
84 selectedIndex: methodToIndex(root.passwordMethod)
86 selectedIndex: methodToIndex(root.passwordMethod)
85
87
86 delegate: OptionSelectorDelegate {
88 delegate: OptionSelectorDelegate {
89+ objectName: "passwdDelegate" + index
90+
87 // use subText because we want the text to be small, and we have no other way to control it
91 // use subText because we want the text to be small, and we have no other way to control it
88 subText: {
92 subText: {
89 var method = indexToMethod(index)
93 var method = indexToMethod(index)
qml/Wizard/Pages/40-wifi.qml+2
@@ -23,6 +23,8 @@ import ".." as LocalComponents
23
23
24LocalComponents.Page {
24LocalComponents.Page {
25 id: wifiPage
25 id: wifiPage
26+ objectName: "wifiPage"
27+
26 title: i18n.tr("Connect to Wi‑Fi")
28 title: i18n.tr("Connect to Wi‑Fi")
27 forwardButtonSourceComponent: forwardButton
29 forwardButtonSourceComponent: forwardButton
28
30
qml/Wizard/Pages/50-location.qml+10−9
@@ -22,29 +22,26 @@ import Ubuntu.Components 1.1
22import ".." as LocalComponents
22import ".." as LocalComponents
23
23
24LocalComponents.Page {
24LocalComponents.Page {
25+ objectName: "locationPage"
26+
25 title: i18n.tr("Location")
27 title: i18n.tr("Location")
26 forwardButtonSourceComponent: forwardButton
28 forwardButtonSourceComponent: forwardButton
27
29
28 property bool pathSet: AccountsService.hereLicensePathValid
30 property bool pathSet: AccountsService.hereLicensePathValid
29− property bool countSet: false
30− skipValid: pathSet && (AccountsService.hereLicensePath === "" || countSet)
31+ skipValid: pathSet && (AccountsService.hereLicensePath === "" || termsModel.count > 0)
31− skip: skipValid && (AccountsService.hereLicensePath === "" || termsModel.count === 0)
32+ skip: skipValid && (AccountsService.hereLicensePath === "" || termsModel.count === 2) // no files but . and ..
32−
33− Connections {
34− target: termsModel
35− onCountChanged: if (pathSet) countSet = true
36− }
37
33
38 FolderListModel {
34 FolderListModel {
39 id: termsModel
35 id: termsModel
40 folder: AccountsService.hereLicensePath
36 folder: AccountsService.hereLicensePath
41 nameFilters: ["*.html"]
37 nameFilters: ["*.html"]
42− showDirs: false
43 showOnlyReadable: true
38 showOnlyReadable: true
39+ showDotAndDotDot: true // so that count == 0 means we're not done scanning yet
44 }
40 }
45
41
46 QMenuModel.QDBusActionGroup {
42 QMenuModel.QDBusActionGroup {
47 id: locationActionGroup
43 id: locationActionGroup
44+ objectName: "locationActionGroup"
48 busType: QMenuModel.DBus.SessionBus
45 busType: QMenuModel.DBus.SessionBus
49 busName: "com.canonical.indicator.location"
46 busName: "com.canonical.indicator.location"
50 objectPath: "/com/canonical/indicator/location"
47 objectPath: "/com/canonical/indicator/location"
@@ -67,6 +64,7 @@ LocalComponents.Page {
67
64
68 LocalComponents.CheckableSetting {
65 LocalComponents.CheckableSetting {
69 id: gpsCheck
66 id: gpsCheck
67+ objectName: "gpsCheck"
70 showDivider: false
68 showDivider: false
71 text: i18n.tr("Using GPS only (less accurate)")
69 text: i18n.tr("Using GPS only (less accurate)")
72 onTriggered: {
70 onTriggered: {
@@ -83,6 +81,7 @@ LocalComponents.Page {
83
81
84 LocalComponents.CheckableSetting {
82 LocalComponents.CheckableSetting {
85 id: hereCheck
83 id: hereCheck
84+ objectName: "hereCheck"
86 showDivider: false
85 showDivider: false
87 text: i18n.tr("Using GPS, anonymized Wi-Fi and cellular network info (recommended)")
86 text: i18n.tr("Using GPS, anonymized Wi-Fi and cellular network info (recommended)")
88 checked: true
87 checked: true
@@ -94,6 +93,7 @@ LocalComponents.Page {
94 }
93 }
95
94
96 Label {
95 Label {
96+ objectName: "hereTermsLink"
97 anchors.left: parent.left
97 anchors.left: parent.left
98 anchors.leftMargin: hereCheck.labelOffset
98 anchors.leftMargin: hereCheck.labelOffset
99 anchors.right: parent.right
99 anchors.right: parent.right
@@ -107,6 +107,7 @@ LocalComponents.Page {
107
107
108 LocalComponents.CheckableSetting {
108 LocalComponents.CheckableSetting {
109 id: nopeCheck
109 id: nopeCheck
110+ objectName: "nopeCheck"
110 showDivider: false
111 showDivider: false
111 text: i18n.tr("Not at all")
112 text: i18n.tr("Not at all")
112 onTriggered: {
113 onTriggered: {
qml/Wizard/Pages/60-reporting.qml+2
@@ -19,6 +19,8 @@ import Ubuntu.Components 0.1
19import ".." as LocalComponents
19import ".." as LocalComponents
20
20
21LocalComponents.Page {
21LocalComponents.Page {
22+ objectName: "reportingPage"
23+
22 title: i18n.tr("Improving your experience")
24 title: i18n.tr("Improving your experience")
23 forwardButtonSourceComponent: forwardButton
25 forwardButtonSourceComponent: forwardButton
24
26
qml/Wizard/Pages/80-finished.qml+2
@@ -19,6 +19,8 @@ import Ubuntu.Components 0.1
19import ".." as LocalComponents
19import ".." as LocalComponents
20
20
21LocalComponents.Page {
21LocalComponents.Page {
22+ objectName: "finishedPage"
23+
22 title: i18n.tr("All done")
24 title: i18n.tr("All done")
23 forwardButtonSourceComponent: forwardButton
25 forwardButtonSourceComponent: forwardButton
24 hasBackButton: false
26 hasBackButton: false
qml/Wizard/Pages/here-terms.qml+4
@@ -22,6 +22,8 @@ import Ubuntu.Web 0.2
22import ".." as LocalComponents
22import ".." as LocalComponents
23
23
24LocalComponents.Page {
24LocalComponents.Page {
25+ objectName: "hereTermsPage"
26+
25 title: i18n.tr("Terms & Conditions")
27 title: i18n.tr("Terms & Conditions")
26 customBack: true
28 customBack: true
27
29
@@ -96,6 +98,7 @@ LocalComponents.Page {
96
98
97 Label {
99 Label {
98 id: termsLabel
100 id: termsLabel
101+ objectName: "termsLabel"
99 anchors.left: parent.left
102 anchors.left: parent.left
100 anchors.right: parent.right
103 anchors.right: parent.right
101 wrapMode: Text.Wrap
104 wrapMode: Text.Wrap
@@ -108,6 +111,7 @@ LocalComponents.Page {
108
111
109 WebView {
112 WebView {
110 id: webview
113 id: webview
114+ objectName: "webview"
111 anchors.left: parent.left
115 anchors.left: parent.left
112 anchors.right: parent.right
116 anchors.right: parent.right
113 height: parent.height
117 height: parent.height
qml/Wizard/Pages/passwd-confirm.qml+2−1
@@ -26,7 +26,8 @@ import "../../Components" as UnityComponents
26 */
26 */
27
27
28LocalComponents.Page {
28LocalComponents.Page {
29− id: passwdSetPage
29+ id: passwdConfirmPage
30+ objectName: "passwdConfirmPage"
30 forwardButtonSourceComponent: forwardButton
31 forwardButtonSourceComponent: forwardButton
31
32
32 skip: root.passwordMethod === UbuntuSecurityPrivacyPanel.Swipe
33 skip: root.passwordMethod === UbuntuSecurityPrivacyPanel.Swipe
qml/Wizard/Pages/passwd-set.qml+1
@@ -27,6 +27,7 @@ import "../../Components" as UnityComponents
27
27
28LocalComponents.Page {
28LocalComponents.Page {
29 id: passwdSetPage
29 id: passwdSetPage
30+ objectName: "passwdSetPage"
30 forwardButtonSourceComponent: forwardButton
31 forwardButtonSourceComponent: forwardButton
31
32
32 skip: root.passwordMethod === UbuntuSecurityPrivacyPanel.Swipe
33 skip: root.passwordMethod === UbuntuSecurityPrivacyPanel.Swipe
tests/mocks/AccountsService/AccountsService.cpp+7−1
@@ -138,7 +138,13 @@ QString AccountsService::hereLicensePath() const
138void AccountsService::setHereLicensePath(const QString &path)
138void AccountsService::setHereLicensePath(const QString &path)
139{
139{
140 // Path should always be valid (this code is all synchronous)
140 // Path should always be valid (this code is all synchronous)
141+ if (path == " ") {
141− m_hereLicensePath = path.isNull() ? "" : path;
142+ m_hereLicensePath = QString::null;
143+ } else if (path.isNull()) { // because qml collapses null and empty
144+ m_hereLicensePath = "";
145+ } else {
146+ m_hereLicensePath = path;
147+ }
142 hereLicensePathChanged();
148 hereLicensePathChanged();
143}
149}
144
150
tests/mocks/CMakeLists.txt+1
@@ -32,6 +32,7 @@ add_subdirectory(AccountsService)
32add_subdirectory(GSettings.1.0)
32add_subdirectory(GSettings.1.0)
33add_subdirectory(libusermetrics)
33add_subdirectory(libusermetrics)
34add_subdirectory(LightDM)
34add_subdirectory(LightDM)
35+add_subdirectory(MeeGo)
35add_subdirectory(Powerd)
36add_subdirectory(Powerd)
36add_subdirectory(QMenuModel)
37add_subdirectory(QMenuModel)
37add_subdirectory(Ubuntu)
38add_subdirectory(Ubuntu)
tests/mocks/MeeGo/CMakeLists.txtnew file+1
@@ -0,0 +1 @@
1+add_subdirectory(QOfono)
tests/mocks/MeeGo/QOfono/CMakeLists.txtnew file+10
@@ -0,0 +1,10 @@
1+set(MOCK_QOFONO_SOURCES
2+ plugin.cpp
3+ MockQOfono.cpp
4+)
5+
6+add_library(MockQOfono MODULE ${MOCK_QOFONO_SOURCES})
7+
8+qt5_use_modules(MockQOfono Qml Quick Core)
9+
10+add_unity8_mock(MeeGo.QOfono 0.2 MeeGo/QOfono TARGETS MockQOfono)
tests/mocks/MeeGo/QOfono/MockOfonoManager.qmlnew file+23
@@ -0,0 +1,23 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.3
18+import MeeGo.QOfono 0.2
19+
20+Item {
21+ readonly property var modems: MockQOfono.modems
22+ readonly property bool available: MockQOfono.available
23+}
tests/mocks/MeeGo/QOfono/MockOfonoSimManager.qmlnew file+42
@@ -0,0 +1,42 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.3
18+import MeeGo.QOfono 0.2
19+
20+Item {
21+ id: simManager
22+
23+ property string modemPath
24+ readonly property alias present: d.present
25+
26+ QtObject {
27+ id: d
28+
29+ property bool present: false
30+
31+ function updatePresence() {
32+ d.present = MockQOfono.isModemPresent(simManager.modemPath)
33+ }
34+ }
35+
36+ onModemPathChanged: d.updatePresence()
37+
38+ Connections {
39+ target: MockQOfono
40+ onModemsChanged: d.updatePresence()
41+ }
42+}
tests/mocks/MeeGo/QOfono/MockQOfono.cppnew file+54
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "MockQOfono.h"
18+
19+MockQOfono::MockQOfono(QObject *parent)
20+ : QObject(parent),
21+ m_available(false),
22+ m_modems()
23+{
24+}
25+
26+bool MockQOfono::available() const
27+{
28+ return m_available;
29+}
30+
31+void MockQOfono::setAvailable(bool available)
32+{
33+ m_available = available;
34+ Q_EMIT availableChanged();
35+}
36+
37+QStringList MockQOfono::modems() const
38+{
39+ return m_modems.keys();
40+}
41+
42+void MockQOfono::setModems(const QStringList &modems, const QList<bool> &present)
43+{
44+ m_modems.clear();
45+ for (int i = 0; i < modems.length(); i++) {
46+ m_modems[modems[i]] = present[i];
47+ }
48+ Q_EMIT modemsChanged();
49+}
50+
51+bool MockQOfono::isModemPresent(const QString &modem)
52+{
53+ return m_modems.value(modem, false);
54+}
tests/mocks/MeeGo/QOfono/MockQOfono.hnew file+52
@@ -0,0 +1,52 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+// This class just exists as a backend for the instantiable Qml objects to pull
18+// from. It exists only for this mock plugin.
19+
20+#ifndef MOCK_QOFONO_H
21+#define MOCK_QOFONO_H
22+
23+#include <QObject>
24+#include <QMap>
25+#include <QStringList>
26+
27+class MockQOfono : public QObject
28+{
29+ Q_OBJECT
30+ Q_PROPERTY(bool available READ available WRITE setAvailable NOTIFY availableChanged)
31+ Q_PROPERTY(QStringList modems READ modems NOTIFY modemsChanged)
32+
33+public:
34+ explicit MockQOfono(QObject *parent = 0);
35+
36+ bool available() const;
37+ void setAvailable(bool available);
38+ QStringList modems() const;
39+
40+ Q_INVOKABLE void setModems(const QStringList &modems, const QList<bool> &present);
41+ Q_INVOKABLE bool isModemPresent(const QString &modem);
42+
43+Q_SIGNALS:
44+ void availableChanged();
45+ void modemsChanged();
46+
47+private:
48+ bool m_available;
49+ QMap<QString, bool> m_modems;
50+};
51+
52+#endif // MOCK_QOFONO_H
tests/mocks/MeeGo/QOfono/plugin.cppnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "plugin.h"
18+#include "MockQOfono.h"
19+
20+#include <QtQml>
21+
22+static QObject *mock_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
23+{
24+ Q_UNUSED(engine)
25+ Q_UNUSED(scriptEngine)
26+ return new MockQOfono();
27+}
28+
29+void BackendPlugin::registerTypes(const char *uri)
30+{
31+ Q_ASSERT(uri == QLatin1String("MeeGo.QOfono"));
32+ qmlRegisterSingletonType<MockQOfono>(uri, 0, 2, "MockQOfono", mock_provider); // just for mock
33+}
tests/mocks/MeeGo/QOfono/plugin.hnew file+31
@@ -0,0 +1,31 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef MOCK_QOFONO_PLUGIN_H
18+#define MOCK_QOFONO_PLUGIN_H
19+
20+#include <QQmlExtensionPlugin>
21+
22+class BackendPlugin : public QQmlExtensionPlugin
23+{
24+ Q_OBJECT
25+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
26+
27+public:
28+ void registerTypes(const char *uri);
29+};
30+
31+#endif // MOCK_QOFONO_PLUGIN_H
tests/mocks/MeeGo/QOfono/qmldirnew file+4
@@ -0,0 +1,4 @@
1+module MeeGo.QOfono
2+plugin MockQOfono
3+OfonoManager 0.2 MockOfonoManager.qml
4+OfonoSimManager 0.2 MockOfonoSimManager.qml
tests/mocks/QMenuModel/QDBusActionGroup.qml+12
@@ -21,6 +21,7 @@ import QtQuick 2.0
21import Ubuntu.Settings.Menus 0.1 as Menus
21import Ubuntu.Settings.Menus 0.1 as Menus
22
22
23QtObject {
23QtObject {
24+ id: actionGroup
24 property int busType
25 property int busType
25 property string busName
26 property string busName
26 property string objectPath
27 property string objectPath
@@ -78,6 +79,17 @@ QtObject {
78 'percent': 0.0
79 'percent': 0.0
79 }
80 }
80 }
81 }
82+ case "gps-detection-enabled":
83+ case "location-detection-enabled":
84+ return Qt.createQmlObject("
85+import QtQuick 2.3
86+QtObject {
87+ property bool valid: true
88+ property bool state: false
89+ function activate() {
90+ state = !state;
91+ }
92+}", actionGroup);
81 default:
93 default:
82 break;
94 break;
83 }
95 }
tests/mocks/Ubuntu/CMakeLists.txt+1
@@ -2,5 +2,6 @@ add_subdirectory(Connectivity)
2add_subdirectory(DownloadDaemonListener)
2add_subdirectory(DownloadDaemonListener)
3add_subdirectory(Payments)
3add_subdirectory(Payments)
4add_subdirectory(SystemImage)
4add_subdirectory(SystemImage)
5+add_subdirectory(SystemSettings)
5add_subdirectory(Telephony)
6add_subdirectory(Telephony)
6add_subdirectory(Thumbnailer)
7add_subdirectory(Thumbnailer)
tests/mocks/Ubuntu/SystemSettings/CMakeLists.txtnew file+2
@@ -0,0 +1,2 @@
1+add_subdirectory(LanguagePlugin)
2+add_subdirectory(SecurityPrivacy)
tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/CMakeLists.txtnew file+1
@@ -0,0 +1 @@
1+add_unity8_mock(Ubuntu.SystemSettings.LanguagePlugin 1.0 Ubuntu/SystemSettings/LanguagePlugin)
tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/MockLanguagePlugin.qmlnew file+23
@@ -0,0 +1,23 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.3
18+
19+Item {
20+ property var languageNames: ["English", "French", "Spanish"]
21+ property var languageCodes: ["en", "fr", "es"]
22+ property int currentLanguage: 0
23+}
tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module Ubuntu.SystemSettings.LanguagePlugin
2+UbuntuLanguagePlugin 1.0 MockLanguagePlugin.qml
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/CMakeLists.txtnew file+10
@@ -0,0 +1,10 @@
1+set(MOCK_SECURITYPRIVACY_SOURCES
2+ plugin.cpp
3+ MockSecurityPrivacy.cpp
4+)
5+
6+add_library(MockSecurityPrivacy MODULE ${MOCK_SECURITYPRIVACY_SOURCES})
7+
8+qt5_use_modules(MockSecurityPrivacy Qml Quick Core)
9+
10+add_unity8_mock(Ubuntu.SystemSettings.SecurityPrivacy 1.0 Ubuntu/SystemSettings/SecurityPrivacy TARGETS MockSecurityPrivacy)
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.cppnew file+28
@@ -0,0 +1,28 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "MockSecurityPrivacy.h"
18+
19+MockSecurityPrivacy::MockSecurityPrivacy(QObject *parent)
20+ : QObject(parent)
21+{
22+}
23+
24+QString MockSecurityPrivacy::setSecurity(const QString &oldPasswd, const QString &newPasswd, SecurityType newType)
25+{
26+ Q_EMIT setSecurityCalled(oldPasswd, newPasswd, newType);
27+ return "";
28+}
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.hnew file+42
@@ -0,0 +1,42 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef MOCK_SECURITYPRIVACY_H
18+#define MOCK_SECURITYPRIVACY_H
19+
20+#include <QObject>
21+
22+class MockSecurityPrivacy : public QObject
23+{
24+ Q_OBJECT
25+ Q_ENUMS(SecurityType)
26+
27+public:
28+ enum SecurityType {
29+ Swipe,
30+ Passcode,
31+ Passphrase,
32+ };
33+
34+ MockSecurityPrivacy(QObject *parent = 0);
35+
36+ Q_INVOKABLE QString setSecurity(const QString &oldPasswd, const QString &newPasswd, SecurityType newType);
37+
38+Q_SIGNALS:
39+ void setSecurityCalled(const QString &oldPasswd, const QString &newPasswd, SecurityType newType); // only in mock
40+};
41+
42+#endif // MOCK_SECURITYPRIVACY_H
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/plugin.cppnew file+26
@@ -0,0 +1,26 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "plugin.h"
18+#include "MockSecurityPrivacy.h"
19+
20+#include <QtQml>
21+
22+void BackendPlugin::registerTypes(const char *uri)
23+{
24+ Q_ASSERT(uri == QLatin1String("Ubuntu.SystemSettings.SecurityPrivacy"));
25+ qmlRegisterType<MockSecurityPrivacy>(uri, 1, 0, "UbuntuSecurityPrivacyPanel");
26+}
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/plugin.hnew file+31
@@ -0,0 +1,31 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef MOCK_SECURITYPRIVACY_PLUGIN_H
18+#define MOCK_SECURITYPRIVACY_PLUGIN_H
19+
20+#include <QQmlExtensionPlugin>
21+
22+class BackendPlugin : public QQmlExtensionPlugin
23+{
24+ Q_OBJECT
25+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
26+
27+public:
28+ void registerTypes(const char *uri);
29+};
30+
31+#endif // MOCK_SECURITYPRIVACY_PLUGIN_H
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module Ubuntu.SystemSettings.SecurityPrivacy
2+plugin MockSecurityPrivacy
tests/mocks/Wizard/MockSystem.cpp+2−1
@@ -33,6 +33,7 @@ void MockSystem::setWizardEnabled(bool enabled)
33 Q_EMIT wizardEnabledChanged();
33 Q_EMIT wizardEnabledChanged();
34}
34}
35
35
36−void MockSystem::updateSessionLanguage(const QString &)
36+void MockSystem::updateSessionLanguage(const QString &locale)
37{
37{
38+ Q_EMIT updateSessionLanguageCalled(locale);
38}
39}
tests/mocks/Wizard/MockSystem.h+1
@@ -36,6 +36,7 @@ public Q_SLOTS:
36
36
37Q_SIGNALS:
37Q_SIGNALS:
38 void wizardEnabledChanged();
38 void wizardEnabledChanged();
39+ void updateSessionLanguageCalled(const QString &locale); // only in mock
39
40
40private:
41private:
41 Q_DISABLE_COPY(MockSystem)
42 Q_DISABLE_COPY(MockSystem)
tests/mocks/Wizard/mockplugin.cpp+1−8
@@ -20,13 +20,6 @@
20
20
21#include <QtQml/qqml.h>
21#include <QtQml/qqml.h>
22
22
23−static QObject *pagelist_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
24−{
25− Q_UNUSED(engine)
26− Q_UNUSED(scriptEngine)
27− return new PageList();
28−}
29−
30static QObject *system_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
23static QObject *system_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
31{
24{
32 Q_UNUSED(engine)
25 Q_UNUSED(engine)
@@ -37,6 +30,6 @@ static QObject *system_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
37void MockWizardPlugin::registerTypes(const char *uri)
30void MockWizardPlugin::registerTypes(const char *uri)
38{
31{
39 Q_ASSERT(uri == QLatin1String("Wizard"));
32 Q_ASSERT(uri == QLatin1String("Wizard"));
40− qmlRegisterSingletonType<PageList>(uri, 0, 1, "PageList", pagelist_provider);
33+ qmlRegisterType<PageList>(uri, 0, 1, "PageList");
41 qmlRegisterSingletonType<MockSystem>(uri, 0, 1, "System", system_provider);
34 qmlRegisterSingletonType<MockSystem>(uri, 0, 1, "System", system_provider);
42}
35}
tests/plugins/Wizard/CMakeLists.txt+9−3
@@ -3,10 +3,16 @@ include_directories(
3 ${CMAKE_SOURCE_DIR}/plugins/Wizard
3 ${CMAKE_SOURCE_DIR}/plugins/Wizard
4)
4)
5
5
6−add_executable(tst-pagelist
6+add_executable(tst-wizard-pagelist
7 tst_pagelist.cpp
7 tst_pagelist.cpp
8 ${CMAKE_SOURCE_DIR}/plugins/Wizard/PageList.cpp
8 ${CMAKE_SOURCE_DIR}/plugins/Wizard/PageList.cpp
9)
9)
10−qt5_use_modules(tst-pagelist Core Qml Test)
10+qt5_use_modules(tst-wizard-pagelist Core Qml Test)
11+add_test(NAME wizardpagelisttest COMMAND env UNITY_TEST_ENV=1 ${CMAKE_CURRENT_BINARY_DIR}/tst-wizard-pagelist)
11
12
13+add_executable(tst-wizard-system
14+ tst_system.cpp
15+ ${CMAKE_SOURCE_DIR}/plugins/Wizard/System.cpp
16+)
17+qt5_use_modules(tst-wizard-system Core DBus Qml Test)
12−add_test(NAME pagelisttest COMMAND env UNITY_TEST_ENV=1 ${CMAKE_CURRENT_BINARY_DIR}/tst-pagelist)
18+add_test(NAME wizardsystemtest COMMAND ${CMAKE_CURRENT_BINARY_DIR}/tst-wizard-system)
tests/plugins/Wizard/tst_system.cppnew file+124
@@ -0,0 +1,124 @@
1+/*
2+ * Copyright (C) 2014 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "System.h"
18+
19+#include <QDebug>
20+#include <QObject>
21+#include <QSignalSpy>
22+#include <QTemporaryDir>
23+#include <QTest>
24+
25+class SystemTest: public QObject
26+{
27+ Q_OBJECT
28+
29+public:
30+ SystemTest();
31+
32+private Q_SLOTS:
33+ void testEnable();
34+ void testDisable();
35+ void testNoticeChanges();
36+
37+private:
38+ void enable();
39+ void disable();
40+ bool isEnabled();
41+
42+ QTemporaryDir dir;
43+ QDir enableDir;
44+ QFile enableFile;
45+};
46+
47+SystemTest::SystemTest()
48+{
49+ qputenv("HOME", dir.path().toUtf8());
50+ enableDir.setPath(dir.path() + "/.config/ubuntu-system-settings");
51+ enableFile.setFileName(enableDir.filePath("wizard-has-run"));
52+}
53+
54+void SystemTest::enable()
55+{
56+ enableFile.remove();
57+ QCOMPARE(isEnabled(), true);
58+}
59+
60+void SystemTest::disable()
61+{
62+ enableDir.mkpath(".");
63+ enableFile.open(QIODevice::WriteOnly);
64+ enableFile.close();
65+ QCOMPARE(isEnabled(), false);
66+}
67+
68+bool SystemTest::isEnabled()
69+{
70+ return !enableFile.exists();
71+}
72+
73+void SystemTest::testEnable()
74+{
75+ disable();
76+
77+ System system;
78+ QVERIFY(!system.wizardEnabled());
79+
80+ system.setWizardEnabled(true);
81+ QVERIFY(system.wizardEnabled());
82+ QVERIFY(isEnabled());
83+}
84+
85+void SystemTest::testDisable()
86+{
87+ enable();
88+
89+ System system;
90+ QVERIFY(system.wizardEnabled());
91+
92+ system.setWizardEnabled(false);
93+ QVERIFY(!system.wizardEnabled());
94+ QVERIFY(!isEnabled());
95+}
96+
97+void SystemTest::testNoticeChanges()
98+{
99+ enable();
100+
101+ System system;
102+ QSignalSpy spy(&system, SIGNAL(wizardEnabledChanged()));
103+
104+ // System only guarantees its signals work correcty when using its own set
105+ // methods (i.e. it won't necessarily notice if we modify the file behind
106+ // the scenes). This is because watching all parent directories of the
107+ // wizard-has-run file with QFileSystemWatcher is a nightmare and waste of
108+ // resources for the corner case it is. So we'll just test the set method.
109+
110+ system.setWizardEnabled(false);
111+ QTRY_COMPARE(spy.count(), 1);
112+
113+ system.setWizardEnabled(true);
114+ QTRY_COMPARE(spy.count(), 2);
115+
116+ system.setWizardEnabled(false);
117+ QTRY_COMPARE(spy.count(), 3);
118+
119+ system.setWizardEnabled(true);
120+ QTRY_COMPARE(spy.count(), 4);
121+}
122+
123+QTEST_MAIN(SystemTest)
124+#include "tst_system.moc"
tests/qmltests/CMakeLists.txt+1
@@ -87,3 +87,4 @@ add_qml_test(Stages SpreadDelegate ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_D
87add_qml_test(Stages SurfaceContainer ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
87add_qml_test(Stages SurfaceContainer ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
88add_qml_test(Stages SessionContainer ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
88add_qml_test(Stages SessionContainer ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
89add_qml_test(Stages Splash)
89add_qml_test(Stages Splash)
90+add_qml_test(Wizard Wizard)
tests/qmltests/Wizard/licenses/en_US.htmlnew file+1
@@ -0,0 +1 @@
1+en_US
tests/qmltests/Wizard/licenses/fr_CA.htmlnew file+1
@@ -0,0 +1 @@
1+fr_CA
tests/qmltests/Wizard/licenses/fr_FR.htmlnew file+1
@@ -0,0 +1 @@
1+fr_FR
tests/qmltests/Wizard/tst_Wizard.qmlnew file+479
@@ -0,0 +1,479 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.3
18+import QtTest 1.0
19+import AccountsService 0.1
20+import MeeGo.QOfono 0.2
21+import Ubuntu.Components 1.1
22+import Ubuntu.SystemSettings.SecurityPrivacy 1.0
23+import Unity.Test 0.1 as UT
24+import Wizard 0.1
25+import "../../../qml/Wizard"
26+
27+Item {
28+ id: root
29+ width: units.gu(40)
30+ height: units.gu(71)
31+
32+ Loader {
33+ id: wizardLoader
34+ anchors.fill: parent
35+
36+ property bool itemDestroyed: false
37+ sourceComponent: Component {
38+ Wizard {
39+ id: wizard
40+ anchors.fill: parent
41+ background: Qt.resolvedUrl("../../../qml/graphics/phone_background.jpg")
42+
43+ Component.onDestruction: {
44+ wizardLoader.itemDestroyed = true;
45+ }
46+ }
47+ }
48+ }
49+
50+ SignalSpy {
51+ id: updateSessionLanguageSpy
52+ target: System
53+ signalName: "updateSessionLanguageCalled"
54+ }
55+
56+ SignalSpy {
57+ id: setSecuritySpy
58+ signalName: "setSecurityCalled"
59+ }
60+
61+ function setup() {
62+ AccountsService.hereEnabled = false;
63+ AccountsService.hereLicensePath = Qt.resolvedUrl("licenses");
64+ i18n.language = "en";
65+ MockQOfono.setModems(["sim1"], [false]);
66+ MockQOfono.available = true;
67+ System.wizardEnabled = true;
68+
69+ updateSessionLanguageSpy.clear();
70+ setSecuritySpy.clear();
71+ }
72+
73+ Component.onCompleted: {
74+ Theme.name = "Ubuntu.Components.Themes.SuruGradient";
75+ setup();
76+ }
77+
78+ UT.UnityTestCase {
79+ id: wizardTests
80+ name: "Wizard"
81+ when: windowShown
82+
83+ property Item wizard: wizardLoader.status === Loader.Ready ? wizardLoader.item : null
84+
85+ function cleanup() {
86+ wizardLoader.itemDestroyed = false;
87+
88+ wizardLoader.active = false;
89+
90+ tryCompare(wizardLoader, "status", Loader.Null);
91+ tryCompare(wizardLoader, "item", null);
92+ // Loader.status might be Loader.Null and Loader.item might be null but the Loader
93+ // item might still be alive. So if we set Loader.active back to true
94+ // again right now we will get the very same Shell instance back. So no reload
95+ // actually took place. Likely because Loader waits until the next event loop
96+ // iteration to do its work. So to ensure the reload, we will wait until the
97+ // Shell instance gets destroyed.
98+ tryCompare(wizardLoader, "itemDestroyed", true);
99+
100+ // reload our test subject to get it in a fresh state once again
101+ wizardLoader.active = true;
102+
103+ tryCompare(wizardLoader, "status", Loader.Ready);
104+
105+ var pages = findChild(wizard, "wizardPages");
106+ var security = findInvisibleChild(pages, "securityPrivacy");
107+ setSecuritySpy.target = security;
108+
109+ setup();
110+ }
111+
112+ function waitForPage(name) {
113+ var pages = findChild(wizard, "wizardPages");
114+ var stack = findChild(pages, "pageStack");
115+ // don't simply call tryCompare here, because stack.currentPage will be swapped out itself
116+ tryCompareFunction(function() { return stack.currentPage.objectName; }, name);
117+ tryCompare(stack.currentPage, "opacity", 1.0);
118+ tryCompare(stack.currentPage, "enabled", true);
119+ waitForRendering(stack.currentPage);
120+ return stack.currentPage;
121+ }
122+
123+ function goToPage(name, skipSim, skipLocation) {
124+ if (skipSim === undefined) {
125+ skipSim = false;
126+ }
127+ if (skipLocation === undefined) {
128+ skipLocation = false;
129+ }
130+
131+ var page = waitForPage("languagePage");
132+ if (name === page.objectName) return page;
133+ tap(findChild(page, "forwardButton"));
134+
135+ if (!skipSim) {
136+ page = waitForPage("simPage");
137+ if (name === page.objectName) return page;
138+ tap(findChild(page, "forwardButton"));
139+ }
140+
141+ page = waitForPage("passwdPage");
142+ if (name === page.objectName) return page;
143+ tap(findChild(page, "passwdDelegate0"));
144+ tap(findChild(page, "forwardButton"));
145+
146+ page = waitForPage("wifiPage");
147+ if (name === page.objectName) return page;
148+ tap(findChild(page, "forwardButton"));
149+
150+ if (!skipLocation) {
151+ page = waitForPage("locationPage");
152+ if (name === page.objectName) return page;
153+ tap(findChild(page, "forwardButton"));
154+ }
155+
156+ page = waitForPage("reportingPage");
157+ if (name === page.objectName) return page;
158+ tap(findChild(page, "forwardButton"));
159+
160+ page = waitForPage("finishedPage");
161+ if (name === page.objectName) return page;
162+ tap(findChild(page, "forwardButton"));
163+
164+ tryCompare(wizard, "shown", false);
165+ compare(name, null);
166+ return null;
167+ }
168+
169+ function test_languageChange() {
170+ var page = goToPage("languagePage");
171+ tap(findChild(page, "languageCombo"));
172+ waitForRendering(findChild(page, "languageDelegate1"));
173+
174+ // For some reason, the delegate *sometimes* (like 1 in 10 maybe)
175+ // needs more time before it can process a tap() call. I can't
176+ // find a rhyme or reason, its properties all seem the same in
177+ // cases where it works and does not. This failure to receive a
178+ // tap() call below does *not* happen when running in xvfb, so
179+ // jenkins is unaffected (and we don't have to worry about 100 not
180+ // being enough time in its slow environment). This wait() call is
181+ // just to help local runs not trip up.
182+ wait(100);
183+ tap(findChild(page, "languageDelegate1"));
184+
185+ tryCompare(i18n, "language", "fr");
186+ tap(findChild(page, "forwardButton"));
187+ tryCompare(updateSessionLanguageSpy, "count", 1);
188+ compare(updateSessionLanguageSpy.signalArguments[0][0], "fr");
189+ }
190+
191+ function test_languageNoChange() {
192+ goToPage("simPage"); // one past language page
193+ compare(updateSessionLanguageSpy.count, 0);
194+ }
195+
196+ function test_simUnavailableSkip() {
197+ MockQOfono.available = false;
198+ goToPage("passwdPage", true);
199+ }
200+
201+ function test_simNoModemsSkip() {
202+ MockQOfono.setModems([], []);
203+ goToPage("passwdPage", true);
204+ }
205+
206+ function test_simFirstSkip() {
207+ MockQOfono.setModems(["a", "b"], [true, false]);
208+ goToPage("passwdPage", true);
209+ }
210+
211+ function test_simSecondSkip() {
212+ MockQOfono.setModems(["a", "b"], [false, true]);
213+ goToPage("passwdPage", true);
214+ }
215+
216+ function test_simBothSkip() {
217+ MockQOfono.setModems(["a", "b"], [true, true]);
218+ goToPage("passwdPage", true);
219+ }
220+
221+ function enterPasscode(passcode) {
222+ for (var i = 0; i < passcode.length; ++i) {
223+ var character = passcode.charAt(i);
224+ var button = findChild(wizard, "pinPadButton" + character);
225+ tap(button);
226+ }
227+ }
228+
229+ function test_passwdPasscode() {
230+ var page = goToPage("passwdPage");
231+
232+ tap(findChild(page, "forwardButton"));
233+ page = waitForPage("passwdSetPage");
234+
235+ enterPasscode("1111");
236+ page = waitForPage("passwdConfirmPage");
237+
238+ // make sure we go back to 'set' page not 'type' page
239+ tap(findChild(page, "backButton"));
240+ page = waitForPage("passwdSetPage");
241+
242+ enterPasscode("1111");
243+ page = waitForPage("passwdConfirmPage");
244+
245+ enterPasscode("1112");
246+ var error = findChild(page, "wrongNoticeLabel");
247+ tryCompareFunction(function() { return error.text !== ""; }, true);
248+
249+ enterPasscode("1111");
250+ page = waitForPage("wifiPage");
251+
252+ // now finish up
253+ tap(findChild(page, "forwardButton"));
254+ page = waitForPage("locationPage");
255+ tap(findChild(page, "forwardButton"));
256+ page = waitForPage("reportingPage");
257+ tap(findChild(page, "forwardButton"));
258+ page = waitForPage("finishedPage");
259+ tap(findChild(page, "forwardButton"));
260+
261+ tryCompare(setSecuritySpy, "count", 1);
262+ compare(setSecuritySpy.signalArguments[0][0], "");
263+ compare(setSecuritySpy.signalArguments[0][1], "1111");
264+ compare(setSecuritySpy.signalArguments[0][2], UbuntuSecurityPrivacyPanel.Passcode);
265+ }
266+
267+ function test_passwdPassphrase() {
268+ var page = goToPage("passwdPage");
269+ tap(findChild(page, "passwdDelegate2"));
270+
271+ tap(findChild(page, "forwardButton"));
272+ page = waitForPage("passwdSetPage");
273+
274+ typeString("aaa");
275+ var continueButton = findChild(page, "forwardButton");
276+ tryCompare(continueButton.item, "enabled", false);
277+ keyClick(Qt.Key_Enter);
278+ var error = findChild(page, "wrongNoticeLabel");
279+ tryCompareFunction(function() { return error.text !== ""; }, true);
280+
281+ typeString("aaaa");
282+ tap(continueButton);
283+ page = waitForPage("passwdConfirmPage");
284+
285+ // make sure we go back to 'set' page not 'type' page
286+ var back = findChild(page, "backButton");
287+ tap(back);
288+ page = waitForPage("passwdSetPage");
289+
290+ typeString("aaaa");
291+ keyClick(Qt.Key_Enter);
292+ page = waitForPage("passwdConfirmPage");
293+
294+ continueButton = findChild(page, "forwardButton");
295+ typeString("aaab");
296+ tryCompare(continueButton.item, "enabled", false);
297+ keyClick(Qt.Key_Enter);
298+ var error = findChild(page, "wrongNoticeLabel");
299+ tryCompareFunction(function() { return error.text !== ""; }, true);
300+
301+ typeString("aaaa");
302+ tap(continueButton);
303+ page = waitForPage("wifiPage");
304+
305+ // now finish up
306+ tap(findChild(page, "forwardButton"));
307+ page = waitForPage("locationPage");
308+ tap(findChild(page, "forwardButton"));
309+ page = waitForPage("reportingPage");
310+ tap(findChild(page, "forwardButton"));
311+ page = waitForPage("finishedPage");
312+ tap(findChild(page, "forwardButton"));
313+
314+ tryCompare(setSecuritySpy, "count", 1);
315+ compare(setSecuritySpy.signalArguments[0][0], "");
316+ compare(setSecuritySpy.signalArguments[0][1], "aaaa");
317+ compare(setSecuritySpy.signalArguments[0][2], UbuntuSecurityPrivacyPanel.Passphrase);
318+ }
319+
320+ function test_passwdSwipe() {
321+ goToPage(null);
322+
323+ tryCompare(setSecuritySpy, "count", 1);
324+ compare(setSecuritySpy.signalArguments[0][0], "");
325+ compare(setSecuritySpy.signalArguments[0][1], "");
326+ compare(setSecuritySpy.signalArguments[0][2], UbuntuSecurityPrivacyPanel.Swipe);
327+ }
328+
329+ function test_locationSkipNoPath() {
330+ AccountsService.hereLicensePath = "";
331+ goToPage("reportingPage", false, true);
332+ }
333+
334+ function test_locationSkipNoFiles() {
335+ AccountsService.hereLicensePath = Qt.resolvedUrl("nolicenses");
336+ goToPage("reportingPage", false, true);
337+ }
338+
339+ function test_locationWaitOnPath() {
340+ AccountsService.hereLicensePath = " "; // means we're still getting the path from dbus
341+
342+ var page = goToPage("wifiPage");
343+
344+ var pages = findChild(wizard, "wizardPages");
345+ var stack = findChild(pages, "pageStack");
346+ tap(findChild(page, "forwardButton"));
347+ // don't simply call tryCompare here, because stack.currentPage will be swapped out itself
348+ tryCompareFunction(function() { return stack.currentPage.objectName; }, "locationPage");
349+ compare(stack.currentPage.enabled, false);
350+ compare(stack.currentPage.skipValid, false);
351+
352+ AccountsService.hereLicensePath = "";
353+ waitForPage("reportingPage");
354+ }
355+
356+ function test_locationGpsOnly() {
357+ var page = goToPage("locationPage");
358+ var gpsCheck = findChild(page, "gpsCheck");
359+ var hereCheck = findChild(page, "hereCheck");
360+ var nopeCheck = findChild(page, "nopeCheck");
361+
362+ var locationActionGroup = findInvisibleChild(page, "locationActionGroup");
363+ tryCompare(locationActionGroup.location, "state", false);
364+ tryCompare(locationActionGroup.gps, "state", false);
365+
366+ tap(gpsCheck);
367+ tryCompare(gpsCheck, "checked", true);
368+ tryCompare(hereCheck, "checked", false);
369+ tryCompare(nopeCheck, "checked", false);
370+
371+ tap(findChild(page, "forwardButton"));
372+ tryCompare(AccountsService, "hereEnabled", false);
373+ tryCompare(locationActionGroup.location, "state", true);
374+ tryCompare(locationActionGroup.gps, "state", true);
375+ }
376+
377+ function test_locationNope() {
378+ var page = goToPage("locationPage");
379+ var gpsCheck = findChild(page, "gpsCheck");
380+ var hereCheck = findChild(page, "hereCheck");
381+ var nopeCheck = findChild(page, "nopeCheck");
382+
383+ var locationActionGroup = findInvisibleChild(page, "locationActionGroup");
384+ tryCompare(locationActionGroup.location, "state", false);
385+ tryCompare(locationActionGroup.gps, "state", false);
386+
387+ tap(nopeCheck);
388+ tryCompare(gpsCheck, "checked", false);
389+ tryCompare(hereCheck, "checked", false);
390+ tryCompare(nopeCheck, "checked", true);
391+
392+ tap(findChild(page, "forwardButton"));
393+ tryCompare(AccountsService, "hereEnabled", false);
394+ tryCompare(locationActionGroup.location, "state", false);
395+ tryCompare(locationActionGroup.gps, "state", false);
396+ }
397+
398+ function test_locationHere() {
399+ var page = goToPage("locationPage");
400+ var gpsCheck = findChild(page, "gpsCheck");
401+ var hereCheck = findChild(page, "hereCheck");
402+ var nopeCheck = findChild(page, "nopeCheck");
403+
404+ var locationActionGroup = findInvisibleChild(page, "locationActionGroup");
405+ tryCompare(locationActionGroup.location, "state", false);
406+ tryCompare(locationActionGroup.gps, "state", false);
407+
408+ // no tap because HERE is the default
409+ tryCompare(gpsCheck, "checked", false);
410+ tryCompare(hereCheck, "checked", true);
411+ tryCompare(nopeCheck, "checked", false);
412+
413+ tap(findChild(page, "forwardButton"));
414+ tryCompare(AccountsService, "hereEnabled", true);
415+ tryCompare(locationActionGroup.location, "state", true);
416+ tryCompare(locationActionGroup.gps, "state", true);
417+ }
418+
419+ function test_locationHereTerms() {
420+ var page = goToPage("locationPage");
421+
422+ var link = findChild(page, "hereTermsLink");
423+
424+ // Test our language lookup code a bit
425+
426+ i18n.language = "fr_FR.UTF-8";
427+ link.linkActivated("not-used");
428+ page = waitForPage("hereTermsPage");
429+ tryCompare(findChild(page, "termsLabel"), "text", "fr_FR\n");
430+ tap(findChild(page, "backButton"));
431+ waitForPage("locationPage");
432+
433+ i18n.language = "fr_CA";
434+ link.linkActivated("not-used");
435+ page = waitForPage("hereTermsPage");
436+ tryCompare(findChild(page, "termsLabel"), "text", "fr_CA\n");
437+ tap(findChild(page, "backButton"));
438+ waitForPage("locationPage");
439+
440+ i18n.language = "fr_US";
441+ link.linkActivated("not-used");
442+ page = waitForPage("hereTermsPage");
443+ tryCompare(findChild(page, "termsLabel"), "text", "fr_FR\n");
444+ tap(findChild(page, "backButton"));
445+ waitForPage("locationPage");
446+
447+ i18n.language = "fr.utf8";
448+ link.linkActivated("not-used");
449+ page = waitForPage("hereTermsPage");
450+ tryCompare(findChild(page, "termsLabel"), "text", "fr_FR\n");
451+ tap(findChild(page, "backButton"));
452+ waitForPage("locationPage");
453+
454+ i18n.language = "es"; // will not be found
455+ link.linkActivated("not-used");
456+ page = waitForPage("hereTermsPage");
457+ tryCompare(findChild(page, "termsLabel"), "text", "en_US\n");
458+
459+ // OK, done with languages, back to actual page
460+
461+ var label = findChild(page, "termsLabel");
462+ label.linkActivated(Qt.resolvedUrl("licenses/en_US.html"));
463+ tryCompare(label, "visible", false);
464+
465+ var webview = findChild(page, "webview");
466+ tryCompare(webview, "visible", true);
467+ tryCompare(webview, "url", Qt.resolvedUrl("licenses/en_US.html"));
468+ tryCompare(webview, "loadProgress", 100);
469+
470+ tap(findChild(page, "backButton"));
471+ waitForPage("hereTermsPage"); // confirm we're on same page
472+ tryCompare(webview, "visible", false);
473+ tryCompare(label, "visible", true);
474+
475+ tap(findChild(page, "backButton"));
476+ waitForPage("locationPage");
477+ }
478+ }
479+}