Merge lp:~jonas-drange/ubuntu-system-settings/1219793-reset into lp:ubuntu-system-settings

Proposed by Jonas G. Drange on 2014-07-30
Status: Merged
Approved by: Ken VanDine on 2014-08-07
Approved revision: 851
Merged at revision: 875
Proposed branch: lp:~jonas-drange/ubuntu-system-settings/1219793-reset
Merge into: lp:ubuntu-system-settings
Diff against target: 640 lines (+350/-62)
11 files modified
plugins/reset/CMakeLists.txt (+2/-0)
plugins/reset/EntryComponent.qml (+1/-1)
plugins/reset/EraseEverything.qml (+22/-4)
plugins/reset/PageComponent.qml (+21/-8)
plugins/reset/ResetLauncherHome.qml (+27/-6)
plugins/reset/reset.cpp (+39/-33)
plugins/reset/reset.h (+5/-2)
plugins/reset/reset.settings (+1/-2)
tests/autopilot/ubuntu_system_settings/__init__.py (+118/-3)
tests/autopilot/ubuntu_system_settings/tests/__init__.py (+64/-3)
tests/autopilot/ubuntu_system_settings/tests/test_reset.py (+50/-0)
To merge this branch: bzr merge lp:~jonas-drange/ubuntu-system-settings/1219793-reset
Reviewer Review Type Date Requested Status
Ken VanDine 2014-07-30 Approve on 2014-08-07
PS Jenkins bot continuous-integration Approve on 2014-08-01
Leo Arias (community) Needs Fixing on 2014-07-31
Review via email: mp+228954@code.launchpad.net

Commit message

[reset] bring back reset and hook it up to the backend. Added happy path tests.

Description of the change

Hi,

this branch makes reset visible by default and exposes "Reset Launcher" and "Erase Everything…" to the user.

The ux has been altered slightly to conform to the new spec.

Binding for factory reset was also written.

Thanks

To post a comment you must log in.
Omer Akram (om26er) wrote :

You should make sure to backup launcher icons before running tests and restore them at the end.

PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:842
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/1106/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/2789
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/2227
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/298
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/298
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/298/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/298
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/2880
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/4032
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/4032/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/10746
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/1846
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/2486
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/2486/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/ubuntu-system-settings-ci/1106/rebuild

review: Approve (continuous-integration)
Leo Arias (elopio) wrote :

408 + def test_reset_page_title_is_correct(self):

This is not a good autopilot tests because it doesn't represent a user story. We are not testing there the reason why the user opens the app. It would be better as a QML test, but as the project currently has no QML tests, it's ok for now.

308 + sleep(2)
334 + sleep(2)

Sleeps should be avoided. If there's no way to avoid them, you should explain why in a comment.
In this case, why do we need it? According to the spawn_server docs:
"This function blocks until the spawned DBusMockObject is ready and listening on the bus."

387 + def reset_launcher(self):
392 + def reset_launcher_action(self):
398 + def factory_reset(self):
403 + def factory_reset_action(self):

We have found that we need to follow the page object pattern in order to make the tests maintainable and to be able to cope with design changes. That amongst other things mean that the UI components need to be hidden in objects that model their parents, and to be called from public methods that represent user actions.
It's explained in more detail here: http://developer.ubuntu.com/apps/platform/guides/acceptance-testing-using-the-page-object-model/
It would be awesome if you can read through it. I'm preparing a branch to show you what I mean. I'll ask for your review when it's ready.

Thanks for adding tests Jonas!

Leo Arias (elopio) :
review: Needs Fixing
Leo Arias (elopio) wrote :

Oh, well, I won't be able to do the branch tonight because it's failing to build. So I'm not able to test my changes.

Jonas G. Drange (jonas-drange) wrote :

Thank you for your comments. I think I have addressed all of them in r844.

The reset launcher functionality on the phone does not work, so putting it back in to WIP.

PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:848
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/1129/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/2932
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/2320
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/321
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/321
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/321/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/321
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/2993
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/4175
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/4175/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/10880
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/1920
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/2585
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/2585/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/ubuntu-system-settings-ci/1129/rebuild

review: Approve (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:843
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/1130/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/2935
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/2323
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/322
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/322
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/322/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/322
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/2996
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/4178
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/4178/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/10883
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/1923
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/2589
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/2589/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/ubuntu-system-settings-ci/1130/rebuild

review: Approve (continuous-integration)
Ken VanDine (ken-vandine) wrote :

Should the launcher reset restart the shell/device or at least tell they user that it's needed?

review: Needs Information
Michael Terry (mterry) wrote :

Me coming here from a unity8 POV -- personally, I'd like unity8 updated to notice when the setting changes to the default again, so it doesn't have to be restarted.

Failing that, we should probably tell the user to turn off and on their phone, but that's a very gross message to receive.

Ken VanDine (ken-vandine) wrote :

Ok, we should at least tell the user they need to do something.

review: Needs Fixing
849. By Jonas G. Drange on 2014-08-07

merge trunk

850. By Jonas G. Drange on 2014-08-07

note up front re: restart

Jonas G. Drange (jonas-drange) wrote :

Added note re: restart. Hopefully this will be handled by Unity at some point.

Ken VanDine (ken-vandine) wrote :

Please remove the debug output in reset.cpp and see inline comment.

851. By Jonas G. Drange on 2014-08-07

removing hide-by-default and debug output

Ken VanDine (ken-vandine) wrote :

Looks good, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/reset/CMakeLists.txt'
2--- plugins/reset/CMakeLists.txt 2013-10-22 14:44:44 +0000
3+++ plugins/reset/CMakeLists.txt 2014-08-07 14:21:27 +0000
4@@ -14,6 +14,8 @@
5 )
6 qt5_use_modules(UbuntuResetPanel Qml Quick DBus)
7
8+target_link_libraries(UbuntuResetPanel uss-accountsservice)
9+
10 set(PLUG_DIR ${PLUGIN_PRIVATE_MODULE_DIR}/Ubuntu/SystemSettings/Reset)
11 install(TARGETS UbuntuResetPanel DESTINATION ${PLUG_DIR})
12 install(FILES qmldir DESTINATION ${PLUG_DIR})
13
14=== modified file 'plugins/reset/EntryComponent.qml'
15--- plugins/reset/EntryComponent.qml 2013-11-28 15:09:15 +0000
16+++ plugins/reset/EntryComponent.qml 2014-08-07 14:21:27 +0000
17@@ -24,7 +24,7 @@
18
19 ListItem.Standard {
20 id: root
21-
22+ objectName: "entryComponent-reset"
23 iconSource: model.icon
24 iconFrame: false
25 text: i18n.tr(model.displayName)
26
27=== modified file 'plugins/reset/EraseEverything.qml'
28--- plugins/reset/EraseEverything.qml 2013-08-23 14:05:39 +0000
29+++ plugins/reset/EraseEverything.qml 2014-08-07 14:21:27 +0000
30@@ -26,15 +26,33 @@
31 id: eraseEverything
32 Dialog {
33 id: dialog
34+ states: State {
35+ name: "clicked"
36+ PropertyChanges {
37+ target: action
38+ enabled: false
39+ }
40+ PropertyChanges {
41+ target: cancel
42+ enabled: false
43+ }
44+ }
45+ objectName: "factoryResetDialog"
46 text: i18n.tr("All documents, saved games, settings, and other items will be permanently deleted from this phone.")
47 Button {
48- text: i18n.tr("Erase & reset everything")
49- enabled: false /* TODO: enable when there is a backend */
50- onClicked: PopupUtils.close(dialog)
51+ id: action
52+ text: i18n.tr("Erase & Reset Everything")
53+ objectName: "factoryResetAction"
54+ onClicked: {
55+ dialog.state = "clicked";
56+ resetBackend.factoryReset();
57+ root.done();
58+ }
59 }
60 Button {
61+ id: cancel
62 text: i18n.tr("Cancel")
63- onClicked: PopupUtils.close(dialog)
64+ onClicked: PopupUtils.close(dialog);
65 }
66 }
67 }
68
69=== modified file 'plugins/reset/PageComponent.qml'
70--- plugins/reset/PageComponent.qml 2013-09-06 13:12:46 +0000
71+++ plugins/reset/PageComponent.qml 2014-08-07 14:21:27 +0000
72@@ -30,8 +30,18 @@
73 id: root
74
75 title: i18n.tr("Reset phone")
76+ objectName: "resetPage"
77 flickable: scrollWidget
78
79+ // workaround for #1231729
80+ // delay destroying popup until pageStack has been popped
81+ property var popup
82+ function done () {
83+ popup.opacity = 0;
84+ pageStack.pop();
85+ popup.destroy(1000);
86+ }
87+
88 Loader {
89 id: buttonActions
90 asynchronous: false
91@@ -59,24 +69,26 @@
92 ListItem.SingleControl {
93 control: Button {
94 id: resetLauncherHomeButton
95- text: i18n.tr("Reset launcher & home screen…")
96+ objectName: "resetLauncher"
97+ text: i18n.tr("Reset Launcher")
98 width: parent.width - units.gu(4)
99 onClicked: {
100- buttonActions.source = "ResetLauncherHome.qml"
101- PopupUtils.open(buttonActions.item)
102+ buttonActions.source = "ResetLauncherHome.qml";
103+ root.popup = PopupUtils.open(buttonActions.item);
104 }
105 }
106 showDivider: false
107 }
108
109 ListItem.SingleControl {
110+ visible: false // enabled when backend is ready/useful
111 control: Button {
112 id: resetAllSettingsButton
113 text: i18n.tr("Reset all system settings…")
114 width: parent.width - units.gu(4)
115 onClicked: {
116- buttonActions.source = "ResetAllSettings.qml"
117- PopupUtils.open(buttonActions.item)
118+ buttonActions.source = "ResetAllSettings.qml";
119+ root.popup = PopupUtils.open(buttonActions.item);
120 }
121 }
122 showDivider: false
123@@ -85,11 +97,12 @@
124 ListItem.SingleControl {
125 control: Button {
126 id: eraseEverythingButton
127- text: i18n.tr("Erase & reset everything…")
128+ objectName: "factoryReset"
129+ text: i18n.tr("Erase & Reset Everything…")
130 width: parent.width - units.gu(4)
131 onClicked: {
132- buttonActions.source = "EraseEverything.qml"
133- PopupUtils.open(buttonActions.item)
134+ buttonActions.source = "EraseEverything.qml";
135+ root.popup = PopupUtils.open(buttonActions.item);
136 }
137 }
138 showDivider: false
139
140=== modified file 'plugins/reset/ResetLauncherHome.qml'
141--- plugins/reset/ResetLauncherHome.qml 2013-09-06 13:12:46 +0000
142+++ plugins/reset/ResetLauncherHome.qml 2014-08-07 14:21:27 +0000
143@@ -24,21 +24,42 @@
144
145 Component {
146 id: resetLauncherHome
147-
148 Dialog {
149 id: dialog
150- text: i18n.tr("The contents and layout of the launcher, and the filters in the home screen will be returned to their original settings.")
151+ states: State {
152+ name: "clicked"
153+ PropertyChanges {
154+ target: action
155+ enabled: false
156+ }
157+ PropertyChanges {
158+ target: cancel
159+ enabled: false
160+ }
161+ }
162+ text: i18n.tr("The Launcher will be returned to its original contents.")
163+ objectName: "resetLauncherDialog"
164 Button {
165- text: i18n.tr("Reset launcher & home screen")
166+ id: action
167+ text: i18n.tr("Reset Launcher")
168+ objectName: "resetLauncherAction"
169 onClicked: {
170- unitySettings.schema.reset("favorites")
171- resetBackend.resetLauncher()
172- PopupUtils.close(dialog)
173+ dialog.state = "clicked";
174+ unitySettings.schema.reset("favorites");
175+ resetBackend.resetLauncher();
176+ root.done();
177 }
178 }
179 Button {
180+ id: cancel
181 text: i18n.tr("Cancel")
182 onClicked: PopupUtils.close(dialog)
183 }
184+ Label {
185+ text: i18n.tr("The phone needs to restart for changes to take effect.")
186+ width: parent.width
187+ wrapMode: Text.Wrap
188+ horizontalAlignment: Text.AlignHCenter
189+ }
190 }
191 }
192
193=== modified file 'plugins/reset/reset.cpp'
194--- plugins/reset/reset.cpp 2013-09-06 13:12:46 +0000
195+++ plugins/reset/reset.cpp 2014-08-07 14:21:27 +0000
196@@ -22,49 +22,55 @@
197 #include <QEvent>
198 #include <QDBusReply>
199 #include <unistd.h>
200-#include <QtCore/QDebug>
201-
202-Reset::Reset(QObject *parent) :
203- QObject(parent),
204- m_systemBusConnection (QDBusConnection::systemBus()),
205- m_accountsserviceIface ("org.freedesktop.Accounts",
206- "/org/freedesktop/Accounts",
207- "org.freedesktop.Accounts",
208- m_systemBusConnection)
209+#include <QDBusMetaType>
210+
211+typedef QList<QVariantMap> resetLauncherItemsArg;
212+Q_DECLARE_METATYPE(resetLauncherItemsArg)
213+
214+Reset::Reset(QObject *parent)
215+ : QObject(parent),
216+ m_systemBusConnection(QDBusConnection::systemBus())
217 {
218- if (!m_accountsserviceIface.isValid()) {
219- return;
220- }
221-
222- QDBusReply<QDBusObjectPath> qObjectPath = m_accountsserviceIface.call(
223- "FindUserById", qlonglong(getuid()));
224-
225- if (qObjectPath.isValid()) {
226- m_objectPath = qObjectPath.value().path();
227+ static bool isRegistered = false;
228+ if(!isRegistered) {
229+ qDBusRegisterMetaType<resetLauncherItemsArg>();
230+ isRegistered = true;
231 }
232 }
233
234 bool Reset::resetLauncher()
235 {
236- QDBusInterface userInterface (
237- "org.freedesktop.Accounts",
238- m_objectPath,
239- "org.freedesktop.DBus.Properties.Set",
240- m_systemBusConnection,
241- this);
242-
243- if (!userInterface.isValid())
244- return false;
245-
246 QList<QVariantMap> items;
247 QVariantMap defaults;
248 defaults.insert("defaults", true);
249 items << defaults;
250- /* TODO: test again-enable once the unity side lands
251- userInterface.call("Set",
252- "com.canonical.unity.AccountsService",
253- "launcher-items",
254- QVariant::fromValue(items));*/
255+ QVariant answer = m_accountsService.setUserProperty(
256+ "com.canonical.unity.AccountsService",
257+ "launcher-items",
258+ QVariant::fromValue(items));
259+
260+ if (answer.isValid())
261+ return true;
262+
263+ return false;
264+}
265+
266+bool Reset::factoryReset()
267+{
268+ QDBusInterface systemServiceInterface (
269+ "com.canonical.SystemImage",
270+ "/Service",
271+ "com.canonical.SystemImage",
272+ m_systemBusConnection,
273+ this);
274+
275+ if (!systemServiceInterface.isValid())
276+ return false;
277+
278+ QDBusReply<QString> reply = systemServiceInterface.call("FactoryReset");
279+ if (!reply.isValid())
280+ return false;
281+
282 return true;
283 }
284
285
286=== modified file 'plugins/reset/reset.h'
287--- plugins/reset/reset.h 2013-09-06 13:12:46 +0000
288+++ plugins/reset/reset.h 2014-08-07 14:21:27 +0000
289@@ -21,7 +21,10 @@
290 #ifndef RESET_H
291 #define RESET_H
292
293+#include "accountsservice.h"
294+
295 #include <QDBusInterface>
296+#include <QDBusServiceWatcher>
297 #include <QObject>
298 #include <QProcess>
299 #include <QUrl>
300@@ -34,11 +37,11 @@
301 explicit Reset(QObject *parent = 0);
302 ~Reset();
303 Q_INVOKABLE bool resetLauncher(void);
304+ Q_INVOKABLE bool factoryReset(void);
305
306 private:
307+ AccountsService m_accountsService;
308 QDBusConnection m_systemBusConnection;
309- QString m_objectPath;
310- QDBusInterface m_accountsserviceIface;
311 };
312
313 #endif // RESET_H
314
315=== modified file 'plugins/reset/reset.settings'
316--- plugins/reset/reset.settings 2014-04-09 13:38:34 +0000
317+++ plugins/reset/reset.settings 2014-08-07 14:21:27 +0000
318@@ -11,6 +11,5 @@
319 "has-dynamic-keywords": false,
320 "has-dynamic-visibility": false,
321 "entry-component": "EntryComponent.qml",
322- "page-component": "PageComponent.qml",
323- "hide-by-default": true
324+ "page-component": "PageComponent.qml"
325 }
326
327=== modified file 'tests/autopilot/ubuntu_system_settings/__init__.py'
328--- tests/autopilot/ubuntu_system_settings/__init__.py 2014-07-22 18:29:46 +0000
329+++ tests/autopilot/ubuntu_system_settings/__init__.py 2014-08-07 14:21:27 +0000
330@@ -101,6 +101,10 @@
331 item.swipe_into_view()
332 self.pointing_device.click_object(item)
333
334+ @autopilot.logging.log_action(logger.debug)
335+ def go_to_reset_phone(self):
336+ return self._go_to_page('entryComponent-reset', 'resetPage')
337+
338 def _go_to_page(self, item_object_name, page_object_name):
339 self.click_item(item_object_name)
340 page = self.wait_select_single(objectName=page_object_name)
341@@ -108,7 +112,7 @@
342 return page
343
344 def scroll_to(self, obj):
345- page = self.select_single(objectName='systemSettingsPage')
346+ page = self.system_settings_page
347 page_right = page.globalRect[0] + page.globalRect[2]
348 page_bottom = page.globalRect[1] + page.globalRect[3]
349 page_center_x = int(page_right / 2)
350@@ -128,6 +132,10 @@
351 self.pointing_device.click_object(obj)
352
353 @property
354+ def system_settings_page(self):
355+ return self.select_single(objectName='systemSettingsPage')
356+
357+ @property
358 def cellular_page(self):
359 """ Return 'Cellular' page """
360 return self.select_single(objectName='cellularPage')
361@@ -165,12 +173,25 @@
362 @classmethod
363 def validate_dbus_object(cls, path, state):
364 name = introspection.get_classname_from_path(path)
365- if name == b'ItemPage':
366+ if name == b'PageComponent':
367 if state['objectName'][1] == 'cellularPage':
368 return True
369 return False
370
371
372+class TimeAndDatePage(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
373+
374+ """Autopilot helper for the Sound page."""
375+
376+ @classmethod
377+ def validate_dbus_object(cls, path, state):
378+ name = introspection.get_classname_from_path(path)
379+ if name == b'PageComponent':
380+ if state['objectName'][1] == 'timeDatePage':
381+ return True
382+ return False
383+
384+
385 class SoundPage(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
386
387 """Autopilot helper for the Sound page."""
388@@ -272,7 +293,101 @@
389 @classmethod
390 def validate_dbus_object(cls, path, state):
391 name = introspection.get_classname_from_path(path)
392- if name == b'ItemPage':
393+ if name == b'PageComponent':
394 if state['objectName'][1] == 'systemUpdatesPage':
395 return True
396 return False
397+
398+
399+class ResetPage(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
400+
401+ """Autopilot helper for the Reset page."""
402+
403+ @classmethod
404+ def validate_dbus_object(cls, path, state):
405+ name = introspection.get_classname_from_path(path)
406+ if name == b'PageComponent':
407+ if state['objectName'][1] == 'resetPage':
408+ return True
409+ return False
410+
411+ @autopilot.logging.log_action(logger.info)
412+ def reset_launcher(self):
413+ """Reset the launcher.
414+
415+ :returns: The main system settings page object, that will be visible
416+ after the reset is complete.
417+
418+ """
419+ confirm_dialog = self._click_reset_launcher()
420+ confirm_dialog.confirm_reset()
421+ return self._wait_and_return_main_system_settins_page()
422+
423+ @autopilot.logging.log_action(logger.debug)
424+ def _click_reset_launcher(self):
425+ button = self.select_single(objectName='resetLauncher')
426+ self.pointing_device.click_object(button)
427+ return self.get_root_instance().select_single(
428+ objectName='resetLauncherDialog')
429+
430+ def _wait_and_return_main_system_settins_page(self):
431+ main_view = self.get_root_instance().select_single(MainWindow)
432+ main_view.system_settings_page.active.wait_for(True)
433+ return main_view.system_settings_page
434+
435+ @autopilot.logging.log_action(logger.info)
436+ def erase_and_reset_everything(self):
437+ """Reset to factory settings.
438+
439+ :returns: The main system settings page object, that will be visible
440+ after the reset is complete.
441+
442+ """
443+ confirm_dialog = self._click_factory_reset()
444+ confirm_dialog.confirm_reset()
445+ return self._wait_and_return_main_system_settins_page()
446+
447+ @autopilot.logging.log_action(logger.debug)
448+ def _click_factory_reset(self):
449+ button = self.select_single(objectName='factoryReset')
450+ self.pointing_device.click_object(button)
451+ return self.get_root_instance().select_single(
452+ objectName='factoryResetDialog')
453+
454+
455+class ResetLauncherConfirmationDialog(
456+ ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
457+
458+ """Autopilot helper for the Reset Launcher Confirmation dialog."""
459+
460+ @classmethod
461+ def validate_dbus_object(cls, path, state):
462+ name = introspection.get_classname_from_path(path)
463+ if name == b'Dialog':
464+ if state['objectName'][1] == 'resetLauncherDialog':
465+ return True
466+ return False
467+
468+ @autopilot.logging.log_action(logger.debug)
469+ def confirm_reset(self):
470+ button = self.select_single('Button', objectName='resetLauncherAction')
471+ self.pointing_device.click_object(button)
472+
473+
474+class FactoryResetConfirmationDialog(
475+ ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
476+
477+ """Autopilot helper for the Reset Launcher Confirmation dialog."""
478+
479+ @classmethod
480+ def validate_dbus_object(cls, path, state):
481+ name = introspection.get_classname_from_path(path)
482+ if name == b'Dialog':
483+ if state['objectName'][1] == 'factoryResetDialog':
484+ return True
485+ return False
486+
487+ @autopilot.logging.log_action(logger.debug)
488+ def confirm_reset(self):
489+ button = self.select_single('Button', objectName='factoryResetAction')
490+ self.pointing_device.click_object(button)
491
492=== modified file 'tests/autopilot/ubuntu_system_settings/tests/__init__.py'
493--- tests/autopilot/ubuntu_system_settings/tests/__init__.py 2014-08-01 17:10:10 +0000
494+++ tests/autopilot/ubuntu_system_settings/tests/__init__.py 2014-08-07 14:21:27 +0000
495@@ -27,13 +27,15 @@
496 ACCOUNTS_IFACE = 'org.freedesktop.Accounts'
497 ACCOUNTS_USER_IFACE = 'org.freedesktop.Accounts.User'
498 ACCOUNTS_OBJ = '/org/freedesktop/Accounts'
499-
500+ACCOUNTS_SERVICE = 'com.canonical.unity.AccountsService'
501 ACCOUNTS_SOUND_IFACE = 'com.ubuntu.touch.AccountsService.Sound'
502 MODEM_IFACE = 'org.ofono.Modem'
503 CONNMAN_IFACE = 'org.ofono.ConnectionManager'
504 RDO_IFACE = 'org.ofono.RadioSettings'
505 SIM_IFACE = 'org.ofono.SimManager'
506 NETREG_IFACE = 'org.ofono.NetworkRegistration'
507+SYSTEM_IFACE = 'com.canonical.SystemImage'
508+SYSTEM_SERVICE_OBJ = '/Service'
509
510
511 class UbuntuSystemSettingsTestCase(
512@@ -479,8 +481,7 @@
513 'IncomingMessageVibrate': dbus.Boolean(False,
514 variant_level=1),
515 'IncomingMessageVibrateSilentMode': dbus.Boolean(False,
516- variant_level=1)
517- }
518+ variant_level=1)}
519
520 # start dbus system bus
521 self.mock_server = self.spawn_server(ACCOUNTS_IFACE, ACCOUNTS_OBJ,
522@@ -555,3 +556,63 @@
523 self.mock_server.terminate()
524 self.mock_server.wait()
525 super(SoundBaseTestCase, self).tearDown()
526+
527+
528+class ResetBaseTestCase(UbuntuSystemSettingsTestCase,
529+ dbusmock.DBusTestCase):
530+ """ Base class for reset settings tests"""
531+
532+ def mock_for_launcher_reset(self):
533+ user_obj = '/user/foo'
534+ # start dbus system bus
535+ self.mock_server = self.spawn_server(ACCOUNTS_IFACE, ACCOUNTS_OBJ,
536+ ACCOUNTS_IFACE, system_bus=True,
537+ stdout=subprocess.PIPE)
538+
539+ # spawn_server does not wait properly
540+ # Reported as bug here: http://pad.lv/1350833
541+ sleep(2)
542+ self.acc_proxy = dbus.Interface(self.dbus_con.get_object(
543+ ACCOUNTS_IFACE, ACCOUNTS_OBJ), dbusmock.MOCK_IFACE)
544+
545+ self.acc_proxy.AddMethod(ACCOUNTS_IFACE, 'FindUserById', 'x', 'o',
546+ 'ret = "%s"' % user_obj)
547+
548+ self.acc_proxy.AddObject(
549+ user_obj, ACCOUNTS_USER_IFACE, {}, [])
550+
551+ self.user_mock = dbus.Interface(self.dbus_con.get_object(
552+ ACCOUNTS_IFACE, user_obj),
553+ dbusmock.MOCK_IFACE)
554+
555+ self.user_mock.AddMethod(
556+ 'org.freedesktop.DBus.Properties', 'Set', 'ssaa{sv}', '', '')
557+
558+ def mock_for_factory_reset(self):
559+ self.mock_server = self.spawn_server(SYSTEM_IFACE, SYSTEM_SERVICE_OBJ,
560+ SYSTEM_IFACE, system_bus=True,
561+ stdout=subprocess.PIPE)
562+ # spawn_server does not wait properly
563+ # Reported as bug here: http://pad.lv/1350833
564+ sleep(2)
565+ self.sys_mock = dbus.Interface(self.dbus_con.get_object(
566+ SYSTEM_IFACE, SYSTEM_SERVICE_OBJ), dbusmock.MOCK_IFACE)
567+
568+ self.sys_mock.AddMethod(SYSTEM_IFACE, 'FactoryReset', '', '', '')
569+
570+ @classmethod
571+ def setUpClass(klass):
572+ klass.start_system_bus()
573+ klass.dbus_con = klass.get_dbus(True)
574+
575+ def setUp(self):
576+ self.mock_for_launcher_reset()
577+ self.mock_for_factory_reset()
578+
579+ super(ResetBaseTestCase, self).setUp()
580+ self.reset_page = self.system_settings.main_view.go_to_reset_phone()
581+
582+ def tearDown(self):
583+ self.mock_server.terminate()
584+ self.mock_server.wait()
585+ super(ResetBaseTestCase, self).tearDown()
586
587=== added file 'tests/autopilot/ubuntu_system_settings/tests/test_reset.py'
588--- tests/autopilot/ubuntu_system_settings/tests/test_reset.py 1970-01-01 00:00:00 +0000
589+++ tests/autopilot/ubuntu_system_settings/tests/test_reset.py 2014-08-07 14:21:27 +0000
590@@ -0,0 +1,50 @@
591+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
592+# Copyright 2014 Canonical
593+#
594+# This program is free software: you can redistribute it and/or modify it
595+# under the terms of the GNU General Public License version 3, as published
596+# by the Free Software Foundation.
597+
598+from __future__ import absolute_import
599+
600+from time import sleep
601+
602+from autopilot.matchers import Eventually
603+from gi.repository import Gio
604+from testtools.matchers import Contains, Equals
605+
606+from ubuntu_system_settings.tests import ResetBaseTestCase
607+from ubuntu_system_settings.utils.i18n import ugettext as _
608+
609+
610+class ResetTestCase(ResetBaseTestCase):
611+ """Tests for Reset Page"""
612+
613+ def set_unity_launcher_favorites(self, gsettings, favorites):
614+ gsettings.set_value('favorites', favorites)
615+ # wait for gsettings
616+ sleep(1)
617+
618+ def test_reset_page_title_is_correct(self):
619+ """Checks whether Reset page is available"""
620+ self.assertThat(
621+ self.reset_page.title,
622+ Equals(_('Reset phone')))
623+
624+ def test_reset_launcher(self):
625+ gsettings = Gio.Settings.new('com.canonical.Unity.Launcher')
626+ favorites = gsettings.get_value('favorites')
627+ self.addCleanup(
628+ self.set_unity_launcher_favorites, gsettings, favorites)
629+
630+ self.reset_page.reset_launcher()
631+
632+ self.assertThat(
633+ lambda: str(self.user_mock.GetCalls()),
634+ Eventually(Contains('com.canonical.unity.AccountsService')))
635+
636+ def test_factory_reset(self):
637+ self.reset_page.erase_and_reset_everything()
638+ self.assertThat(
639+ lambda: str(self.sys_mock.GetCalls()),
640+ Eventually(Contains('FactoryReset')))

Subscribers

People subscribed via source and target branches