Merge lp:~nataliabidart/ubuntuone-control-panel/handle-errors into lp:ubuntuone-control-panel

Proposed by Natalia Bidart
Status: Merged
Approved by: Roberto Alsina
Approved revision: 216
Merged at revision: 218
Proposed branch: lp:~nataliabidart/ubuntuone-control-panel/handle-errors
Merge into: lp:ubuntuone-control-panel
Diff against target: 1063 lines (+396/-127)
21 files modified
data/qt/signin.ui (+0/-7)
ubuntuone/controlpanel/cache.py (+7/-2)
ubuntuone/controlpanel/gui/qt/__init__.py (+49/-0)
ubuntuone/controlpanel/gui/qt/account.py (+1/-0)
ubuntuone/controlpanel/gui/qt/addfolder.py (+2/-0)
ubuntuone/controlpanel/gui/qt/controlpanel.py (+1/-0)
ubuntuone/controlpanel/gui/qt/device.py (+11/-2)
ubuntuone/controlpanel/gui/qt/devices.py (+1/-0)
ubuntuone/controlpanel/gui/qt/folders.py (+1/-0)
ubuntuone/controlpanel/gui/qt/preferences.py (+1/-0)
ubuntuone/controlpanel/gui/qt/signin.py (+9/-10)
ubuntuone/controlpanel/gui/qt/tests/__init__.py (+43/-5)
ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py (+20/-23)
ubuntuone/controlpanel/gui/qt/tests/test_common.py (+166/-3)
ubuntuone/controlpanel/gui/qt/tests/test_device.py (+19/-11)
ubuntuone/controlpanel/gui/qt/tests/test_devices.py (+0/-2)
ubuntuone/controlpanel/gui/qt/tests/test_folders.py (+14/-31)
ubuntuone/controlpanel/gui/qt/tests/test_signin.py (+14/-30)
ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py (+19/-1)
ubuntuone/controlpanel/gui/qt/ubuntuonebin.py (+11/-0)
ubuntuone/controlpanel/tests/test_cache.py (+7/-0)
To merge this branch: bzr merge lp:~nataliabidart/ubuntuone-control-panel/handle-errors
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Diego Sarmentero (community) Approve
Review via email: mp+74490@code.launchpad.net

Commit message

- Added decorator to handle errors from the backend (LP: #807021).

To post a comment you must log in.
216. By Natalia Bidart

Forgotten is_processing = False.

Revision history for this message
Diego Sarmentero (diegosarmentero) wrote :

+1

review: Approve
Revision history for this message
Roberto Alsina (ralsina) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'data/qt/signin.ui'
--- data/qt/signin.ui 2011-08-30 23:18:35 +0000
+++ data/qt/signin.ui 2011-09-08 01:17:23 +0000
@@ -41,13 +41,6 @@
41 </widget>41 </widget>
42 </item>42 </item>
43 <item>43 <item>
44 <widget class="QLabel" name="warning_label">
45 <property name="text">
46 <string>warning label!</string>
47 </property>
48 </widget>
49 </item>
50 <item>
51 <layout class="QHBoxLayout" name="horizontalLayout">44 <layout class="QHBoxLayout" name="horizontalLayout">
52 <item>45 <item>
53 <layout class="QVBoxLayout" name="verticalLayout_2">46 <layout class="QVBoxLayout" name="verticalLayout_2">
5447
=== modified file 'ubuntuone/controlpanel/cache.py'
--- ubuntuone/controlpanel/cache.py 2011-09-02 17:59:39 +0000
+++ ubuntuone/controlpanel/cache.py 2011-09-08 01:17:23 +0000
@@ -33,13 +33,18 @@
33 if self.logger is not None:33 if self.logger is not None:
34 self.logger.debug('%s: started.', self.__class__.__name__)34 self.logger.debug('%s: started.', self.__class__.__name__)
3535
36 @property36 def get_backend(self):
37 def backend(self):
38 """A cached ControlBackend instance."""37 """A cached ControlBackend instance."""
39 if not self._shared_objects:38 if not self._shared_objects:
40 self._shared_objects['backend'] = backend.ControlBackend()39 self._shared_objects['backend'] = backend.ControlBackend()
41 return self._shared_objects['backend']40 return self._shared_objects['backend']
4241
42 def set_backend(self, new_value):
43 """Set a new ControlBackend instance."""
44 self._shared_objects['backend'] = new_value
45
46 backend = property(fget=get_backend, fset=set_backend)
47
43 def clear(self):48 def clear(self):
44 """Clear all cached objects."""49 """Clear all cached objects."""
45 self._shared_objects = {}50 self._shared_objects = {}
4651
=== modified file 'ubuntuone/controlpanel/gui/qt/__init__.py'
--- ubuntuone/controlpanel/gui/qt/__init__.py 2011-09-01 17:11:16 +0000
+++ ubuntuone/controlpanel/gui/qt/__init__.py 2011-09-08 01:17:23 +0000
@@ -18,7 +18,13 @@
1818
19"""The Qt graphical interface for the control panel for Ubuntu One."""19"""The Qt graphical interface for the control panel for Ubuntu One."""
2020
21import collections
22import logging
23
24from functools import wraps
25
21from PyQt4 import QtGui, QtCore26from PyQt4 import QtGui, QtCore
27from twisted.internet import defer
2228
2329
24def uri_hook(uri):30def uri_hook(uri):
@@ -53,3 +59,46 @@
53 icon.icon_name = icon_name59 icon.icon_name = icon_name
5460
55 return icon61 return icon
62
63
64def handle_errors(error_handler=None, logger=None):
65 """Decorator to handle errors when calling a function.
66
67 if 'error_handler' is not None, it will be yielded on if any error happens.
68
69 """
70 if logger is None:
71 logger = logging.getLogger()
72
73 def middle(f):
74 """Decorator to handle errors when calling 'f'."""
75
76 @defer.inlineCallbacks
77 @wraps(f)
78 def inner(*args, **kwargs):
79 """Call 'f' passing 'args' and 'kwargs'.
80
81 Catch any error and show a error message.
82
83 """
84 try:
85 res = yield f(*args, **kwargs)
86 except Exception, e: # pylint: disable=W0703
87 logger.exception(f.__name__)
88 else:
89 defer.returnValue(res)
90
91 # this code will only be executed if there was an exception
92 if error_handler is not None:
93 yield error_handler()
94
95 if len(e.args) > 0 and isinstance(e.args[0], collections.Mapping):
96 msgs = e.args[0].itervalues()
97 else:
98 msgs = [e.__class__.__name__] + map(repr, e.args)
99 msg = '\n'.join(msgs)
100 QtGui.QMessageBox.warning(None, '', msg, QtGui.QMessageBox.Close)
101
102 return inner
103
104 return middle
56105
=== modified file 'ubuntuone/controlpanel/gui/qt/account.py'
--- ubuntuone/controlpanel/gui/qt/account.py 2011-08-31 17:18:56 +0000
+++ ubuntuone/controlpanel/gui/qt/account.py 2011-09-08 01:17:23 +0000
@@ -45,6 +45,7 @@
45 self.ui.edit_profile_button.uri = EDIT_PROFILE_LINK45 self.ui.edit_profile_button.uri = EDIT_PROFILE_LINK
46 self.ui.edit_services_button.uri = EDIT_ACCOUNT_LINK46 self.ui.edit_services_button.uri = EDIT_ACCOUNT_LINK
4747
48 # pylint: disable=E0202
48 @defer.inlineCallbacks49 @defer.inlineCallbacks
49 def load(self):50 def load(self):
50 """Load info."""51 """Load info."""
5152
=== modified file 'ubuntuone/controlpanel/gui/qt/addfolder.py'
--- ubuntuone/controlpanel/gui/qt/addfolder.py 2011-09-02 17:59:39 +0000
+++ ubuntuone/controlpanel/gui/qt/addfolder.py 2011-09-08 01:17:23 +0000
@@ -28,6 +28,7 @@
28from ubuntuone.controlpanel import cache28from ubuntuone.controlpanel import cache
29from ubuntuone.controlpanel.logger import setup_logging29from ubuntuone.controlpanel.logger import setup_logging
30from ubuntuone.controlpanel.gui import FOLDER_INVALID_PATH30from ubuntuone.controlpanel.gui import FOLDER_INVALID_PATH
31from ubuntuone.controlpanel.gui.qt import handle_errors
3132
3233
33logger = setup_logging('qt.addfolder')34logger = setup_logging('qt.addfolder')
@@ -50,6 +51,7 @@
50 self.clicked.connect(self.on_clicked)51 self.clicked.connect(self.on_clicked)
5152
52 @QtCore.pyqtSlot()53 @QtCore.pyqtSlot()
54 @handle_errors(logger=logger)
53 @defer.inlineCallbacks55 @defer.inlineCallbacks
54 def on_clicked(self):56 def on_clicked(self):
55 """The 'Sync another folder' button was clicked."""57 """The 'Sync another folder' button was clicked."""
5658
=== modified file 'ubuntuone/controlpanel/gui/qt/controlpanel.py'
--- ubuntuone/controlpanel/gui/qt/controlpanel.py 2011-09-01 17:11:16 +0000
+++ ubuntuone/controlpanel/gui/qt/controlpanel.py 2011-09-08 01:17:23 +0000
@@ -72,6 +72,7 @@
72 self.ui.switcher.setCurrentWidget(self.ui.management)72 self.ui.switcher.setCurrentWidget(self.ui.management)
73 self.is_processing = False73 self.is_processing = False
7474
75 # pylint: disable=E0202
75 @defer.inlineCallbacks76 @defer.inlineCallbacks
76 def load(self):77 def load(self):
77 """Load info."""78 """Load info."""
7879
=== modified file 'ubuntuone/controlpanel/gui/qt/device.py'
--- ubuntuone/controlpanel/gui/qt/device.py 2011-09-02 17:59:39 +0000
+++ ubuntuone/controlpanel/gui/qt/device.py 2011-09-08 01:17:23 +0000
@@ -27,8 +27,13 @@
27)27)
28from ubuntuone.controlpanel import cache28from ubuntuone.controlpanel import cache
29from ubuntuone.controlpanel.gui import DEVICE_CONFIRM_REMOVE29from ubuntuone.controlpanel.gui import DEVICE_CONFIRM_REMOVE
30from ubuntuone.controlpanel.gui.qt import icon_from_name, pixmap_from_name30from ubuntuone.controlpanel.gui.qt import (
31 handle_errors,
32 icon_from_name,
33 pixmap_from_name,
34)
31from ubuntuone.controlpanel.gui.qt.ui import device_ui35from ubuntuone.controlpanel.gui.qt.ui import device_ui
36from ubuntuone.controlpanel.logger import setup_logging
3237
33COMPUTER_ICON = "computer"38COMPUTER_ICON = "computer"
34PHONE_ICON = "phone"39PHONE_ICON = "phone"
@@ -44,6 +49,9 @@
44YES = QtGui.QMessageBox.Yes49YES = QtGui.QMessageBox.Yes
4550
4651
52logger = setup_logging('qt.device')
53
54
47def icon_name_from_type(device_type):55def icon_name_from_type(device_type):
48 """Get the icon name for the device."""56 """Get the icon name for the device."""
49 icon_name = DEVICE_TYPE_TO_ICON_MAP.get(device_type, DEFAULT_ICON)57 icon_name = DEVICE_TYPE_TO_ICON_MAP.get(device_type, DEFAULT_ICON)
@@ -70,8 +78,9 @@
70 pixmap = pixmap_from_name(icon_name)78 pixmap = pixmap_from_name(icon_name)
71 self.ui.device_icon_label.setPixmap(pixmap)79 self.ui.device_icon_label.setPixmap(pixmap)
7280
81 @QtCore.pyqtSlot()
82 @handle_errors(logger=logger)
73 @defer.inlineCallbacks83 @defer.inlineCallbacks
74 @QtCore.pyqtSlot()
75 def on_remove_device_button_clicked(self):84 def on_remove_device_button_clicked(self):
76 """The user wants to remove this device."""85 """The user wants to remove this device."""
77 msg = DEVICE_CONFIRM_REMOVE86 msg = DEVICE_CONFIRM_REMOVE
7887
=== modified file 'ubuntuone/controlpanel/gui/qt/devices.py'
--- ubuntuone/controlpanel/gui/qt/devices.py 2011-09-02 17:59:39 +0000
+++ ubuntuone/controlpanel/gui/qt/devices.py 2011-09-08 01:17:23 +0000
@@ -47,6 +47,7 @@
47 super(DevicesPanel, self)._setup()47 super(DevicesPanel, self)._setup()
48 self.ui.manage_devices_button.uri = EDIT_DEVICES_LINK48 self.ui.manage_devices_button.uri = EDIT_DEVICES_LINK
4949
50 # pylint: disable=E0202
50 @defer.inlineCallbacks51 @defer.inlineCallbacks
51 def load(self):52 def load(self):
52 """Load info."""53 """Load info."""
5354
=== modified file 'ubuntuone/controlpanel/gui/qt/folders.py'
--- ubuntuone/controlpanel/gui/qt/folders.py 2011-08-31 17:18:56 +0000
+++ ubuntuone/controlpanel/gui/qt/folders.py 2011-09-08 01:17:23 +0000
@@ -82,6 +82,7 @@
82 icon = icon_from_name('external_icon_orange')82 icon = icon_from_name('external_icon_orange')
83 self.ui.share_publish_button.setIcon(icon)83 self.ui.share_publish_button.setIcon(icon)
8484
85 # pylint: disable=E0202
85 @defer.inlineCallbacks86 @defer.inlineCallbacks
86 def load(self):87 def load(self):
87 """Load specific tab info."""88 """Load specific tab info."""
8889
=== modified file 'ubuntuone/controlpanel/gui/qt/preferences.py'
--- ubuntuone/controlpanel/gui/qt/preferences.py 2011-08-31 17:18:56 +0000
+++ ubuntuone/controlpanel/gui/qt/preferences.py 2011-09-08 01:17:23 +0000
@@ -64,6 +64,7 @@
64 ui_class = preferences_ui64 ui_class = preferences_ui
65 logger = logger65 logger = logger
6666
67 # pylint: disable=E0202
67 @defer.inlineCallbacks68 @defer.inlineCallbacks
68 def load(self):69 def load(self):
69 """Load info."""70 """Load info."""
7071
=== modified file 'ubuntuone/controlpanel/gui/qt/signin.py'
--- ubuntuone/controlpanel/gui/qt/signin.py 2011-08-31 17:18:56 +0000
+++ ubuntuone/controlpanel/gui/qt/signin.py 2011-09-08 01:17:23 +0000
@@ -19,12 +19,10 @@
19"""The signin page."""19"""The signin page."""
2020
21from PyQt4 import QtCore21from PyQt4 import QtCore
22
23from twisted.internet import defer22from twisted.internet import defer
24from ubuntuone.platform.credentials import CredentialsError
2523
26from ubuntuone.controlpanel.gui import RESET_PASSWORD_LINK24from ubuntuone.controlpanel.gui import RESET_PASSWORD_LINK
27from ubuntuone.controlpanel.gui.qt import icon_from_name25from ubuntuone.controlpanel.gui.qt import icon_from_name, handle_errors
28from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin26from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin
29from ubuntuone.controlpanel.gui.qt.ui import signin_ui27from ubuntuone.controlpanel.gui.qt.ui import signin_ui
30from ubuntuone.controlpanel.logger import setup_logging, log_call28from ubuntuone.controlpanel.logger import setup_logging, log_call
@@ -45,7 +43,6 @@
45 def _setup(self):43 def _setup(self):
46 """Do some extra setupping for the UI."""44 """Do some extra setupping for the UI."""
47 super(SignInPanel, self)._setup()45 super(SignInPanel, self)._setup()
48 self.ui.warning_label.setText("")
4946
50 self.ui.forgot_password_button.uri = RESET_PASSWORD_LINK47 self.ui.forgot_password_button.uri = RESET_PASSWORD_LINK
51 icon = icon_from_name('external_icon_orange')48 icon = icon_from_name('external_icon_orange')
@@ -64,21 +61,23 @@
64 self.ui.signin_button.style().unpolish(self.ui.signin_button)61 self.ui.signin_button.style().unpolish(self.ui.signin_button)
65 self.ui.signin_button.style().polish(self.ui.signin_button)62 self.ui.signin_button.style().polish(self.ui.signin_button)
6663
64 # pylint: disable=E0202
65 @defer.inlineCallbacks
66 def load(self):
67 """Load specific tab info."""
68 yield self.backend.get_credentials()
69
70 @QtCore.pyqtSlot()
71 @handle_errors(logger=logger)
67 @log_call(logger.debug)72 @log_call(logger.debug)
68 @defer.inlineCallbacks73 @defer.inlineCallbacks
69 @QtCore.pyqtSlot()
70 def on_signin_button_clicked(self):74 def on_signin_button_clicked(self):
71 """The 'Sign in' button was clicked."""75 """The 'Sign in' button was clicked."""
72 self.ui.warning_label.setText("")
73 email = unicode(self.ui.email_entry.text())76 email = unicode(self.ui.email_entry.text())
74 password = unicode(self.ui.password_entry.text())77 password = unicode(self.ui.password_entry.text())
75 self.is_processing = True78 self.is_processing = True
76 try:79 try:
77 result = yield self.backend.login(email=email, password=password)80 result = yield self.backend.login(email=email, password=password)
78 except CredentialsError, e:
79 logger.info('on_signin_button_clicked: %r', e)
80 self.ui.warning_label.setText(e.args[0]['message'])
81 else:
82 logger.info('Emitting credentialsFound for email %r.', email)81 logger.info('Emitting credentialsFound for email %r.', email)
83 self.credentialsFound.emit(result)82 self.credentialsFound.emit(result)
84 finally:83 finally:
8584
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/__init__.py'
--- ubuntuone/controlpanel/gui/qt/tests/__init__.py 2011-09-02 17:59:39 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/__init__.py 2011-09-08 01:17:23 +0000
@@ -22,7 +22,7 @@
22import os22import os
23import urllib23import urllib
2424
25from PyQt4 import QtCore25from PyQt4 import QtGui, QtCore
26from ubuntuone.devtools.handlers import MementoHandler26from ubuntuone.devtools.handlers import MementoHandler
2727
28from ubuntuone.controlpanel import backend, cache28from ubuntuone.controlpanel import backend, cache
@@ -126,9 +126,32 @@
126 return TOKEN126 return TOKEN
127127
128128
129class FakedConfirmDialog(object):129class CrashyBackendException(Exception):
130 """A faked backend crash."""
131
132
133class CrashyBackend(FakedControlPanelBackend):
134 """A faked backend that crashes."""
135
136 def __init__(self, *args, **kwargs):
137 super(CrashyBackend, self).__init__(*args, **kwargs)
138 for i in self.exposed_methods + ['get_credentials']:
139 setattr(self, i, self._fail(i))
140
141 def _fail(self, f):
142 """Crash boom bang."""
143
144 def inner(*args, **kwargs):
145 """Raise a custom exception."""
146 raise CrashyBackendException(f)
147
148 return inner
149
150
151class FakedDialog(object):
130 """Fake a confirmation dialog."""152 """Fake a confirmation dialog."""
131153
154 Close = 0
132 response = args = kwargs = None155 response = args = kwargs = None
133156
134 @classmethod157 @classmethod
@@ -163,6 +186,7 @@
163 innerclass_name = None186 innerclass_name = None
164 class_ui = None187 class_ui = None
165 kwargs = {}188 kwargs = {}
189 logger = None
166190
167 def setUp(self):191 def setUp(self):
168 cache.Cache._shared_objects = {}192 cache.Cache._shared_objects = {}
@@ -180,11 +204,25 @@
180 if getattr(self.ui, 'backend', None) is not None:204 if getattr(self.ui, 'backend', None) is not None:
181 self.addCleanup(self.ui.backend._called.clear)205 self.addCleanup(self.ui.backend._called.clear)
182206
183 if getattr(self.ui, 'logger', None) is not None:207 logger = self.logger if self.logger is not None else \
208 getattr(self.ui, 'logger', None)
209 self.memento = None
210 if logger is not None:
184 self.memento = MementoHandler()211 self.memento = MementoHandler()
185 self.memento.setLevel(logging.DEBUG)212 self.memento.setLevel(logging.DEBUG)
186 self.ui.logger.addHandler(self.memento)213 logger.addHandler(self.memento)
187 self.addCleanup(self.ui.logger.removeHandler, self.memento)214 self.addCleanup(logger.removeHandler, self.memento)
215
216 # default response if user does nothing
217 FakedFileDialog.response = QtCore.QString('')
218 FakedFileDialog.args = None
219 FakedFileDialog.kwargs = None
220 self.patch(QtGui, 'QFileDialog', FakedFileDialog)
221
222 FakedDialog.response = None
223 FakedDialog.args = None
224 FakedDialog.kwargs = None
225 self.patch(QtGui, 'QMessageBox', FakedDialog)
188226
189 def get_pixmap_data(self, pixmap):227 def get_pixmap_data(self, pixmap):
190 """Get the raw data of a QPixmap."""228 """Get the raw data of a QPixmap."""
191229
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py 2011-08-29 13:28:58 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py 2011-09-08 01:17:23 +0000
@@ -29,7 +29,9 @@
29from ubuntuone.controlpanel.gui.qt import addfolder as gui29from ubuntuone.controlpanel.gui.qt import addfolder as gui
30from ubuntuone.controlpanel.gui.qt.tests import (30from ubuntuone.controlpanel.gui.qt.tests import (
31 BaseTestCase,31 BaseTestCase,
32 FakedConfirmDialog,32 CrashyBackend,
33 CrashyBackendException,
34 FakedDialog,
33 FakedFileDialog,35 FakedFileDialog,
34 set_path_on_file_dialog,36 set_path_on_file_dialog,
35)37)
@@ -53,20 +55,6 @@
53 os.environ['HOME'] = USER_HOME55 os.environ['HOME'] = USER_HOME
54 self.addCleanup(lambda: os.environ.__setitem__('HOME', old_home))56 self.addCleanup(lambda: os.environ.__setitem__('HOME', old_home))
5557
56 # default response if user does nothing
57 FakedFileDialog.response = gui.QtCore.QString('')
58 FakedFileDialog.args = None
59 FakedFileDialog.kwargs = None
60 self.patch(gui.QtGui, 'QFileDialog', FakedFileDialog)
61
62 FakedConfirmDialog.response = None
63 FakedConfirmDialog.args = None
64 FakedConfirmDialog.kwargs = None
65 self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog)
66
67 # reset backend state
68 self.ui.backend._called.clear()
69
70 @defer.inlineCallbacks58 @defer.inlineCallbacks
71 def assert_does_nothing(self, method_call):59 def assert_does_nothing(self, method_call):
72 """Nothing happens.60 """Nothing happens.
@@ -103,8 +91,8 @@
103 yield self.assert_does_nothing(self.ui.click)91 yield self.assert_does_nothing(self.ui.click)
10492
105 # the warning dialog was not opened93 # the warning dialog was not opened
106 self.assertEqual(FakedConfirmDialog.args, None)94 self.assertEqual(FakedDialog.args, None)
107 self.assertEqual(FakedConfirmDialog.kwargs, None)95 self.assertEqual(FakedDialog.kwargs, None)
10896
109 @defer.inlineCallbacks97 @defer.inlineCallbacks
110 def test_opens_warning_if_folder_path_not_valid(self):98 def test_opens_warning_if_folder_path_not_valid(self):
@@ -116,9 +104,9 @@
116104
117 args = {'folder_path': folder_path, 'home_folder': USER_HOME}105 args = {'folder_path': folder_path, 'home_folder': USER_HOME}
118 msg = gui.FOLDER_INVALID_PATH % args106 msg = gui.FOLDER_INVALID_PATH % args
119 self.assertEqual(FakedConfirmDialog.args,107 self.assertEqual(FakedDialog.args,
120 (self.ui, '', msg, gui.CLOSE))108 (self.ui, '', msg, gui.CLOSE))
121 self.assertEqual(FakedConfirmDialog.kwargs, {})109 self.assertEqual(FakedDialog.kwargs, {})
122110
123 yield self.assert_does_nothing(self.ui.click)111 yield self.assert_does_nothing(self.ui.click)
124112
@@ -129,8 +117,8 @@
129 yield self.ui.click()117 yield self.ui.click()
130118
131 # no warning119 # no warning
132 self.assertEqual(FakedConfirmDialog.args, None)120 self.assertEqual(FakedDialog.args, None)
133 self.assertEqual(FakedConfirmDialog.kwargs, None)121 self.assertEqual(FakedDialog.kwargs, None)
134 # backend called122 # backend called
135 self.assert_backend_called('create_folder', folder_path=folder)123 self.assert_backend_called('create_folder', folder_path=folder)
136124
@@ -141,8 +129,8 @@
141 yield self.ui.click()129 yield self.ui.click()
142130
143 # no warning131 # no warning
144 self.assertEqual(FakedConfirmDialog.args, None)132 self.assertEqual(FakedDialog.args, None)
145 self.assertEqual(FakedConfirmDialog.kwargs, None)133 self.assertEqual(FakedDialog.kwargs, None)
146 # backend called134 # backend called
147 self.assert_backend_called('create_folder', folder_path=folder)135 self.assert_backend_called('create_folder', folder_path=folder)
148136
@@ -170,3 +158,12 @@
170 yield self.ui.click()158 yield self.ui.click()
171159
172 self.assertEqual(self._called, ((), {}))160 self.assertEqual(self._called, ((), {}))
161
162 @defer.inlineCallbacks
163 def test_backend_error_is_handled(self):
164 """Any error from the backend is properly handled."""
165 set_path_on_file_dialog()
166 self.patch(self.ui, 'backend', CrashyBackend())
167 yield self.ui.click()
168
169 self.assertTrue(self.memento.check_exception(CrashyBackendException))
173170
=== renamed file 'ubuntuone/controlpanel/gui/qt/tests/test_urihook.py' => 'ubuntuone/controlpanel/gui/qt/tests/test_common.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_urihook.py 2011-09-01 17:11:16 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_common.py 2011-09-08 01:17:23 +0000
@@ -18,12 +18,17 @@
1818
19"""Tests for the uri_hook helper."""19"""Tests for the uri_hook helper."""
2020
21import logging
22
21from PyQt4 import QtGui, QtCore23from PyQt4 import QtGui, QtCore
22
23from twisted.internet import defer24from twisted.internet import defer
2425
25from ubuntuone.controlpanel.gui.qt import uri_hook26from ubuntuone.controlpanel.logger import setup_logging
26from ubuntuone.controlpanel.gui.qt.tests import BaseTestCase27from ubuntuone.controlpanel.gui.qt import uri_hook, handle_errors
28from ubuntuone.controlpanel.gui.qt.tests import (
29 BaseTestCase,
30 FakedDialog,
31)
2732
2833
29class UriHookTestCase(BaseTestCase):34class UriHookTestCase(BaseTestCase):
@@ -45,3 +50,161 @@
45 expected = 'http://foo.bar/?next=https://one.ubuntu.com/'50 expected = 'http://foo.bar/?next=https://one.ubuntu.com/'
46 uri_hook(expected)51 uri_hook(expected)
47 self.assertEqual(self._called, ((QtCore.QUrl(expected),), {}))52 self.assertEqual(self._called, ((QtCore.QUrl(expected),), {}))
53
54
55class HandleErrorTestCase(BaseTestCase):
56 """Test suite for the generic error handler."""
57
58 error_handler = None
59 use_logger = False
60 logger = logging.getLogger() # root logger
61
62 @defer.inlineCallbacks
63 def setUp(self):
64 yield super(HandleErrorTestCase, self).setUp()
65 self.called = None
66 self.result = None
67 self.failure = None
68 self.error_handler_called = None
69
70 if self.use_logger:
71 logger = self.logger
72 else:
73 logger = None
74
75 self.decorate_me = handle_errors(error_handler=self.error_handler,
76 logger=logger)(self._decorate_me)
77
78 @defer.inlineCallbacks
79 def _decorate_me(self, *args, **kwargs):
80 """Helper to test thye decorator."""
81 if self.failure:
82 # Raising only classes, instances or string are allowed
83 # pylint: disable=E0702
84 raise self.failure
85
86 yield
87 self.called = (args, kwargs)
88 defer.returnValue(self.result)
89
90 @defer.inlineCallbacks
91 def test_is_decorator(self):
92 """Is a decorator."""
93 yield self.decorate_me()
94
95 @defer.inlineCallbacks
96 def test_params_are_passed(self):
97 """Named and unnamed arguments are passed."""
98 args = ({}, object(), 'foo')
99 kwargs = {'1': 1, 'test': None, '0': ['a']}
100 yield self.decorate_me(*args, **kwargs)
101
102 self.assertTrue(self.called, (args, kwargs))
103
104 @defer.inlineCallbacks
105 def test_result_is_returned(self):
106 """Result is returned."""
107 self.result = object()
108 result = yield self.decorate_me()
109
110 self.assertEqual(self.result, result)
111
112 def test_name_is_preserved(self):
113 """The method name is not masqueraded."""
114 self.assertEqual(self.decorate_me.__name__, self._decorate_me.__name__)
115
116 @defer.inlineCallbacks
117 def test_exeptions_are_handled(self):
118 """Any exception is handled and logged in the root logger."""
119 msg = 'This is me failing badly.'
120 self.failure = Exception(msg)
121
122 yield self.decorate_me()
123
124 logged = self.memento.check_exception(self.failure.__class__, msg)
125 recs = '\n'.join(rec.exc_text for rec in self.memento.records)
126 self.assertTrue(logged, 'Exception must be logged, got:\n%s' % recs)
127
128 @defer.inlineCallbacks
129 def test_show_error_message(self):
130 """On error, show an error message."""
131 self.failure = Exception()
132
133 yield self.decorate_me()
134
135 msg = self.failure.__class__.__name__
136 self.assertEqual(FakedDialog.args,
137 (None, '', msg, QtGui.QMessageBox.Close))
138 self.assertEqual(FakedDialog.kwargs, {})
139
140 @defer.inlineCallbacks
141 def test_show_error_message_if_args(self):
142 """On error, show an error message."""
143 msg1 = 'This is me failing badly.'
144 msg2 = 'More details about what went wrong.'
145 obj = object()
146 self.failure = Exception(msg1, msg2, obj)
147
148 yield self.decorate_me()
149
150 msg = '\n'.join(map(repr, (msg1, msg2, obj)))
151 msg = self.failure.__class__.__name__ + '\n' + msg
152 self.assertEqual(FakedDialog.args,
153 (None, '', msg, QtGui.QMessageBox.Close))
154 self.assertEqual(FakedDialog.kwargs, {})
155
156 @defer.inlineCallbacks
157 def test_show_error_message_if_mapping(self):
158 """On error, show an error message."""
159 msg1 = 'This is me failing badly.'
160 msg2 = 'More details about what went wrong.'
161 errdict = {'foo': msg1, 'bar': msg2}
162 self.failure = Exception(errdict)
163
164 yield self.decorate_me()
165
166 msg = '\n'.join((msg1, msg2))
167 self.assertEqual(FakedDialog.args,
168 (None, '', msg, QtGui.QMessageBox.Close))
169 self.assertEqual(FakedDialog.kwargs, {})
170
171 @defer.inlineCallbacks
172 def test_no_error_message_if_no_exception(self):
173 """On success, do not show an error message."""
174 yield self.decorate_me()
175
176 self.assertEqual(FakedDialog.args, None)
177 self.assertEqual(FakedDialog.kwargs, None)
178
179 @defer.inlineCallbacks
180 def test_call_error_handler(self):
181 """On success, do not execute error_handler."""
182 yield self.decorate_me()
183 self.assertFalse(self.error_handler_called)
184
185
186class HandleErrorWithCustomLoggerTestCase(HandleErrorTestCase):
187 """Test suite for the generic error handler."""
188
189 use_logger = True
190 logger = setup_logging('HandleErrorWithoutLoggerTestCase') # custom logger
191
192
193class HandleErrorWithHandlerTestCase(HandleErrorTestCase):
194 """Test suite for the generic error handler when using a custom handler."""
195
196 @defer.inlineCallbacks
197 def error_handler(self, *a, **kw):
198 """Implement an error handler."""
199 self.error_handler_called = (a, kw)
200 yield
201
202 @defer.inlineCallbacks
203 def test_call_error_handler(self):
204 """On error, execute error_handler."""
205 msg = 'This is me failing badly.'
206 self.failure = Exception(msg)
207
208 yield self.decorate_me()
209
210 self.assertEqual(self.error_handler_called, ((), {}))
48211
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_device.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_device.py 2011-09-02 17:59:39 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_device.py 2011-09-08 01:17:23 +0000
@@ -23,7 +23,9 @@
23from ubuntuone.controlpanel.gui.qt import device as gui23from ubuntuone.controlpanel.gui.qt import device as gui
24from ubuntuone.controlpanel.gui.qt.tests import (24from ubuntuone.controlpanel.gui.qt.tests import (
25 BaseTestCase,25 BaseTestCase,
26 FakedConfirmDialog,26 CrashyBackend,
27 CrashyBackendException,
28 FakedDialog,
27 SAMPLE_COMPUTER_INFO,29 SAMPLE_COMPUTER_INFO,
28 SAMPLE_PHONE_INFO,30 SAMPLE_PHONE_INFO,
29)31)
@@ -41,6 +43,7 @@
41 class_ui = gui.DeviceWidget43 class_ui = gui.DeviceWidget
42 device_id = 'zaraza'44 device_id = 'zaraza'
43 kwargs = {'device_id': device_id}45 kwargs = {'device_id': device_id}
46 logger = gui.logger
4447
45 def test_has_id(self):48 def test_has_id(self):
46 """The device as an id, None by default."""49 """The device as an id, None by default."""
@@ -98,10 +101,7 @@
98 @defer.inlineCallbacks101 @defer.inlineCallbacks
99 def setUp(self):102 def setUp(self):
100 yield super(RemoveDeviceTestCase, self).setUp()103 yield super(RemoveDeviceTestCase, self).setUp()
101 FakedConfirmDialog.response = gui.NO104 FakedDialog.response = gui.YES
102 FakedConfirmDialog.args = None
103 FakedConfirmDialog.kwargs = None
104 self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog)
105105
106 def test_remove_device_opens_confirmation_dialog(self):106 def test_remove_device_opens_confirmation_dialog(self):
107 """A confirmation dialog is opened when user clicks 'delete device'."""107 """A confirmation dialog is opened when user clicks 'delete device'."""
@@ -109,13 +109,13 @@
109109
110 msg = gui.DEVICE_CONFIRM_REMOVE110 msg = gui.DEVICE_CONFIRM_REMOVE
111 buttons = gui.YES | gui.NO111 buttons = gui.YES | gui.NO
112 self.assertEqual(FakedConfirmDialog.args,112 self.assertEqual(FakedDialog.args,
113 (self.ui, '', msg, buttons, gui.NO))113 (self.ui, '', msg, buttons, gui.NO))
114 self.assertEqual(FakedConfirmDialog.kwargs, {})114 self.assertEqual(FakedDialog.kwargs, {})
115115
116 def test_remove_device_does_not_remove_if_answer_is_no(self):116 def test_remove_device_does_not_remove_if_answer_is_no(self):
117 """The device is not removed is answer is No."""117 """The device is not removed is answer is No."""
118 FakedConfirmDialog.response = gui.NO118 FakedDialog.response = gui.NO
119 self.ui.removed.connect(self._set_called)119 self.ui.removed.connect(self._set_called)
120 self.ui.ui.remove_device_button.click()120 self.ui.ui.remove_device_button.click()
121121
@@ -124,7 +124,7 @@
124124
125 def test_remove_device_does_remove_if_answer_is_yes(self):125 def test_remove_device_does_remove_if_answer_is_yes(self):
126 """The device is removed is answer is Yes."""126 """The device is removed is answer is Yes."""
127 FakedConfirmDialog.response = gui.YES127 FakedDialog.response = gui.YES
128 self.ui.ui.remove_device_button.click()128 self.ui.ui.remove_device_button.click()
129129
130 self.assert_backend_called('remove_device', device_id=self.device_id)130 self.assert_backend_called('remove_device', device_id=self.device_id)
@@ -138,7 +138,7 @@
138 """Fire deferred when the device was removed."""138 """Fire deferred when the device was removed."""
139 d.callback(device_id)139 d.callback(device_id)
140140
141 FakedConfirmDialog.response = gui.YES141 FakedDialog.response = gui.YES
142 self.ui.removed.connect(self._set_called)142 self.ui.removed.connect(self._set_called)
143 self.patch(self.ui.backend, 'remove_device', check)143 self.patch(self.ui.backend, 'remove_device', check)
144 self.ui.ui.remove_device_button.click()144 self.ui.ui.remove_device_button.click()
@@ -148,8 +148,16 @@
148148
149 def test_remove_device_emits_signal_when_not_removed(self):149 def test_remove_device_emits_signal_when_not_removed(self):
150 """The signal 'removeCanceled' is emitted when user cancels removal."""150 """The signal 'removeCanceled' is emitted when user cancels removal."""
151 FakedConfirmDialog.response = gui.NO151 FakedDialog.response = gui.NO
152 self.ui.removeCanceled.connect(self._set_called)152 self.ui.removeCanceled.connect(self._set_called)
153 self.ui.ui.remove_device_button.click()153 self.ui.ui.remove_device_button.click()
154154
155 self.assertEqual(self._called, ((), {}))155 self.assertEqual(self._called, ((), {}))
156
157 @defer.inlineCallbacks
158 def test_backend_error_is_handled(self):
159 """Any error from the backend is properly handled."""
160 self.patch(self.ui, 'backend', CrashyBackend())
161 yield self.ui.ui.remove_device_button.click()
162
163 self.assertTrue(self.memento.check_exception(CrashyBackendException))
156164
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_devices.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2011-09-01 17:11:16 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2011-09-08 01:17:23 +0000
@@ -22,7 +22,6 @@
2222
23from ubuntuone.controlpanel.gui.qt import devices as gui23from ubuntuone.controlpanel.gui.qt import devices as gui
24from ubuntuone.controlpanel.gui.qt.tests import (24from ubuntuone.controlpanel.gui.qt.tests import (
25 FakedConfirmDialog,
26 SAMPLE_DEVICES_INFO,25 SAMPLE_DEVICES_INFO,
27)26)
28from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import (27from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import (
@@ -41,7 +40,6 @@
41 def setUp(self):40 def setUp(self):
42 yield super(DevicesPanelTestCase, self).setUp()41 yield super(DevicesPanelTestCase, self).setUp()
43 self.ui.backend.next_result = SAMPLE_DEVICES_INFO42 self.ui.backend.next_result = SAMPLE_DEVICES_INFO
44 self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog)
4543
46 def test_is_processing_while_asking_info(self):44 def test_is_processing_while_asking_info(self):
47 """The ui is processing while the contents are loaded."""45 """The ui is processing while the contents are loaded."""
4846
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_folders.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2011-09-01 17:11:16 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2011-09-08 01:17:23 +0000
@@ -33,8 +33,7 @@
33)33)
34from ubuntuone.controlpanel.gui.qt import folders as gui34from ubuntuone.controlpanel.gui.qt import folders as gui
35from ubuntuone.controlpanel.gui.qt.tests import (35from ubuntuone.controlpanel.gui.qt.tests import (
36 FakedConfirmDialog,36 FakedDialog,
37 FakedFileDialog,
38)37)
39from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import (38from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import (
40 UbuntuOneBinTestCase,39 UbuntuOneBinTestCase,
@@ -320,17 +319,6 @@
320 # reset backend state319 # reset backend state
321 self.ui.backend._called.clear()320 self.ui.backend._called.clear()
322321
323 # default response if user does nothing
324 FakedFileDialog.response = gui.QtCore.QString('')
325 FakedFileDialog.args = None
326 FakedFileDialog.kwargs = None
327 self.patch(gui.QtGui, 'QFileDialog', FakedFileDialog)
328
329 FakedConfirmDialog.response = None
330 FakedConfirmDialog.args = None
331 FakedConfirmDialog.kwargs = None
332 self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog)
333
334 def test_not_is_processing(self):322 def test_not_is_processing(self):
335 """Before clicking the add folder button, the UI is not processing."""323 """Before clicking the add folder button, the UI is not processing."""
336 self.assertFalse(self.ui.is_processing, 'ui must not be processing')324 self.assertFalse(self.ui.is_processing, 'ui must not be processing')
@@ -354,10 +342,7 @@
354 def setUp(self):342 def setUp(self):
355 yield super(FoldersPanelSubscriptionTestCase, self).setUp()343 yield super(FoldersPanelSubscriptionTestCase, self).setUp()
356 self.patch(gui.os.path, 'exists', lambda path: True)344 self.patch(gui.os.path, 'exists', lambda path: True)
357 FakedConfirmDialog.response = gui.YES345 FakedDialog.response = gui.YES
358 FakedConfirmDialog.args = None
359 FakedConfirmDialog.kwargs = None
360 self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog)
361346
362 self.ui.process_info(FAKE_VOLUMES_MINIMAL_INFO)347 self.ui.process_info(FAKE_VOLUMES_MINIMAL_INFO)
363 # the music folder348 # the music folder
@@ -436,9 +421,9 @@
436 volume_path = self.item.volume_path421 volume_path = self.item.volume_path
437 msg = gui.FOLDERS_CONFIRM_MERGE % {'folder_path': volume_path}422 msg = gui.FOLDERS_CONFIRM_MERGE % {'folder_path': volume_path}
438 buttons = gui.YES | gui.NO | gui.CANCEL423 buttons = gui.YES | gui.NO | gui.CANCEL
439 self.assertEqual(FakedConfirmDialog.args,424 self.assertEqual(FakedDialog.args,
440 (self.ui, '', msg, buttons, gui.YES))425 (self.ui, '', msg, buttons, gui.YES))
441 self.assertEqual(FakedConfirmDialog.kwargs, {})426 self.assertEqual(FakedDialog.kwargs, {})
442427
443 @defer.inlineCallbacks428 @defer.inlineCallbacks
444 def test_confirm_dialog_if_path_does_not_exist(self):429 def test_confirm_dialog_if_path_does_not_exist(self):
@@ -452,14 +437,13 @@
452437
453 yield self.ui.on_folders_itemChanged(self.item)438 yield self.ui.on_folders_itemChanged(self.item)
454439
455 self.assertEqual(FakedConfirmDialog.args, None)440 self.assertEqual(FakedDialog.args, None)
456 self.assertEqual(FakedConfirmDialog.kwargs, None)441 self.assertEqual(FakedDialog.kwargs, None)
457442
458 @defer.inlineCallbacks443 @defer.inlineCallbacks
459 def test_subscribe_does_not_call_backend_if_dialog_closed(self):444 def test_subscribe_does_not_call_backend_if_dialog_closed(self):
460 """Backend is not called if users closes the confirmation dialog."""445 """Backend is not called if users closes the confirmation dialog."""
461 FakedConfirmDialog.response = gui.CANCEL446 FakedDialog.response = gui.CANCEL
462 self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog)
463447
464 # make sure the item is subscribed448 # make sure the item is subscribed
465 self.ui.is_processing = True449 self.ui.is_processing = True
@@ -468,7 +452,7 @@
468452
469 yield self.ui.on_folders_itemChanged(self.item)453 yield self.ui.on_folders_itemChanged(self.item)
470454
471 self.assertFalse(FakedConfirmDialog.args is None, 'warning was called')455 self.assertFalse(FakedDialog.args is None, 'warning was called')
472 self.assertNotIn('change_volume_settings', self.ui.backend._called)456 self.assertNotIn('change_volume_settings', self.ui.backend._called)
473 self.assertFalse(self.ui.is_processing)457 self.assertFalse(self.ui.is_processing)
474458
@@ -478,8 +462,7 @@
478 @defer.inlineCallbacks462 @defer.inlineCallbacks
479 def test_subscribe_does_not_call_backend_if_answer_is_no(self):463 def test_subscribe_does_not_call_backend_if_answer_is_no(self):
480 """Backend is not called if users clicks on 'No'."""464 """Backend is not called if users clicks on 'No'."""
481 FakedConfirmDialog.response = gui.NO465 FakedDialog.response = gui.NO
482 self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog)
483466
484 # make sure the item is subscribed467 # make sure the item is subscribed
485 self.ui.is_processing = True468 self.ui.is_processing = True
@@ -488,7 +471,7 @@
488471
489 yield self.ui.on_folders_itemChanged(self.item)472 yield self.ui.on_folders_itemChanged(self.item)
490473
491 self.assertFalse(FakedConfirmDialog.args is None, 'warning was called')474 self.assertFalse(FakedDialog.args is None, 'warning was called')
492 self.assertNotIn('change_volume_settings', self.ui.backend._called)475 self.assertNotIn('change_volume_settings', self.ui.backend._called)
493 self.assertFalse(self.ui.is_processing)476 self.assertFalse(self.ui.is_processing)
494477
@@ -504,10 +487,10 @@
504 self.ui.is_processing = False487 self.ui.is_processing = False
505488
506 # the confirm dialog was not called so far489 # the confirm dialog was not called so far
507 assert FakedConfirmDialog.args is None490 assert FakedDialog.args is None
508 assert FakedConfirmDialog.kwargs is None491 assert FakedDialog.kwargs is None
509492
510 yield self.ui.on_folders_itemChanged(self.item)493 yield self.ui.on_folders_itemChanged(self.item)
511494
512 self.assertTrue(FakedConfirmDialog.args is None, 'dialog was not run')495 self.assertTrue(FakedDialog.args is None, 'dialog was not run')
513 self.assertTrue(FakedConfirmDialog.kwargs is None, 'dialog was hid')496 self.assertTrue(FakedDialog.kwargs is None, 'dialog was hid')
514497
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_signin.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_signin.py 2011-08-31 17:18:56 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_signin.py 2011-09-08 01:17:23 +0000
@@ -22,6 +22,10 @@
2222
23from ubuntuone.controlpanel.gui import qt23from ubuntuone.controlpanel.gui import qt
24from ubuntuone.controlpanel.gui.qt import signin as gui24from ubuntuone.controlpanel.gui.qt import signin as gui
25from ubuntuone.controlpanel.gui.qt.tests import (
26 CrashyBackend,
27 CrashyBackendException,
28)
25from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import (29from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import (
26 UbuntuOneBinTestCase,30 UbuntuOneBinTestCase,
27)31)
@@ -36,7 +40,7 @@
3640
37def fail(*a, **kw):41def fail(*a, **kw):
38 """Emit CredentialsError."""42 """Emit CredentialsError."""
39 raise gui.CredentialsError(MSG)43 raise TypeError(MSG)
4044
4145
42class BaseSignInPanelTestCase(UbuntuOneBinTestCase):46class BaseSignInPanelTestCase(UbuntuOneBinTestCase):
@@ -81,10 +85,6 @@
81 yield self.ui.ui.signin_button.click()85 yield self.ui.ui.signin_button.click()
82 self.assertFalse(self.ui.is_processing)86 self.assertFalse(self.ui.is_processing)
8387
84 def test_warning_label_empty(self):
85 """The warning_label is empty at startup."""
86 self.assertEqual('', unicode(self.ui.ui.warning_label.text()))
87
88 def test_signin_disabled_at_startup(self):88 def test_signin_disabled_at_startup(self):
89 """The signin_button is disabled at startup."""89 """The signin_button is disabled at startup."""
90 self.assertFalse(self.ui.ui.signin_button.isEnabled())90 self.assertFalse(self.ui.ui.signin_button.isEnabled())
@@ -139,31 +139,7 @@
139 yield self.ui.ui.signin_button.click()139 yield self.ui.ui.signin_button.click()
140140
141 self.assertEqual(self._called, ((TOKEN,), {}))141 self.assertEqual(self._called, ((TOKEN,), {}))
142 self.assertEqual('', unicode(self.ui.ui.warning_label.text()))142 self.assertFalse(self.ui.is_processing)
143 self.assertFalse(self.ui.is_processing)
144
145 @defer.inlineCallbacks
146 def test_signin_credentials_error(self):
147 """Show error when CredentialsError was raised from the backend."""
148 self.patch(self.ui.backend, 'login', fail)
149 self.ui.credentialsFound.connect(self._set_called)
150 yield self.ui.ui.signin_button.click()
151
152 self.assertFalse(self._called, 'credentialsFound must not be emitted.')
153 self.assertEqual(MSG['message'],
154 unicode(self.ui.ui.warning_label.text()))
155 self.assertFalse(self.ui.is_processing)
156 self.assertTrue(self.memento.check_info('signin_button_clicked',
157 repr(MSG)))
158
159 @defer.inlineCallbacks
160 def test_signin_success_after_error(self):
161 """Emit credentialsFound on signin success."""
162 self.patch(self.ui.backend, 'login', fail) # login failed
163 yield self.ui.ui.signin_button.click()
164
165 self.patch(self.ui.backend, 'login', lambda *a, **kw: TOKEN) # success
166 yield self.test_signin_success()
167143
168 def test_signin_enabled_if_email_and_password(self):144 def test_signin_enabled_if_email_and_password(self):
169 """Enable signin_button if email and password are non empty."""145 """Enable signin_button if email and password are non empty."""
@@ -182,3 +158,11 @@
182 self.assertEqual(1, receivers)158 self.assertEqual(1, receivers)
183159
184 self._called = False160 self._called = False
161
162 @defer.inlineCallbacks
163 def test_backend_error_is_handled(self):
164 """Any error from the backend is properly handled."""
165 self.patch(self.ui, 'backend', CrashyBackend())
166 yield self.ui.ui.signin_button.click()
167
168 self.assertTrue(self.memento.check_exception(CrashyBackendException))
185169
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py 2011-09-02 17:59:39 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py 2011-09-08 01:17:23 +0000
@@ -18,10 +18,15 @@
1818
19"""Tests for the Ubuntu One Bin."""19"""Tests for the Ubuntu One Bin."""
2020
21from twisted.internet import defer
21from ubuntuone.devtools.testcase import skipIfOS22from ubuntuone.devtools.testcase import skipIfOS
2223
23from ubuntuone.controlpanel.gui.qt import ubuntuonebin as gui24from ubuntuone.controlpanel.gui.qt import ubuntuonebin as gui
24from ubuntuone.controlpanel.gui.qt.tests import BaseTestCase25from ubuntuone.controlpanel.gui.qt.tests import (
26 BaseTestCase,
27 CrashyBackend,
28 CrashyBackendException,
29)
2530
26# Attribute 'yyy' defined outside __init__, access to a protected member31# Attribute 'yyy' defined outside __init__, access to a protected member
27# pylint: disable=W0201, W021232# pylint: disable=W0201, W0212
@@ -45,6 +50,7 @@
45 def test_is_enabled_if_not_processing(self):50 def test_is_enabled_if_not_processing(self):
46 """If not processing, the UI is enabled."""51 """If not processing, the UI is enabled."""
47 self.ui.show() # need to show to test widgets visibility52 self.ui.show() # need to show to test widgets visibility
53 self.addCleanup(self.ui.hide)
4854
49 self.ui.is_processing = False55 self.ui.is_processing = False
5056
@@ -55,8 +61,20 @@
55 def test_is_not_enabled_if_processing(self):61 def test_is_not_enabled_if_processing(self):
56 """If processing, the UI is disabled."""62 """If processing, the UI is disabled."""
57 self.ui.show() # need to show to test widgets visibility63 self.ui.show() # need to show to test widgets visibility
64 self.addCleanup(self.ui.hide)
5865
59 self.ui.is_processing = True66 self.ui.is_processing = True
6067
61 self.assertFalse(self.ui.isEnabled())68 self.assertFalse(self.ui.isEnabled())
62 self.assertTrue(self.ui.overlay.isVisible())69 self.assertTrue(self.ui.overlay.isVisible())
70
71 @defer.inlineCallbacks
72 def test_backend_error_is_handled(self):
73 """Any error from the backend is properly handled."""
74 self.patch(self.ui, 'backend', CrashyBackend())
75 yield self.ui.load()
76
77 self.assertFalse(self.ui.is_processing)
78 if self.memento:
79 logged = self.memento.check_exception(CrashyBackendException)
80 self.assertTrue(logged)
6381
=== modified file 'ubuntuone/controlpanel/gui/qt/ubuntuonebin.py'
--- ubuntuone/controlpanel/gui/qt/ubuntuonebin.py 2011-09-02 17:59:39 +0000
+++ ubuntuone/controlpanel/gui/qt/ubuntuonebin.py 2011-09-08 01:17:23 +0000
@@ -21,6 +21,7 @@
21from PyQt4 import QtGui21from PyQt4 import QtGui
2222
23from ubuntuone.controlpanel import cache23from ubuntuone.controlpanel import cache
24from ubuntuone.controlpanel.gui.qt import handle_errors
24from ubuntuone.controlpanel.gui.qt.loadingoverlay import LoadingOverlay25from ubuntuone.controlpanel.gui.qt.loadingoverlay import LoadingOverlay
2526
2627
@@ -45,6 +46,11 @@
45 self._is_processing = None46 self._is_processing = None
46 self.is_processing = False47 self.is_processing = False
4748
49 # pylint: disable=E0202
50 handler = handle_errors(logger=self.logger,
51 error_handler=self._error_handler)
52 self.load = handler(self.load)
53
48 self._setup()54 self._setup()
4955
50 def _get_is_processing(self):56 def _get_is_processing(self):
@@ -64,6 +70,10 @@
6470
65 is_processing = property(fget=_get_is_processing, fset=_set_is_processing)71 is_processing = property(fget=_get_is_processing, fset=_set_is_processing)
6672
73 def _error_handler(self):
74 """Custom error handler, unset is_processing."""
75 self.is_processing = False
76
67 def _setup(self):77 def _setup(self):
68 """Do some extra setupping for the UI."""78 """Do some extra setupping for the UI."""
6979
@@ -82,5 +92,6 @@
8292
83 # pylint: enable=C010393 # pylint: enable=C0103
8494
95 # pylint: disable=E0202
85 def load(self):96 def load(self):
86 """Load the widget with specific info."""97 """Load the widget with specific info."""
8798
=== modified file 'ubuntuone/controlpanel/tests/test_cache.py'
--- ubuntuone/controlpanel/tests/test_cache.py 2011-09-02 18:10:13 +0000
+++ ubuntuone/controlpanel/tests/test_cache.py 2011-09-08 01:17:23 +0000
@@ -39,6 +39,13 @@
39 """The backend instance is successfully created."""39 """The backend instance is successfully created."""
40 self.assertIsInstance(self.obj.backend, cache.backend.ControlBackend)40 self.assertIsInstance(self.obj.backend, cache.backend.ControlBackend)
4141
42 def test_set_backend(self):
43 """The backend instance is successfully assigned."""
44 expected = object()
45 assert self.obj.backend is not expected
46 self.obj.backend = expected
47 self.assertTrue(self.obj.backend is expected)
48
42 def test_backend_is_cached(self):49 def test_backend_is_cached(self):
43 """The backend instance is cached."""50 """The backend instance is cached."""
44 obj2 = cache.Cache()51 obj2 = cache.Cache()

Subscribers

People subscribed via source and target branches