Merge lp:~nataliabidart/ubuntuone-control-panel/handle-errors into lp:ubuntuone-control-panel
- handle-errors
- Merge into trunk
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 |
Related bugs: |
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).
Description of the change
To post a comment you must log in.
- 216. By Natalia Bidart
-
Forgotten is_processing = False.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'data/qt/signin.ui' | |||
2 | --- data/qt/signin.ui 2011-08-30 23:18:35 +0000 | |||
3 | +++ data/qt/signin.ui 2011-09-08 01:17:23 +0000 | |||
4 | @@ -41,13 +41,6 @@ | |||
5 | 41 | </widget> | 41 | </widget> |
6 | 42 | </item> | 42 | </item> |
7 | 43 | <item> | 43 | <item> |
8 | 44 | <widget class="QLabel" name="warning_label"> | ||
9 | 45 | <property name="text"> | ||
10 | 46 | <string>warning label!</string> | ||
11 | 47 | </property> | ||
12 | 48 | </widget> | ||
13 | 49 | </item> | ||
14 | 50 | <item> | ||
15 | 51 | <layout class="QHBoxLayout" name="horizontalLayout"> | 44 | <layout class="QHBoxLayout" name="horizontalLayout"> |
16 | 52 | <item> | 45 | <item> |
17 | 53 | <layout class="QVBoxLayout" name="verticalLayout_2"> | 46 | <layout class="QVBoxLayout" name="verticalLayout_2"> |
18 | 54 | 47 | ||
19 | === modified file 'ubuntuone/controlpanel/cache.py' | |||
20 | --- ubuntuone/controlpanel/cache.py 2011-09-02 17:59:39 +0000 | |||
21 | +++ ubuntuone/controlpanel/cache.py 2011-09-08 01:17:23 +0000 | |||
22 | @@ -33,13 +33,18 @@ | |||
23 | 33 | if self.logger is not None: | 33 | if self.logger is not None: |
24 | 34 | self.logger.debug('%s: started.', self.__class__.__name__) | 34 | self.logger.debug('%s: started.', self.__class__.__name__) |
25 | 35 | 35 | ||
28 | 36 | @property | 36 | def get_backend(self): |
27 | 37 | def backend(self): | ||
29 | 38 | """A cached ControlBackend instance.""" | 37 | """A cached ControlBackend instance.""" |
30 | 39 | if not self._shared_objects: | 38 | if not self._shared_objects: |
31 | 40 | self._shared_objects['backend'] = backend.ControlBackend() | 39 | self._shared_objects['backend'] = backend.ControlBackend() |
32 | 41 | return self._shared_objects['backend'] | 40 | return self._shared_objects['backend'] |
33 | 42 | 41 | ||
34 | 42 | def set_backend(self, new_value): | ||
35 | 43 | """Set a new ControlBackend instance.""" | ||
36 | 44 | self._shared_objects['backend'] = new_value | ||
37 | 45 | |||
38 | 46 | backend = property(fget=get_backend, fset=set_backend) | ||
39 | 47 | |||
40 | 43 | def clear(self): | 48 | def clear(self): |
41 | 44 | """Clear all cached objects.""" | 49 | """Clear all cached objects.""" |
42 | 45 | self._shared_objects = {} | 50 | self._shared_objects = {} |
43 | 46 | 51 | ||
44 | === modified file 'ubuntuone/controlpanel/gui/qt/__init__.py' | |||
45 | --- ubuntuone/controlpanel/gui/qt/__init__.py 2011-09-01 17:11:16 +0000 | |||
46 | +++ ubuntuone/controlpanel/gui/qt/__init__.py 2011-09-08 01:17:23 +0000 | |||
47 | @@ -18,7 +18,13 @@ | |||
48 | 18 | 18 | ||
49 | 19 | """The Qt graphical interface for the control panel for Ubuntu One.""" | 19 | """The Qt graphical interface for the control panel for Ubuntu One.""" |
50 | 20 | 20 | ||
51 | 21 | import collections | ||
52 | 22 | import logging | ||
53 | 23 | |||
54 | 24 | from functools import wraps | ||
55 | 25 | |||
56 | 21 | from PyQt4 import QtGui, QtCore | 26 | from PyQt4 import QtGui, QtCore |
57 | 27 | from twisted.internet import defer | ||
58 | 22 | 28 | ||
59 | 23 | 29 | ||
60 | 24 | def uri_hook(uri): | 30 | def uri_hook(uri): |
61 | @@ -53,3 +59,46 @@ | |||
62 | 53 | icon.icon_name = icon_name | 59 | icon.icon_name = icon_name |
63 | 54 | 60 | ||
64 | 55 | return icon | 61 | return icon |
65 | 62 | |||
66 | 63 | |||
67 | 64 | def handle_errors(error_handler=None, logger=None): | ||
68 | 65 | """Decorator to handle errors when calling a function. | ||
69 | 66 | |||
70 | 67 | if 'error_handler' is not None, it will be yielded on if any error happens. | ||
71 | 68 | |||
72 | 69 | """ | ||
73 | 70 | if logger is None: | ||
74 | 71 | logger = logging.getLogger() | ||
75 | 72 | |||
76 | 73 | def middle(f): | ||
77 | 74 | """Decorator to handle errors when calling 'f'.""" | ||
78 | 75 | |||
79 | 76 | @defer.inlineCallbacks | ||
80 | 77 | @wraps(f) | ||
81 | 78 | def inner(*args, **kwargs): | ||
82 | 79 | """Call 'f' passing 'args' and 'kwargs'. | ||
83 | 80 | |||
84 | 81 | Catch any error and show a error message. | ||
85 | 82 | |||
86 | 83 | """ | ||
87 | 84 | try: | ||
88 | 85 | res = yield f(*args, **kwargs) | ||
89 | 86 | except Exception, e: # pylint: disable=W0703 | ||
90 | 87 | logger.exception(f.__name__) | ||
91 | 88 | else: | ||
92 | 89 | defer.returnValue(res) | ||
93 | 90 | |||
94 | 91 | # this code will only be executed if there was an exception | ||
95 | 92 | if error_handler is not None: | ||
96 | 93 | yield error_handler() | ||
97 | 94 | |||
98 | 95 | if len(e.args) > 0 and isinstance(e.args[0], collections.Mapping): | ||
99 | 96 | msgs = e.args[0].itervalues() | ||
100 | 97 | else: | ||
101 | 98 | msgs = [e.__class__.__name__] + map(repr, e.args) | ||
102 | 99 | msg = '\n'.join(msgs) | ||
103 | 100 | QtGui.QMessageBox.warning(None, '', msg, QtGui.QMessageBox.Close) | ||
104 | 101 | |||
105 | 102 | return inner | ||
106 | 103 | |||
107 | 104 | return middle | ||
108 | 56 | 105 | ||
109 | === modified file 'ubuntuone/controlpanel/gui/qt/account.py' | |||
110 | --- ubuntuone/controlpanel/gui/qt/account.py 2011-08-31 17:18:56 +0000 | |||
111 | +++ ubuntuone/controlpanel/gui/qt/account.py 2011-09-08 01:17:23 +0000 | |||
112 | @@ -45,6 +45,7 @@ | |||
113 | 45 | self.ui.edit_profile_button.uri = EDIT_PROFILE_LINK | 45 | self.ui.edit_profile_button.uri = EDIT_PROFILE_LINK |
114 | 46 | self.ui.edit_services_button.uri = EDIT_ACCOUNT_LINK | 46 | self.ui.edit_services_button.uri = EDIT_ACCOUNT_LINK |
115 | 47 | 47 | ||
116 | 48 | # pylint: disable=E0202 | ||
117 | 48 | @defer.inlineCallbacks | 49 | @defer.inlineCallbacks |
118 | 49 | def load(self): | 50 | def load(self): |
119 | 50 | """Load info.""" | 51 | """Load info.""" |
120 | 51 | 52 | ||
121 | === modified file 'ubuntuone/controlpanel/gui/qt/addfolder.py' | |||
122 | --- ubuntuone/controlpanel/gui/qt/addfolder.py 2011-09-02 17:59:39 +0000 | |||
123 | +++ ubuntuone/controlpanel/gui/qt/addfolder.py 2011-09-08 01:17:23 +0000 | |||
124 | @@ -28,6 +28,7 @@ | |||
125 | 28 | from ubuntuone.controlpanel import cache | 28 | from ubuntuone.controlpanel import cache |
126 | 29 | from ubuntuone.controlpanel.logger import setup_logging | 29 | from ubuntuone.controlpanel.logger import setup_logging |
127 | 30 | from ubuntuone.controlpanel.gui import FOLDER_INVALID_PATH | 30 | from ubuntuone.controlpanel.gui import FOLDER_INVALID_PATH |
128 | 31 | from ubuntuone.controlpanel.gui.qt import handle_errors | ||
129 | 31 | 32 | ||
130 | 32 | 33 | ||
131 | 33 | logger = setup_logging('qt.addfolder') | 34 | logger = setup_logging('qt.addfolder') |
132 | @@ -50,6 +51,7 @@ | |||
133 | 50 | self.clicked.connect(self.on_clicked) | 51 | self.clicked.connect(self.on_clicked) |
134 | 51 | 52 | ||
135 | 52 | @QtCore.pyqtSlot() | 53 | @QtCore.pyqtSlot() |
136 | 54 | @handle_errors(logger=logger) | ||
137 | 53 | @defer.inlineCallbacks | 55 | @defer.inlineCallbacks |
138 | 54 | def on_clicked(self): | 56 | def on_clicked(self): |
139 | 55 | """The 'Sync another folder' button was clicked.""" | 57 | """The 'Sync another folder' button was clicked.""" |
140 | 56 | 58 | ||
141 | === modified file 'ubuntuone/controlpanel/gui/qt/controlpanel.py' | |||
142 | --- ubuntuone/controlpanel/gui/qt/controlpanel.py 2011-09-01 17:11:16 +0000 | |||
143 | +++ ubuntuone/controlpanel/gui/qt/controlpanel.py 2011-09-08 01:17:23 +0000 | |||
144 | @@ -72,6 +72,7 @@ | |||
145 | 72 | self.ui.switcher.setCurrentWidget(self.ui.management) | 72 | self.ui.switcher.setCurrentWidget(self.ui.management) |
146 | 73 | self.is_processing = False | 73 | self.is_processing = False |
147 | 74 | 74 | ||
148 | 75 | # pylint: disable=E0202 | ||
149 | 75 | @defer.inlineCallbacks | 76 | @defer.inlineCallbacks |
150 | 76 | def load(self): | 77 | def load(self): |
151 | 77 | """Load info.""" | 78 | """Load info.""" |
152 | 78 | 79 | ||
153 | === modified file 'ubuntuone/controlpanel/gui/qt/device.py' | |||
154 | --- ubuntuone/controlpanel/gui/qt/device.py 2011-09-02 17:59:39 +0000 | |||
155 | +++ ubuntuone/controlpanel/gui/qt/device.py 2011-09-08 01:17:23 +0000 | |||
156 | @@ -27,8 +27,13 @@ | |||
157 | 27 | ) | 27 | ) |
158 | 28 | from ubuntuone.controlpanel import cache | 28 | from ubuntuone.controlpanel import cache |
159 | 29 | from ubuntuone.controlpanel.gui import DEVICE_CONFIRM_REMOVE | 29 | from ubuntuone.controlpanel.gui import DEVICE_CONFIRM_REMOVE |
161 | 30 | from ubuntuone.controlpanel.gui.qt import icon_from_name, pixmap_from_name | 30 | from ubuntuone.controlpanel.gui.qt import ( |
162 | 31 | handle_errors, | ||
163 | 32 | icon_from_name, | ||
164 | 33 | pixmap_from_name, | ||
165 | 34 | ) | ||
166 | 31 | from ubuntuone.controlpanel.gui.qt.ui import device_ui | 35 | from ubuntuone.controlpanel.gui.qt.ui import device_ui |
167 | 36 | from ubuntuone.controlpanel.logger import setup_logging | ||
168 | 32 | 37 | ||
169 | 33 | COMPUTER_ICON = "computer" | 38 | COMPUTER_ICON = "computer" |
170 | 34 | PHONE_ICON = "phone" | 39 | PHONE_ICON = "phone" |
171 | @@ -44,6 +49,9 @@ | |||
172 | 44 | YES = QtGui.QMessageBox.Yes | 49 | YES = QtGui.QMessageBox.Yes |
173 | 45 | 50 | ||
174 | 46 | 51 | ||
175 | 52 | logger = setup_logging('qt.device') | ||
176 | 53 | |||
177 | 54 | |||
178 | 47 | def icon_name_from_type(device_type): | 55 | def icon_name_from_type(device_type): |
179 | 48 | """Get the icon name for the device.""" | 56 | """Get the icon name for the device.""" |
180 | 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) |
181 | @@ -70,8 +78,9 @@ | |||
182 | 70 | pixmap = pixmap_from_name(icon_name) | 78 | pixmap = pixmap_from_name(icon_name) |
183 | 71 | self.ui.device_icon_label.setPixmap(pixmap) | 79 | self.ui.device_icon_label.setPixmap(pixmap) |
184 | 72 | 80 | ||
185 | 81 | @QtCore.pyqtSlot() | ||
186 | 82 | @handle_errors(logger=logger) | ||
187 | 73 | @defer.inlineCallbacks | 83 | @defer.inlineCallbacks |
188 | 74 | @QtCore.pyqtSlot() | ||
189 | 75 | def on_remove_device_button_clicked(self): | 84 | def on_remove_device_button_clicked(self): |
190 | 76 | """The user wants to remove this device.""" | 85 | """The user wants to remove this device.""" |
191 | 77 | msg = DEVICE_CONFIRM_REMOVE | 86 | msg = DEVICE_CONFIRM_REMOVE |
192 | 78 | 87 | ||
193 | === modified file 'ubuntuone/controlpanel/gui/qt/devices.py' | |||
194 | --- ubuntuone/controlpanel/gui/qt/devices.py 2011-09-02 17:59:39 +0000 | |||
195 | +++ ubuntuone/controlpanel/gui/qt/devices.py 2011-09-08 01:17:23 +0000 | |||
196 | @@ -47,6 +47,7 @@ | |||
197 | 47 | super(DevicesPanel, self)._setup() | 47 | super(DevicesPanel, self)._setup() |
198 | 48 | self.ui.manage_devices_button.uri = EDIT_DEVICES_LINK | 48 | self.ui.manage_devices_button.uri = EDIT_DEVICES_LINK |
199 | 49 | 49 | ||
200 | 50 | # pylint: disable=E0202 | ||
201 | 50 | @defer.inlineCallbacks | 51 | @defer.inlineCallbacks |
202 | 51 | def load(self): | 52 | def load(self): |
203 | 52 | """Load info.""" | 53 | """Load info.""" |
204 | 53 | 54 | ||
205 | === modified file 'ubuntuone/controlpanel/gui/qt/folders.py' | |||
206 | --- ubuntuone/controlpanel/gui/qt/folders.py 2011-08-31 17:18:56 +0000 | |||
207 | +++ ubuntuone/controlpanel/gui/qt/folders.py 2011-09-08 01:17:23 +0000 | |||
208 | @@ -82,6 +82,7 @@ | |||
209 | 82 | icon = icon_from_name('external_icon_orange') | 82 | icon = icon_from_name('external_icon_orange') |
210 | 83 | self.ui.share_publish_button.setIcon(icon) | 83 | self.ui.share_publish_button.setIcon(icon) |
211 | 84 | 84 | ||
212 | 85 | # pylint: disable=E0202 | ||
213 | 85 | @defer.inlineCallbacks | 86 | @defer.inlineCallbacks |
214 | 86 | def load(self): | 87 | def load(self): |
215 | 87 | """Load specific tab info.""" | 88 | """Load specific tab info.""" |
216 | 88 | 89 | ||
217 | === modified file 'ubuntuone/controlpanel/gui/qt/preferences.py' | |||
218 | --- ubuntuone/controlpanel/gui/qt/preferences.py 2011-08-31 17:18:56 +0000 | |||
219 | +++ ubuntuone/controlpanel/gui/qt/preferences.py 2011-09-08 01:17:23 +0000 | |||
220 | @@ -64,6 +64,7 @@ | |||
221 | 64 | ui_class = preferences_ui | 64 | ui_class = preferences_ui |
222 | 65 | logger = logger | 65 | logger = logger |
223 | 66 | 66 | ||
224 | 67 | # pylint: disable=E0202 | ||
225 | 67 | @defer.inlineCallbacks | 68 | @defer.inlineCallbacks |
226 | 68 | def load(self): | 69 | def load(self): |
227 | 69 | """Load info.""" | 70 | """Load info.""" |
228 | 70 | 71 | ||
229 | === modified file 'ubuntuone/controlpanel/gui/qt/signin.py' | |||
230 | --- ubuntuone/controlpanel/gui/qt/signin.py 2011-08-31 17:18:56 +0000 | |||
231 | +++ ubuntuone/controlpanel/gui/qt/signin.py 2011-09-08 01:17:23 +0000 | |||
232 | @@ -19,12 +19,10 @@ | |||
233 | 19 | """The signin page.""" | 19 | """The signin page.""" |
234 | 20 | 20 | ||
235 | 21 | from PyQt4 import QtCore | 21 | from PyQt4 import QtCore |
236 | 22 | |||
237 | 23 | from twisted.internet import defer | 22 | from twisted.internet import defer |
238 | 24 | from ubuntuone.platform.credentials import CredentialsError | ||
239 | 25 | 23 | ||
240 | 26 | from ubuntuone.controlpanel.gui import RESET_PASSWORD_LINK | 24 | from ubuntuone.controlpanel.gui import RESET_PASSWORD_LINK |
242 | 27 | from ubuntuone.controlpanel.gui.qt import icon_from_name | 25 | from ubuntuone.controlpanel.gui.qt import icon_from_name, handle_errors |
243 | 28 | from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin | 26 | from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin |
244 | 29 | from ubuntuone.controlpanel.gui.qt.ui import signin_ui | 27 | from ubuntuone.controlpanel.gui.qt.ui import signin_ui |
245 | 30 | from ubuntuone.controlpanel.logger import setup_logging, log_call | 28 | from ubuntuone.controlpanel.logger import setup_logging, log_call |
246 | @@ -45,7 +43,6 @@ | |||
247 | 45 | def _setup(self): | 43 | def _setup(self): |
248 | 46 | """Do some extra setupping for the UI.""" | 44 | """Do some extra setupping for the UI.""" |
249 | 47 | super(SignInPanel, self)._setup() | 45 | super(SignInPanel, self)._setup() |
250 | 48 | self.ui.warning_label.setText("") | ||
251 | 49 | 46 | ||
252 | 50 | self.ui.forgot_password_button.uri = RESET_PASSWORD_LINK | 47 | self.ui.forgot_password_button.uri = RESET_PASSWORD_LINK |
253 | 51 | icon = icon_from_name('external_icon_orange') | 48 | icon = icon_from_name('external_icon_orange') |
254 | @@ -64,21 +61,23 @@ | |||
255 | 64 | self.ui.signin_button.style().unpolish(self.ui.signin_button) | 61 | self.ui.signin_button.style().unpolish(self.ui.signin_button) |
256 | 65 | self.ui.signin_button.style().polish(self.ui.signin_button) | 62 | self.ui.signin_button.style().polish(self.ui.signin_button) |
257 | 66 | 63 | ||
258 | 64 | # pylint: disable=E0202 | ||
259 | 65 | @defer.inlineCallbacks | ||
260 | 66 | def load(self): | ||
261 | 67 | """Load specific tab info.""" | ||
262 | 68 | yield self.backend.get_credentials() | ||
263 | 69 | |||
264 | 70 | @QtCore.pyqtSlot() | ||
265 | 71 | @handle_errors(logger=logger) | ||
266 | 67 | @log_call(logger.debug) | 72 | @log_call(logger.debug) |
267 | 68 | @defer.inlineCallbacks | 73 | @defer.inlineCallbacks |
268 | 69 | @QtCore.pyqtSlot() | ||
269 | 70 | def on_signin_button_clicked(self): | 74 | def on_signin_button_clicked(self): |
270 | 71 | """The 'Sign in' button was clicked.""" | 75 | """The 'Sign in' button was clicked.""" |
271 | 72 | self.ui.warning_label.setText("") | ||
272 | 73 | email = unicode(self.ui.email_entry.text()) | 76 | email = unicode(self.ui.email_entry.text()) |
273 | 74 | password = unicode(self.ui.password_entry.text()) | 77 | password = unicode(self.ui.password_entry.text()) |
274 | 75 | self.is_processing = True | 78 | self.is_processing = True |
275 | 76 | try: | 79 | try: |
276 | 77 | result = yield self.backend.login(email=email, password=password) | 80 | result = yield self.backend.login(email=email, password=password) |
277 | 78 | except CredentialsError, e: | ||
278 | 79 | logger.info('on_signin_button_clicked: %r', e) | ||
279 | 80 | self.ui.warning_label.setText(e.args[0]['message']) | ||
280 | 81 | else: | ||
281 | 82 | logger.info('Emitting credentialsFound for email %r.', email) | 81 | logger.info('Emitting credentialsFound for email %r.', email) |
282 | 83 | self.credentialsFound.emit(result) | 82 | self.credentialsFound.emit(result) |
283 | 84 | finally: | 83 | finally: |
284 | 85 | 84 | ||
285 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/__init__.py' | |||
286 | --- ubuntuone/controlpanel/gui/qt/tests/__init__.py 2011-09-02 17:59:39 +0000 | |||
287 | +++ ubuntuone/controlpanel/gui/qt/tests/__init__.py 2011-09-08 01:17:23 +0000 | |||
288 | @@ -22,7 +22,7 @@ | |||
289 | 22 | import os | 22 | import os |
290 | 23 | import urllib | 23 | import urllib |
291 | 24 | 24 | ||
293 | 25 | from PyQt4 import QtCore | 25 | from PyQt4 import QtGui, QtCore |
294 | 26 | from ubuntuone.devtools.handlers import MementoHandler | 26 | from ubuntuone.devtools.handlers import MementoHandler |
295 | 27 | 27 | ||
296 | 28 | from ubuntuone.controlpanel import backend, cache | 28 | from ubuntuone.controlpanel import backend, cache |
297 | @@ -126,9 +126,32 @@ | |||
298 | 126 | return TOKEN | 126 | return TOKEN |
299 | 127 | 127 | ||
300 | 128 | 128 | ||
302 | 129 | class FakedConfirmDialog(object): | 129 | class CrashyBackendException(Exception): |
303 | 130 | """A faked backend crash.""" | ||
304 | 131 | |||
305 | 132 | |||
306 | 133 | class CrashyBackend(FakedControlPanelBackend): | ||
307 | 134 | """A faked backend that crashes.""" | ||
308 | 135 | |||
309 | 136 | def __init__(self, *args, **kwargs): | ||
310 | 137 | super(CrashyBackend, self).__init__(*args, **kwargs) | ||
311 | 138 | for i in self.exposed_methods + ['get_credentials']: | ||
312 | 139 | setattr(self, i, self._fail(i)) | ||
313 | 140 | |||
314 | 141 | def _fail(self, f): | ||
315 | 142 | """Crash boom bang.""" | ||
316 | 143 | |||
317 | 144 | def inner(*args, **kwargs): | ||
318 | 145 | """Raise a custom exception.""" | ||
319 | 146 | raise CrashyBackendException(f) | ||
320 | 147 | |||
321 | 148 | return inner | ||
322 | 149 | |||
323 | 150 | |||
324 | 151 | class FakedDialog(object): | ||
325 | 130 | """Fake a confirmation dialog.""" | 152 | """Fake a confirmation dialog.""" |
326 | 131 | 153 | ||
327 | 154 | Close = 0 | ||
328 | 132 | response = args = kwargs = None | 155 | response = args = kwargs = None |
329 | 133 | 156 | ||
330 | 134 | @classmethod | 157 | @classmethod |
331 | @@ -163,6 +186,7 @@ | |||
332 | 163 | innerclass_name = None | 186 | innerclass_name = None |
333 | 164 | class_ui = None | 187 | class_ui = None |
334 | 165 | kwargs = {} | 188 | kwargs = {} |
335 | 189 | logger = None | ||
336 | 166 | 190 | ||
337 | 167 | def setUp(self): | 191 | def setUp(self): |
338 | 168 | cache.Cache._shared_objects = {} | 192 | cache.Cache._shared_objects = {} |
339 | @@ -180,11 +204,25 @@ | |||
340 | 180 | if getattr(self.ui, 'backend', None) is not None: | 204 | if getattr(self.ui, 'backend', None) is not None: |
341 | 181 | self.addCleanup(self.ui.backend._called.clear) | 205 | self.addCleanup(self.ui.backend._called.clear) |
342 | 182 | 206 | ||
344 | 183 | if getattr(self.ui, 'logger', None) is not None: | 207 | logger = self.logger if self.logger is not None else \ |
345 | 208 | getattr(self.ui, 'logger', None) | ||
346 | 209 | self.memento = None | ||
347 | 210 | if logger is not None: | ||
348 | 184 | self.memento = MementoHandler() | 211 | self.memento = MementoHandler() |
349 | 185 | self.memento.setLevel(logging.DEBUG) | 212 | self.memento.setLevel(logging.DEBUG) |
352 | 186 | self.ui.logger.addHandler(self.memento) | 213 | logger.addHandler(self.memento) |
353 | 187 | self.addCleanup(self.ui.logger.removeHandler, self.memento) | 214 | self.addCleanup(logger.removeHandler, self.memento) |
354 | 215 | |||
355 | 216 | # default response if user does nothing | ||
356 | 217 | FakedFileDialog.response = QtCore.QString('') | ||
357 | 218 | FakedFileDialog.args = None | ||
358 | 219 | FakedFileDialog.kwargs = None | ||
359 | 220 | self.patch(QtGui, 'QFileDialog', FakedFileDialog) | ||
360 | 221 | |||
361 | 222 | FakedDialog.response = None | ||
362 | 223 | FakedDialog.args = None | ||
363 | 224 | FakedDialog.kwargs = None | ||
364 | 225 | self.patch(QtGui, 'QMessageBox', FakedDialog) | ||
365 | 188 | 226 | ||
366 | 189 | def get_pixmap_data(self, pixmap): | 227 | def get_pixmap_data(self, pixmap): |
367 | 190 | """Get the raw data of a QPixmap.""" | 228 | """Get the raw data of a QPixmap.""" |
368 | 191 | 229 | ||
369 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py' | |||
370 | --- ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py 2011-08-29 13:28:58 +0000 | |||
371 | +++ ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py 2011-09-08 01:17:23 +0000 | |||
372 | @@ -29,7 +29,9 @@ | |||
373 | 29 | from ubuntuone.controlpanel.gui.qt import addfolder as gui | 29 | from ubuntuone.controlpanel.gui.qt import addfolder as gui |
374 | 30 | from ubuntuone.controlpanel.gui.qt.tests import ( | 30 | from ubuntuone.controlpanel.gui.qt.tests import ( |
375 | 31 | BaseTestCase, | 31 | BaseTestCase, |
377 | 32 | FakedConfirmDialog, | 32 | CrashyBackend, |
378 | 33 | CrashyBackendException, | ||
379 | 34 | FakedDialog, | ||
380 | 33 | FakedFileDialog, | 35 | FakedFileDialog, |
381 | 34 | set_path_on_file_dialog, | 36 | set_path_on_file_dialog, |
382 | 35 | ) | 37 | ) |
383 | @@ -53,20 +55,6 @@ | |||
384 | 53 | os.environ['HOME'] = USER_HOME | 55 | os.environ['HOME'] = USER_HOME |
385 | 54 | self.addCleanup(lambda: os.environ.__setitem__('HOME', old_home)) | 56 | self.addCleanup(lambda: os.environ.__setitem__('HOME', old_home)) |
386 | 55 | 57 | ||
387 | 56 | # default response if user does nothing | ||
388 | 57 | FakedFileDialog.response = gui.QtCore.QString('') | ||
389 | 58 | FakedFileDialog.args = None | ||
390 | 59 | FakedFileDialog.kwargs = None | ||
391 | 60 | self.patch(gui.QtGui, 'QFileDialog', FakedFileDialog) | ||
392 | 61 | |||
393 | 62 | FakedConfirmDialog.response = None | ||
394 | 63 | FakedConfirmDialog.args = None | ||
395 | 64 | FakedConfirmDialog.kwargs = None | ||
396 | 65 | self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) | ||
397 | 66 | |||
398 | 67 | # reset backend state | ||
399 | 68 | self.ui.backend._called.clear() | ||
400 | 69 | |||
401 | 70 | @defer.inlineCallbacks | 58 | @defer.inlineCallbacks |
402 | 71 | def assert_does_nothing(self, method_call): | 59 | def assert_does_nothing(self, method_call): |
403 | 72 | """Nothing happens. | 60 | """Nothing happens. |
404 | @@ -103,8 +91,8 @@ | |||
405 | 103 | yield self.assert_does_nothing(self.ui.click) | 91 | yield self.assert_does_nothing(self.ui.click) |
406 | 104 | 92 | ||
407 | 105 | # the warning dialog was not opened | 93 | # the warning dialog was not opened |
410 | 106 | self.assertEqual(FakedConfirmDialog.args, None) | 94 | self.assertEqual(FakedDialog.args, None) |
411 | 107 | self.assertEqual(FakedConfirmDialog.kwargs, None) | 95 | self.assertEqual(FakedDialog.kwargs, None) |
412 | 108 | 96 | ||
413 | 109 | @defer.inlineCallbacks | 97 | @defer.inlineCallbacks |
414 | 110 | def test_opens_warning_if_folder_path_not_valid(self): | 98 | def test_opens_warning_if_folder_path_not_valid(self): |
415 | @@ -116,9 +104,9 @@ | |||
416 | 116 | 104 | ||
417 | 117 | args = {'folder_path': folder_path, 'home_folder': USER_HOME} | 105 | args = {'folder_path': folder_path, 'home_folder': USER_HOME} |
418 | 118 | msg = gui.FOLDER_INVALID_PATH % args | 106 | msg = gui.FOLDER_INVALID_PATH % args |
420 | 119 | self.assertEqual(FakedConfirmDialog.args, | 107 | self.assertEqual(FakedDialog.args, |
421 | 120 | (self.ui, '', msg, gui.CLOSE)) | 108 | (self.ui, '', msg, gui.CLOSE)) |
423 | 121 | self.assertEqual(FakedConfirmDialog.kwargs, {}) | 109 | self.assertEqual(FakedDialog.kwargs, {}) |
424 | 122 | 110 | ||
425 | 123 | yield self.assert_does_nothing(self.ui.click) | 111 | yield self.assert_does_nothing(self.ui.click) |
426 | 124 | 112 | ||
427 | @@ -129,8 +117,8 @@ | |||
428 | 129 | yield self.ui.click() | 117 | yield self.ui.click() |
429 | 130 | 118 | ||
430 | 131 | # no warning | 119 | # no warning |
433 | 132 | self.assertEqual(FakedConfirmDialog.args, None) | 120 | self.assertEqual(FakedDialog.args, None) |
434 | 133 | self.assertEqual(FakedConfirmDialog.kwargs, None) | 121 | self.assertEqual(FakedDialog.kwargs, None) |
435 | 134 | # backend called | 122 | # backend called |
436 | 135 | self.assert_backend_called('create_folder', folder_path=folder) | 123 | self.assert_backend_called('create_folder', folder_path=folder) |
437 | 136 | 124 | ||
438 | @@ -141,8 +129,8 @@ | |||
439 | 141 | yield self.ui.click() | 129 | yield self.ui.click() |
440 | 142 | 130 | ||
441 | 143 | # no warning | 131 | # no warning |
444 | 144 | self.assertEqual(FakedConfirmDialog.args, None) | 132 | self.assertEqual(FakedDialog.args, None) |
445 | 145 | self.assertEqual(FakedConfirmDialog.kwargs, None) | 133 | self.assertEqual(FakedDialog.kwargs, None) |
446 | 146 | # backend called | 134 | # backend called |
447 | 147 | self.assert_backend_called('create_folder', folder_path=folder) | 135 | self.assert_backend_called('create_folder', folder_path=folder) |
448 | 148 | 136 | ||
449 | @@ -170,3 +158,12 @@ | |||
450 | 170 | yield self.ui.click() | 158 | yield self.ui.click() |
451 | 171 | 159 | ||
452 | 172 | self.assertEqual(self._called, ((), {})) | 160 | self.assertEqual(self._called, ((), {})) |
453 | 161 | |||
454 | 162 | @defer.inlineCallbacks | ||
455 | 163 | def test_backend_error_is_handled(self): | ||
456 | 164 | """Any error from the backend is properly handled.""" | ||
457 | 165 | set_path_on_file_dialog() | ||
458 | 166 | self.patch(self.ui, 'backend', CrashyBackend()) | ||
459 | 167 | yield self.ui.click() | ||
460 | 168 | |||
461 | 169 | self.assertTrue(self.memento.check_exception(CrashyBackendException)) | ||
462 | 173 | 170 | ||
463 | === renamed file 'ubuntuone/controlpanel/gui/qt/tests/test_urihook.py' => 'ubuntuone/controlpanel/gui/qt/tests/test_common.py' | |||
464 | --- ubuntuone/controlpanel/gui/qt/tests/test_urihook.py 2011-09-01 17:11:16 +0000 | |||
465 | +++ ubuntuone/controlpanel/gui/qt/tests/test_common.py 2011-09-08 01:17:23 +0000 | |||
466 | @@ -18,12 +18,17 @@ | |||
467 | 18 | 18 | ||
468 | 19 | """Tests for the uri_hook helper.""" | 19 | """Tests for the uri_hook helper.""" |
469 | 20 | 20 | ||
470 | 21 | import logging | ||
471 | 22 | |||
472 | 21 | from PyQt4 import QtGui, QtCore | 23 | from PyQt4 import QtGui, QtCore |
473 | 22 | |||
474 | 23 | from twisted.internet import defer | 24 | from twisted.internet import defer |
475 | 24 | 25 | ||
478 | 25 | from ubuntuone.controlpanel.gui.qt import uri_hook | 26 | from ubuntuone.controlpanel.logger import setup_logging |
479 | 26 | from ubuntuone.controlpanel.gui.qt.tests import BaseTestCase | 27 | from ubuntuone.controlpanel.gui.qt import uri_hook, handle_errors |
480 | 28 | from ubuntuone.controlpanel.gui.qt.tests import ( | ||
481 | 29 | BaseTestCase, | ||
482 | 30 | FakedDialog, | ||
483 | 31 | ) | ||
484 | 27 | 32 | ||
485 | 28 | 33 | ||
486 | 29 | class UriHookTestCase(BaseTestCase): | 34 | class UriHookTestCase(BaseTestCase): |
487 | @@ -45,3 +50,161 @@ | |||
488 | 45 | expected = 'http://foo.bar/?next=https://one.ubuntu.com/' | 50 | expected = 'http://foo.bar/?next=https://one.ubuntu.com/' |
489 | 46 | uri_hook(expected) | 51 | uri_hook(expected) |
490 | 47 | self.assertEqual(self._called, ((QtCore.QUrl(expected),), {})) | 52 | self.assertEqual(self._called, ((QtCore.QUrl(expected),), {})) |
491 | 53 | |||
492 | 54 | |||
493 | 55 | class HandleErrorTestCase(BaseTestCase): | ||
494 | 56 | """Test suite for the generic error handler.""" | ||
495 | 57 | |||
496 | 58 | error_handler = None | ||
497 | 59 | use_logger = False | ||
498 | 60 | logger = logging.getLogger() # root logger | ||
499 | 61 | |||
500 | 62 | @defer.inlineCallbacks | ||
501 | 63 | def setUp(self): | ||
502 | 64 | yield super(HandleErrorTestCase, self).setUp() | ||
503 | 65 | self.called = None | ||
504 | 66 | self.result = None | ||
505 | 67 | self.failure = None | ||
506 | 68 | self.error_handler_called = None | ||
507 | 69 | |||
508 | 70 | if self.use_logger: | ||
509 | 71 | logger = self.logger | ||
510 | 72 | else: | ||
511 | 73 | logger = None | ||
512 | 74 | |||
513 | 75 | self.decorate_me = handle_errors(error_handler=self.error_handler, | ||
514 | 76 | logger=logger)(self._decorate_me) | ||
515 | 77 | |||
516 | 78 | @defer.inlineCallbacks | ||
517 | 79 | def _decorate_me(self, *args, **kwargs): | ||
518 | 80 | """Helper to test thye decorator.""" | ||
519 | 81 | if self.failure: | ||
520 | 82 | # Raising only classes, instances or string are allowed | ||
521 | 83 | # pylint: disable=E0702 | ||
522 | 84 | raise self.failure | ||
523 | 85 | |||
524 | 86 | yield | ||
525 | 87 | self.called = (args, kwargs) | ||
526 | 88 | defer.returnValue(self.result) | ||
527 | 89 | |||
528 | 90 | @defer.inlineCallbacks | ||
529 | 91 | def test_is_decorator(self): | ||
530 | 92 | """Is a decorator.""" | ||
531 | 93 | yield self.decorate_me() | ||
532 | 94 | |||
533 | 95 | @defer.inlineCallbacks | ||
534 | 96 | def test_params_are_passed(self): | ||
535 | 97 | """Named and unnamed arguments are passed.""" | ||
536 | 98 | args = ({}, object(), 'foo') | ||
537 | 99 | kwargs = {'1': 1, 'test': None, '0': ['a']} | ||
538 | 100 | yield self.decorate_me(*args, **kwargs) | ||
539 | 101 | |||
540 | 102 | self.assertTrue(self.called, (args, kwargs)) | ||
541 | 103 | |||
542 | 104 | @defer.inlineCallbacks | ||
543 | 105 | def test_result_is_returned(self): | ||
544 | 106 | """Result is returned.""" | ||
545 | 107 | self.result = object() | ||
546 | 108 | result = yield self.decorate_me() | ||
547 | 109 | |||
548 | 110 | self.assertEqual(self.result, result) | ||
549 | 111 | |||
550 | 112 | def test_name_is_preserved(self): | ||
551 | 113 | """The method name is not masqueraded.""" | ||
552 | 114 | self.assertEqual(self.decorate_me.__name__, self._decorate_me.__name__) | ||
553 | 115 | |||
554 | 116 | @defer.inlineCallbacks | ||
555 | 117 | def test_exeptions_are_handled(self): | ||
556 | 118 | """Any exception is handled and logged in the root logger.""" | ||
557 | 119 | msg = 'This is me failing badly.' | ||
558 | 120 | self.failure = Exception(msg) | ||
559 | 121 | |||
560 | 122 | yield self.decorate_me() | ||
561 | 123 | |||
562 | 124 | logged = self.memento.check_exception(self.failure.__class__, msg) | ||
563 | 125 | recs = '\n'.join(rec.exc_text for rec in self.memento.records) | ||
564 | 126 | self.assertTrue(logged, 'Exception must be logged, got:\n%s' % recs) | ||
565 | 127 | |||
566 | 128 | @defer.inlineCallbacks | ||
567 | 129 | def test_show_error_message(self): | ||
568 | 130 | """On error, show an error message.""" | ||
569 | 131 | self.failure = Exception() | ||
570 | 132 | |||
571 | 133 | yield self.decorate_me() | ||
572 | 134 | |||
573 | 135 | msg = self.failure.__class__.__name__ | ||
574 | 136 | self.assertEqual(FakedDialog.args, | ||
575 | 137 | (None, '', msg, QtGui.QMessageBox.Close)) | ||
576 | 138 | self.assertEqual(FakedDialog.kwargs, {}) | ||
577 | 139 | |||
578 | 140 | @defer.inlineCallbacks | ||
579 | 141 | def test_show_error_message_if_args(self): | ||
580 | 142 | """On error, show an error message.""" | ||
581 | 143 | msg1 = 'This is me failing badly.' | ||
582 | 144 | msg2 = 'More details about what went wrong.' | ||
583 | 145 | obj = object() | ||
584 | 146 | self.failure = Exception(msg1, msg2, obj) | ||
585 | 147 | |||
586 | 148 | yield self.decorate_me() | ||
587 | 149 | |||
588 | 150 | msg = '\n'.join(map(repr, (msg1, msg2, obj))) | ||
589 | 151 | msg = self.failure.__class__.__name__ + '\n' + msg | ||
590 | 152 | self.assertEqual(FakedDialog.args, | ||
591 | 153 | (None, '', msg, QtGui.QMessageBox.Close)) | ||
592 | 154 | self.assertEqual(FakedDialog.kwargs, {}) | ||
593 | 155 | |||
594 | 156 | @defer.inlineCallbacks | ||
595 | 157 | def test_show_error_message_if_mapping(self): | ||
596 | 158 | """On error, show an error message.""" | ||
597 | 159 | msg1 = 'This is me failing badly.' | ||
598 | 160 | msg2 = 'More details about what went wrong.' | ||
599 | 161 | errdict = {'foo': msg1, 'bar': msg2} | ||
600 | 162 | self.failure = Exception(errdict) | ||
601 | 163 | |||
602 | 164 | yield self.decorate_me() | ||
603 | 165 | |||
604 | 166 | msg = '\n'.join((msg1, msg2)) | ||
605 | 167 | self.assertEqual(FakedDialog.args, | ||
606 | 168 | (None, '', msg, QtGui.QMessageBox.Close)) | ||
607 | 169 | self.assertEqual(FakedDialog.kwargs, {}) | ||
608 | 170 | |||
609 | 171 | @defer.inlineCallbacks | ||
610 | 172 | def test_no_error_message_if_no_exception(self): | ||
611 | 173 | """On success, do not show an error message.""" | ||
612 | 174 | yield self.decorate_me() | ||
613 | 175 | |||
614 | 176 | self.assertEqual(FakedDialog.args, None) | ||
615 | 177 | self.assertEqual(FakedDialog.kwargs, None) | ||
616 | 178 | |||
617 | 179 | @defer.inlineCallbacks | ||
618 | 180 | def test_call_error_handler(self): | ||
619 | 181 | """On success, do not execute error_handler.""" | ||
620 | 182 | yield self.decorate_me() | ||
621 | 183 | self.assertFalse(self.error_handler_called) | ||
622 | 184 | |||
623 | 185 | |||
624 | 186 | class HandleErrorWithCustomLoggerTestCase(HandleErrorTestCase): | ||
625 | 187 | """Test suite for the generic error handler.""" | ||
626 | 188 | |||
627 | 189 | use_logger = True | ||
628 | 190 | logger = setup_logging('HandleErrorWithoutLoggerTestCase') # custom logger | ||
629 | 191 | |||
630 | 192 | |||
631 | 193 | class HandleErrorWithHandlerTestCase(HandleErrorTestCase): | ||
632 | 194 | """Test suite for the generic error handler when using a custom handler.""" | ||
633 | 195 | |||
634 | 196 | @defer.inlineCallbacks | ||
635 | 197 | def error_handler(self, *a, **kw): | ||
636 | 198 | """Implement an error handler.""" | ||
637 | 199 | self.error_handler_called = (a, kw) | ||
638 | 200 | yield | ||
639 | 201 | |||
640 | 202 | @defer.inlineCallbacks | ||
641 | 203 | def test_call_error_handler(self): | ||
642 | 204 | """On error, execute error_handler.""" | ||
643 | 205 | msg = 'This is me failing badly.' | ||
644 | 206 | self.failure = Exception(msg) | ||
645 | 207 | |||
646 | 208 | yield self.decorate_me() | ||
647 | 209 | |||
648 | 210 | self.assertEqual(self.error_handler_called, ((), {})) | ||
649 | 48 | 211 | ||
650 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_device.py' | |||
651 | --- ubuntuone/controlpanel/gui/qt/tests/test_device.py 2011-09-02 17:59:39 +0000 | |||
652 | +++ ubuntuone/controlpanel/gui/qt/tests/test_device.py 2011-09-08 01:17:23 +0000 | |||
653 | @@ -23,7 +23,9 @@ | |||
654 | 23 | from ubuntuone.controlpanel.gui.qt import device as gui | 23 | from ubuntuone.controlpanel.gui.qt import device as gui |
655 | 24 | from ubuntuone.controlpanel.gui.qt.tests import ( | 24 | from ubuntuone.controlpanel.gui.qt.tests import ( |
656 | 25 | BaseTestCase, | 25 | BaseTestCase, |
658 | 26 | FakedConfirmDialog, | 26 | CrashyBackend, |
659 | 27 | CrashyBackendException, | ||
660 | 28 | FakedDialog, | ||
661 | 27 | SAMPLE_COMPUTER_INFO, | 29 | SAMPLE_COMPUTER_INFO, |
662 | 28 | SAMPLE_PHONE_INFO, | 30 | SAMPLE_PHONE_INFO, |
663 | 29 | ) | 31 | ) |
664 | @@ -41,6 +43,7 @@ | |||
665 | 41 | class_ui = gui.DeviceWidget | 43 | class_ui = gui.DeviceWidget |
666 | 42 | device_id = 'zaraza' | 44 | device_id = 'zaraza' |
667 | 43 | kwargs = {'device_id': device_id} | 45 | kwargs = {'device_id': device_id} |
668 | 46 | logger = gui.logger | ||
669 | 44 | 47 | ||
670 | 45 | def test_has_id(self): | 48 | def test_has_id(self): |
671 | 46 | """The device as an id, None by default.""" | 49 | """The device as an id, None by default.""" |
672 | @@ -98,10 +101,7 @@ | |||
673 | 98 | @defer.inlineCallbacks | 101 | @defer.inlineCallbacks |
674 | 99 | def setUp(self): | 102 | def setUp(self): |
675 | 100 | yield super(RemoveDeviceTestCase, self).setUp() | 103 | yield super(RemoveDeviceTestCase, self).setUp() |
680 | 101 | FakedConfirmDialog.response = gui.NO | 104 | FakedDialog.response = gui.YES |
677 | 102 | FakedConfirmDialog.args = None | ||
678 | 103 | FakedConfirmDialog.kwargs = None | ||
679 | 104 | self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) | ||
681 | 105 | 105 | ||
682 | 106 | def test_remove_device_opens_confirmation_dialog(self): | 106 | def test_remove_device_opens_confirmation_dialog(self): |
683 | 107 | """A confirmation dialog is opened when user clicks 'delete device'.""" | 107 | """A confirmation dialog is opened when user clicks 'delete device'.""" |
684 | @@ -109,13 +109,13 @@ | |||
685 | 109 | 109 | ||
686 | 110 | msg = gui.DEVICE_CONFIRM_REMOVE | 110 | msg = gui.DEVICE_CONFIRM_REMOVE |
687 | 111 | buttons = gui.YES | gui.NO | 111 | buttons = gui.YES | gui.NO |
689 | 112 | self.assertEqual(FakedConfirmDialog.args, | 112 | self.assertEqual(FakedDialog.args, |
690 | 113 | (self.ui, '', msg, buttons, gui.NO)) | 113 | (self.ui, '', msg, buttons, gui.NO)) |
692 | 114 | self.assertEqual(FakedConfirmDialog.kwargs, {}) | 114 | self.assertEqual(FakedDialog.kwargs, {}) |
693 | 115 | 115 | ||
694 | 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): |
695 | 117 | """The device is not removed is answer is No.""" | 117 | """The device is not removed is answer is No.""" |
697 | 118 | FakedConfirmDialog.response = gui.NO | 118 | FakedDialog.response = gui.NO |
698 | 119 | self.ui.removed.connect(self._set_called) | 119 | self.ui.removed.connect(self._set_called) |
699 | 120 | self.ui.ui.remove_device_button.click() | 120 | self.ui.ui.remove_device_button.click() |
700 | 121 | 121 | ||
701 | @@ -124,7 +124,7 @@ | |||
702 | 124 | 124 | ||
703 | 125 | def test_remove_device_does_remove_if_answer_is_yes(self): | 125 | def test_remove_device_does_remove_if_answer_is_yes(self): |
704 | 126 | """The device is removed is answer is Yes.""" | 126 | """The device is removed is answer is Yes.""" |
706 | 127 | FakedConfirmDialog.response = gui.YES | 127 | FakedDialog.response = gui.YES |
707 | 128 | self.ui.ui.remove_device_button.click() | 128 | self.ui.ui.remove_device_button.click() |
708 | 129 | 129 | ||
709 | 130 | self.assert_backend_called('remove_device', device_id=self.device_id) | 130 | self.assert_backend_called('remove_device', device_id=self.device_id) |
710 | @@ -138,7 +138,7 @@ | |||
711 | 138 | """Fire deferred when the device was removed.""" | 138 | """Fire deferred when the device was removed.""" |
712 | 139 | d.callback(device_id) | 139 | d.callback(device_id) |
713 | 140 | 140 | ||
715 | 141 | FakedConfirmDialog.response = gui.YES | 141 | FakedDialog.response = gui.YES |
716 | 142 | self.ui.removed.connect(self._set_called) | 142 | self.ui.removed.connect(self._set_called) |
717 | 143 | self.patch(self.ui.backend, 'remove_device', check) | 143 | self.patch(self.ui.backend, 'remove_device', check) |
718 | 144 | self.ui.ui.remove_device_button.click() | 144 | self.ui.ui.remove_device_button.click() |
719 | @@ -148,8 +148,16 @@ | |||
720 | 148 | 148 | ||
721 | 149 | def test_remove_device_emits_signal_when_not_removed(self): | 149 | def test_remove_device_emits_signal_when_not_removed(self): |
722 | 150 | """The signal 'removeCanceled' is emitted when user cancels removal.""" | 150 | """The signal 'removeCanceled' is emitted when user cancels removal.""" |
724 | 151 | FakedConfirmDialog.response = gui.NO | 151 | FakedDialog.response = gui.NO |
725 | 152 | self.ui.removeCanceled.connect(self._set_called) | 152 | self.ui.removeCanceled.connect(self._set_called) |
726 | 153 | self.ui.ui.remove_device_button.click() | 153 | self.ui.ui.remove_device_button.click() |
727 | 154 | 154 | ||
728 | 155 | self.assertEqual(self._called, ((), {})) | 155 | self.assertEqual(self._called, ((), {})) |
729 | 156 | |||
730 | 157 | @defer.inlineCallbacks | ||
731 | 158 | def test_backend_error_is_handled(self): | ||
732 | 159 | """Any error from the backend is properly handled.""" | ||
733 | 160 | self.patch(self.ui, 'backend', CrashyBackend()) | ||
734 | 161 | yield self.ui.ui.remove_device_button.click() | ||
735 | 162 | |||
736 | 163 | self.assertTrue(self.memento.check_exception(CrashyBackendException)) | ||
737 | 156 | 164 | ||
738 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_devices.py' | |||
739 | --- ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2011-09-01 17:11:16 +0000 | |||
740 | +++ ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2011-09-08 01:17:23 +0000 | |||
741 | @@ -22,7 +22,6 @@ | |||
742 | 22 | 22 | ||
743 | 23 | from ubuntuone.controlpanel.gui.qt import devices as gui | 23 | from ubuntuone.controlpanel.gui.qt import devices as gui |
744 | 24 | from ubuntuone.controlpanel.gui.qt.tests import ( | 24 | from ubuntuone.controlpanel.gui.qt.tests import ( |
745 | 25 | FakedConfirmDialog, | ||
746 | 26 | SAMPLE_DEVICES_INFO, | 25 | SAMPLE_DEVICES_INFO, |
747 | 27 | ) | 26 | ) |
748 | 28 | from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import ( | 27 | from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import ( |
749 | @@ -41,7 +40,6 @@ | |||
750 | 41 | def setUp(self): | 40 | def setUp(self): |
751 | 42 | yield super(DevicesPanelTestCase, self).setUp() | 41 | yield super(DevicesPanelTestCase, self).setUp() |
752 | 43 | self.ui.backend.next_result = SAMPLE_DEVICES_INFO | 42 | self.ui.backend.next_result = SAMPLE_DEVICES_INFO |
753 | 44 | self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) | ||
754 | 45 | 43 | ||
755 | 46 | def test_is_processing_while_asking_info(self): | 44 | def test_is_processing_while_asking_info(self): |
756 | 47 | """The ui is processing while the contents are loaded.""" | 45 | """The ui is processing while the contents are loaded.""" |
757 | 48 | 46 | ||
758 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_folders.py' | |||
759 | --- ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2011-09-01 17:11:16 +0000 | |||
760 | +++ ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2011-09-08 01:17:23 +0000 | |||
761 | @@ -33,8 +33,7 @@ | |||
762 | 33 | ) | 33 | ) |
763 | 34 | from ubuntuone.controlpanel.gui.qt import folders as gui | 34 | from ubuntuone.controlpanel.gui.qt import folders as gui |
764 | 35 | from ubuntuone.controlpanel.gui.qt.tests import ( | 35 | from ubuntuone.controlpanel.gui.qt.tests import ( |
767 | 36 | FakedConfirmDialog, | 36 | FakedDialog, |
766 | 37 | FakedFileDialog, | ||
768 | 38 | ) | 37 | ) |
769 | 39 | from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import ( | 38 | from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import ( |
770 | 40 | UbuntuOneBinTestCase, | 39 | UbuntuOneBinTestCase, |
771 | @@ -320,17 +319,6 @@ | |||
772 | 320 | # reset backend state | 319 | # reset backend state |
773 | 321 | self.ui.backend._called.clear() | 320 | self.ui.backend._called.clear() |
774 | 322 | 321 | ||
775 | 323 | # default response if user does nothing | ||
776 | 324 | FakedFileDialog.response = gui.QtCore.QString('') | ||
777 | 325 | FakedFileDialog.args = None | ||
778 | 326 | FakedFileDialog.kwargs = None | ||
779 | 327 | self.patch(gui.QtGui, 'QFileDialog', FakedFileDialog) | ||
780 | 328 | |||
781 | 329 | FakedConfirmDialog.response = None | ||
782 | 330 | FakedConfirmDialog.args = None | ||
783 | 331 | FakedConfirmDialog.kwargs = None | ||
784 | 332 | self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) | ||
785 | 333 | |||
786 | 334 | def test_not_is_processing(self): | 322 | def test_not_is_processing(self): |
787 | 335 | """Before clicking the add folder button, the UI is not processing.""" | 323 | """Before clicking the add folder button, the UI is not processing.""" |
788 | 336 | self.assertFalse(self.ui.is_processing, 'ui must not be processing') | 324 | self.assertFalse(self.ui.is_processing, 'ui must not be processing') |
789 | @@ -354,10 +342,7 @@ | |||
790 | 354 | def setUp(self): | 342 | def setUp(self): |
791 | 355 | yield super(FoldersPanelSubscriptionTestCase, self).setUp() | 343 | yield super(FoldersPanelSubscriptionTestCase, self).setUp() |
792 | 356 | self.patch(gui.os.path, 'exists', lambda path: True) | 344 | self.patch(gui.os.path, 'exists', lambda path: True) |
797 | 357 | FakedConfirmDialog.response = gui.YES | 345 | FakedDialog.response = gui.YES |
794 | 358 | FakedConfirmDialog.args = None | ||
795 | 359 | FakedConfirmDialog.kwargs = None | ||
796 | 360 | self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) | ||
798 | 361 | 346 | ||
799 | 362 | self.ui.process_info(FAKE_VOLUMES_MINIMAL_INFO) | 347 | self.ui.process_info(FAKE_VOLUMES_MINIMAL_INFO) |
800 | 363 | # the music folder | 348 | # the music folder |
801 | @@ -436,9 +421,9 @@ | |||
802 | 436 | volume_path = self.item.volume_path | 421 | volume_path = self.item.volume_path |
803 | 437 | msg = gui.FOLDERS_CONFIRM_MERGE % {'folder_path': volume_path} | 422 | msg = gui.FOLDERS_CONFIRM_MERGE % {'folder_path': volume_path} |
804 | 438 | buttons = gui.YES | gui.NO | gui.CANCEL | 423 | buttons = gui.YES | gui.NO | gui.CANCEL |
806 | 439 | self.assertEqual(FakedConfirmDialog.args, | 424 | self.assertEqual(FakedDialog.args, |
807 | 440 | (self.ui, '', msg, buttons, gui.YES)) | 425 | (self.ui, '', msg, buttons, gui.YES)) |
809 | 441 | self.assertEqual(FakedConfirmDialog.kwargs, {}) | 426 | self.assertEqual(FakedDialog.kwargs, {}) |
810 | 442 | 427 | ||
811 | 443 | @defer.inlineCallbacks | 428 | @defer.inlineCallbacks |
812 | 444 | def test_confirm_dialog_if_path_does_not_exist(self): | 429 | def test_confirm_dialog_if_path_does_not_exist(self): |
813 | @@ -452,14 +437,13 @@ | |||
814 | 452 | 437 | ||
815 | 453 | yield self.ui.on_folders_itemChanged(self.item) | 438 | yield self.ui.on_folders_itemChanged(self.item) |
816 | 454 | 439 | ||
819 | 455 | self.assertEqual(FakedConfirmDialog.args, None) | 440 | self.assertEqual(FakedDialog.args, None) |
820 | 456 | self.assertEqual(FakedConfirmDialog.kwargs, None) | 441 | self.assertEqual(FakedDialog.kwargs, None) |
821 | 457 | 442 | ||
822 | 458 | @defer.inlineCallbacks | 443 | @defer.inlineCallbacks |
823 | 459 | def test_subscribe_does_not_call_backend_if_dialog_closed(self): | 444 | def test_subscribe_does_not_call_backend_if_dialog_closed(self): |
824 | 460 | """Backend is not called if users closes the confirmation dialog.""" | 445 | """Backend is not called if users closes the confirmation dialog.""" |
827 | 461 | FakedConfirmDialog.response = gui.CANCEL | 446 | FakedDialog.response = gui.CANCEL |
826 | 462 | self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) | ||
828 | 463 | 447 | ||
829 | 464 | # make sure the item is subscribed | 448 | # make sure the item is subscribed |
830 | 465 | self.ui.is_processing = True | 449 | self.ui.is_processing = True |
831 | @@ -468,7 +452,7 @@ | |||
832 | 468 | 452 | ||
833 | 469 | yield self.ui.on_folders_itemChanged(self.item) | 453 | yield self.ui.on_folders_itemChanged(self.item) |
834 | 470 | 454 | ||
836 | 471 | self.assertFalse(FakedConfirmDialog.args is None, 'warning was called') | 455 | self.assertFalse(FakedDialog.args is None, 'warning was called') |
837 | 472 | self.assertNotIn('change_volume_settings', self.ui.backend._called) | 456 | self.assertNotIn('change_volume_settings', self.ui.backend._called) |
838 | 473 | self.assertFalse(self.ui.is_processing) | 457 | self.assertFalse(self.ui.is_processing) |
839 | 474 | 458 | ||
840 | @@ -478,8 +462,7 @@ | |||
841 | 478 | @defer.inlineCallbacks | 462 | @defer.inlineCallbacks |
842 | 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): |
843 | 480 | """Backend is not called if users clicks on 'No'.""" | 464 | """Backend is not called if users clicks on 'No'.""" |
846 | 481 | FakedConfirmDialog.response = gui.NO | 465 | FakedDialog.response = gui.NO |
845 | 482 | self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) | ||
847 | 483 | 466 | ||
848 | 484 | # make sure the item is subscribed | 467 | # make sure the item is subscribed |
849 | 485 | self.ui.is_processing = True | 468 | self.ui.is_processing = True |
850 | @@ -488,7 +471,7 @@ | |||
851 | 488 | 471 | ||
852 | 489 | yield self.ui.on_folders_itemChanged(self.item) | 472 | yield self.ui.on_folders_itemChanged(self.item) |
853 | 490 | 473 | ||
855 | 491 | self.assertFalse(FakedConfirmDialog.args is None, 'warning was called') | 474 | self.assertFalse(FakedDialog.args is None, 'warning was called') |
856 | 492 | self.assertNotIn('change_volume_settings', self.ui.backend._called) | 475 | self.assertNotIn('change_volume_settings', self.ui.backend._called) |
857 | 493 | self.assertFalse(self.ui.is_processing) | 476 | self.assertFalse(self.ui.is_processing) |
858 | 494 | 477 | ||
859 | @@ -504,10 +487,10 @@ | |||
860 | 504 | self.ui.is_processing = False | 487 | self.ui.is_processing = False |
861 | 505 | 488 | ||
862 | 506 | # the confirm dialog was not called so far | 489 | # the confirm dialog was not called so far |
865 | 507 | assert FakedConfirmDialog.args is None | 490 | assert FakedDialog.args is None |
866 | 508 | assert FakedConfirmDialog.kwargs is None | 491 | assert FakedDialog.kwargs is None |
867 | 509 | 492 | ||
868 | 510 | yield self.ui.on_folders_itemChanged(self.item) | 493 | yield self.ui.on_folders_itemChanged(self.item) |
869 | 511 | 494 | ||
872 | 512 | self.assertTrue(FakedConfirmDialog.args is None, 'dialog was not run') | 495 | self.assertTrue(FakedDialog.args is None, 'dialog was not run') |
873 | 513 | self.assertTrue(FakedConfirmDialog.kwargs is None, 'dialog was hid') | 496 | self.assertTrue(FakedDialog.kwargs is None, 'dialog was hid') |
874 | 514 | 497 | ||
875 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_signin.py' | |||
876 | --- ubuntuone/controlpanel/gui/qt/tests/test_signin.py 2011-08-31 17:18:56 +0000 | |||
877 | +++ ubuntuone/controlpanel/gui/qt/tests/test_signin.py 2011-09-08 01:17:23 +0000 | |||
878 | @@ -22,6 +22,10 @@ | |||
879 | 22 | 22 | ||
880 | 23 | from ubuntuone.controlpanel.gui import qt | 23 | from ubuntuone.controlpanel.gui import qt |
881 | 24 | from ubuntuone.controlpanel.gui.qt import signin as gui | 24 | from ubuntuone.controlpanel.gui.qt import signin as gui |
882 | 25 | from ubuntuone.controlpanel.gui.qt.tests import ( | ||
883 | 26 | CrashyBackend, | ||
884 | 27 | CrashyBackendException, | ||
885 | 28 | ) | ||
886 | 25 | from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import ( | 29 | from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import ( |
887 | 26 | UbuntuOneBinTestCase, | 30 | UbuntuOneBinTestCase, |
888 | 27 | ) | 31 | ) |
889 | @@ -36,7 +40,7 @@ | |||
890 | 36 | 40 | ||
891 | 37 | def fail(*a, **kw): | 41 | def fail(*a, **kw): |
892 | 38 | """Emit CredentialsError.""" | 42 | """Emit CredentialsError.""" |
894 | 39 | raise gui.CredentialsError(MSG) | 43 | raise TypeError(MSG) |
895 | 40 | 44 | ||
896 | 41 | 45 | ||
897 | 42 | class BaseSignInPanelTestCase(UbuntuOneBinTestCase): | 46 | class BaseSignInPanelTestCase(UbuntuOneBinTestCase): |
898 | @@ -81,10 +85,6 @@ | |||
899 | 81 | yield self.ui.ui.signin_button.click() | 85 | yield self.ui.ui.signin_button.click() |
900 | 82 | self.assertFalse(self.ui.is_processing) | 86 | self.assertFalse(self.ui.is_processing) |
901 | 83 | 87 | ||
902 | 84 | def test_warning_label_empty(self): | ||
903 | 85 | """The warning_label is empty at startup.""" | ||
904 | 86 | self.assertEqual('', unicode(self.ui.ui.warning_label.text())) | ||
905 | 87 | |||
906 | 88 | def test_signin_disabled_at_startup(self): | 88 | def test_signin_disabled_at_startup(self): |
907 | 89 | """The signin_button is disabled at startup.""" | 89 | """The signin_button is disabled at startup.""" |
908 | 90 | self.assertFalse(self.ui.ui.signin_button.isEnabled()) | 90 | self.assertFalse(self.ui.ui.signin_button.isEnabled()) |
909 | @@ -139,31 +139,7 @@ | |||
910 | 139 | yield self.ui.ui.signin_button.click() | 139 | yield self.ui.ui.signin_button.click() |
911 | 140 | 140 | ||
912 | 141 | self.assertEqual(self._called, ((TOKEN,), {})) | 141 | self.assertEqual(self._called, ((TOKEN,), {})) |
938 | 142 | self.assertEqual('', unicode(self.ui.ui.warning_label.text())) | 142 | self.assertFalse(self.ui.is_processing) |
914 | 143 | self.assertFalse(self.ui.is_processing) | ||
915 | 144 | |||
916 | 145 | @defer.inlineCallbacks | ||
917 | 146 | def test_signin_credentials_error(self): | ||
918 | 147 | """Show error when CredentialsError was raised from the backend.""" | ||
919 | 148 | self.patch(self.ui.backend, 'login', fail) | ||
920 | 149 | self.ui.credentialsFound.connect(self._set_called) | ||
921 | 150 | yield self.ui.ui.signin_button.click() | ||
922 | 151 | |||
923 | 152 | self.assertFalse(self._called, 'credentialsFound must not be emitted.') | ||
924 | 153 | self.assertEqual(MSG['message'], | ||
925 | 154 | unicode(self.ui.ui.warning_label.text())) | ||
926 | 155 | self.assertFalse(self.ui.is_processing) | ||
927 | 156 | self.assertTrue(self.memento.check_info('signin_button_clicked', | ||
928 | 157 | repr(MSG))) | ||
929 | 158 | |||
930 | 159 | @defer.inlineCallbacks | ||
931 | 160 | def test_signin_success_after_error(self): | ||
932 | 161 | """Emit credentialsFound on signin success.""" | ||
933 | 162 | self.patch(self.ui.backend, 'login', fail) # login failed | ||
934 | 163 | yield self.ui.ui.signin_button.click() | ||
935 | 164 | |||
936 | 165 | self.patch(self.ui.backend, 'login', lambda *a, **kw: TOKEN) # success | ||
937 | 166 | yield self.test_signin_success() | ||
939 | 167 | 143 | ||
940 | 168 | def test_signin_enabled_if_email_and_password(self): | 144 | def test_signin_enabled_if_email_and_password(self): |
941 | 169 | """Enable signin_button if email and password are non empty.""" | 145 | """Enable signin_button if email and password are non empty.""" |
942 | @@ -182,3 +158,11 @@ | |||
943 | 182 | self.assertEqual(1, receivers) | 158 | self.assertEqual(1, receivers) |
944 | 183 | 159 | ||
945 | 184 | self._called = False | 160 | self._called = False |
946 | 161 | |||
947 | 162 | @defer.inlineCallbacks | ||
948 | 163 | def test_backend_error_is_handled(self): | ||
949 | 164 | """Any error from the backend is properly handled.""" | ||
950 | 165 | self.patch(self.ui, 'backend', CrashyBackend()) | ||
951 | 166 | yield self.ui.ui.signin_button.click() | ||
952 | 167 | |||
953 | 168 | self.assertTrue(self.memento.check_exception(CrashyBackendException)) | ||
954 | 185 | 169 | ||
955 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py' | |||
956 | --- ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py 2011-09-02 17:59:39 +0000 | |||
957 | +++ ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py 2011-09-08 01:17:23 +0000 | |||
958 | @@ -18,10 +18,15 @@ | |||
959 | 18 | 18 | ||
960 | 19 | """Tests for the Ubuntu One Bin.""" | 19 | """Tests for the Ubuntu One Bin.""" |
961 | 20 | 20 | ||
962 | 21 | from twisted.internet import defer | ||
963 | 21 | from ubuntuone.devtools.testcase import skipIfOS | 22 | from ubuntuone.devtools.testcase import skipIfOS |
964 | 22 | 23 | ||
965 | 23 | from ubuntuone.controlpanel.gui.qt import ubuntuonebin as gui | 24 | from ubuntuone.controlpanel.gui.qt import ubuntuonebin as gui |
967 | 24 | from ubuntuone.controlpanel.gui.qt.tests import BaseTestCase | 25 | from ubuntuone.controlpanel.gui.qt.tests import ( |
968 | 26 | BaseTestCase, | ||
969 | 27 | CrashyBackend, | ||
970 | 28 | CrashyBackendException, | ||
971 | 29 | ) | ||
972 | 25 | 30 | ||
973 | 26 | # Attribute 'yyy' defined outside __init__, access to a protected member | 31 | # Attribute 'yyy' defined outside __init__, access to a protected member |
974 | 27 | # pylint: disable=W0201, W0212 | 32 | # pylint: disable=W0201, W0212 |
975 | @@ -45,6 +50,7 @@ | |||
976 | 45 | def test_is_enabled_if_not_processing(self): | 50 | def test_is_enabled_if_not_processing(self): |
977 | 46 | """If not processing, the UI is enabled.""" | 51 | """If not processing, the UI is enabled.""" |
978 | 47 | self.ui.show() # need to show to test widgets visibility | 52 | self.ui.show() # need to show to test widgets visibility |
979 | 53 | self.addCleanup(self.ui.hide) | ||
980 | 48 | 54 | ||
981 | 49 | self.ui.is_processing = False | 55 | self.ui.is_processing = False |
982 | 50 | 56 | ||
983 | @@ -55,8 +61,20 @@ | |||
984 | 55 | def test_is_not_enabled_if_processing(self): | 61 | def test_is_not_enabled_if_processing(self): |
985 | 56 | """If processing, the UI is disabled.""" | 62 | """If processing, the UI is disabled.""" |
986 | 57 | self.ui.show() # need to show to test widgets visibility | 63 | self.ui.show() # need to show to test widgets visibility |
987 | 64 | self.addCleanup(self.ui.hide) | ||
988 | 58 | 65 | ||
989 | 59 | self.ui.is_processing = True | 66 | self.ui.is_processing = True |
990 | 60 | 67 | ||
991 | 61 | self.assertFalse(self.ui.isEnabled()) | 68 | self.assertFalse(self.ui.isEnabled()) |
992 | 62 | self.assertTrue(self.ui.overlay.isVisible()) | 69 | self.assertTrue(self.ui.overlay.isVisible()) |
993 | 70 | |||
994 | 71 | @defer.inlineCallbacks | ||
995 | 72 | def test_backend_error_is_handled(self): | ||
996 | 73 | """Any error from the backend is properly handled.""" | ||
997 | 74 | self.patch(self.ui, 'backend', CrashyBackend()) | ||
998 | 75 | yield self.ui.load() | ||
999 | 76 | |||
1000 | 77 | self.assertFalse(self.ui.is_processing) | ||
1001 | 78 | if self.memento: | ||
1002 | 79 | logged = self.memento.check_exception(CrashyBackendException) | ||
1003 | 80 | self.assertTrue(logged) | ||
1004 | 63 | 81 | ||
1005 | === modified file 'ubuntuone/controlpanel/gui/qt/ubuntuonebin.py' | |||
1006 | --- ubuntuone/controlpanel/gui/qt/ubuntuonebin.py 2011-09-02 17:59:39 +0000 | |||
1007 | +++ ubuntuone/controlpanel/gui/qt/ubuntuonebin.py 2011-09-08 01:17:23 +0000 | |||
1008 | @@ -21,6 +21,7 @@ | |||
1009 | 21 | from PyQt4 import QtGui | 21 | from PyQt4 import QtGui |
1010 | 22 | 22 | ||
1011 | 23 | from ubuntuone.controlpanel import cache | 23 | from ubuntuone.controlpanel import cache |
1012 | 24 | from ubuntuone.controlpanel.gui.qt import handle_errors | ||
1013 | 24 | from ubuntuone.controlpanel.gui.qt.loadingoverlay import LoadingOverlay | 25 | from ubuntuone.controlpanel.gui.qt.loadingoverlay import LoadingOverlay |
1014 | 25 | 26 | ||
1015 | 26 | 27 | ||
1016 | @@ -45,6 +46,11 @@ | |||
1017 | 45 | self._is_processing = None | 46 | self._is_processing = None |
1018 | 46 | self.is_processing = False | 47 | self.is_processing = False |
1019 | 47 | 48 | ||
1020 | 49 | # pylint: disable=E0202 | ||
1021 | 50 | handler = handle_errors(logger=self.logger, | ||
1022 | 51 | error_handler=self._error_handler) | ||
1023 | 52 | self.load = handler(self.load) | ||
1024 | 53 | |||
1025 | 48 | self._setup() | 54 | self._setup() |
1026 | 49 | 55 | ||
1027 | 50 | def _get_is_processing(self): | 56 | def _get_is_processing(self): |
1028 | @@ -64,6 +70,10 @@ | |||
1029 | 64 | 70 | ||
1030 | 65 | is_processing = property(fget=_get_is_processing, fset=_set_is_processing) | 71 | is_processing = property(fget=_get_is_processing, fset=_set_is_processing) |
1031 | 66 | 72 | ||
1032 | 73 | def _error_handler(self): | ||
1033 | 74 | """Custom error handler, unset is_processing.""" | ||
1034 | 75 | self.is_processing = False | ||
1035 | 76 | |||
1036 | 67 | def _setup(self): | 77 | def _setup(self): |
1037 | 68 | """Do some extra setupping for the UI.""" | 78 | """Do some extra setupping for the UI.""" |
1038 | 69 | 79 | ||
1039 | @@ -82,5 +92,6 @@ | |||
1040 | 82 | 92 | ||
1041 | 83 | # pylint: enable=C0103 | 93 | # pylint: enable=C0103 |
1042 | 84 | 94 | ||
1043 | 95 | # pylint: disable=E0202 | ||
1044 | 85 | def load(self): | 96 | def load(self): |
1045 | 86 | """Load the widget with specific info.""" | 97 | """Load the widget with specific info.""" |
1046 | 87 | 98 | ||
1047 | === modified file 'ubuntuone/controlpanel/tests/test_cache.py' | |||
1048 | --- ubuntuone/controlpanel/tests/test_cache.py 2011-09-02 18:10:13 +0000 | |||
1049 | +++ ubuntuone/controlpanel/tests/test_cache.py 2011-09-08 01:17:23 +0000 | |||
1050 | @@ -39,6 +39,13 @@ | |||
1051 | 39 | """The backend instance is successfully created.""" | 39 | """The backend instance is successfully created.""" |
1052 | 40 | self.assertIsInstance(self.obj.backend, cache.backend.ControlBackend) | 40 | self.assertIsInstance(self.obj.backend, cache.backend.ControlBackend) |
1053 | 41 | 41 | ||
1054 | 42 | def test_set_backend(self): | ||
1055 | 43 | """The backend instance is successfully assigned.""" | ||
1056 | 44 | expected = object() | ||
1057 | 45 | assert self.obj.backend is not expected | ||
1058 | 46 | self.obj.backend = expected | ||
1059 | 47 | self.assertTrue(self.obj.backend is expected) | ||
1060 | 48 | |||
1061 | 42 | def test_backend_is_cached(self): | 49 | def test_backend_is_cached(self): |
1062 | 43 | """The backend instance is cached.""" | 50 | """The backend instance is cached.""" |
1063 | 44 | obj2 = cache.Cache() | 51 | obj2 = cache.Cache() |
+1