Merge lp:~nataliabidart/ubuntuone-control-panel/applications-woohoo into lp:ubuntuone-control-panel
- applications-woohoo
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Natalia Bidart |
Approved revision: | 55 |
Merged at revision: | 42 |
Proposed branch: | lp:~nataliabidart/ubuntuone-control-panel/applications-woohoo |
Merge into: | lp:ubuntuone-control-panel |
Diff against target: |
1986 lines (+1422/-188) 15 files modified
data/install.ui (+46/-0) data/management.ui (+7/-7) data/services.ui (+57/-1) po/POTFILES.in (+3/-2) ubuntuone/controlpanel/backend.py (+12/-0) ubuntuone/controlpanel/dbus_service.py (+47/-0) ubuntuone/controlpanel/gtk/gui.py (+271/-16) ubuntuone/controlpanel/gtk/package_manager.py (+60/-0) ubuntuone/controlpanel/gtk/tests/__init__.py (+150/-0) ubuntuone/controlpanel/gtk/tests/test_gui.py (+525/-157) ubuntuone/controlpanel/gtk/tests/test_package_manager.py (+177/-0) ubuntuone/controlpanel/integrationtests/test_dbus_service.py (+44/-0) ubuntuone/controlpanel/logger.py (+1/-1) ubuntuone/controlpanel/tests/__init__.py (+2/-2) ubuntuone/controlpanel/tests/test_backend.py (+20/-2) |
To merge this branch: | bzr merge lp:~nataliabidart/ubuntuone-control-panel/applications-woohoo |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Roberto Alsina (community) | Approve | ||
John Lenton (community) | Approve | ||
Review via email: mp+44623@code.launchpad.net |
Commit message
* renamed Account to Dashboard
* renamed Applications to Services
* added enable_
* added a new dbus signal FileSyncStatusC
* desktopcouch replication exclusion layer is acceded directly on the GUI. We should later move that to the backend.
* a new module package_manager was added to the gtk package, since we need to do some deeper work to abstract that manager from the toolkit (since it uses a gtk progress bar)(LP: #673673).
* a new widget InstallPackage that provides package installation.
* widgets FilesService and DesktopcouchService that can be re used as needed.
* ServicesPanel checks for depenencies and creates widget as necessary (LP: #673672).
Description of the change
This is an epic branch, I know, please don't hate me. Think on the good things, we have a full featured control panel!
This branch implements all bits needed to list the services offered and install package dependencies if needed.
What was done:
(see commit message for the full list)
All this is tested with code and was tested IRL.
To run the tests, do:
./run-tests
To test IRL:
* uninstall desktopcouch, xul-ext-bindwood, evolution-couchdb
* on terminal 1: DEBUG=True PYTHONPATH=. ./bin/ubuntuone
* on terminal 2: DEBUG=True PYTHONPATH=. ./bin/ubuntuone
Got to the Services tab, and install desktopcouch using the same UI, and then install (if you want) the bindwood and evocouch packages.
Natalia Bidart (nataliabidart) wrote : | # |
Natalia Bidart (nataliabidart) wrote : | # |
Code to properly handle ValueError is now in place. The lack of a pairing record with Ubuntu One should be handled in the pairing_ubuntuone plugin of desktopcouch, see bug #694495.
Natalia Bidart (nataliabidart) wrote : | # |
Just filled bug #696782 to make the DC service starts on the backend.
- 53. By Natalia Bidart
-
aptdaemon.defer on natty is just defer.
- 54. By Natalia Bidart
-
Proper namespace for defer.
- 55. By Natalia Bidart
-
Avoiding lint warnings.
John Lenton (chipaca) : | # |
Preview Diff
1 | === renamed file 'data/account.ui' => 'data/dashboard.ui' | |||
2 | === added file 'data/install.ui' | |||
3 | --- data/install.ui 1970-01-01 00:00:00 +0000 | |||
4 | +++ data/install.ui 2011-01-03 14:24:42 +0000 | |||
5 | @@ -0,0 +1,46 @@ | |||
6 | 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
7 | 2 | <interface> | ||
8 | 3 | <requires lib="gtk+" version="2.16"/> | ||
9 | 4 | <!-- interface-naming-policy project-wide --> | ||
10 | 5 | <object class="GtkVBox" id="itself"> | ||
11 | 6 | <property name="visible">True</property> | ||
12 | 7 | <property name="border_width">10</property> | ||
13 | 8 | <property name="spacing">10</property> | ||
14 | 9 | <child> | ||
15 | 10 | <object class="GtkLabel" id="install_label"> | ||
16 | 11 | <property name="visible">True</property> | ||
17 | 12 | <property name="xalign">0</property> | ||
18 | 13 | <property name="label">label</property> | ||
19 | 14 | <property name="wrap">True</property> | ||
20 | 15 | </object> | ||
21 | 16 | <packing> | ||
22 | 17 | <property name="expand">False</property> | ||
23 | 18 | <property name="position">0</property> | ||
24 | 19 | </packing> | ||
25 | 20 | </child> | ||
26 | 21 | <child> | ||
27 | 22 | <object class="GtkHButtonBox" id="install_button_box"> | ||
28 | 23 | <property name="visible">True</property> | ||
29 | 24 | <child> | ||
30 | 25 | <object class="GtkButton" id="install_button"> | ||
31 | 26 | <property name="label">gtk-ok</property> | ||
32 | 27 | <property name="visible">True</property> | ||
33 | 28 | <property name="can_focus">True</property> | ||
34 | 29 | <property name="receives_default">True</property> | ||
35 | 30 | <property name="use_stock">True</property> | ||
36 | 31 | <signal name="clicked" handler="on_install_button_clicked"/> | ||
37 | 32 | </object> | ||
38 | 33 | <packing> | ||
39 | 34 | <property name="expand">False</property> | ||
40 | 35 | <property name="fill">False</property> | ||
41 | 36 | <property name="position">0</property> | ||
42 | 37 | </packing> | ||
43 | 38 | </child> | ||
44 | 39 | </object> | ||
45 | 40 | <packing> | ||
46 | 41 | <property name="expand">False</property> | ||
47 | 42 | <property name="position">1</property> | ||
48 | 43 | </packing> | ||
49 | 44 | </child> | ||
50 | 45 | </object> | ||
51 | 46 | </interface> | ||
52 | 0 | 47 | ||
53 | === modified file 'data/management.ui' | |||
54 | --- data/management.ui 2010-12-20 20:23:57 +0000 | |||
55 | +++ data/management.ui 2011-01-03 14:24:42 +0000 | |||
56 | @@ -64,8 +64,8 @@ | |||
57 | 64 | <property name="visible">True</property> | 64 | <property name="visible">True</property> |
58 | 65 | <property name="layout_style">center</property> | 65 | <property name="layout_style">center</property> |
59 | 66 | <child> | 66 | <child> |
62 | 67 | <object class="GtkRadioButton" id="account_button"> | 67 | <object class="GtkRadioButton" id="dashboard_button"> |
63 | 68 | <property name="label" translatable="yes">Account</property> | 68 | <property name="label" translatable="yes">Dashboard</property> |
64 | 69 | <property name="visible">True</property> | 69 | <property name="visible">True</property> |
65 | 70 | <property name="can_focus">True</property> | 70 | <property name="can_focus">True</property> |
66 | 71 | <property name="receives_default">False</property> | 71 | <property name="receives_default">False</property> |
67 | @@ -85,7 +85,7 @@ | |||
68 | 85 | <property name="can_focus">True</property> | 85 | <property name="can_focus">True</property> |
69 | 86 | <property name="receives_default">False</property> | 86 | <property name="receives_default">False</property> |
70 | 87 | <property name="draw_indicator">False</property> | 87 | <property name="draw_indicator">False</property> |
72 | 88 | <property name="group">account_button</property> | 88 | <property name="group">dashboard_button</property> |
73 | 89 | </object> | 89 | </object> |
74 | 90 | <packing> | 90 | <packing> |
75 | 91 | <property name="expand">False</property> | 91 | <property name="expand">False</property> |
76 | @@ -100,7 +100,7 @@ | |||
77 | 100 | <property name="can_focus">True</property> | 100 | <property name="can_focus">True</property> |
78 | 101 | <property name="receives_default">False</property> | 101 | <property name="receives_default">False</property> |
79 | 102 | <property name="draw_indicator">False</property> | 102 | <property name="draw_indicator">False</property> |
81 | 103 | <property name="group">account_button</property> | 103 | <property name="group">dashboard_button</property> |
82 | 104 | </object> | 104 | </object> |
83 | 105 | <packing> | 105 | <packing> |
84 | 106 | <property name="expand">False</property> | 106 | <property name="expand">False</property> |
85 | @@ -109,13 +109,13 @@ | |||
86 | 109 | </packing> | 109 | </packing> |
87 | 110 | </child> | 110 | </child> |
88 | 111 | <child> | 111 | <child> |
91 | 112 | <object class="GtkRadioButton" id="applications_button"> | 112 | <object class="GtkRadioButton" id="services_button"> |
92 | 113 | <property name="label" translatable="yes">Applications</property> | 113 | <property name="label" translatable="yes">Services</property> |
93 | 114 | <property name="visible">True</property> | 114 | <property name="visible">True</property> |
94 | 115 | <property name="can_focus">True</property> | 115 | <property name="can_focus">True</property> |
95 | 116 | <property name="receives_default">False</property> | 116 | <property name="receives_default">False</property> |
96 | 117 | <property name="draw_indicator">False</property> | 117 | <property name="draw_indicator">False</property> |
98 | 118 | <property name="group">account_button</property> | 118 | <property name="group">dashboard_button</property> |
99 | 119 | </object> | 119 | </object> |
100 | 120 | <packing> | 120 | <packing> |
101 | 121 | <property name="expand">False</property> | 121 | <property name="expand">False</property> |
102 | 122 | 122 | ||
103 | === renamed file 'data/applications.ui' => 'data/services.ui' | |||
104 | --- data/applications.ui 2010-10-21 21:14:24 +0000 | |||
105 | +++ data/services.ui 2011-01-03 14:24:42 +0000 | |||
106 | @@ -7,7 +7,63 @@ | |||
107 | 7 | <property name="border_width">10</property> | 7 | <property name="border_width">10</property> |
108 | 8 | <property name="spacing">10</property> | 8 | <property name="spacing">10</property> |
109 | 9 | <child> | 9 | <child> |
111 | 10 | <placeholder/> | 10 | <object class="GtkScrolledWindow" id="scrolledwindow1"> |
112 | 11 | <property name="visible">True</property> | ||
113 | 12 | <property name="can_focus">True</property> | ||
114 | 13 | <property name="hscrollbar_policy">automatic</property> | ||
115 | 14 | <property name="vscrollbar_policy">automatic</property> | ||
116 | 15 | <child> | ||
117 | 16 | <object class="GtkViewport" id="viewport1"> | ||
118 | 17 | <property name="visible">True</property> | ||
119 | 18 | <property name="resize_mode">queue</property> | ||
120 | 19 | <property name="shadow_type">none</property> | ||
121 | 20 | <child> | ||
122 | 21 | <object class="GtkVBox" id="vbox1"> | ||
123 | 22 | <property name="visible">True</property> | ||
124 | 23 | <child> | ||
125 | 24 | <object class="GtkAlignment" id="alignment1"> | ||
126 | 25 | <property name="visible">True</property> | ||
127 | 26 | <child> | ||
128 | 27 | <object class="GtkVBox" id="replications"> | ||
129 | 28 | <property name="visible">True</property> | ||
130 | 29 | <property name="spacing">5</property> | ||
131 | 30 | <child> | ||
132 | 31 | <placeholder/> | ||
133 | 32 | </child> | ||
134 | 33 | </object> | ||
135 | 34 | </child> | ||
136 | 35 | </object> | ||
137 | 36 | <packing> | ||
138 | 37 | <property name="expand">False</property> | ||
139 | 38 | <property name="position">0</property> | ||
140 | 39 | </packing> | ||
141 | 40 | </child> | ||
142 | 41 | <child> | ||
143 | 42 | <object class="GtkAlignment" id="alignment2"> | ||
144 | 43 | <property name="visible">True</property> | ||
145 | 44 | <child> | ||
146 | 45 | <object class="GtkVBox" id="files"> | ||
147 | 46 | <property name="visible">True</property> | ||
148 | 47 | <property name="spacing">5</property> | ||
149 | 48 | <child> | ||
150 | 49 | <placeholder/> | ||
151 | 50 | </child> | ||
152 | 51 | </object> | ||
153 | 52 | </child> | ||
154 | 53 | </object> | ||
155 | 54 | <packing> | ||
156 | 55 | <property name="expand">False</property> | ||
157 | 56 | <property name="position">1</property> | ||
158 | 57 | </packing> | ||
159 | 58 | </child> | ||
160 | 59 | </object> | ||
161 | 60 | </child> | ||
162 | 61 | </object> | ||
163 | 62 | </child> | ||
164 | 63 | </object> | ||
165 | 64 | <packing> | ||
166 | 65 | <property name="position">0</property> | ||
167 | 66 | </packing> | ||
168 | 11 | </child> | 67 | </child> |
169 | 12 | </object> | 68 | </object> |
170 | 13 | </interface> | 69 | </interface> |
171 | 14 | 70 | ||
172 | === modified file 'po/POTFILES.in' | |||
173 | --- po/POTFILES.in 2010-12-22 13:20:20 +0000 | |||
174 | +++ po/POTFILES.in 2011-01-03 14:24:42 +0000 | |||
175 | @@ -1,6 +1,7 @@ | |||
176 | 1 | ubuntuone/controlpanel/gtk/gui.py | 1 | ubuntuone/controlpanel/gtk/gui.py |
179 | 2 | [type: gettext/glade] data/account.ui | 2 | [type: gettext/glade] data/dashboard.ui |
180 | 3 | [type: gettext/glade] data/applications.ui | 3 | [type: gettext/glade] data/services.ui |
181 | 4 | [type: gettext/glade] data/device.ui | ||
182 | 4 | [type: gettext/glade] data/devices.ui | 5 | [type: gettext/glade] data/devices.ui |
183 | 5 | [type: gettext/glade] data/management.ui | 6 | [type: gettext/glade] data/management.ui |
184 | 6 | [type: gettext/glade] data/overview.ui | 7 | [type: gettext/glade] data/overview.ui |
185 | 7 | 8 | ||
186 | === modified file 'ubuntuone/controlpanel/backend.py' | |||
187 | --- ubuntuone/controlpanel/backend.py 2010-12-18 20:16:18 +0000 | |||
188 | +++ ubuntuone/controlpanel/backend.py 2011-01-03 14:24:42 +0000 | |||
189 | @@ -273,6 +273,18 @@ | |||
190 | 273 | 273 | ||
191 | 274 | @log_call(logger.debug) | 274 | @log_call(logger.debug) |
192 | 275 | @inlineCallbacks | 275 | @inlineCallbacks |
193 | 276 | def enable_files(self): | ||
194 | 277 | """Enable the files service.""" | ||
195 | 278 | yield dbus_client.set_files_sync_enabled(True) | ||
196 | 279 | |||
197 | 280 | @log_call(logger.debug) | ||
198 | 281 | @inlineCallbacks | ||
199 | 282 | def disable_files(self): | ||
200 | 283 | """Enable the files service.""" | ||
201 | 284 | yield dbus_client.set_files_sync_enabled(False) | ||
202 | 285 | |||
203 | 286 | @log_call(logger.debug) | ||
204 | 287 | @inlineCallbacks | ||
205 | 276 | def volumes_info(self): | 288 | def volumes_info(self): |
206 | 277 | """Get the volumes info.""" | 289 | """Get the volumes info.""" |
207 | 278 | result = yield dbus_client.get_folders() | 290 | result = yield dbus_client.get_folders() |
208 | 279 | 291 | ||
209 | === modified file 'ubuntuone/controlpanel/dbus_service.py' | |||
210 | --- ubuntuone/controlpanel/dbus_service.py 2010-12-16 21:09:46 +0000 | |||
211 | +++ ubuntuone/controlpanel/dbus_service.py 2011-01-03 14:24:42 +0000 | |||
212 | @@ -209,6 +209,8 @@ | |||
213 | 209 | else: | 209 | else: |
214 | 210 | self.FileSyncStatusError(error_handler(status_dict)) | 210 | self.FileSyncStatusError(error_handler(status_dict)) |
215 | 211 | 211 | ||
216 | 212 | self.FileSyncStatusChanged(status) | ||
217 | 213 | |||
218 | 212 | @log_call(logger.debug) | 214 | @log_call(logger.debug) |
219 | 213 | @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="") | 215 | @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="") |
220 | 214 | def file_sync_status(self): | 216 | def file_sync_status(self): |
221 | @@ -242,6 +244,11 @@ | |||
222 | 242 | def FileSyncStatusIdle(self, msg): | 244 | def FileSyncStatusIdle(self, msg): |
223 | 243 | """The file sync service is idle.""" | 245 | """The file sync service is idle.""" |
224 | 244 | 246 | ||
225 | 247 | @log_call(logger.debug) | ||
226 | 248 | @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="s") | ||
227 | 249 | def FileSyncStatusChanged(self, msg): | ||
228 | 250 | """The file sync service status changed.""" | ||
229 | 251 | |||
230 | 245 | @log_call(logger.error) | 252 | @log_call(logger.error) |
231 | 246 | @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="a{ss}") | 253 | @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="a{ss}") |
232 | 247 | def FileSyncStatusError(self, error): | 254 | def FileSyncStatusError(self, error): |
233 | @@ -251,6 +258,46 @@ | |||
234 | 251 | 258 | ||
235 | 252 | @log_call(logger.debug) | 259 | @log_call(logger.debug) |
236 | 253 | @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="") | 260 | @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="") |
237 | 261 | def enable_files(self): | ||
238 | 262 | """Enable the files service.""" | ||
239 | 263 | d = self.backend.enable_files() | ||
240 | 264 | d.addCallback(lambda _: self.FilesEnabled()) | ||
241 | 265 | d.addErrback(transform_failure(self.FilesEnableError)) | ||
242 | 266 | |||
243 | 267 | @log_call(logger.debug) | ||
244 | 268 | @signal(dbus_interface=DBUS_PREFERENCES_IFACE) | ||
245 | 269 | def FilesEnabled(self): | ||
246 | 270 | """The files service is enabled.""" | ||
247 | 271 | |||
248 | 272 | @log_call(logger.error) | ||
249 | 273 | @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="a{ss}") | ||
250 | 274 | def FilesEnableError(self, error): | ||
251 | 275 | """Problem enabling the files service.""" | ||
252 | 276 | |||
253 | 277 | #--- | ||
254 | 278 | |||
255 | 279 | @log_call(logger.debug) | ||
256 | 280 | @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="") | ||
257 | 281 | def disable_files(self): | ||
258 | 282 | """Disable the files service.""" | ||
259 | 283 | d = self.backend.disable_files() | ||
260 | 284 | d.addCallback(lambda _: self.FilesDisabled()) | ||
261 | 285 | d.addErrback(transform_failure(self.FilesDisableError)) | ||
262 | 286 | |||
263 | 287 | @log_call(logger.debug) | ||
264 | 288 | @signal(dbus_interface=DBUS_PREFERENCES_IFACE) | ||
265 | 289 | def FilesDisabled(self): | ||
266 | 290 | """The files service is disabled.""" | ||
267 | 291 | |||
268 | 292 | @log_call(logger.error) | ||
269 | 293 | @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="a{ss}") | ||
270 | 294 | def FilesDisableError(self, error): | ||
271 | 295 | """Problem disabling the files service.""" | ||
272 | 296 | |||
273 | 297 | #--- | ||
274 | 298 | |||
275 | 299 | @log_call(logger.debug) | ||
276 | 300 | @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="") | ||
277 | 254 | def volumes_info(self): | 301 | def volumes_info(self): |
278 | 255 | """Find out the volumes info for the logged in user.""" | 302 | """Find out the volumes info for the logged in user.""" |
279 | 256 | d = self.backend.volumes_info() | 303 | d = self.backend.volumes_info() |
280 | 257 | 304 | ||
281 | === modified file 'ubuntuone/controlpanel/gtk/gui.py' | |||
282 | --- ubuntuone/controlpanel/gtk/gui.py 2010-12-20 21:55:49 +0000 | |||
283 | +++ ubuntuone/controlpanel/gtk/gui.py 2011-01-03 14:24:42 +0000 | |||
284 | @@ -46,12 +46,13 @@ | |||
285 | 46 | from ubuntuone.controlpanel.gtk.widgets import GreyableBin | 46 | from ubuntuone.controlpanel.gtk.widgets import GreyableBin |
286 | 47 | 47 | ||
287 | 48 | from ubuntuone.controlpanel import (DBUS_BUS_NAME, DBUS_PREFERENCES_PATH, | 48 | from ubuntuone.controlpanel import (DBUS_BUS_NAME, DBUS_PREFERENCES_PATH, |
289 | 49 | DBUS_PREFERENCES_IFACE) | 49 | DBUS_PREFERENCES_IFACE, backend) |
290 | 50 | from ubuntuone.controlpanel.backend import (DEVICE_TYPE_PHONE, | 50 | from ubuntuone.controlpanel.backend import (DEVICE_TYPE_PHONE, |
291 | 51 | DEVICE_TYPE_COMPUTER, bool_str) | 51 | DEVICE_TYPE_COMPUTER, bool_str) |
292 | 52 | from ubuntuone.controlpanel.logger import setup_logging, log_call | 52 | from ubuntuone.controlpanel.logger import setup_logging, log_call |
293 | 53 | from ubuntuone.controlpanel.utils import get_data_file | 53 | from ubuntuone.controlpanel.utils import get_data_file |
294 | 54 | 54 | ||
295 | 55 | from ubuntuone.controlpanel.gtk import package_manager | ||
296 | 55 | 56 | ||
297 | 56 | logger = setup_logging('gtk.gui') | 57 | logger = setup_logging('gtk.gui') |
298 | 57 | _ = gettext.gettext | 58 | _ = gettext.gettext |
299 | @@ -149,7 +150,7 @@ | |||
300 | 149 | class ControlPanelWindow(gtk.Window): | 150 | class ControlPanelWindow(gtk.Window): |
301 | 150 | """The main window for the Ubuntu One control panel.""" | 151 | """The main window for the Ubuntu One control panel.""" |
302 | 151 | 152 | ||
304 | 152 | TITLE = _('My %(app_name)s Account') | 153 | TITLE = _('My %(app_name)s Dashboard') |
305 | 153 | 154 | ||
306 | 154 | def __init__(self): | 155 | def __init__(self): |
307 | 155 | super(ControlPanelWindow, self).__init__() | 156 | super(ControlPanelWindow, self).__init__() |
308 | @@ -410,8 +411,8 @@ | |||
309 | 410 | self.sso_backend.find_credentials(U1_APP_NAME, {}) | 411 | self.sso_backend.find_credentials(U1_APP_NAME, {}) |
310 | 411 | 412 | ||
311 | 412 | 413 | ||
314 | 413 | class AccountPanel(UbuntuOneBin, ControlPanelMixin): | 414 | class DashboardPanel(UbuntuOneBin, ControlPanelMixin): |
315 | 414 | """The account panel. The user can manage the subscription.""" | 415 | """The dashboard panel. The user can manage the subscription.""" |
316 | 415 | 416 | ||
317 | 416 | TITLE = _('Welcome to Ubuntu One!') | 417 | TITLE = _('Welcome to Ubuntu One!') |
318 | 417 | NAME = _('Name') | 418 | NAME = _('Name') |
319 | @@ -420,7 +421,7 @@ | |||
320 | 420 | 421 | ||
321 | 421 | def __init__(self): | 422 | def __init__(self): |
322 | 422 | UbuntuOneBin.__init__(self) | 423 | UbuntuOneBin.__init__(self) |
324 | 423 | ControlPanelMixin.__init__(self, filename='account.ui') | 424 | ControlPanelMixin.__init__(self, filename='dashboard.ui') |
325 | 424 | self.add(self.itself) | 425 | self.add(self.itself) |
326 | 425 | self.show() | 426 | self.show() |
327 | 426 | 427 | ||
328 | @@ -750,26 +751,276 @@ | |||
329 | 750 | self.message.start() | 751 | self.message.start() |
330 | 751 | 752 | ||
331 | 752 | 753 | ||
334 | 753 | class ApplicationsPanel(UbuntuOneBin, ControlPanelMixin): | 754 | class InstallPackage(gtk.VBox, ControlPanelMixin): |
335 | 754 | """The applications panel.""" | 755 | """A widget to process the install of a package.""" |
336 | 756 | |||
337 | 757 | INSTALL_PACKAGE = _('You need to install the package <i>%(package_name)s' | ||
338 | 758 | '</i> in order to enable replication.') | ||
339 | 759 | INSTALLING = _('The package <i>%(package_name)s</i> is being installed, ' | ||
340 | 760 | 'please wait...') | ||
341 | 761 | FAILED_INSTALL = _('The installation of <i>%(package_name)s</i> failed.') | ||
342 | 762 | SUCCESS_INSTALL = _('The installation of <i>%(package_name)s</i> ' | ||
343 | 763 | 'was successful.') | ||
344 | 764 | |||
345 | 765 | def __init__(self, package_name): | ||
346 | 766 | gtk.VBox.__init__(self) | ||
347 | 767 | ControlPanelMixin.__init__(self, filename='install.ui') | ||
348 | 768 | self.add(self.itself) | ||
349 | 769 | |||
350 | 770 | self.package_name = package_name | ||
351 | 771 | self.package_manager = package_manager.PackageManager() | ||
352 | 772 | self.args = {'package_name': self.package_name} | ||
353 | 773 | self.transaction = None | ||
354 | 774 | |||
355 | 775 | self.progress_bar = None | ||
356 | 776 | self.install_label.set_markup(self.INSTALL_PACKAGE % self.args) | ||
357 | 777 | |||
358 | 778 | self.show() | ||
359 | 779 | |||
360 | 780 | @package_manager.inline_callbacks | ||
361 | 781 | def on_install_button_clicked(self, button): | ||
362 | 782 | """The install button was clicked.""" | ||
363 | 783 | try: | ||
364 | 784 | # create the install transaction | ||
365 | 785 | self.transaction = yield self.package_manager.install( | ||
366 | 786 | self.package_name) | ||
367 | 787 | |||
368 | 788 | # create the progress bar and pack it to the box | ||
369 | 789 | self.progress_bar = package_manager.PackageManagerProgressBar( | ||
370 | 790 | self.transaction) | ||
371 | 791 | self.progress_bar.show() | ||
372 | 792 | |||
373 | 793 | self.itself.remove(self.install_button_box) | ||
374 | 794 | self.itself.pack_start(self.progress_bar) | ||
375 | 795 | |||
376 | 796 | self.transaction.connect('finished', self.on_install_finished) | ||
377 | 797 | self.install_label.set_markup(self.INSTALLING % self.args) | ||
378 | 798 | yield self.transaction.run() | ||
379 | 799 | except: # pylint: disable=W0702 | ||
380 | 800 | self._set_warning(self.FAILED_INSTALL % self.args, | ||
381 | 801 | self.install_label) | ||
382 | 802 | |||
383 | 803 | @log_call(logger.info) | ||
384 | 804 | def on_install_finished(self, transaction, exit_code): | ||
385 | 805 | """The installation finished.""" | ||
386 | 806 | self.progress_bar.set_sensitive(False) | ||
387 | 807 | |||
388 | 808 | if exit_code != package_manager.aptdaemon.enums.EXIT_SUCCESS: | ||
389 | 809 | if hasattr(transaction, 'error'): | ||
390 | 810 | logger.error('transaction failed: %r', transaction.error) | ||
391 | 811 | self._set_warning(self.FAILED_INSTALL % self.args, | ||
392 | 812 | self.install_label) | ||
393 | 813 | else: | ||
394 | 814 | self.install_label.set_markup(self.SUCCESS_INSTALL % self.args) | ||
395 | 815 | self.emit('finished') | ||
396 | 816 | |||
397 | 817 | |||
398 | 818 | class Service(gtk.VBox, ControlPanelMixin): | ||
399 | 819 | """A service.""" | ||
400 | 820 | |||
401 | 821 | def __init__(self, name, localized_name, *args, **kwargs): | ||
402 | 822 | gtk.VBox.__init__(self) | ||
403 | 823 | ControlPanelMixin.__init__(self) | ||
404 | 824 | self.service_name = name | ||
405 | 825 | |||
406 | 826 | self.button = gtk.CheckButton(label=localized_name) | ||
407 | 827 | self.pack_start(self.button, expand=False) | ||
408 | 828 | |||
409 | 829 | self.show_all() | ||
410 | 830 | |||
411 | 831 | |||
412 | 832 | class FilesService(Service): | ||
413 | 833 | """The file sync service.""" | ||
414 | 834 | |||
415 | 835 | FILES_SERVICE_NAME = _('Files') | ||
416 | 836 | |||
417 | 837 | def __init__(self): | ||
418 | 838 | Service.__init__(self, name='files', | ||
419 | 839 | localized_name=self.FILES_SERVICE_NAME) | ||
420 | 840 | |||
421 | 841 | self.set_sensitive(False) | ||
422 | 842 | self.backend.connect_to_signal('FileSyncStatusChanged', | ||
423 | 843 | self.on_file_sync_status_changed) | ||
424 | 844 | self.backend.connect_to_signal('FilesEnabled', self.on_files_enabled) | ||
425 | 845 | self.backend.connect_to_signal('FilesDisabled', self.on_files_disabled) | ||
426 | 846 | self.backend.file_sync_status() | ||
427 | 847 | |||
428 | 848 | @log_call(logger.debug) | ||
429 | 849 | def on_file_sync_status_changed(self, status): | ||
430 | 850 | """File sync status changed.""" | ||
431 | 851 | enabled = status != backend.FILE_SYNC_DISABLED | ||
432 | 852 | self.button.set_active(enabled) | ||
433 | 853 | |||
434 | 854 | if not self.is_sensitive(): | ||
435 | 855 | # first time we're getting this event | ||
436 | 856 | self.button.connect('toggled', self.on_button_toggled) | ||
437 | 857 | self.set_sensitive(True) | ||
438 | 858 | |||
439 | 859 | def on_files_enabled(self): | ||
440 | 860 | """Files service was enabled.""" | ||
441 | 861 | self.on_file_sync_status_changed('enabled!') | ||
442 | 862 | |||
443 | 863 | def on_files_disabled(self): | ||
444 | 864 | """Files service was disabled.""" | ||
445 | 865 | self.on_file_sync_status_changed(backend.FILE_SYNC_DISABLED) | ||
446 | 866 | |||
447 | 867 | @log_call(logger.debug) | ||
448 | 868 | def on_button_toggled(self, button): | ||
449 | 869 | """Button was toggled, exclude/replicate the service properly.""" | ||
450 | 870 | logger.info('File sync enabled? %r', self.button.get_active()) | ||
451 | 871 | if self.button.get_active(): | ||
452 | 872 | self.backend.enable_files() | ||
453 | 873 | else: | ||
454 | 874 | self.backend.disable_files() | ||
455 | 875 | |||
456 | 876 | |||
457 | 877 | class DesktopcouchService(Service): | ||
458 | 878 | """A desktopcouch service.""" | ||
459 | 879 | |||
460 | 880 | def __init__(self, name, localized_name, | ||
461 | 881 | replication_service, dependency=None): | ||
462 | 882 | Service.__init__(self, name, localized_name) | ||
463 | 883 | self.replication_service = replication_service | ||
464 | 884 | enabled = name not in self.replication_service.all_exclusions() | ||
465 | 885 | self.button.set_active(enabled) | ||
466 | 886 | |||
467 | 887 | self.dependency = None | ||
468 | 888 | if dependency is not None: | ||
469 | 889 | self.dependency = InstallPackage(dependency) | ||
470 | 890 | self.dependency.connect('finished', self.on_depedency_finished) | ||
471 | 891 | self.pack_start(self.dependency, expand=False) | ||
472 | 892 | self.button.set_sensitive(False) | ||
473 | 893 | |||
474 | 894 | self.button.connect('toggled', self.on_button_toggled) | ||
475 | 895 | |||
476 | 896 | def on_depedency_finished(self, widget): | ||
477 | 897 | """The dependency was installed.""" | ||
478 | 898 | self.button.set_sensitive(True) | ||
479 | 899 | self.remove(self.dependency) | ||
480 | 900 | self.dependency = None | ||
481 | 901 | |||
482 | 902 | @log_call(logger.debug) | ||
483 | 903 | def on_button_toggled(self, button): | ||
484 | 904 | """Button was toggled, exclude/replicate the service properly.""" | ||
485 | 905 | logger.info('Starting replication for %r? %r', | ||
486 | 906 | self.service_name, self.button.get_active()) | ||
487 | 907 | if self.button.get_active(): | ||
488 | 908 | self.replication_service.replicate(self.service_name) | ||
489 | 909 | else: | ||
490 | 910 | self.replication_service.exclude(self.service_name) | ||
491 | 911 | |||
492 | 912 | |||
493 | 913 | class ServicesPanel(UbuntuOneBin, ControlPanelMixin): | ||
494 | 914 | """The services panel.""" | ||
495 | 755 | 915 | ||
496 | 756 | TITLE = _('Ubuntu One services including data sync are enabled for the ' | 916 | TITLE = _('Ubuntu One services including data sync are enabled for the ' |
498 | 757 | 'data types and applications listed below:') | 917 | 'data types and services listed below.') |
499 | 918 | CHOOSE_SERVICES = _('Choose services to synchronize with this computer:') | ||
500 | 919 | DESKTOPCOUCH_PKG = 'desktopcouch' | ||
501 | 920 | BINDWOOD_PKG = 'xul-ext-bindwood' | ||
502 | 921 | EVOCOUCH_PKG = 'evolution-couchdb' | ||
503 | 922 | BOOKMARKS = _('Bookmarks (Firefox)') | ||
504 | 923 | CONTACTS = _('Contacts (Evolution)') | ||
505 | 924 | NO_PAIRING_RECORD = _('There is no Ubuntu One pairing record.') | ||
506 | 758 | 925 | ||
508 | 759 | def __init__(self): | 926 | def __init__(self, replication_exclusion_class=None): |
509 | 760 | UbuntuOneBin.__init__(self) | 927 | UbuntuOneBin.__init__(self) |
511 | 761 | ControlPanelMixin.__init__(self, filename='applications.ui') | 928 | ControlPanelMixin.__init__(self, filename='services.ui') |
512 | 762 | self.add(self.itself) | 929 | self.add(self.itself) |
513 | 930 | |||
514 | 931 | self.replication_exclusion_class = replication_exclusion_class | ||
515 | 932 | self.replication_service = None | ||
516 | 933 | self.has_desktopcouch = False | ||
517 | 934 | self.has_bindwood = False | ||
518 | 935 | self.has_evocouch = False | ||
519 | 936 | self.package_manager = package_manager.PackageManager() | ||
520 | 937 | self.install_box = None | ||
521 | 938 | self.bookmarks = None | ||
522 | 939 | self.contacts = None | ||
523 | 940 | |||
524 | 941 | self.files.pack_start(FilesService(), expand=False) | ||
525 | 942 | |||
526 | 763 | self.show() | 943 | self.show() |
527 | 764 | 944 | ||
528 | 945 | @log_call(logger.debug) | ||
529 | 946 | def load(self): | ||
530 | 947 | """Load info.""" | ||
531 | 948 | if self.install_box is not None: | ||
532 | 949 | self.itself.remove(self.install_box) | ||
533 | 950 | self.install_box = None | ||
534 | 951 | |||
535 | 952 | self.has_desktopcouch = \ | ||
536 | 953 | self.package_manager.is_installed(self.DESKTOPCOUCH_PKG) | ||
537 | 954 | self.has_bindwood = \ | ||
538 | 955 | self.package_manager.is_installed(self.BINDWOOD_PKG) | ||
539 | 956 | self.has_evocouch = \ | ||
540 | 957 | self.package_manager.is_installed(self.EVOCOUCH_PKG) | ||
541 | 958 | |||
542 | 959 | logger.info('load: has_desktopcouch? %r has_bindwood? %s ' | ||
543 | 960 | 'has_evocouch? %s', self.has_desktopcouch, | ||
544 | 961 | self.has_bindwood, self.has_evocouch) | ||
545 | 962 | if not self.has_desktopcouch: | ||
546 | 963 | self.message.set_text('') | ||
547 | 964 | self.replications.hide() | ||
548 | 965 | |||
549 | 966 | self.install_box = InstallPackage(self.DESKTOPCOUCH_PKG) | ||
550 | 967 | self.install_box.connect('finished', self.load_replications) | ||
551 | 968 | self.itself.pack_start(self.install_box, expand=False) | ||
552 | 969 | self.itself.reorder_child(self.install_box, 0) | ||
553 | 970 | else: | ||
554 | 971 | self.load_replications() | ||
555 | 972 | |||
556 | 765 | self.message.stop() | 973 | self.message.stop() |
558 | 766 | self.message.set_text('Under construction') | 974 | |
559 | 975 | @log_call(logger.debug) | ||
560 | 976 | def load_replications(self, *args): | ||
561 | 977 | """Load replications info.""" | ||
562 | 978 | self.replications.show() | ||
563 | 979 | |||
564 | 980 | if self.install_box is not None: | ||
565 | 981 | self.itself.remove(self.install_box) | ||
566 | 982 | self.install_box = None | ||
567 | 983 | |||
568 | 984 | self.message.set_text(self.CHOOSE_SERVICES) | ||
569 | 985 | for child in self.replications.get_children(): | ||
570 | 986 | self.replications.remove(child) | ||
571 | 987 | |||
572 | 988 | # Unable to import 'desktopcouch.application.replication_services' | ||
573 | 989 | # pylint: disable=F0401 | ||
574 | 990 | if self.replication_exclusion_class is None: | ||
575 | 991 | from desktopcouch.application.replication_services import \ | ||
576 | 992 | ubuntuone as u1rep | ||
577 | 993 | self.replication_exclusion_class = u1rep.ReplicationExclusion | ||
578 | 994 | |||
579 | 995 | if self.replication_service is None: | ||
580 | 996 | try: | ||
581 | 997 | self.replication_service = self.replication_exclusion_class() | ||
582 | 998 | except ValueError: | ||
583 | 999 | logger.exception('Can not load replications:') | ||
584 | 1000 | self._set_warning(self.NO_PAIRING_RECORD, self.message) | ||
585 | 1001 | return | ||
586 | 1002 | |||
587 | 1003 | pkg = None | ||
588 | 1004 | if not self.has_bindwood: | ||
589 | 1005 | pkg = self.BINDWOOD_PKG | ||
590 | 1006 | self.bookmarks = DesktopcouchService('bookmarks', self.BOOKMARKS, | ||
591 | 1007 | self.replication_service, | ||
592 | 1008 | dependency=pkg) | ||
593 | 1009 | self.replications.pack_start(self.bookmarks, expand=False) | ||
594 | 1010 | |||
595 | 1011 | pkg = None | ||
596 | 1012 | if not self.has_evocouch: | ||
597 | 1013 | pkg = self.EVOCOUCH_PKG | ||
598 | 1014 | self.contacts = DesktopcouchService('contacts', self.CONTACTS, | ||
599 | 1015 | self.replication_service, | ||
600 | 1016 | dependency=pkg) | ||
601 | 1017 | self.replications.pack_start(self.contacts, expand=False) | ||
602 | 767 | 1018 | ||
603 | 768 | 1019 | ||
604 | 769 | class ManagementPanel(gtk.VBox, ControlPanelMixin): | 1020 | class ManagementPanel(gtk.VBox, ControlPanelMixin): |
605 | 770 | """The management panel. | 1021 | """The management panel. |
606 | 771 | 1022 | ||
608 | 772 | The user can manage account, folders, devices and applications. | 1023 | The user can manage dashboard, folders, devices and services. |
609 | 773 | 1024 | ||
610 | 774 | """ | 1025 | """ |
611 | 775 | 1026 | ||
612 | @@ -817,13 +1068,13 @@ | |||
613 | 817 | self.status_label = LabelLoading(LOADING, fg_color=DEFAULT_FG) | 1068 | self.status_label = LabelLoading(LOADING, fg_color=DEFAULT_FG) |
614 | 818 | self.status_box.pack_end(self.status_label, expand=False) | 1069 | self.status_box.pack_end(self.status_label, expand=False) |
615 | 819 | 1070 | ||
617 | 820 | self.account = AccountPanel() | 1071 | self.dashboard = DashboardPanel() |
618 | 821 | self.folders = FoldersPanel() | 1072 | self.folders = FoldersPanel() |
619 | 822 | self.devices = DevicesPanel() | 1073 | self.devices = DevicesPanel() |
621 | 823 | self.applications = ApplicationsPanel() | 1074 | self.services = ServicesPanel() |
622 | 824 | 1075 | ||
623 | 825 | cb = lambda button, page_num: self.notebook.set_current_page(page_num) | 1076 | cb = lambda button, page_num: self.notebook.set_current_page(page_num) |
625 | 826 | self.tabs = (u'account', u'folders', u'devices', u'applications') | 1077 | self.tabs = (u'dashboard', u'folders', u'devices', u'services') |
626 | 827 | for page_num, tab in enumerate(self.tabs): | 1078 | for page_num, tab in enumerate(self.tabs): |
627 | 828 | setattr(self, ('%s_page' % tab).upper(), page_num) | 1079 | setattr(self, ('%s_page' % tab).upper(), page_num) |
628 | 829 | button = getattr(self, '%s_button' % tab) | 1080 | button = getattr(self, '%s_button' % tab) |
629 | @@ -835,6 +1086,7 @@ | |||
630 | 835 | 1086 | ||
631 | 836 | self.folders_button.connect('clicked', lambda b: self.folders.load()) | 1087 | self.folders_button.connect('clicked', lambda b: self.folders.load()) |
632 | 837 | self.devices_button.connect('clicked', lambda b: self.devices.load()) | 1088 | self.devices_button.connect('clicked', lambda b: self.devices.load()) |
633 | 1089 | self.services_button.connect('clicked', lambda b: self.services.load()) | ||
634 | 838 | self.devices.connect('local-device-removed', | 1090 | self.devices.connect('local-device-removed', |
635 | 839 | lambda widget: self.emit('local-device-removed')) | 1091 | lambda widget: self.emit('local-device-removed')) |
636 | 840 | 1092 | ||
637 | @@ -857,7 +1109,7 @@ | |||
638 | 857 | """Load the account info and file sync status list.""" | 1109 | """Load the account info and file sync status list.""" |
639 | 858 | self.backend.account_info() | 1110 | self.backend.account_info() |
640 | 859 | self.backend.file_sync_status() | 1111 | self.backend.file_sync_status() |
642 | 860 | self.account_button.clicked() | 1112 | self.dashboard_button.clicked() |
643 | 861 | 1113 | ||
644 | 862 | @log_call(logger.debug) | 1114 | @log_call(logger.debug) |
645 | 863 | def on_account_info_ready(self, info): | 1115 | def on_account_info_ready(self, info): |
646 | @@ -910,3 +1162,6 @@ | |||
647 | 910 | 1162 | ||
648 | 911 | gobject.signal_new('local-device-removed', DevicesPanel, | 1163 | gobject.signal_new('local-device-removed', DevicesPanel, |
649 | 912 | gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()) | 1164 | gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()) |
650 | 1165 | |||
651 | 1166 | gobject.signal_new('finished', InstallPackage, | ||
652 | 1167 | gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()) | ||
653 | 913 | 1168 | ||
654 | === added file 'ubuntuone/controlpanel/gtk/package_manager.py' | |||
655 | --- ubuntuone/controlpanel/gtk/package_manager.py 1970-01-01 00:00:00 +0000 | |||
656 | +++ ubuntuone/controlpanel/gtk/package_manager.py 2011-01-03 14:24:42 +0000 | |||
657 | @@ -0,0 +1,60 @@ | |||
658 | 1 | # -*- coding: utf-8 -*- | ||
659 | 2 | |||
660 | 3 | # Authors: Natalia B. Bidart <nataliabidart@canonical.com> | ||
661 | 4 | # | ||
662 | 5 | # Copyright 2010 Canonical Ltd. | ||
663 | 6 | # | ||
664 | 7 | # This program is free software: you can redistribute it and/or modify it | ||
665 | 8 | # under the terms of the GNU General Public License version 3, as published | ||
666 | 9 | # by the Free Software Foundation. | ||
667 | 10 | # | ||
668 | 11 | # This program is distributed in the hope that it will be useful, but | ||
669 | 12 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
670 | 13 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
671 | 14 | # PURPOSE. See the GNU General Public License for more details. | ||
672 | 15 | # | ||
673 | 16 | # You should have received a copy of the GNU General Public License along | ||
674 | 17 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
675 | 18 | |||
676 | 19 | """Client to manage packages.""" | ||
677 | 20 | |||
678 | 21 | import apt | ||
679 | 22 | import aptdaemon.client | ||
680 | 23 | import aptdaemon.enums | ||
681 | 24 | |||
682 | 25 | try: | ||
683 | 26 | # Unable to import 'defer', pylint: disable=F0401,E0611 | ||
684 | 27 | from aptdaemon.defer import inline_callbacks, return_value | ||
685 | 28 | except ImportError: | ||
686 | 29 | # Unable to import 'defer', pylint: disable=F0401,E0611 | ||
687 | 30 | from defer import inline_callbacks, return_value | ||
688 | 31 | from aptdaemon.gtkwidgets import AptProgressBar | ||
689 | 32 | |||
690 | 33 | from ubuntuone.controlpanel.logger import setup_logging | ||
691 | 34 | |||
692 | 35 | |||
693 | 36 | logger = setup_logging('package_manager') | ||
694 | 37 | |||
695 | 38 | |||
696 | 39 | class PackageManagerProgressBar(AptProgressBar): | ||
697 | 40 | """A progress bar for a transaction.""" | ||
698 | 41 | |||
699 | 42 | |||
700 | 43 | class PackageManager(object): | ||
701 | 44 | """Manage packages (check if is installed, install).""" | ||
702 | 45 | |||
703 | 46 | def is_installed(self, package_name): | ||
704 | 47 | """Return whether 'package_name' is installed in this system.""" | ||
705 | 48 | cache = apt.Cache() | ||
706 | 49 | result = package_name in cache and cache[package_name].is_installed | ||
707 | 50 | return result | ||
708 | 51 | |||
709 | 52 | @inline_callbacks | ||
710 | 53 | def install(self, package_name): | ||
711 | 54 | """Install 'package_name' if is not installed in this system.""" | ||
712 | 55 | if self.is_installed(package_name): | ||
713 | 56 | return_value(aptdaemon.enums.EXIT_SUCCESS) | ||
714 | 57 | |||
715 | 58 | client = aptdaemon.client.AptClient() | ||
716 | 59 | transaction = yield client.install_packages([package_name]) | ||
717 | 60 | return_value(transaction) | ||
718 | 0 | 61 | ||
719 | === modified file 'ubuntuone/controlpanel/gtk/tests/__init__.py' | |||
720 | --- ubuntuone/controlpanel/gtk/tests/__init__.py 2010-12-02 16:23:03 +0000 | |||
721 | +++ ubuntuone/controlpanel/gtk/tests/__init__.py 2011-01-03 14:24:42 +0000 | |||
722 | @@ -17,3 +17,153 @@ | |||
723 | 17 | # with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
724 | 18 | 18 | ||
725 | 19 | """The test suite for the GTK UI for the control panel for Ubuntu One.""" | 19 | """The test suite for the GTK UI for the control panel for Ubuntu One.""" |
726 | 20 | |||
727 | 21 | from collections import defaultdict | ||
728 | 22 | |||
729 | 23 | from ubuntuone.controlpanel.gtk import gui | ||
730 | 24 | from ubuntuone.controlpanel.gtk.tests.test_package_manager import ( | ||
731 | 25 | FakedTransaction) | ||
732 | 26 | |||
733 | 27 | |||
734 | 28 | FAKE_ACCOUNT_INFO = {'type': 'Payed', 'name': 'Test me', | ||
735 | 29 | 'email': 'test.com', 'quota_total': '12345', 'quota_used': '9999'} | ||
736 | 30 | |||
737 | 31 | FAKE_VOLUMES_INFO = [ | ||
738 | 32 | {'volume_id': '0', 'suggested_path': '~/foo', 'subscribed': ''}, | ||
739 | 33 | {'volume_id': '1', 'suggested_path': '~/bar', 'subscribed': 'True'}, | ||
740 | 34 | {'volume_id': '2', 'suggested_path': '~/baz', 'subscribed': 'True'}, | ||
741 | 35 | ] | ||
742 | 36 | |||
743 | 37 | FAKE_DEVICE_INFO = { | ||
744 | 38 | 'device_id': '1258-6854', 'device_name': 'Baz', 'device_type': 'Computer', | ||
745 | 39 | 'is_local': 'True', 'configurable': 'True', 'limit_bandwidth': 'True', | ||
746 | 40 | 'max_upload_speed': '1000', 'max_download_speed': '72548', | ||
747 | 41 | } | ||
748 | 42 | |||
749 | 43 | FAKE_DEVICES_INFO = [ | ||
750 | 44 | {'device_id': '0', 'name': 'Foo', 'type': 'Computer', | ||
751 | 45 | 'is_local': '', 'configurable': ''}, | ||
752 | 46 | {'device_id': '1', 'name': 'Bar', 'type': 'Phone', | ||
753 | 47 | 'is_local': '', 'configurable': ''}, | ||
754 | 48 | {'device_id': '2', 'name': 'Z', 'type': 'Computer', | ||
755 | 49 | 'is_local': '', 'configurable': 'True', 'limit_bandwidth': '', | ||
756 | 50 | 'max_upload_speed': '0', 'max_download_speed': '0'}, | ||
757 | 51 | {'device_id': '1258-6854', 'name': 'Baz', 'type': 'Computer', | ||
758 | 52 | 'is_local': 'True', 'configurable': 'True', 'limit_bandwidth': 'True', | ||
759 | 53 | 'max_upload_speed': '1000', 'max_download_speed': '72548'}, # local | ||
760 | 54 | ] | ||
761 | 55 | |||
762 | 56 | |||
763 | 57 | class FakedObject(object): | ||
764 | 58 | """Fake an object, record every call.""" | ||
765 | 59 | |||
766 | 60 | exposed_methods = [] | ||
767 | 61 | |||
768 | 62 | def __init__(self, *args, **kwargs): | ||
769 | 63 | self._args = args | ||
770 | 64 | self._kwargs = kwargs | ||
771 | 65 | self._called = {} | ||
772 | 66 | for i in self.exposed_methods: | ||
773 | 67 | setattr(self, i, self._record_call(i)) | ||
774 | 68 | |||
775 | 69 | def _record_call(self, func_name): | ||
776 | 70 | """Store values when calling 'func_name'.""" | ||
777 | 71 | |||
778 | 72 | def inner(*args, **kwargs): | ||
779 | 73 | """Fake 'func_name'.""" | ||
780 | 74 | self._called[func_name] = (args, kwargs) | ||
781 | 75 | |||
782 | 76 | return inner | ||
783 | 77 | |||
784 | 78 | |||
785 | 79 | class FakedNMState(FakedObject): | ||
786 | 80 | """Fake a NetworkManagerState.""" | ||
787 | 81 | |||
788 | 82 | exposed_methods = ['find_online_state'] | ||
789 | 83 | |||
790 | 84 | |||
791 | 85 | class FakedDBusBackend(FakedObject): | ||
792 | 86 | """Fake a DBus Backend.""" | ||
793 | 87 | |||
794 | 88 | bus_name = None | ||
795 | 89 | object_path = None | ||
796 | 90 | iface = None | ||
797 | 91 | |||
798 | 92 | def __init__(self, obj, dbus_interface, *args, **kwargs): | ||
799 | 93 | if dbus_interface != self.iface: | ||
800 | 94 | raise TypeError() | ||
801 | 95 | self._signals = defaultdict(list) | ||
802 | 96 | super(FakedDBusBackend, self).__init__(*args, **kwargs) | ||
803 | 97 | |||
804 | 98 | def connect_to_signal(self, signal, handler): | ||
805 | 99 | """Bind 'handler' to be callback'd when 'signal' is fired.""" | ||
806 | 100 | self._signals[signal].append(handler) | ||
807 | 101 | |||
808 | 102 | |||
809 | 103 | class FakedSSOBackend(FakedDBusBackend): | ||
810 | 104 | """Fake a SSO Backend, act as a dbus.Interface.""" | ||
811 | 105 | |||
812 | 106 | bus_name = gui.ubuntu_sso.DBUS_BUS_NAME | ||
813 | 107 | object_path = gui.ubuntu_sso.DBUS_CREDENTIALS_PATH | ||
814 | 108 | iface = gui.ubuntu_sso.DBUS_CREDENTIALS_IFACE | ||
815 | 109 | exposed_methods = ['find_credentials', 'clear_credentials', | ||
816 | 110 | 'login', 'register'] | ||
817 | 111 | |||
818 | 112 | |||
819 | 113 | class FakedControlPanelBackend(FakedDBusBackend): | ||
820 | 114 | """Fake a Control Panel Backend, act as a dbus.Interface.""" | ||
821 | 115 | |||
822 | 116 | bus_name = gui.DBUS_BUS_NAME | ||
823 | 117 | object_path = gui.DBUS_PREFERENCES_PATH | ||
824 | 118 | iface = gui.DBUS_PREFERENCES_IFACE | ||
825 | 119 | exposed_methods = [ | ||
826 | 120 | 'account_info', 'devices_info', 'change_device_settings', | ||
827 | 121 | 'volumes_info', 'change_volume_settings', 'file_sync_status', | ||
828 | 122 | 'remove_device', 'enable_files', 'disable_files', | ||
829 | 123 | ] | ||
830 | 124 | |||
831 | 125 | |||
832 | 126 | class FakedSessionBus(object): | ||
833 | 127 | """Fake a session bus.""" | ||
834 | 128 | |||
835 | 129 | def get_object(self, bus_name, object_path, introspect=True, | ||
836 | 130 | follow_name_owner_changes=False, **kwargs): | ||
837 | 131 | """Return a faked proxy for the given remote object.""" | ||
838 | 132 | return None | ||
839 | 133 | |||
840 | 134 | |||
841 | 135 | class FakedInterface(object): | ||
842 | 136 | """Fake a dbus interface.""" | ||
843 | 137 | |||
844 | 138 | def __new__(cls, obj, dbus_interface, *args, **kwargs): | ||
845 | 139 | if dbus_interface == gui.DBUS_PREFERENCES_IFACE: | ||
846 | 140 | return FakedControlPanelBackend(obj, dbus_interface, | ||
847 | 141 | *args, **kwargs) | ||
848 | 142 | if dbus_interface == gui.ubuntu_sso.DBUS_CREDENTIALS_IFACE: | ||
849 | 143 | return FakedSSOBackend(obj, dbus_interface, *args, **kwargs) | ||
850 | 144 | |||
851 | 145 | |||
852 | 146 | class FakedPackageManager(object): | ||
853 | 147 | """Faked a package manager.""" | ||
854 | 148 | |||
855 | 149 | def __init__(self): | ||
856 | 150 | self._installed = {} | ||
857 | 151 | self.is_installed = lambda package_name: \ | ||
858 | 152 | self._installed.setdefault(package_name, False) | ||
859 | 153 | |||
860 | 154 | @gui.package_manager.inline_callbacks | ||
861 | 155 | def install(self, package_name): | ||
862 | 156 | """Install 'package_name' if is not installed in this system.""" | ||
863 | 157 | yield | ||
864 | 158 | self._installed[package_name] = True | ||
865 | 159 | gui.package_manager.return_value(FakedTransaction([package_name])) | ||
866 | 160 | |||
867 | 161 | |||
868 | 162 | class FakedReplication(object): | ||
869 | 163 | """Faked a DC replication exclusion.""" | ||
870 | 164 | |||
871 | 165 | def __init__(self): | ||
872 | 166 | self._exclusions = set() | ||
873 | 167 | self.all_exclusions = lambda: self._exclusions | ||
874 | 168 | self.replicate = self._exclusions.remove | ||
875 | 169 | self.exclude = self._exclusions.add | ||
876 | 20 | 170 | ||
877 | === modified file 'ubuntuone/controlpanel/gtk/tests/test_gui.py' | |||
878 | --- ubuntuone/controlpanel/gtk/tests/test_gui.py 2010-12-20 20:58:39 +0000 | |||
879 | +++ ubuntuone/controlpanel/gtk/tests/test_gui.py 2011-01-03 14:24:42 +0000 | |||
880 | @@ -22,136 +22,21 @@ | |||
881 | 22 | 22 | ||
882 | 23 | import logging | 23 | import logging |
883 | 24 | 24 | ||
884 | 25 | from collections import defaultdict | ||
885 | 26 | |||
886 | 27 | from ubuntuone.devtools.handlers import MementoHandler | 25 | from ubuntuone.devtools.handlers import MementoHandler |
887 | 28 | 26 | ||
888 | 29 | from ubuntuone.controlpanel.gtk import gui | 27 | from ubuntuone.controlpanel.gtk import gui |
889 | 28 | from ubuntuone.controlpanel.gtk.tests import (FAKE_ACCOUNT_INFO, | ||
890 | 29 | FAKE_VOLUMES_INFO, FAKE_DEVICE_INFO, FAKE_DEVICES_INFO, | ||
891 | 30 | FakedNMState, FakedSSOBackend, FakedSessionBus, FakedInterface, | ||
892 | 31 | FakedPackageManager, FakedReplication, | ||
893 | 32 | ) | ||
894 | 30 | from ubuntuone.controlpanel.tests import TOKEN, TestCase | 33 | from ubuntuone.controlpanel.tests import TOKEN, TestCase |
1019 | 31 | 34 | from ubuntuone.controlpanel.gtk.tests.test_package_manager import ( | |
1020 | 32 | # Attribute 'yyy' defined outside __init__ | 35 | SUCCESS, FAILURE) |
1021 | 33 | # pylint: disable=W0201 | 36 | |
1022 | 34 | 37 | ||
1023 | 35 | # Access to a protected member 'yyy' of a client class | 38 | # Attribute 'yyy' defined outside __init__, access to a protected member |
1024 | 36 | # pylint: disable=W0212 | 39 | # pylint: disable=W0201, W0212 |
901 | 37 | |||
902 | 38 | |||
903 | 39 | FAKE_ACCOUNT_INFO = {'type': 'Payed', 'name': 'Test me', | ||
904 | 40 | 'email': 'test.com', 'quota_total': '12345', 'quota_used': '9999'} | ||
905 | 41 | |||
906 | 42 | FAKE_VOLUMES_INFO = [ | ||
907 | 43 | {'volume_id': '0', 'suggested_path': '~/foo', 'subscribed': ''}, | ||
908 | 44 | {'volume_id': '1', 'suggested_path': '~/bar', 'subscribed': 'True'}, | ||
909 | 45 | {'volume_id': '2', 'suggested_path': '~/baz', 'subscribed': 'True'}, | ||
910 | 46 | ] | ||
911 | 47 | |||
912 | 48 | FAKE_DEVICE_INFO = { | ||
913 | 49 | 'device_id': '1258-6854', 'device_name': 'Baz', 'device_type': 'Computer', | ||
914 | 50 | 'is_local': 'True', 'configurable': 'True', 'limit_bandwidth': 'True', | ||
915 | 51 | 'max_upload_speed': '1000', 'max_download_speed': '72548', | ||
916 | 52 | } | ||
917 | 53 | |||
918 | 54 | FAKE_DEVICES_INFO = [ | ||
919 | 55 | {'device_id': '0', 'name': 'Foo', 'type': 'Computer', | ||
920 | 56 | 'is_local': '', 'configurable': ''}, | ||
921 | 57 | {'device_id': '1', 'name': 'Bar', 'type': 'Phone', | ||
922 | 58 | 'is_local': '', 'configurable': ''}, | ||
923 | 59 | {'device_id': '2', 'name': 'Z', 'type': 'Computer', | ||
924 | 60 | 'is_local': '', 'configurable': 'True', 'limit_bandwidth': '', | ||
925 | 61 | 'max_upload_speed': '0', 'max_download_speed': '0'}, | ||
926 | 62 | {'device_id': '1258-6854', 'name': 'Baz', 'type': 'Computer', | ||
927 | 63 | 'is_local': 'True', 'configurable': 'True', 'limit_bandwidth': 'True', | ||
928 | 64 | 'max_upload_speed': '1000', 'max_download_speed': '72548'}, # local | ||
929 | 65 | ] | ||
930 | 66 | |||
931 | 67 | |||
932 | 68 | class FakedObject(object): | ||
933 | 69 | """Fake an object, record every call.""" | ||
934 | 70 | |||
935 | 71 | exposed_methods = [] | ||
936 | 72 | |||
937 | 73 | def __init__(self, *args, **kwargs): | ||
938 | 74 | self._args = args | ||
939 | 75 | self._kwargs = kwargs | ||
940 | 76 | self._called = {} | ||
941 | 77 | for i in self.exposed_methods: | ||
942 | 78 | setattr(self, i, self._record_call(i)) | ||
943 | 79 | |||
944 | 80 | def _record_call(self, func_name): | ||
945 | 81 | """Store values when calling 'func_name'.""" | ||
946 | 82 | |||
947 | 83 | def inner(*args, **kwargs): | ||
948 | 84 | """Fake 'func_name'.""" | ||
949 | 85 | self._called[func_name] = (args, kwargs) | ||
950 | 86 | |||
951 | 87 | return inner | ||
952 | 88 | |||
953 | 89 | |||
954 | 90 | class FakedNMState(FakedObject): | ||
955 | 91 | """Fake a NetworkManagerState.""" | ||
956 | 92 | |||
957 | 93 | exposed_methods = ['find_online_state'] | ||
958 | 94 | |||
959 | 95 | |||
960 | 96 | class FakedDBusBackend(FakedObject): | ||
961 | 97 | """Fake a DBus Backend.""" | ||
962 | 98 | |||
963 | 99 | bus_name = None | ||
964 | 100 | object_path = None | ||
965 | 101 | iface = None | ||
966 | 102 | |||
967 | 103 | def __init__(self, obj, dbus_interface, *args, **kwargs): | ||
968 | 104 | if dbus_interface != self.iface: | ||
969 | 105 | raise TypeError() | ||
970 | 106 | self._signals = defaultdict(list) | ||
971 | 107 | super(FakedDBusBackend, self).__init__(*args, **kwargs) | ||
972 | 108 | |||
973 | 109 | def connect_to_signal(self, signal, handler): | ||
974 | 110 | """Bind 'handler' to be callback'd when 'signal' is fired.""" | ||
975 | 111 | self._signals[signal].append(handler) | ||
976 | 112 | |||
977 | 113 | |||
978 | 114 | class FakedSSOBackend(FakedDBusBackend): | ||
979 | 115 | """Fake a SSO Backend, act as a dbus.Interface.""" | ||
980 | 116 | |||
981 | 117 | bus_name = gui.ubuntu_sso.DBUS_BUS_NAME | ||
982 | 118 | object_path = gui.ubuntu_sso.DBUS_CREDENTIALS_PATH | ||
983 | 119 | iface = gui.ubuntu_sso.DBUS_CREDENTIALS_IFACE | ||
984 | 120 | exposed_methods = ['find_credentials', 'clear_credentials', | ||
985 | 121 | 'login', 'register'] | ||
986 | 122 | |||
987 | 123 | |||
988 | 124 | class FakedControlPanelBackend(FakedDBusBackend): | ||
989 | 125 | """Fake a Control Panel Backend, act as a dbus.Interface.""" | ||
990 | 126 | |||
991 | 127 | bus_name = gui.DBUS_BUS_NAME | ||
992 | 128 | object_path = gui.DBUS_PREFERENCES_PATH | ||
993 | 129 | iface = gui.DBUS_PREFERENCES_IFACE | ||
994 | 130 | exposed_methods = [ | ||
995 | 131 | 'account_info', 'devices_info', 'change_device_settings', | ||
996 | 132 | 'volumes_info', 'change_volume_settings', 'file_sync_status', | ||
997 | 133 | 'remove_device', | ||
998 | 134 | ] | ||
999 | 135 | |||
1000 | 136 | |||
1001 | 137 | class FakedSessionBus(object): | ||
1002 | 138 | """Fake a session bus.""" | ||
1003 | 139 | |||
1004 | 140 | def get_object(self, bus_name, object_path, introspect=True, | ||
1005 | 141 | follow_name_owner_changes=False, **kwargs): | ||
1006 | 142 | """Return a faked proxy for the given remote object.""" | ||
1007 | 143 | return None | ||
1008 | 144 | |||
1009 | 145 | |||
1010 | 146 | class FakedInterface(object): | ||
1011 | 147 | """Fake a dbus interface.""" | ||
1012 | 148 | |||
1013 | 149 | def __new__(cls, obj, dbus_interface, *args, **kwargs): | ||
1014 | 150 | if dbus_interface == gui.DBUS_PREFERENCES_IFACE: | ||
1015 | 151 | return FakedControlPanelBackend(obj, dbus_interface, | ||
1016 | 152 | *args, **kwargs) | ||
1017 | 153 | if dbus_interface == gui.ubuntu_sso.DBUS_CREDENTIALS_IFACE: | ||
1018 | 154 | return FakedSSOBackend(obj, dbus_interface, *args, **kwargs) | ||
1025 | 155 | 40 | ||
1026 | 156 | 41 | ||
1027 | 157 | class BaseTestCase(TestCase): | 42 | class BaseTestCase(TestCase): |
1028 | @@ -168,6 +53,7 @@ | |||
1029 | 168 | self.patch(gui.dbus, 'SessionBus', FakedSessionBus) | 53 | self.patch(gui.dbus, 'SessionBus', FakedSessionBus) |
1030 | 169 | self.patch(gui.dbus, 'Interface', FakedInterface) | 54 | self.patch(gui.dbus, 'Interface', FakedInterface) |
1031 | 170 | self.patch(gui.networkstate, 'NetworkManagerState', FakedNMState) | 55 | self.patch(gui.networkstate, 'NetworkManagerState', FakedNMState) |
1032 | 56 | self.patch(gui.package_manager, 'PackageManager', FakedPackageManager) | ||
1033 | 171 | 57 | ||
1034 | 172 | if self.klass is not None: | 58 | if self.klass is not None: |
1035 | 173 | self.ui = self.klass(**self.kwargs) | 59 | self.ui = self.klass(**self.kwargs) |
1036 | @@ -339,10 +225,10 @@ | |||
1037 | 339 | 225 | ||
1038 | 340 | self.assert_current_tab_correct(self.ui.management) | 226 | self.assert_current_tab_correct(self.ui.management) |
1039 | 341 | 227 | ||
1041 | 342 | def test_credentials_found_shows_account_management_panel(self): | 228 | def test_credentials_found_shows_dashboard_management_panel(self): |
1042 | 343 | """On 'credentials-found' signal, the management panel is shown. | 229 | """On 'credentials-found' signal, the management panel is shown. |
1043 | 344 | 230 | ||
1045 | 345 | If first signal parameter is False, visible tab should be account. | 231 | If first signal parameter is False, visible tab should be dashboard. |
1046 | 346 | 232 | ||
1047 | 347 | """ | 233 | """ |
1048 | 348 | self.patch(self.ui.management, 'load', self._set_called) | 234 | self.patch(self.ui.management, 'load', self._set_called) |
1049 | @@ -350,7 +236,7 @@ | |||
1050 | 350 | 236 | ||
1051 | 351 | self.assert_current_tab_correct(self.ui.management) | 237 | self.assert_current_tab_correct(self.ui.management) |
1052 | 352 | self.assertEqual(self.ui.management.notebook.get_current_page(), | 238 | self.assertEqual(self.ui.management.notebook.get_current_page(), |
1054 | 353 | self.ui.management.ACCOUNT_PAGE) | 239 | self.ui.management.DASHBOARD_PAGE) |
1055 | 354 | self.assertEqual(self._called, ((), {})) | 240 | self.assertEqual(self._called, ((), {})) |
1056 | 355 | 241 | ||
1057 | 356 | def test_credentials_found_shows_folders_management_panel(self): | 242 | def test_credentials_found_shows_folders_management_panel(self): |
1058 | @@ -736,11 +622,11 @@ | |||
1059 | 736 | messages = ['<small>Test me</small>', 'A <b>little</b> bit more'] | 622 | messages = ['<small>Test me</small>', 'A <b>little</b> bit more'] |
1060 | 737 | 623 | ||
1061 | 738 | 624 | ||
1064 | 739 | class AccountTestCase(ControlPanelMixinTestCase): | 625 | class DashboardTestCase(ControlPanelMixinTestCase): |
1065 | 740 | """The test suite for the account panel.""" | 626 | """The test suite for the dashboard panel.""" |
1066 | 741 | 627 | ||
1069 | 742 | klass = gui.AccountPanel | 628 | klass = gui.DashboardPanel |
1070 | 743 | ui_filename = 'account.ui' | 629 | ui_filename = 'dashboard.ui' |
1071 | 744 | 630 | ||
1072 | 745 | def assert_account_info_correct(self, info): | 631 | def assert_account_info_correct(self, info): |
1073 | 746 | """Check that the displayed account info matches 'info'.""" | 632 | """Check that the displayed account info matches 'info'.""" |
1074 | @@ -1087,7 +973,8 @@ | |||
1075 | 1087 | 973 | ||
1076 | 1088 | def test_on_limit_bandwidth_toggled(self): | 974 | def test_on_limit_bandwidth_toggled(self): |
1077 | 1089 | """When toggling limit_bandwidth, backend is updated.""" | 975 | """When toggling limit_bandwidth, backend is updated.""" |
1079 | 1090 | self.ui.limit_bandwidth.toggled() | 976 | value = not self.ui.limit_bandwidth.get_active() |
1080 | 977 | self.ui.limit_bandwidth.set_active(value) | ||
1081 | 1091 | self.assert_device_settings_changed() | 978 | self.assert_device_settings_changed() |
1082 | 1092 | 979 | ||
1083 | 1093 | def test_on_max_upload_speed_value_changed(self): | 980 | def test_on_max_upload_speed_value_changed(self): |
1084 | @@ -1365,11 +1252,294 @@ | |||
1085 | 1365 | self.assertEqual(new_devices, old_devices) | 1252 | self.assertEqual(new_devices, old_devices) |
1086 | 1366 | 1253 | ||
1087 | 1367 | 1254 | ||
1093 | 1368 | class ApplicationsTestCase(ControlPanelMixinTestCase): | 1255 | class InstallPackageTestCase(ControlPanelMixinTestCase): |
1094 | 1369 | """The test suite for the applications panel.""" | 1256 | """The test suite for the install widget.""" |
1095 | 1370 | 1257 | ||
1096 | 1371 | klass = gui.ApplicationsPanel | 1258 | klass = gui.InstallPackage |
1097 | 1372 | ui_filename = 'applications.ui' | 1259 | ui_filename = 'install.ui' |
1098 | 1260 | kwargs = {'package_name': 'a test package'} | ||
1099 | 1261 | |||
1100 | 1262 | def test_is_an_box(self): | ||
1101 | 1263 | """Inherits from gtk.VBox.""" | ||
1102 | 1264 | self.assertIsInstance(self.ui, gui.gtk.VBox) | ||
1103 | 1265 | |||
1104 | 1266 | def test_inner_widget_is_packed(self): | ||
1105 | 1267 | """The 'itself' vbox is packed into the widget.""" | ||
1106 | 1268 | self.assertIn(self.ui.itself, self.ui.get_children()) | ||
1107 | 1269 | |||
1108 | 1270 | def test_is_visible(self): | ||
1109 | 1271 | """Is visible.""" | ||
1110 | 1272 | self.assertTrue(self.ui.get_visible()) | ||
1111 | 1273 | |||
1112 | 1274 | def test_package_name(self): | ||
1113 | 1275 | """The package_name is stored.""" | ||
1114 | 1276 | self.assertEqual(self.ui.package_name, self.kwargs['package_name']) | ||
1115 | 1277 | |||
1116 | 1278 | def test_children(self): | ||
1117 | 1279 | """The children is correct.""" | ||
1118 | 1280 | children = self.ui.itself.get_children() | ||
1119 | 1281 | self.assertEqual(len(children), 2) | ||
1120 | 1282 | self.assertEqual(self.ui.install_label, children[0]) | ||
1121 | 1283 | self.assertIn(self.ui.install_button, children[1].get_children()) | ||
1122 | 1284 | |||
1123 | 1285 | def test_install_label(self): | ||
1124 | 1286 | """The install label is correct.""" | ||
1125 | 1287 | msg = self.ui.INSTALL_PACKAGE % self.kwargs | ||
1126 | 1288 | self.assertEqual(self.ui.install_label.get_label(), msg) | ||
1127 | 1289 | |||
1128 | 1290 | @gui.package_manager.inline_callbacks | ||
1129 | 1291 | def test_install_button_clicked_shows_progress(self): | ||
1130 | 1292 | """The install button is correct.""" | ||
1131 | 1293 | yield self.ui.install_button.clicked() | ||
1132 | 1294 | |||
1133 | 1295 | children = self.ui.itself.get_children() | ||
1134 | 1296 | self.assertEqual(len(children), 2) | ||
1135 | 1297 | self.assertEqual(self.ui.progress_bar, children[1]) | ||
1136 | 1298 | self.assertTrue(self.ui.progress_bar.get_visible()) | ||
1137 | 1299 | self.assertIsInstance(self.ui.progress_bar, | ||
1138 | 1300 | gui.package_manager.PackageManagerProgressBar) | ||
1139 | 1301 | |||
1140 | 1302 | def test_install_button_clicked_install_label(self): | ||
1141 | 1303 | """The install label is correct.""" | ||
1142 | 1304 | yield self.ui.install_button.clicked() | ||
1143 | 1305 | |||
1144 | 1306 | children = self.ui.itself.get_children() | ||
1145 | 1307 | self.assertEqual(len(children), 2) | ||
1146 | 1308 | self.assertEqual(self.ui.install_label, children[0]) | ||
1147 | 1309 | msg = self.ui.INSTALLING % self.kwargs | ||
1148 | 1310 | self.assertEqual(self.ui.install_label.get_label(), msg) | ||
1149 | 1311 | |||
1150 | 1312 | @gui.package_manager.inline_callbacks | ||
1151 | 1313 | def test_install_button_clicked_transaction(self): | ||
1152 | 1314 | """The install button transaction is correct.""" | ||
1153 | 1315 | yield self.ui.install_button.clicked() | ||
1154 | 1316 | |||
1155 | 1317 | transaction = self.ui.transaction | ||
1156 | 1318 | self.assertTrue(transaction.packages, [self.ui.package_name]) | ||
1157 | 1319 | self.assertIn(self.ui.on_install_finished, | ||
1158 | 1320 | transaction._signals['finished']) | ||
1159 | 1321 | self.assertTrue(transaction.was_run) | ||
1160 | 1322 | |||
1161 | 1323 | @gui.package_manager.inline_callbacks | ||
1162 | 1324 | def test_install_button_clicked_fails(self): | ||
1163 | 1325 | """The install button transaction is correct.""" | ||
1164 | 1326 | |||
1165 | 1327 | def fail(*args): | ||
1166 | 1328 | """Simulate an error.""" | ||
1167 | 1329 | raise Exception(args) | ||
1168 | 1330 | |||
1169 | 1331 | self.patch(self.ui.package_manager, 'install', fail) | ||
1170 | 1332 | yield self.ui.install_button.clicked() | ||
1171 | 1333 | |||
1172 | 1334 | msg = self.ui.FAILED_INSTALL % self.kwargs | ||
1173 | 1335 | self.assert_warning_correct(self.ui.install_label, msg) | ||
1174 | 1336 | |||
1175 | 1337 | @gui.package_manager.inline_callbacks | ||
1176 | 1338 | def test_on_install_finished_success(self): | ||
1177 | 1339 | """The install finished.""" | ||
1178 | 1340 | self.ui.connect('finished', self._set_called) | ||
1179 | 1341 | yield self.ui.install_button.clicked() | ||
1180 | 1342 | self.ui.on_install_finished(object(), SUCCESS) | ||
1181 | 1343 | |||
1182 | 1344 | self.assertFalse(self.ui.progress_bar.get_sensitive()) | ||
1183 | 1345 | msg = self.ui.SUCCESS_INSTALL % self.kwargs | ||
1184 | 1346 | self.assertEqual(self.ui.install_label.get_label(), msg) | ||
1185 | 1347 | self.assertEqual(self._called, ((self.ui,), {})) | ||
1186 | 1348 | |||
1187 | 1349 | @gui.package_manager.inline_callbacks | ||
1188 | 1350 | def test_on_install_finished_failed(self): | ||
1189 | 1351 | """The install finished.""" | ||
1190 | 1352 | yield self.ui.install_button.clicked() | ||
1191 | 1353 | self.ui.on_install_finished(object(), FAILURE) | ||
1192 | 1354 | |||
1193 | 1355 | self.assertFalse(self.ui.progress_bar.get_sensitive()) | ||
1194 | 1356 | msg = self.ui.FAILED_INSTALL % self.kwargs | ||
1195 | 1357 | self.assert_warning_correct(self.ui.install_label, msg) | ||
1196 | 1358 | |||
1197 | 1359 | |||
1198 | 1360 | class ServiceTestCase(ControlPanelMixinTestCase): | ||
1199 | 1361 | """The test suite for a service.""" | ||
1200 | 1362 | |||
1201 | 1363 | klass = gui.Service | ||
1202 | 1364 | name = 'dc_test' | ||
1203 | 1365 | localized_name = u'Qué lindo test!' | ||
1204 | 1366 | kwargs = {'name': 'dc_test', 'localized_name': u'Qué lindo test!'} | ||
1205 | 1367 | |||
1206 | 1368 | def test_is_an_box(self): | ||
1207 | 1369 | """Inherits from gtk.VBox.""" | ||
1208 | 1370 | self.assertIsInstance(self.ui, gui.gtk.VBox) | ||
1209 | 1371 | |||
1210 | 1372 | def test_is_visible(self): | ||
1211 | 1373 | """Is visible.""" | ||
1212 | 1374 | self.assertTrue(self.ui.get_visible()) | ||
1213 | 1375 | |||
1214 | 1376 | def test_check_button_packed(self): | ||
1215 | 1377 | """A check button is packed as only child.""" | ||
1216 | 1378 | self.assertIn(self.ui.button, self.ui.get_children()) | ||
1217 | 1379 | |||
1218 | 1380 | def test_label(self): | ||
1219 | 1381 | """The label is set.""" | ||
1220 | 1382 | self.assertEqual(self.localized_name, self.ui.button.get_label()) | ||
1221 | 1383 | |||
1222 | 1384 | def test_service_name(self): | ||
1223 | 1385 | """The service_name is set.""" | ||
1224 | 1386 | self.assertEqual(self.name, self.ui.service_name) | ||
1225 | 1387 | |||
1226 | 1388 | |||
1227 | 1389 | class FilesServiceTestCase(ServiceTestCase): | ||
1228 | 1390 | """The test suite for the file sync service.""" | ||
1229 | 1391 | |||
1230 | 1392 | klass = gui.FilesService | ||
1231 | 1393 | kwargs = {} | ||
1232 | 1394 | |||
1233 | 1395 | def setUp(self): | ||
1234 | 1396 | self.name = 'files' | ||
1235 | 1397 | self.localized_name = gui.FilesService.FILES_SERVICE_NAME | ||
1236 | 1398 | super(FilesServiceTestCase, self).setUp() | ||
1237 | 1399 | |||
1238 | 1400 | def test_backend_account_signals(self): | ||
1239 | 1401 | """The proper signals are connected to the backend.""" | ||
1240 | 1402 | self.assertEqual(self.ui.backend._signals['FileSyncStatusChanged'], | ||
1241 | 1403 | [self.ui.on_file_sync_status_changed]) | ||
1242 | 1404 | self.assertEqual(self.ui.backend._signals['FilesEnabled'], | ||
1243 | 1405 | [self.ui.on_files_enabled]) | ||
1244 | 1406 | self.assertEqual(self.ui.backend._signals['FilesDisabled'], | ||
1245 | 1407 | [self.ui.on_files_disabled]) | ||
1246 | 1408 | |||
1247 | 1409 | def test_file_sync_status_is_requested(self): | ||
1248 | 1410 | """The file sync status is requested to the backend.""" | ||
1249 | 1411 | self.assert_backend_called('file_sync_status', ()) | ||
1250 | 1412 | |||
1251 | 1413 | def test_is_disabled(self): | ||
1252 | 1414 | """Until file sync status is given, the widget is disabled.""" | ||
1253 | 1415 | self.assertFalse(self.ui.get_sensitive()) | ||
1254 | 1416 | |||
1255 | 1417 | def test_is_enabled_on_file_sync_status_changed(self): | ||
1256 | 1418 | """When the file sync status is given, the widget is enabled.""" | ||
1257 | 1419 | self.ui.on_file_sync_status_changed('something') | ||
1258 | 1420 | self.assertTrue(self.ui.get_sensitive()) | ||
1259 | 1421 | |||
1260 | 1422 | def test_active(self): | ||
1261 | 1423 | """Is active when file status is anything but 'file-sync-disabled'.""" | ||
1262 | 1424 | self.ui.on_file_sync_status_changed('something not disabled') | ||
1263 | 1425 | self.assertTrue(self.ui.button.get_active()) | ||
1264 | 1426 | |||
1265 | 1427 | def test_not_active(self): | ||
1266 | 1428 | """Is not active when status is exactly but 'file-sync-disabled'.""" | ||
1267 | 1429 | self.ui.on_file_sync_status_changed(gui.backend.FILE_SYNC_DISABLED) | ||
1268 | 1430 | self.assertFalse(self.ui.button.get_active()) | ||
1269 | 1431 | |||
1270 | 1432 | def test_on_button_toggled(self): | ||
1271 | 1433 | """When toggling the button, the file sync service is updated.""" | ||
1272 | 1434 | self.ui.on_file_sync_status_changed('something not disabled') | ||
1273 | 1435 | assert self.ui.button.get_active() | ||
1274 | 1436 | |||
1275 | 1437 | self.ui.button.set_active(not self.ui.button.get_active()) | ||
1276 | 1438 | self.assert_backend_called('disable_files', ()) | ||
1277 | 1439 | |||
1278 | 1440 | self.ui.button.set_active(not self.ui.button.get_active()) | ||
1279 | 1441 | self.assert_backend_called('enable_files', ()) | ||
1280 | 1442 | |||
1281 | 1443 | def test_on_file_sync_enabled(self): | ||
1282 | 1444 | """When file sync is enabled, the button is active.""" | ||
1283 | 1445 | self.ui.on_files_disabled() | ||
1284 | 1446 | assert not self.ui.button.get_active() | ||
1285 | 1447 | |||
1286 | 1448 | self.ui.on_files_enabled() | ||
1287 | 1449 | self.assertTrue(self.ui.button.get_active()) | ||
1288 | 1450 | |||
1289 | 1451 | def test_on_file_sync_disabled(self): | ||
1290 | 1452 | """When file sync is disabled, the button is not active.""" | ||
1291 | 1453 | self.ui.on_files_enabled() | ||
1292 | 1454 | assert self.ui.button.get_active() | ||
1293 | 1455 | |||
1294 | 1456 | self.ui.on_files_disabled() | ||
1295 | 1457 | self.assertFalse(self.ui.button.get_active()) | ||
1296 | 1458 | |||
1297 | 1459 | |||
1298 | 1460 | class DesktopcouchServiceTestCase(ServiceTestCase): | ||
1299 | 1461 | """The test suite for a desktopcouch service.""" | ||
1300 | 1462 | |||
1301 | 1463 | klass = gui.DesktopcouchService | ||
1302 | 1464 | |||
1303 | 1465 | def setUp(self): | ||
1304 | 1466 | self.replication = FakedReplication() | ||
1305 | 1467 | self.name = self.kwargs['name'] | ||
1306 | 1468 | self.kwargs['replication_service'] = self.replication | ||
1307 | 1469 | super(DesktopcouchServiceTestCase, self).setUp() | ||
1308 | 1470 | |||
1309 | 1471 | def test_active(self): | ||
1310 | 1472 | """Is active since replication has an empty database.""" | ||
1311 | 1473 | self.assertTrue(self.ui.button.get_active()) | ||
1312 | 1474 | |||
1313 | 1475 | def test_not_active(self): | ||
1314 | 1476 | """Is not active since 'name' is excluded on replication database.""" | ||
1315 | 1477 | self.replication.exclude(self.name) | ||
1316 | 1478 | self.ui = self.klass(**self.kwargs) | ||
1317 | 1479 | self.assertFalse(self.ui.button.get_active()) | ||
1318 | 1480 | |||
1319 | 1481 | def test_on_button_toggled(self): | ||
1320 | 1482 | """When toggling the button, the DC exclude list is updated.""" | ||
1321 | 1483 | assert self.ui.button.get_active() | ||
1322 | 1484 | self.ui.button.set_active(not self.ui.button.get_active()) | ||
1323 | 1485 | self.assertEqual(set([self.name]), self.replication.all_exclusions()) | ||
1324 | 1486 | |||
1325 | 1487 | def test_on_button_toggled_twice(self): | ||
1326 | 1488 | """When toggling the button twice, the DC exclude list is updated.""" | ||
1327 | 1489 | assert self.ui.button.get_active() | ||
1328 | 1490 | self.ui.button.set_active(not self.ui.button.get_active()) | ||
1329 | 1491 | self.ui.button.set_active(not self.ui.button.get_active()) | ||
1330 | 1492 | self.assertEqual(set(), self.replication.all_exclusions()) | ||
1331 | 1493 | |||
1332 | 1494 | def test_dependency(self): | ||
1333 | 1495 | """The dependency box is None.""" | ||
1334 | 1496 | self.assertTrue(self.ui.dependency is None) | ||
1335 | 1497 | |||
1336 | 1498 | def test_button_sensitiveness(self): | ||
1337 | 1499 | """The check button is sensitive.""" | ||
1338 | 1500 | self.assertTrue(self.ui.button.get_sensitive()) | ||
1339 | 1501 | |||
1340 | 1502 | |||
1341 | 1503 | class DesktopcouchServiceWithDependencyTestCase(DesktopcouchServiceTestCase): | ||
1342 | 1504 | """The test suite for a desktopcouch service when it needs a dependency.""" | ||
1343 | 1505 | |||
1344 | 1506 | def setUp(self): | ||
1345 | 1507 | self.kwargs['dependency'] = 'a package' | ||
1346 | 1508 | super(DesktopcouchServiceWithDependencyTestCase, self).setUp() | ||
1347 | 1509 | |||
1348 | 1510 | def test_dependency(self): | ||
1349 | 1511 | """The dependency bos is not hidden.""" | ||
1350 | 1512 | self.assertIsInstance(self.ui.dependency, gui.InstallPackage) | ||
1351 | 1513 | self.assertEqual(self.ui.dependency.package_name, | ||
1352 | 1514 | self.kwargs['dependency']) | ||
1353 | 1515 | |||
1354 | 1516 | def test_dependency_is_packed(self): | ||
1355 | 1517 | """The dependency is packed in the ui.""" | ||
1356 | 1518 | self.assertIn(self.ui.dependency, self.ui.get_children()) | ||
1357 | 1519 | |||
1358 | 1520 | def test_button_sensitiveness(self): | ||
1359 | 1521 | """The check button is not sensitive until depedency installed.""" | ||
1360 | 1522 | self.assertFalse(self.ui.button.get_sensitive()) | ||
1361 | 1523 | |||
1362 | 1524 | def test_button_is_enabled_on_dependency_installed(self): | ||
1363 | 1525 | """The check button is sensitive when depedency is installed.""" | ||
1364 | 1526 | self.ui.dependency.emit('finished') | ||
1365 | 1527 | |||
1366 | 1528 | self.assertTrue(self.ui.button.get_sensitive()) | ||
1367 | 1529 | |||
1368 | 1530 | def test_install_widget_is_removed_on_dependency_installed(self): | ||
1369 | 1531 | """The install button is removed when depedency is installed.""" | ||
1370 | 1532 | self.ui.dependency.emit('finished') | ||
1371 | 1533 | |||
1372 | 1534 | self.assertTrue(self.ui.dependency is None) | ||
1373 | 1535 | self.assertEqual(self.ui.get_children(), [self.ui.button]) | ||
1374 | 1536 | |||
1375 | 1537 | |||
1376 | 1538 | class ServicesTestCase(ControlPanelMixinTestCase): | ||
1377 | 1539 | """The test suite for the services panel.""" | ||
1378 | 1540 | |||
1379 | 1541 | klass = gui.ServicesPanel | ||
1380 | 1542 | ui_filename = 'services.ui' | ||
1381 | 1373 | 1543 | ||
1382 | 1374 | def test_is_an_ubuntuone_bin(self): | 1544 | def test_is_an_ubuntuone_bin(self): |
1383 | 1375 | """Inherits from UbuntuOneBin.""" | 1545 | """Inherits from UbuntuOneBin.""" |
1384 | @@ -1383,6 +1553,200 @@ | |||
1385 | 1383 | """Is visible.""" | 1553 | """Is visible.""" |
1386 | 1384 | self.assertTrue(self.ui.get_visible()) | 1554 | self.assertTrue(self.ui.get_visible()) |
1387 | 1385 | 1555 | ||
1388 | 1556 | def test_package_manager(self): | ||
1389 | 1557 | """Has a package manager.""" | ||
1390 | 1558 | self.assertIsInstance(self.ui.package_manager, | ||
1391 | 1559 | gui.package_manager.PackageManager) | ||
1392 | 1560 | |||
1393 | 1561 | def test_install_box(self): | ||
1394 | 1562 | """The install box is None.""" | ||
1395 | 1563 | self.assertTrue(self.ui.install_box is None) | ||
1396 | 1564 | |||
1397 | 1565 | |||
1398 | 1566 | class ServicesFilesTestCase(ServicesTestCase): | ||
1399 | 1567 | """The test suite for the services panel (files section).""" | ||
1400 | 1568 | |||
1401 | 1569 | def test_files_is_visible(self): | ||
1402 | 1570 | """Files section is visible.""" | ||
1403 | 1571 | self.assertTrue(self.ui.files.get_visible()) | ||
1404 | 1572 | |||
1405 | 1573 | def test_files_is_a_file_sync_service(self): | ||
1406 | 1574 | """Files contains a FilesService.""" | ||
1407 | 1575 | child, = self.ui.files.get_children() | ||
1408 | 1576 | self.assertIsInstance(child, gui.FilesService) | ||
1409 | 1577 | |||
1410 | 1578 | |||
1411 | 1579 | class ServicesWithoutDesktopcouchTestCase(ServicesTestCase): | ||
1412 | 1580 | """The test suite for the services panel when DC is not installed.""" | ||
1413 | 1581 | |||
1414 | 1582 | def setUp(self): | ||
1415 | 1583 | super(ServicesWithoutDesktopcouchTestCase, self).setUp() | ||
1416 | 1584 | self.patch(self.ui.package_manager, 'is_installed', lambda *a: False) | ||
1417 | 1585 | self.ui.load() | ||
1418 | 1586 | |||
1419 | 1587 | def test_message(self): | ||
1420 | 1588 | """Global load message is stopped and cleared.""" | ||
1421 | 1589 | self.assertFalse(self.ui.message.active) | ||
1422 | 1590 | self.assertEqual(self.ui.message.get_text(), '') | ||
1423 | 1591 | |||
1424 | 1592 | def test_replication_service(self): | ||
1425 | 1593 | """Has a replication service.""" | ||
1426 | 1594 | self.assertEqual(self.ui.replication_service, None) | ||
1427 | 1595 | |||
1428 | 1596 | def test_has_desktopcouch(self): | ||
1429 | 1597 | """Has desktopcouch installed?""" | ||
1430 | 1598 | self.assertFalse(self.ui.has_desktopcouch) | ||
1431 | 1599 | |||
1432 | 1600 | def test_has_bindwood(self): | ||
1433 | 1601 | """Has bindwood installed?""" | ||
1434 | 1602 | self.assertFalse(self.ui.has_bindwood) | ||
1435 | 1603 | |||
1436 | 1604 | def test_has_evocouch(self): | ||
1437 | 1605 | """Has evocouch installed?""" | ||
1438 | 1606 | self.assertFalse(self.ui.has_evocouch) | ||
1439 | 1607 | |||
1440 | 1608 | def test_install_box_is_hidden(self): | ||
1441 | 1609 | """The install box is not hidden.""" | ||
1442 | 1610 | self.assertTrue(self.ui.install_box.get_visible()) | ||
1443 | 1611 | |||
1444 | 1612 | def test_replications_is_hidden(self): | ||
1445 | 1613 | """The replications section is disabled.""" | ||
1446 | 1614 | self.assertFalse(self.ui.replications.get_visible()) | ||
1447 | 1615 | |||
1448 | 1616 | def test_install_box(self): | ||
1449 | 1617 | """The install box is enabled.""" | ||
1450 | 1618 | self.assertTrue(self.ui.install_box.get_visible()) | ||
1451 | 1619 | self.assertIn(self.ui.install_box, self.ui.itself.get_children()) | ||
1452 | 1620 | self.assertEqual(self.ui.install_box.package_name, | ||
1453 | 1621 | self.ui.DESKTOPCOUCH_PKG) | ||
1454 | 1622 | |||
1455 | 1623 | def test_install_box_finished_connected(self): | ||
1456 | 1624 | """The install box 'finished' signal is connected.""" | ||
1457 | 1625 | self.patch(self.ui, 'load_replications', self._set_called) | ||
1458 | 1626 | self.ui.load() # ensure signal connection uses the new method | ||
1459 | 1627 | |||
1460 | 1628 | self.ui.install_box.emit('finished') | ||
1461 | 1629 | |||
1462 | 1630 | self.assertEqual(self._called, ((self.ui.install_box,), {})) | ||
1463 | 1631 | |||
1464 | 1632 | |||
1465 | 1633 | class ServicesWithDesktopcouchTestCase(ServicesTestCase): | ||
1466 | 1634 | """The test suite for the services panel.""" | ||
1467 | 1635 | |||
1468 | 1636 | kwargs = {'replication_exclusion_class': FakedReplication} | ||
1469 | 1637 | |||
1470 | 1638 | def setUp(self): | ||
1471 | 1639 | super(ServicesWithDesktopcouchTestCase, self).setUp() | ||
1472 | 1640 | self.ui.package_manager._installed[self.ui.DESKTOPCOUCH_PKG] = True | ||
1473 | 1641 | self.ui.load() | ||
1474 | 1642 | |||
1475 | 1643 | def test_message(self): | ||
1476 | 1644 | """Global load message is stopped and proper test is shown.""" | ||
1477 | 1645 | self.assertFalse(self.ui.message.active) | ||
1478 | 1646 | self.assertEqual(self.ui.message.get_text(), self.ui.CHOOSE_SERVICES) | ||
1479 | 1647 | |||
1480 | 1648 | def test_replication_service(self): | ||
1481 | 1649 | """Has a replication service.""" | ||
1482 | 1650 | self.assertIsInstance(self.ui.replication_service, FakedReplication) | ||
1483 | 1651 | |||
1484 | 1652 | def test_no_pairing_record(self): | ||
1485 | 1653 | """The pairing record is not in place.""" | ||
1486 | 1654 | |||
1487 | 1655 | def no_pairing_record(*a): | ||
1488 | 1656 | """Fake a ReplicationExclusion with no pairing record.""" | ||
1489 | 1657 | raise ValueError("No pairing record for ubuntuone.") | ||
1490 | 1658 | |||
1491 | 1659 | self.ui.replication_exclusion_class = no_pairing_record | ||
1492 | 1660 | self.ui.replication_service = None | ||
1493 | 1661 | self.ui.load() | ||
1494 | 1662 | |||
1495 | 1663 | self.assertEqual(self.ui.replications.get_children(), []) | ||
1496 | 1664 | self.assertFalse(self.ui.message.active) | ||
1497 | 1665 | self.assert_warning_correct(self.ui.message, self.ui.NO_PAIRING_RECORD) | ||
1498 | 1666 | |||
1499 | 1667 | def test_has_desktopcouch(self): | ||
1500 | 1668 | """Has desktopcouch installed?""" | ||
1501 | 1669 | self.assertTrue(self.ui.has_desktopcouch) | ||
1502 | 1670 | |||
1503 | 1671 | def test_replications(self): | ||
1504 | 1672 | """Has proper child for each desktopcouch replication available.""" | ||
1505 | 1673 | self.assertTrue(self.ui.replications.get_visible()) | ||
1506 | 1674 | |||
1507 | 1675 | children = self.ui.replications.get_children() | ||
1508 | 1676 | self.assertEqual(len(children), 2) | ||
1509 | 1677 | for child in children: | ||
1510 | 1678 | self.assertIsInstance(child, gui.DesktopcouchService) | ||
1511 | 1679 | |||
1512 | 1680 | self.assertTrue(self.ui.bookmarks is children[0]) | ||
1513 | 1681 | self.assertTrue(self.ui.contacts is children[1]) | ||
1514 | 1682 | |||
1515 | 1683 | def test_replications_after_loading_twice(self): | ||
1516 | 1684 | """Has proper child after loading twice.""" | ||
1517 | 1685 | self.ui.load() | ||
1518 | 1686 | self.test_replications() | ||
1519 | 1687 | |||
1520 | 1688 | def test_bookmarks(self): | ||
1521 | 1689 | """The bookmarks is correct.""" | ||
1522 | 1690 | self.assertEqual(self.ui.bookmarks.service_name, 'bookmarks') | ||
1523 | 1691 | self.assertEqual(self.ui.bookmarks.button.get_label(), | ||
1524 | 1692 | self.ui.BOOKMARKS) | ||
1525 | 1693 | self.assertTrue(self.ui.bookmarks.replication_service is | ||
1526 | 1694 | self.ui.replication_service) | ||
1527 | 1695 | |||
1528 | 1696 | def test_bookmarks_dependency(self): | ||
1529 | 1697 | """The bookmarks dependency is correct.""" | ||
1530 | 1698 | self.assertTrue(self.ui.bookmarks.dependency is not None) | ||
1531 | 1699 | self.assertEqual(self.ui.bookmarks.dependency.package_name, | ||
1532 | 1700 | self.ui.BINDWOOD_PKG) | ||
1533 | 1701 | |||
1534 | 1702 | def test_contacts(self): | ||
1535 | 1703 | """The contacts is correct.""" | ||
1536 | 1704 | self.assertEqual(self.ui.contacts.service_name, 'contacts') | ||
1537 | 1705 | self.assertEqual(self.ui.contacts.button.get_label(), | ||
1538 | 1706 | self.ui.CONTACTS) | ||
1539 | 1707 | self.assertTrue(self.ui.contacts.replication_service is | ||
1540 | 1708 | self.ui.replication_service) | ||
1541 | 1709 | |||
1542 | 1710 | def test_contacts_dependency(self): | ||
1543 | 1711 | """The contacts dependency is correct.""" | ||
1544 | 1712 | self.assertTrue(self.ui.contacts.dependency is not None) | ||
1545 | 1713 | self.assertEqual(self.ui.contacts.dependency.package_name, | ||
1546 | 1714 | self.ui.EVOCOUCH_PKG) | ||
1547 | 1715 | |||
1548 | 1716 | |||
1549 | 1717 | class ServicesWithDCAndBindwoodTestCase(ServicesWithDesktopcouchTestCase): | ||
1550 | 1718 | """The test suite for the services panel.""" | ||
1551 | 1719 | |||
1552 | 1720 | def setUp(self): | ||
1553 | 1721 | super(ServicesWithDCAndBindwoodTestCase, self).setUp() | ||
1554 | 1722 | self.ui.package_manager._installed[self.ui.BINDWOOD_PKG] = True | ||
1555 | 1723 | self.ui.load() | ||
1556 | 1724 | |||
1557 | 1725 | def test_has_bindwood(self): | ||
1558 | 1726 | """Has bindwood installed?""" | ||
1559 | 1727 | self.assertTrue(self.ui.has_bindwood) | ||
1560 | 1728 | |||
1561 | 1729 | def test_bookmarks_dependency(self): | ||
1562 | 1730 | """The bookmarks dependency is correct.""" | ||
1563 | 1731 | self.assertTrue(self.ui.bookmarks.dependency is None) | ||
1564 | 1732 | |||
1565 | 1733 | |||
1566 | 1734 | class ServicesWithDCAndEvocouchTestCase(ServicesWithDesktopcouchTestCase): | ||
1567 | 1735 | """The test suite for the services panel.""" | ||
1568 | 1736 | |||
1569 | 1737 | def setUp(self): | ||
1570 | 1738 | super(ServicesWithDCAndEvocouchTestCase, self).setUp() | ||
1571 | 1739 | self.ui.package_manager._installed[self.ui.EVOCOUCH_PKG] = True | ||
1572 | 1740 | self.ui.load() | ||
1573 | 1741 | |||
1574 | 1742 | def test_has_evocouch(self): | ||
1575 | 1743 | """Has evocoucg installed?""" | ||
1576 | 1744 | self.assertTrue(self.ui.has_evocouch) | ||
1577 | 1745 | |||
1578 | 1746 | def test_contacts_dependency(self): | ||
1579 | 1747 | """The bookmarks dependency is correct.""" | ||
1580 | 1748 | self.assertTrue(self.ui.contacts.dependency is None) | ||
1581 | 1749 | |||
1582 | 1386 | 1750 | ||
1583 | 1387 | class ManagementPanelTestCase(ControlPanelMixinTestCase): | 1751 | class ManagementPanelTestCase(ControlPanelMixinTestCase): |
1584 | 1388 | """The test suite for the management panel.""" | 1752 | """The test suite for the management panel.""" |
1585 | @@ -1420,11 +1784,11 @@ | |||
1586 | 1420 | """Tabs are not shown.""" | 1784 | """Tabs are not shown.""" |
1587 | 1421 | self.assertFalse(self.ui.notebook.get_show_tabs()) | 1785 | self.assertFalse(self.ui.notebook.get_show_tabs()) |
1588 | 1422 | 1786 | ||
1591 | 1423 | def test_default_page_is_account(self): | 1787 | def test_default_page_is_dashboard(self): |
1592 | 1424 | """The default page is Account.""" | 1788 | """The default page is Dashboard.""" |
1593 | 1425 | self.assertEqual(self.ui.notebook.get_current_page(), | 1789 | self.assertEqual(self.ui.notebook.get_current_page(), |
1596 | 1426 | self.ui.ACCOUNT_PAGE) | 1790 | self.ui.DASHBOARD_PAGE) |
1597 | 1427 | self.assertTrue(self.ui.account_button.get_active()) | 1791 | self.assertTrue(self.ui.dashboard_button.get_active()) |
1598 | 1428 | 1792 | ||
1599 | 1429 | def test_buttons_set_notebook_pages(self): | 1793 | def test_buttons_set_notebook_pages(self): |
1600 | 1430 | """The notebook pages are set when clicking buttons.""" | 1794 | """The notebook pages are set when clicking buttons.""" |
1601 | @@ -1449,10 +1813,6 @@ | |||
1602 | 1449 | active = getattr(self.ui, '%s_button' % other).get_active() | 1813 | active = getattr(self.ui, '%s_button' % other).get_active() |
1603 | 1450 | self.assertFalse(active, msg % (button, other)) | 1814 | self.assertFalse(active, msg % (button, other)) |
1604 | 1451 | 1815 | ||
1605 | 1452 | |||
1606 | 1453 | class ManagementPanelAccountTestCase(ManagementPanelTestCase): | ||
1607 | 1454 | """The test suite for the management panel (account tab).""" | ||
1608 | 1455 | |||
1609 | 1456 | def test_backend_account_signals(self): | 1816 | def test_backend_account_signals(self): |
1610 | 1457 | """The proper signals are connected to the backend.""" | 1817 | """The proper signals are connected to the backend.""" |
1611 | 1458 | self.assertEqual(self.ui.backend._signals['AccountInfoReady'], | 1818 | self.assertEqual(self.ui.backend._signals['AccountInfoReady'], |
1612 | @@ -1465,11 +1825,11 @@ | |||
1613 | 1465 | self.ui.load() | 1825 | self.ui.load() |
1614 | 1466 | self.assert_backend_called('account_info', ()) | 1826 | self.assert_backend_called('account_info', ()) |
1615 | 1467 | 1827 | ||
1621 | 1468 | def test_account_panel_is_packed(self): | 1828 | def test_dashboard_panel_is_packed(self): |
1622 | 1469 | """The account panel is packed.""" | 1829 | """The dashboard panel is packed.""" |
1623 | 1470 | self.assertIsInstance(self.ui.account, gui.AccountPanel) | 1830 | self.assertIsInstance(self.ui.dashboard, gui.DashboardPanel) |
1624 | 1471 | actual = self.ui.notebook.get_nth_page(self.ui.ACCOUNT_PAGE) | 1831 | actual = self.ui.notebook.get_nth_page(self.ui.DASHBOARD_PAGE) |
1625 | 1472 | self.assertTrue(self.ui.account is actual) | 1832 | self.assertTrue(self.ui.dashboard is actual) |
1626 | 1473 | 1833 | ||
1627 | 1474 | def test_folders_panel_is_packed(self): | 1834 | def test_folders_panel_is_packed(self): |
1628 | 1475 | """The folders panel is packed.""" | 1835 | """The folders panel is packed.""" |
1629 | @@ -1483,11 +1843,11 @@ | |||
1630 | 1483 | actual = self.ui.notebook.get_nth_page(self.ui.DEVICES_PAGE) | 1843 | actual = self.ui.notebook.get_nth_page(self.ui.DEVICES_PAGE) |
1631 | 1484 | self.assertTrue(self.ui.devices is actual) | 1844 | self.assertTrue(self.ui.devices is actual) |
1632 | 1485 | 1845 | ||
1638 | 1486 | def test_applications_panel_is_packed(self): | 1846 | def test_services_panel_is_packed(self): |
1639 | 1487 | """The applications panel is packed.""" | 1847 | """The services panel is packed.""" |
1640 | 1488 | self.assertIsInstance(self.ui.applications, gui.ApplicationsPanel) | 1848 | self.assertIsInstance(self.ui.services, gui.ServicesPanel) |
1641 | 1489 | actual = self.ui.notebook.get_nth_page(self.ui.APPLICATIONS_PAGE) | 1849 | actual = self.ui.notebook.get_nth_page(self.ui.SERVICES_PAGE) |
1642 | 1490 | self.assertTrue(self.ui.applications is actual) | 1850 | self.assertTrue(self.ui.services is actual) |
1643 | 1491 | 1851 | ||
1644 | 1492 | def test_entering_folders_tab_loads_content(self): | 1852 | def test_entering_folders_tab_loads_content(self): |
1645 | 1493 | """The volumes info is loaded when entering the Folders tab.""" | 1853 | """The volumes info is loaded when entering the Folders tab.""" |
1646 | @@ -1505,6 +1865,14 @@ | |||
1647 | 1505 | 1865 | ||
1648 | 1506 | self.assertEqual(self._called, ((), {})) | 1866 | self.assertEqual(self._called, ((), {})) |
1649 | 1507 | 1867 | ||
1650 | 1868 | def test_entering_services_tab_loads_content(self): | ||
1651 | 1869 | """The services info is loaded when entering the Devices tab.""" | ||
1652 | 1870 | self.patch(self.ui.services, 'load', self._set_called) | ||
1653 | 1871 | # clean backend calls | ||
1654 | 1872 | self.ui.services_button.clicked() | ||
1655 | 1873 | |||
1656 | 1874 | self.assertEqual(self._called, ((), {})) | ||
1657 | 1875 | |||
1658 | 1508 | def test_quota_placeholder_is_loading(self): | 1876 | def test_quota_placeholder_is_loading(self): |
1659 | 1509 | """Placeholders for quota label is a Loading widget.""" | 1877 | """Placeholders for quota label is a Loading widget.""" |
1660 | 1510 | self.assertIsInstance(self.ui.quota_label, gui.LabelLoading) | 1878 | self.assertIsInstance(self.ui.quota_label, gui.LabelLoading) |
1661 | 1511 | 1879 | ||
1662 | === added file 'ubuntuone/controlpanel/gtk/tests/test_package_manager.py' | |||
1663 | --- ubuntuone/controlpanel/gtk/tests/test_package_manager.py 1970-01-01 00:00:00 +0000 | |||
1664 | +++ ubuntuone/controlpanel/gtk/tests/test_package_manager.py 2011-01-03 14:24:42 +0000 | |||
1665 | @@ -0,0 +1,177 @@ | |||
1666 | 1 | # -*- coding: utf-8 -*- | ||
1667 | 2 | |||
1668 | 3 | # Authors: Natalia B. Bidart <nataliabidart@canonical.com> | ||
1669 | 4 | # | ||
1670 | 5 | # Copyright 2010 Canonical Ltd. | ||
1671 | 6 | # | ||
1672 | 7 | # This program is free software: you can redistribute it and/or modify it | ||
1673 | 8 | # under the terms of the GNU General Public License version 3, as published | ||
1674 | 9 | # by the Free Software Foundation. | ||
1675 | 10 | # | ||
1676 | 11 | # This program is distributed in the hope that it will be useful, but | ||
1677 | 12 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1678 | 13 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1679 | 14 | # PURPOSE. See the GNU General Public License for more details. | ||
1680 | 15 | # | ||
1681 | 16 | # You should have received a copy of the GNU General Public License along | ||
1682 | 17 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1683 | 18 | |||
1684 | 19 | """Tests for the package manager service.""" | ||
1685 | 20 | |||
1686 | 21 | import collections | ||
1687 | 22 | |||
1688 | 23 | try: | ||
1689 | 24 | # Unable to import 'defer', pylint: disable=F0401,E0611 | ||
1690 | 25 | from aptdaemon import defer | ||
1691 | 26 | except ImportError: | ||
1692 | 27 | # Unable to import 'defer', pylint: disable=F0401,E0611 | ||
1693 | 28 | import defer | ||
1694 | 29 | |||
1695 | 30 | from ubuntuone.controlpanel.gtk import package_manager | ||
1696 | 31 | from ubuntuone.controlpanel.tests import TestCase | ||
1697 | 32 | |||
1698 | 33 | |||
1699 | 34 | FAKED_CACHE = {} | ||
1700 | 35 | SUCCESS = package_manager.aptdaemon.enums.EXIT_SUCCESS | ||
1701 | 36 | FAILURE = package_manager.aptdaemon.enums.EXIT_FAILED | ||
1702 | 37 | |||
1703 | 38 | |||
1704 | 39 | class FakedPackage(object): | ||
1705 | 40 | """Fake a package.""" | ||
1706 | 41 | |||
1707 | 42 | def __init__(self, name=None, is_installed=False): | ||
1708 | 43 | self.name = name | ||
1709 | 44 | self.is_installed = is_installed | ||
1710 | 45 | |||
1711 | 46 | |||
1712 | 47 | class FakedTransaction(object): | ||
1713 | 48 | """Fake a transaction.""" | ||
1714 | 49 | |||
1715 | 50 | failure = None | ||
1716 | 51 | |||
1717 | 52 | def __init__(self, packages, cache=None): | ||
1718 | 53 | self._signals = collections.defaultdict(list) | ||
1719 | 54 | self._cache = cache | ||
1720 | 55 | self.was_run = False | ||
1721 | 56 | self.packages = packages | ||
1722 | 57 | self.connect = lambda sig, f: self._signals[sig].append(f) | ||
1723 | 58 | |||
1724 | 59 | def run(self): | ||
1725 | 60 | """Run!""" | ||
1726 | 61 | self.was_run = True | ||
1727 | 62 | |||
1728 | 63 | if self._cache is not None: | ||
1729 | 64 | for package in self.packages: | ||
1730 | 65 | FAKED_CACHE[package].is_installed = True | ||
1731 | 66 | |||
1732 | 67 | if self.failure is None: | ||
1733 | 68 | code = SUCCESS | ||
1734 | 69 | else: | ||
1735 | 70 | code = FAILURE | ||
1736 | 71 | |||
1737 | 72 | for listener in self._signals['finished']: | ||
1738 | 73 | listener(self, code) | ||
1739 | 74 | |||
1740 | 75 | d = defer.Deferred() | ||
1741 | 76 | d.callback(code) | ||
1742 | 77 | return d | ||
1743 | 78 | |||
1744 | 79 | |||
1745 | 80 | class FakedClient(object): | ||
1746 | 81 | """Fake an apt client.""" | ||
1747 | 82 | |||
1748 | 83 | def install_packages(self, packages_names, **kwargs): | ||
1749 | 84 | """Install packages listed in 'package_names'. | ||
1750 | 85 | |||
1751 | 86 | package_names - a list of package names | ||
1752 | 87 | wait - if True run the transaction immediately and return its exit | ||
1753 | 88 | state instead of the transaction itself. | ||
1754 | 89 | reply_handler - callback function. If specified in combination with | ||
1755 | 90 | error_handler the method will be called asynchrounsouly. | ||
1756 | 91 | error_handler - in case of an error the given callback gets the | ||
1757 | 92 | corresponding DBus exception instance | ||
1758 | 93 | |||
1759 | 94 | """ | ||
1760 | 95 | if kwargs.get('wait', False): | ||
1761 | 96 | return package_manager.aptdaemon.enums.EXIT_FAILED | ||
1762 | 97 | d = defer.Deferred() | ||
1763 | 98 | d.callback(FakedTransaction(packages_names, cache=FAKED_CACHE)) | ||
1764 | 99 | return d | ||
1765 | 100 | |||
1766 | 101 | |||
1767 | 102 | class PackageManagerTestCase(TestCase): | ||
1768 | 103 | """Test for the package manager.""" | ||
1769 | 104 | |||
1770 | 105 | timeout = 2 | ||
1771 | 106 | |||
1772 | 107 | def setUp(self): | ||
1773 | 108 | FAKED_CACHE.clear() # clean cache | ||
1774 | 109 | self.patch(package_manager.apt, 'Cache', lambda: FAKED_CACHE) | ||
1775 | 110 | self.patch(package_manager.aptdaemon.client, 'AptClient', FakedClient) | ||
1776 | 111 | self.obj = package_manager.PackageManager() | ||
1777 | 112 | |||
1778 | 113 | def test_is_installed(self): | ||
1779 | 114 | """Check that a package is installed.""" | ||
1780 | 115 | name = 'test' | ||
1781 | 116 | FAKED_CACHE[name] = FakedPackage(name, is_installed=True) | ||
1782 | 117 | |||
1783 | 118 | result = self.obj.is_installed(name) | ||
1784 | 119 | |||
1785 | 120 | self.assertTrue(result, 'must be installed') | ||
1786 | 121 | |||
1787 | 122 | def test_is_not_installed(self): | ||
1788 | 123 | """Check if a package is installed.""" | ||
1789 | 124 | name = 'test' | ||
1790 | 125 | FAKED_CACHE[name] = FakedPackage(name) # not installed by default | ||
1791 | 126 | |||
1792 | 127 | result = self.obj.is_installed(name) | ||
1793 | 128 | |||
1794 | 129 | self.assertFalse(result, 'must not be installed') | ||
1795 | 130 | |||
1796 | 131 | def test_is_not_installed_if_key_error(self): | ||
1797 | 132 | """Check if a package is installed when cache raises KeyError.""" | ||
1798 | 133 | name = 'test' # is not in the cache | ||
1799 | 134 | result = self.obj.is_installed(name) | ||
1800 | 135 | |||
1801 | 136 | self.assertFalse(result, 'must not be installed') | ||
1802 | 137 | |||
1803 | 138 | def test_progress_bar(self): | ||
1804 | 139 | """The progress bar class is correct.""" | ||
1805 | 140 | self.assertIsInstance(package_manager.PackageManagerProgressBar(), | ||
1806 | 141 | package_manager.AptProgressBar) | ||
1807 | 142 | |||
1808 | 143 | @package_manager.inline_callbacks | ||
1809 | 144 | def test_install(self): | ||
1810 | 145 | """Install is correct.""" | ||
1811 | 146 | name = 'test' | ||
1812 | 147 | FAKED_CACHE[name] = FakedPackage(name) # not installed by default | ||
1813 | 148 | |||
1814 | 149 | result = yield self.obj.install(name) | ||
1815 | 150 | |||
1816 | 151 | self.assertIsInstance(result, FakedTransaction) | ||
1817 | 152 | self.assertFalse(result.was_run, 'transaction must not be run') | ||
1818 | 153 | |||
1819 | 154 | @package_manager.inline_callbacks | ||
1820 | 155 | def test_transaction_install(self): | ||
1821 | 156 | """Install is correct.""" | ||
1822 | 157 | name = 'test' | ||
1823 | 158 | FAKED_CACHE[name] = FakedPackage(name) # not installed by default | ||
1824 | 159 | |||
1825 | 160 | trans = yield self.obj.install(name) | ||
1826 | 161 | |||
1827 | 162 | trans.connect('finished', self._set_called) | ||
1828 | 163 | trans.run() | ||
1829 | 164 | |||
1830 | 165 | self.assertEqual(self._called, ((trans, SUCCESS), {})) | ||
1831 | 166 | self.assertTrue(trans.was_run, 'transaction must be run') | ||
1832 | 167 | self.assertTrue(self.obj.is_installed(name)) | ||
1833 | 168 | |||
1834 | 169 | @package_manager.inline_callbacks | ||
1835 | 170 | def test_install_if_installed(self): | ||
1836 | 171 | """Install does nothing is package is already installed.""" | ||
1837 | 172 | name = 'test' | ||
1838 | 173 | FAKED_CACHE[name] = FakedPackage(name, is_installed=True) | ||
1839 | 174 | |||
1840 | 175 | result = yield self.obj.install(name) | ||
1841 | 176 | |||
1842 | 177 | self.assertEqual(result, SUCCESS) | ||
1843 | 0 | 178 | ||
1844 | === modified file 'ubuntuone/controlpanel/integrationtests/test_dbus_service.py' | |||
1845 | --- ubuntuone/controlpanel/integrationtests/test_dbus_service.py 2010-12-16 21:09:46 +0000 | |||
1846 | +++ ubuntuone/controlpanel/integrationtests/test_dbus_service.py 2011-01-03 14:24:42 +0000 | |||
1847 | @@ -150,6 +150,14 @@ | |||
1848 | 150 | """Return the status of the file sync service.""" | 150 | """Return the status of the file sync service.""" |
1849 | 151 | return self._process(self.sample_status) | 151 | return self._process(self.sample_status) |
1850 | 152 | 152 | ||
1851 | 153 | def enable_files(self): | ||
1852 | 154 | """Enable files service.""" | ||
1853 | 155 | return self._process(None) | ||
1854 | 156 | |||
1855 | 157 | def disable_files(self): | ||
1856 | 158 | """Disable files service.""" | ||
1857 | 159 | return self._process(None) | ||
1858 | 160 | |||
1859 | 153 | def volumes_info(self): | 161 | def volumes_info(self): |
1860 | 154 | """Get the user volumes info.""" | 162 | """Get the user volumes info.""" |
1861 | 155 | return self._process(SAMPLE_VOLUMES_INFO) | 163 | return self._process(SAMPLE_VOLUMES_INFO) |
1862 | @@ -383,6 +391,28 @@ | |||
1863 | 383 | self.backend.remove_device, sample_token) | 391 | self.backend.remove_device, sample_token) |
1864 | 384 | return self.assert_correct_method_call(*args) | 392 | return self.assert_correct_method_call(*args) |
1865 | 385 | 393 | ||
1866 | 394 | def test_enable_files(self): | ||
1867 | 395 | """Enable files service.""" | ||
1868 | 396 | |||
1869 | 397 | def got_signal(*args): | ||
1870 | 398 | """The correct signal was received.""" | ||
1871 | 399 | self.deferred.callback("success") | ||
1872 | 400 | |||
1873 | 401 | args = ("FilesEnabled", "FilesEnableError", got_signal, | ||
1874 | 402 | self.backend.enable_files) | ||
1875 | 403 | return self.assert_correct_method_call(*args) | ||
1876 | 404 | |||
1877 | 405 | def test_disable_files(self): | ||
1878 | 406 | """Disable files service.""" | ||
1879 | 407 | |||
1880 | 408 | def got_signal(): | ||
1881 | 409 | """The correct signal was received.""" | ||
1882 | 410 | self.deferred.callback("success") | ||
1883 | 411 | |||
1884 | 412 | args = ("FilesDisabled", "FilesDisableError", got_signal, | ||
1885 | 413 | self.backend.disable_files) | ||
1886 | 414 | return self.assert_correct_method_call(*args) | ||
1887 | 415 | |||
1888 | 386 | def test_volumes_info(self): | 416 | def test_volumes_info(self): |
1889 | 387 | """The volumes info is reported.""" | 417 | """The volumes info is reported.""" |
1890 | 388 | 418 | ||
1891 | @@ -527,6 +557,20 @@ | |||
1892 | 527 | args = (dbus_service.FILE_SYNC_IDLE, "FileSyncStatusIdle") | 557 | args = (dbus_service.FILE_SYNC_IDLE, "FileSyncStatusIdle") |
1893 | 528 | return self.assert_correct_status_signal(*args) | 558 | return self.assert_correct_status_signal(*args) |
1894 | 529 | 559 | ||
1895 | 560 | def test_file_sync_status_changed(self): | ||
1896 | 561 | """The file sync status is reported every time status changed.""" | ||
1897 | 562 | status = ( | ||
1898 | 563 | dbus_service.FILE_SYNC_DISABLED, | ||
1899 | 564 | dbus_service.FILE_SYNC_DISCONNECTED, | ||
1900 | 565 | dbus_service.FILE_SYNC_ERROR, | ||
1901 | 566 | dbus_service.FILE_SYNC_IDLE, | ||
1902 | 567 | dbus_service.FILE_SYNC_STARTING, | ||
1903 | 568 | dbus_service.FILE_SYNC_SYNCING, | ||
1904 | 569 | ) | ||
1905 | 570 | for arg in status: | ||
1906 | 571 | args = (arg, "FileSyncStatusChanged") | ||
1907 | 572 | return self.assert_correct_status_signal(*args, expected_msg=arg) | ||
1908 | 573 | |||
1909 | 530 | def test_status_changed_handler(self): | 574 | def test_status_changed_handler(self): |
1910 | 531 | """The status changed handler is properly set.""" | 575 | """The status changed handler is properly set.""" |
1911 | 532 | be = MockBackend() | 576 | be = MockBackend() |
1912 | 533 | 577 | ||
1913 | === modified file 'ubuntuone/controlpanel/logger.py' | |||
1914 | --- ubuntuone/controlpanel/logger.py 2010-12-08 22:25:24 +0000 | |||
1915 | +++ ubuntuone/controlpanel/logger.py 2011-01-03 14:24:42 +0000 | |||
1916 | @@ -33,7 +33,7 @@ | |||
1917 | 33 | LOG_LEVEL = logging.DEBUG | 33 | LOG_LEVEL = logging.DEBUG |
1918 | 34 | else: | 34 | else: |
1919 | 35 | # Only log this level and above | 35 | # Only log this level and above |
1921 | 36 | LOG_LEVEL = logging.INFO | 36 | LOG_LEVEL = logging.DEBUG # before final release, switch to INFO |
1922 | 37 | 37 | ||
1923 | 38 | MAIN_HANDLER = RotatingFileHandler(os.path.join(LOGFOLDER, 'controlpanel.log'), | 38 | MAIN_HANDLER = RotatingFileHandler(os.path.join(LOGFOLDER, 'controlpanel.log'), |
1924 | 39 | maxBytes=1048576, | 39 | maxBytes=1048576, |
1925 | 40 | 40 | ||
1926 | === modified file 'ubuntuone/controlpanel/tests/__init__.py' | |||
1927 | --- ubuntuone/controlpanel/tests/__init__.py 2010-12-02 16:23:03 +0000 | |||
1928 | +++ ubuntuone/controlpanel/tests/__init__.py 2011-01-03 14:24:42 +0000 | |||
1929 | @@ -18,7 +18,7 @@ | |||
1930 | 18 | 18 | ||
1931 | 19 | """The test suite for the control panel for Ubuntu One.""" | 19 | """The test suite for the control panel for Ubuntu One.""" |
1932 | 20 | 20 | ||
1934 | 21 | from twisted.trial import unittest | 21 | from ubuntuone.devtools.testcase import TestCase as BaseTestCase |
1935 | 22 | 22 | ||
1936 | 23 | 23 | ||
1937 | 24 | TOKEN = {u'consumer_key': u'xQ7xDAz', | 24 | TOKEN = {u'consumer_key': u'xQ7xDAz', |
1938 | @@ -28,7 +28,7 @@ | |||
1939 | 28 | u'token_secret': u'qFYImEtlczPbsCnYyuwLoPDlPEnvNcIktZphPQklAWrvyfFMV'} | 28 | u'token_secret': u'qFYImEtlczPbsCnYyuwLoPDlPEnvNcIktZphPQklAWrvyfFMV'} |
1940 | 29 | 29 | ||
1941 | 30 | 30 | ||
1943 | 31 | class TestCase(unittest.TestCase): | 31 | class TestCase(BaseTestCase): |
1944 | 32 | """Basics for testing.""" | 32 | """Basics for testing.""" |
1945 | 33 | 33 | ||
1946 | 34 | def setUp(self): | 34 | def setUp(self): |
1947 | 35 | 35 | ||
1948 | === modified file 'ubuntuone/controlpanel/tests/test_backend.py' | |||
1949 | --- ubuntuone/controlpanel/tests/test_backend.py 2010-12-18 20:16:18 +0000 | |||
1950 | +++ ubuntuone/controlpanel/tests/test_backend.py 2011-01-03 14:24:42 +0000 | |||
1951 | @@ -257,11 +257,11 @@ | |||
1952 | 257 | 257 | ||
1953 | 258 | def files_sync_enabled(self): | 258 | def files_sync_enabled(self): |
1954 | 259 | """Get if file sync service is enabled.""" | 259 | """Get if file sync service is enabled.""" |
1956 | 260 | return self.file_sync | 260 | return MockDBusClient.file_sync |
1957 | 261 | 261 | ||
1958 | 262 | def set_files_sync_enabled(self, enabled): | 262 | def set_files_sync_enabled(self, enabled): |
1959 | 263 | """Set the file sync service to be 'enabled'.""" | 263 | """Set the file sync service to be 'enabled'.""" |
1961 | 264 | self.file_sync = enabled | 264 | MockDBusClient.file_sync = enabled |
1962 | 265 | 265 | ||
1963 | 266 | def get_folders(self): | 266 | def get_folders(self): |
1964 | 267 | """Grab list of folders.""" | 267 | """Grab list of folders.""" |
1965 | @@ -653,3 +653,21 @@ | |||
1966 | 653 | # Access to a protected member _process_file_sync_status | 653 | # Access to a protected member _process_file_sync_status |
1967 | 654 | expected_status = self.be._process_file_sync_status(status) | 654 | expected_status = self.be._process_file_sync_status(status) |
1968 | 655 | self.assertEqual(self._called, ((expected_status,), {})) | 655 | self.assertEqual(self._called, ((expected_status,), {})) |
1969 | 656 | |||
1970 | 657 | |||
1971 | 658 | class BackendSyncEnabledTestCase(BackendBasicTestCase): | ||
1972 | 659 | """Syncdaemon enable/disable for the backend.""" | ||
1973 | 660 | |||
1974 | 661 | def test_enable_files(self): | ||
1975 | 662 | """Files service is enabled.""" | ||
1976 | 663 | self.be.disable_files() | ||
1977 | 664 | |||
1978 | 665 | self.be.enable_files() | ||
1979 | 666 | self.assertTrue(MockDBusClient.file_sync) | ||
1980 | 667 | |||
1981 | 668 | def test_disable_files(self): | ||
1982 | 669 | """Files service is disabled.""" | ||
1983 | 670 | self.be.enable_files() | ||
1984 | 671 | |||
1985 | 672 | self.be.disable_files() | ||
1986 | 673 | self.assertFalse(MockDBusClient.file_sync) |
Need to handle the case where the pairing record is not present:
File "/home/ ralsina/ canonical/ ubuntuone/ woo/ubuntuone/ controlpanel/ logger. py", line 75, in inner ralsina/ canonical/ ubuntuone/ woo/ubuntuone/ controlpanel/ gtk/gui. py", line 992, in load_replications replication_ service = self.replicatio n_exclusion_ class() pymodules/ python2. 7/desktopcouch/ application/ replication_ services/ ubuntuone. py", line 140, in __init__
res = f(*args, **kwargs)
File "/home/
self.
File "/usr/lib/
raise ValueError("No pairing record for ubuntuone.")
ValueError: No pairing record for ubuntuone.