Merge lp:~nataliabidart/ubuntuone-control-panel/folders-tweaks into lp:ubuntuone-control-panel
- folders-tweaks
- Merge into trunk
Proposed by
Natalia Bidart
Status: | Merged |
---|---|
Approved by: | Natalia Bidart |
Approved revision: | 88 |
Merged at revision: | 86 |
Proposed branch: | lp:~nataliabidart/ubuntuone-control-panel/folders-tweaks |
Merge into: | lp:ubuntuone-control-panel |
Diff against target: |
1340 lines (+656/-575) 4 files modified
ubuntuone/controlpanel/gtk/gui.py (+16/-5) ubuntuone/controlpanel/gtk/tests/__init__.py (+17/-6) ubuntuone/controlpanel/gtk/tests/test_gui.py (+35/-564) ubuntuone/controlpanel/gtk/tests/test_gui_basic.py (+588/-0) |
To merge this branch: | bzr merge lp:~nataliabidart/ubuntuone-control-panel/folders-tweaks |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Roberto Alsina (community) | Approve | ||
Martin Albisetti (community) | ui | Approve | |
Review via email: mp+51765@code.launchpad.net |
Description of the change
To post a comment you must log in.
Revision history for this message
Martin Albisetti (beuno) : | # |
review:
Approve
(ui)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'ubuntuone/controlpanel/gtk/gui.py' | |||
2 | --- ubuntuone/controlpanel/gtk/gui.py 2011-02-28 23:24:53 +0000 | |||
3 | +++ ubuntuone/controlpanel/gtk/gui.py 2011-03-01 15:44:47 +0000 | |||
4 | @@ -397,12 +397,15 @@ | |||
5 | 397 | CONFIRM_MERGE = _('The contents of your cloud folder will be merged with ' | 397 | CONFIRM_MERGE = _('The contents of your cloud folder will be merged with ' |
6 | 398 | 'your local folder "%(folder_path)s" when subscribing.\n' | 398 | 'your local folder "%(folder_path)s" when subscribing.\n' |
7 | 399 | 'Do you want to subscribe to this cloud folder?') | 399 | 'Do you want to subscribe to this cloud folder?') |
8 | 400 | MUSIC_DISPLAY_NAME = _('Purchased Music') | ||
9 | 401 | MUSIC_REAL_PATH = '~/.ubuntuone/Purchased from Ubuntu One' | ||
10 | 400 | 402 | ||
11 | 401 | MAX_COLS = 8 | 403 | MAX_COLS = 8 |
12 | 402 | 404 | ||
14 | 403 | CONTACT_ICON_NAME = 'system-users' | 405 | CONTACT_ICON_NAME = 'avatar-default' |
15 | 404 | FOLDER_ICON_NAME = 'folder' | 406 | FOLDER_ICON_NAME = 'folder' |
16 | 405 | SHARE_ICON_NAME = 'folder-remote' | 407 | SHARE_ICON_NAME = 'folder-remote' |
17 | 408 | MUSIC_ICON_NAME = 'audio-x-generic' | ||
18 | 406 | ROW_HEADER = '<span font_size="large"><b>%s</b></span> ' \ | 409 | ROW_HEADER = '<span font_size="large"><b>%s</b></span> ' \ |
19 | 407 | '<span foreground="grey">%s</span>' | 410 | '<span foreground="grey">%s</span>' |
20 | 408 | ROOT = '%s - <span foreground="%s" font_size="small">%s</span>' | 411 | ROOT = '%s - <span foreground="%s" font_size="small">%s</span>' |
21 | @@ -436,7 +439,14 @@ | |||
22 | 436 | def _process_path(self, path): | 439 | def _process_path(self, path): |
23 | 437 | """Trim 'path' so the '~' is removed.""" | 440 | """Trim 'path' so the '~' is removed.""" |
24 | 438 | home = os.path.expanduser('~') | 441 | home = os.path.expanduser('~') |
26 | 439 | return path.replace(os.path.join(home, ''), '') | 442 | music_path = os.path.expanduser(self.MUSIC_REAL_PATH) |
27 | 443 | |||
28 | 444 | if path == music_path: | ||
29 | 445 | result = self.MUSIC_DISPLAY_NAME | ||
30 | 446 | else: | ||
31 | 447 | result = path.replace(os.path.join(home, ''), '') | ||
32 | 448 | |||
33 | 449 | return result | ||
34 | 440 | 450 | ||
35 | 441 | def on_volumes_info_ready(self, info): | 451 | def on_volumes_info_ready(self, info): |
36 | 442 | """Backend notifies of volumes info.""" | 452 | """Backend notifies of volumes info.""" |
37 | @@ -454,13 +464,10 @@ | |||
38 | 454 | 464 | ||
39 | 455 | if name: | 465 | if name: |
40 | 456 | name = name + "'s" | 466 | name = name + "'s" |
41 | 457 | icon_name = self.SHARE_ICON_NAME | ||
42 | 458 | |||
43 | 459 | # we already added user folders, let's add an empty row | 467 | # we already added user folders, let's add an empty row |
44 | 460 | treeiter = self.volumes_store.append(None, self._empty_row) | 468 | treeiter = self.volumes_store.append(None, self._empty_row) |
45 | 461 | else: | 469 | else: |
46 | 462 | name = self.MY_FOLDERS | 470 | name = self.MY_FOLDERS |
47 | 463 | icon_name = self.FOLDER_ICON_NAME | ||
48 | 464 | 471 | ||
49 | 465 | free_bytes_args = {'free_space': self.humanize(int(free_bytes))} | 472 | free_bytes_args = {'free_space': self.humanize(int(free_bytes))} |
50 | 466 | row = (self.ROW_HEADER % (name, self.FREE_SPACE % free_bytes_args), | 473 | row = (self.ROW_HEADER % (name, self.FREE_SPACE % free_bytes_args), |
51 | @@ -472,6 +479,7 @@ | |||
52 | 472 | for volume in volumes: | 479 | for volume in volumes: |
53 | 473 | sensitive = True | 480 | sensitive = True |
54 | 474 | name = self._process_path(volume[u'path']) | 481 | name = self._process_path(volume[u'path']) |
55 | 482 | icon_name = self.FOLDER_ICON_NAME | ||
56 | 475 | 483 | ||
57 | 476 | is_root = volume[u'type'] == backend.ControlBackend.ROOT_TYPE | 484 | is_root = volume[u'type'] == backend.ControlBackend.ROOT_TYPE |
58 | 477 | is_share = volume[u'type'] == backend.ControlBackend.SHARE_TYPE | 485 | is_share = volume[u'type'] == backend.ControlBackend.SHARE_TYPE |
59 | @@ -481,6 +489,9 @@ | |||
60 | 481 | name = self.ROOT % (name, ORANGE, self.ALWAYS_SUBSCRIBED) | 489 | name = self.ROOT % (name, ORANGE, self.ALWAYS_SUBSCRIBED) |
61 | 482 | elif is_share: | 490 | elif is_share: |
62 | 483 | name = volume[u'name'] | 491 | name = volume[u'name'] |
63 | 492 | icon_name = self.SHARE_ICON_NAME | ||
64 | 493 | elif name == self.MUSIC_DISPLAY_NAME: | ||
65 | 494 | icon_name = self.MUSIC_ICON_NAME | ||
66 | 484 | 495 | ||
67 | 485 | row = (name, bool(volume[u'subscribed']), icon_name, True, | 496 | row = (name, bool(volume[u'subscribed']), icon_name, True, |
68 | 486 | sensitive, gtk.ICON_SIZE_MENU, volume['volume_id'], | 497 | sensitive, gtk.ICON_SIZE_MENU, volume['volume_id'], |
69 | 487 | 498 | ||
70 | === modified file 'ubuntuone/controlpanel/gtk/tests/__init__.py' | |||
71 | --- ubuntuone/controlpanel/gtk/tests/__init__.py 2011-02-28 19:53:50 +0000 | |||
72 | +++ ubuntuone/controlpanel/gtk/tests/__init__.py 2011-03-01 15:44:47 +0000 | |||
73 | @@ -24,6 +24,7 @@ | |||
74 | 24 | 24 | ||
75 | 25 | from ubuntuone.devtools.handlers import MementoHandler | 25 | from ubuntuone.devtools.handlers import MementoHandler |
76 | 26 | 26 | ||
77 | 27 | from ubuntuone.controlpanel.backend import ControlBackend | ||
78 | 27 | from ubuntuone.controlpanel.gtk import gui | 28 | from ubuntuone.controlpanel.gtk import gui |
79 | 28 | from ubuntuone.controlpanel.gtk.tests.test_package_manager import ( | 29 | from ubuntuone.controlpanel.gtk.tests.test_package_manager import ( |
80 | 29 | FakedTransaction) | 30 | FakedTransaction) |
81 | @@ -41,26 +42,36 @@ | |||
82 | 41 | 42 | ||
83 | 42 | ROOT = { | 43 | ROOT = { |
84 | 43 | u'volume_id': '', u'path': '/home/tester/My Ubuntu', | 44 | u'volume_id': '', u'path': '/home/tester/My Ubuntu', |
86 | 44 | u'subscribed': 'True', u'type': u'ROOT', | 45 | u'subscribed': 'True', u'type': ControlBackend.ROOT_TYPE, |
87 | 46 | } | ||
88 | 47 | |||
89 | 48 | MUSIC_FOLDER = { | ||
90 | 49 | u'volume_id': u'58236', u'subscribed': u'True', | ||
91 | 50 | u'type': ControlBackend.FOLDER_TYPE, | ||
92 | 51 | u'path': u'/home/tester/.ubuntuone/Purchased from Ubuntu One', | ||
93 | 52 | u'suggested_path': u'~/.ubuntuone/Purchased from Ubuntu One', | ||
94 | 45 | } | 53 | } |
95 | 46 | 54 | ||
96 | 47 | FAKE_FOLDERS_INFO = [ | 55 | FAKE_FOLDERS_INFO = [ |
97 | 48 | {u'volume_id': u'0', u'path': u'/home/tester/foo', | 56 | {u'volume_id': u'0', u'path': u'/home/tester/foo', |
99 | 49 | u'suggested_path': u'~/foo', u'subscribed': u'', u'type': u'UDF'}, | 57 | u'suggested_path': u'~/foo', u'subscribed': u'', |
100 | 58 | u'type': ControlBackend.FOLDER_TYPE}, | ||
101 | 50 | {u'volume_id': u'1', u'path': u'/home/tester/bar', | 59 | {u'volume_id': u'1', u'path': u'/home/tester/bar', |
103 | 51 | u'suggested_path': u'~/bar', u'subscribed': u'True', u'type': u'UDF'}, | 60 | u'suggested_path': u'~/bar', u'subscribed': u'True', |
104 | 61 | u'type': ControlBackend.FOLDER_TYPE}, | ||
105 | 52 | {u'volume_id': u'2', u'path': u'/home/tester/baz', | 62 | {u'volume_id': u'2', u'path': u'/home/tester/baz', |
107 | 53 | u'suggested_path': u'~/baz', u'subscribed': u'True', u'type': u'UDF'}, | 63 | u'suggested_path': u'~/baz', u'subscribed': u'True', |
108 | 64 | u'type': ControlBackend.FOLDER_TYPE}, | ||
109 | 54 | ] | 65 | ] |
110 | 55 | 66 | ||
111 | 56 | FAKE_SHARES_INFO = [ | 67 | FAKE_SHARES_INFO = [ |
112 | 57 | {u'volume_id': u'1234', u'name': u'do', | 68 | {u'volume_id': u'1234', u'name': u'do', |
113 | 58 | u'path': u'/home/tester/.local/share/ubuntuone/shares/do from Other User', | 69 | u'path': u'/home/tester/.local/share/ubuntuone/shares/do from Other User', |
115 | 59 | u'subscribed': u'', u'type': u'SHARE'}, | 70 | u'subscribed': u'', u'type': ControlBackend.SHARE_TYPE}, |
116 | 60 | 71 | ||
117 | 61 | {u'volume_id': u'5678', u'name': u're', | 72 | {u'volume_id': u'5678', u'name': u're', |
118 | 62 | u'path': u'/home/tester/.local/share/ubuntuone/shares/re from Other User', | 73 | u'path': u'/home/tester/.local/share/ubuntuone/shares/re from Other User', |
120 | 63 | u'subscribed': u'True', u'type': u'SHARE'}, | 74 | u'subscribed': u'True', u'type': ControlBackend.SHARE_TYPE}, |
121 | 64 | ] | 75 | ] |
122 | 65 | 76 | ||
123 | 66 | FAKE_VOLUMES_INFO = [ | 77 | FAKE_VOLUMES_INFO = [ |
124 | 67 | 78 | ||
125 | === modified file 'ubuntuone/controlpanel/gtk/tests/test_gui.py' | |||
126 | --- ubuntuone/controlpanel/gtk/tests/test_gui.py 2011-02-28 23:24:53 +0000 | |||
127 | +++ ubuntuone/controlpanel/gtk/tests/test_gui.py 2011-03-01 15:44:47 +0000 | |||
128 | @@ -23,577 +23,19 @@ | |||
129 | 23 | from ubuntuone.controlpanel.gtk import gui | 23 | from ubuntuone.controlpanel.gtk import gui |
130 | 24 | from ubuntuone.controlpanel.gtk.tests import (FAKE_ACCOUNT_INFO, | 24 | from ubuntuone.controlpanel.gtk.tests import (FAKE_ACCOUNT_INFO, |
131 | 25 | FAKE_DEVICE_INFO, FAKE_DEVICES_INFO, FAKE_FOLDERS_INFO, | 25 | FAKE_DEVICE_INFO, FAKE_DEVICES_INFO, FAKE_FOLDERS_INFO, |
134 | 26 | FAKE_VOLUMES_INFO, FAKE_REPLICATIONS_INFO, ROOT, USER_HOME, | 26 | FAKE_VOLUMES_INFO, FAKE_REPLICATIONS_INFO, |
135 | 27 | BaseTestCase, FakedSSOBackend, FakedConfirmDialog, | 27 | MUSIC_FOLDER, ROOT, USER_HOME, |
136 | 28 | FakedConfirmDialog, | ||
137 | 29 | ) | ||
138 | 30 | from ubuntuone.controlpanel.gtk.tests.test_gui_basic import ( | ||
139 | 31 | ControlPanelMixinTestCase, | ||
140 | 28 | ) | 32 | ) |
141 | 29 | from ubuntuone.controlpanel.gtk.tests.test_package_manager import ( | 33 | from ubuntuone.controlpanel.gtk.tests.test_package_manager import ( |
142 | 30 | SUCCESS, FAILURE) | 34 | SUCCESS, FAILURE) |
143 | 31 | from ubuntuone.controlpanel.tests import TOKEN | ||
144 | 32 | 35 | ||
145 | 33 | 36 | ||
146 | 34 | # Attribute 'yyy' defined outside __init__, access to a protected member | 37 | # Attribute 'yyy' defined outside __init__, access to a protected member |
147 | 35 | # pylint: disable=W0201, W0212 | 38 | # pylint: disable=W0201, W0212 |
148 | 36 | # Too many lines in module | ||
149 | 37 | # pylint: disable=C0302 | ||
150 | 38 | |||
151 | 39 | |||
152 | 40 | class ControlPanelMixinTestCase(BaseTestCase): | ||
153 | 41 | """The test suite for the control panel widget.""" | ||
154 | 42 | |||
155 | 43 | klass = gui.ControlPanelMixin | ||
156 | 44 | ui_filename = None | ||
157 | 45 | |||
158 | 46 | def test_is_a_control_panel_mixin(self): | ||
159 | 47 | """Inherits from ControlPanelMixin.""" | ||
160 | 48 | self.assertIsInstance(self.ui, gui.ControlPanelMixin) | ||
161 | 49 | |||
162 | 50 | def test_ui_can_be_created(self): | ||
163 | 51 | """UI main class exists and can be created.""" | ||
164 | 52 | self.assertTrue(self.ui is not None) | ||
165 | 53 | |||
166 | 54 | |||
167 | 55 | class ControlPanelWindowTestCase(BaseTestCase): | ||
168 | 56 | """The test suite for the control panel window.""" | ||
169 | 57 | |||
170 | 58 | klass = gui.ControlPanelWindow | ||
171 | 59 | |||
172 | 60 | def test_is_a_window(self): | ||
173 | 61 | """Inherits from gtk.Window.""" | ||
174 | 62 | self.assertIsInstance(self.ui, gui.gtk.Window) | ||
175 | 63 | |||
176 | 64 | def test_startup_visibility(self): | ||
177 | 65 | """The widget is visible at startup.""" | ||
178 | 66 | self.assertTrue(self.ui.get_visible(), 'must be visible at startup.') | ||
179 | 67 | |||
180 | 68 | def test_main_start_gtk_main_loop(self): | ||
181 | 69 | """The GTK main loop is started when calling main().""" | ||
182 | 70 | self.patch(gui.gtk, 'main', self._set_called) | ||
183 | 71 | self.ui.main() | ||
184 | 72 | self.assertEqual(self._called, ((), {}), 'gtk.main was called.') | ||
185 | 73 | |||
186 | 74 | def test_closing_stops_the_main_lopp(self): | ||
187 | 75 | """The GTK main loop is stopped when closing the window.""" | ||
188 | 76 | self.patch(gui.gtk, 'main_quit', self._set_called) | ||
189 | 77 | self.ui.emit('delete-event', None) | ||
190 | 78 | self.assertEqual(self._called, ((), {}), 'gtk.main_quit was called.') | ||
191 | 79 | |||
192 | 80 | def test_title_is_correct(self): | ||
193 | 81 | """The window title is correct.""" | ||
194 | 82 | expected = self.ui.TITLE % {'app_name': gui.U1_APP_NAME} | ||
195 | 83 | self.assertEqual(self.ui.get_title(), expected) | ||
196 | 84 | |||
197 | 85 | def test_control_panel_is_the_only_child(self): | ||
198 | 86 | """The control panel is the window's content.""" | ||
199 | 87 | children = self.ui.get_children() | ||
200 | 88 | self.assertEqual(1, len(children)) | ||
201 | 89 | |||
202 | 90 | control_panel = self.ui.get_children()[0] | ||
203 | 91 | self.assertTrue(control_panel is self.ui.control_panel) | ||
204 | 92 | self.assertIsInstance(self.ui.control_panel, gui.ControlPanel) | ||
205 | 93 | self.assertTrue(self.ui.control_panel.get_visible()) | ||
206 | 94 | |||
207 | 95 | def test_main_window_is_passed_to_child(self): | ||
208 | 96 | """The child gets the main_window.""" | ||
209 | 97 | self.assertEqual(self.ui.control_panel.main_window, self.ui) | ||
210 | 98 | |||
211 | 99 | def test_icon_name_is_correct(self): | ||
212 | 100 | """The icon name is correct.""" | ||
213 | 101 | self.assertEqual(self.ui.get_icon_name(), 'ubuntuone') | ||
214 | 102 | |||
215 | 103 | def test_max_size(self): | ||
216 | 104 | """Max size is not bigger than 736x525 (LP: #645526, LP: #683164).""" | ||
217 | 105 | self.assertTrue(self.ui.get_size_request() <= (736, 525)) | ||
218 | 106 | |||
219 | 107 | |||
220 | 108 | class ControlPanelWindowParamsTestCase(ControlPanelWindowTestCase): | ||
221 | 109 | """The test suite for the control panel window when passing params.""" | ||
222 | 110 | |||
223 | 111 | kwargs = {'switch_to': 'devices'} | ||
224 | 112 | |||
225 | 113 | def test_switch_to(self): | ||
226 | 114 | """Can pass a 'switch_to' parameter to start on a particular tab.""" | ||
227 | 115 | actual = self.ui.control_panel.management.notebook.get_current_page() | ||
228 | 116 | self.assertEqual(actual, self.ui.control_panel.management.DEVICES_PAGE) | ||
229 | 117 | |||
230 | 118 | |||
231 | 119 | class ControlPanelWindowParamsNoneTestCase(ControlPanelWindowTestCase): | ||
232 | 120 | """The suite for the control panel window when passing None params.""" | ||
233 | 121 | |||
234 | 122 | kwargs = {'switch_to': None} | ||
235 | 123 | |||
236 | 124 | def test_switch_to(self): | ||
237 | 125 | """Can pass a 'switch_to' being None. Should default to dashboard.""" | ||
238 | 126 | actual = self.ui.control_panel.management.notebook.get_current_page() | ||
239 | 127 | expected = self.ui.control_panel.management.DASHBOARD_PAGE | ||
240 | 128 | self.assertEqual(actual, expected) | ||
241 | 129 | |||
242 | 130 | |||
243 | 131 | class ControlPanelWindowInvalidParamsTestCase(ControlPanelWindowTestCase): | ||
244 | 132 | """The suite for the control panel window when passing invalid params.""" | ||
245 | 133 | |||
246 | 134 | kwargs = {'switch_to': 'yadda-yadda'} | ||
247 | 135 | |||
248 | 136 | def test_switch_to(self): | ||
249 | 137 | """Can pass an invalid 'switch_to'. Should default to dashboard.""" | ||
250 | 138 | actual = self.ui.control_panel.management.notebook.get_current_page() | ||
251 | 139 | expected = self.ui.control_panel.management.DASHBOARD_PAGE | ||
252 | 140 | self.assertEqual(actual, expected) | ||
253 | 141 | |||
254 | 142 | |||
255 | 143 | class ControlPanelTestCase(BaseTestCase): | ||
256 | 144 | """The test suite for the control panel itself.""" | ||
257 | 145 | |||
258 | 146 | klass = gui.ControlPanel | ||
259 | 147 | kwargs = {'main_window': object()} | ||
260 | 148 | |||
261 | 149 | def assert_current_tab_correct(self, expected_tab): | ||
262 | 150 | """Check that the wiget 'expected_tab' is the current page.""" | ||
263 | 151 | actual = self.ui.get_nth_page(self.ui.get_current_page()) | ||
264 | 152 | self.assertTrue(expected_tab is actual) | ||
265 | 153 | |||
266 | 154 | def test_is_a_notebook(self): | ||
267 | 155 | """Inherits from gtk.VBox.""" | ||
268 | 156 | self.assertIsInstance(self.ui, gui.gtk.Notebook) | ||
269 | 157 | |||
270 | 158 | def test_startup_visibility(self): | ||
271 | 159 | """The widget is visible at startup.""" | ||
272 | 160 | self.assertTrue(self.ui.get_visible(), | ||
273 | 161 | 'must be visible at startup.') | ||
274 | 162 | |||
275 | 163 | def test_startup_props(self): | ||
276 | 164 | """The tabs and border are not shown.""" | ||
277 | 165 | self.assertFalse(self.ui.get_show_border(), 'must not show border.') | ||
278 | 166 | self.assertFalse(self.ui.get_show_tabs(), 'must not show tabs.') | ||
279 | 167 | |||
280 | 168 | def test_overview_is_shown_at_startup(self): | ||
281 | 169 | """The overview is shown at startup.""" | ||
282 | 170 | self.assertIsInstance(self.ui.overview, gui.OverviewPanel) | ||
283 | 171 | self.assert_current_tab_correct(self.ui.overview) | ||
284 | 172 | |||
285 | 173 | def test_main_window_is_passed_to_child(self): | ||
286 | 174 | """The child gets the main_window.""" | ||
287 | 175 | self.assertEqual(self.ui.overview.main_window, | ||
288 | 176 | self.kwargs['main_window']) | ||
289 | 177 | |||
290 | 178 | def test_on_show_management_panel(self): | ||
291 | 179 | """A ManagementPanel is shown when the callback is executed.""" | ||
292 | 180 | self.ui.on_show_management_panel() | ||
293 | 181 | self.assert_current_tab_correct(self.ui.management) | ||
294 | 182 | |||
295 | 183 | def test_on_show_management_panel_is_idempotent(self): | ||
296 | 184 | """Only one ManagementPanel is shown.""" | ||
297 | 185 | self.ui.on_show_management_panel() | ||
298 | 186 | self.ui.on_show_management_panel() | ||
299 | 187 | |||
300 | 188 | self.assert_current_tab_correct(self.ui.management) | ||
301 | 189 | |||
302 | 190 | def test_credentials_found_shows_dashboard_management_panel(self): | ||
303 | 191 | """On 'credentials-found' signal, the management panel is shown. | ||
304 | 192 | |||
305 | 193 | If first signal parameter is False, visible tab should be dashboard. | ||
306 | 194 | |||
307 | 195 | """ | ||
308 | 196 | self.patch(self.ui.management, 'load', self._set_called) | ||
309 | 197 | self.ui.overview.emit('credentials-found', False, object()) | ||
310 | 198 | |||
311 | 199 | self.assert_current_tab_correct(self.ui.management) | ||
312 | 200 | self.assertEqual(self.ui.management.notebook.get_current_page(), | ||
313 | 201 | self.ui.management.DASHBOARD_PAGE) | ||
314 | 202 | self.assertEqual(self._called, ((), {})) | ||
315 | 203 | |||
316 | 204 | def test_credentials_found_shows_volumes_management_panel(self): | ||
317 | 205 | """On 'credentials-found' signal, the management panel is shown. | ||
318 | 206 | |||
319 | 207 | If first signal parameter is True, visible tab should be volumes. | ||
320 | 208 | |||
321 | 209 | """ | ||
322 | 210 | a_token = object() | ||
323 | 211 | self.ui.overview.emit('credentials-found', True, a_token) | ||
324 | 212 | |||
325 | 213 | self.assert_current_tab_correct(self.ui.management) | ||
326 | 214 | self.assertEqual(self.ui.management.notebook.get_current_page(), | ||
327 | 215 | self.ui.management.VOLUMES_PAGE) | ||
328 | 216 | |||
329 | 217 | def test_local_device_removed_shows_overview_panel(self): | ||
330 | 218 | """On 'local-device-removed' signal, the overview panel is shown.""" | ||
331 | 219 | self.ui.overview.emit('credentials-found', True, object()) | ||
332 | 220 | self.ui.management.emit('local-device-removed') | ||
333 | 221 | |||
334 | 222 | self.assert_current_tab_correct(self.ui.overview) | ||
335 | 223 | |||
336 | 224 | |||
337 | 225 | class UbuntuOneBinTestCase(BaseTestCase): | ||
338 | 226 | """The test suite for a Ubuntu One panel.""" | ||
339 | 227 | |||
340 | 228 | klass = gui.UbuntuOneBin | ||
341 | 229 | kwargs = {'title': 'Something old, something new and something blue.'} | ||
342 | 230 | |||
343 | 231 | def test_is_a_vbox(self): | ||
344 | 232 | """Inherits from proper gtk widget.""" | ||
345 | 233 | self.assertIsInstance(self.ui, gui.gtk.VBox) | ||
346 | 234 | |||
347 | 235 | def test_startup_visibility(self): | ||
348 | 236 | """The widget is visible at startup.""" | ||
349 | 237 | self.assertTrue(self.ui.get_visible(), | ||
350 | 238 | 'must be visible at startup.') | ||
351 | 239 | for child in self.ui.get_children(): | ||
352 | 240 | self.assertTrue(child.get_visible()) | ||
353 | 241 | |||
354 | 242 | def test_title_is_a_panel_title(self): | ||
355 | 243 | """Title is the correct widget.""" | ||
356 | 244 | self.assertIsInstance(self.ui.title, gui.PanelTitle) | ||
357 | 245 | self.assertIn(self.ui.title, self.ui.get_children()) | ||
358 | 246 | |||
359 | 247 | def test_title_markup_is_correct(self): | ||
360 | 248 | """The title markup is correctly set when passed as argument.""" | ||
361 | 249 | self.assertEqual(self.ui.title.label.get_text(), self.kwargs['title']) | ||
362 | 250 | |||
363 | 251 | def test_title_is_correct(self): | ||
364 | 252 | """The title markup is correctly set when defined at class level.""" | ||
365 | 253 | ui = self.klass() # no title given | ||
366 | 254 | self.assertEqual(ui.title.label.get_text(), '') | ||
367 | 255 | |||
368 | 256 | def test_message_is_a_label_loading(self): | ||
369 | 257 | """Message is the correct widget.""" | ||
370 | 258 | self.assertIsInstance(self.ui.message, gui.LabelLoading) | ||
371 | 259 | self.assertIn(self.ui.message, self.ui.get_children()) | ||
372 | 260 | |||
373 | 261 | def test_on_success(self): | ||
374 | 262 | """Callback to stop the Loading and clear messages.""" | ||
375 | 263 | self.ui.on_success() | ||
376 | 264 | self.assertEqual(self.ui.message.get_label(), '') | ||
377 | 265 | self.assertFalse(self.ui.message.active) | ||
378 | 266 | |||
379 | 267 | def test_on_success_with_message(self): | ||
380 | 268 | """Callback to stop the Loading and show a info message.""" | ||
381 | 269 | msg = 'WOW! <i>this rocks</i>' | ||
382 | 270 | self.ui.on_success(message=msg) | ||
383 | 271 | self.assertEqual(self.ui.message.get_label(), msg) | ||
384 | 272 | self.assertFalse(self.ui.message.active) | ||
385 | 273 | |||
386 | 274 | def test_on_error(self): | ||
387 | 275 | """Callback to stop the Loading and clear messages.""" | ||
388 | 276 | self.ui.on_error() | ||
389 | 277 | self.assert_warning_correct(self.ui.message, gui.VALUE_ERROR) | ||
390 | 278 | self.assertFalse(self.ui.message.active) | ||
391 | 279 | |||
392 | 280 | def test_on_error_with_message(self): | ||
393 | 281 | """Callback to stop the Loading and show a info message.""" | ||
394 | 282 | msg = 'WOW! <i>this does not rock</i> :-/' | ||
395 | 283 | self.ui.on_error(message=msg) | ||
396 | 284 | self.assert_warning_correct(self.ui.message, msg) | ||
397 | 285 | self.assertFalse(self.ui.message.active) | ||
398 | 286 | |||
399 | 287 | def test_is_processing(self): | ||
400 | 288 | """The flag 'is_processing' is False on start.""" | ||
401 | 289 | self.assertFalse(self.ui.is_processing) | ||
402 | 290 | self.assertTrue(self.ui.is_sensitive()) | ||
403 | 291 | |||
404 | 292 | def test_set_is_processing(self): | ||
405 | 293 | """When setting 'is_processing', the spinner is shown.""" | ||
406 | 294 | self.ui.is_processing = False | ||
407 | 295 | self.ui.is_processing = True | ||
408 | 296 | |||
409 | 297 | self.assertTrue(self.ui.message.get_visible()) | ||
410 | 298 | self.assertTrue(self.ui.message.active) | ||
411 | 299 | self.assertFalse(self.ui.is_sensitive()) | ||
412 | 300 | |||
413 | 301 | def test_unset_is_processing(self): | ||
414 | 302 | """When unsetting 'is_processing', the spinner is not shown.""" | ||
415 | 303 | self.ui.is_processing = True | ||
416 | 304 | self.ui.is_processing = False | ||
417 | 305 | |||
418 | 306 | self.assertTrue(self.ui.message.get_visible()) | ||
419 | 307 | self.assertFalse(self.ui.message.active) | ||
420 | 308 | self.assertTrue(self.ui.is_sensitive()) | ||
421 | 309 | |||
422 | 310 | |||
423 | 311 | class OverwiewPanelTestCase(ControlPanelMixinTestCase): | ||
424 | 312 | """The test suite for the overview panel.""" | ||
425 | 313 | |||
426 | 314 | klass = gui.OverviewPanel | ||
427 | 315 | kwargs = {'main_window': gui.gtk.Window()} | ||
428 | 316 | ui_filename = 'overview.ui' | ||
429 | 317 | |||
430 | 318 | def test_is_a_greyable_bin(self): | ||
431 | 319 | """Inherits from GreyableBin.""" | ||
432 | 320 | self.assertIsInstance(self.ui, gui.GreyableBin) | ||
433 | 321 | |||
434 | 322 | def test_inner_widget_is_packed(self): | ||
435 | 323 | """The 'itself' vbox is packed into the widget.""" | ||
436 | 324 | self.assertIn(self.ui.itself, self.ui.get_children()) | ||
437 | 325 | |||
438 | 326 | def test_join_now_is_default(self): | ||
439 | 327 | """The 'join_now' button is the default widget.""" | ||
440 | 328 | self.assertTrue(self.ui.join_now_button.get_property('can-default')) | ||
441 | 329 | |||
442 | 330 | def test_sso_backend(self): | ||
443 | 331 | """Has a correct SSO backend.""" | ||
444 | 332 | self.assertIsInstance(self.ui.sso_backend, FakedSSOBackend) | ||
445 | 333 | |||
446 | 334 | def test_sso_backend_signals(self): | ||
447 | 335 | """The proper signals are connected to the backend.""" | ||
448 | 336 | self.assertEqual(self.ui.sso_backend._signals['CredentialsFound'], | ||
449 | 337 | [self.ui.on_credentials_found]) | ||
450 | 338 | self.assertEqual(self.ui.sso_backend._signals['CredentialsNotFound'], | ||
451 | 339 | [self.ui.on_credentials_not_found]) | ||
452 | 340 | self.assertEqual(self.ui.sso_backend._signals['CredentialsError'], | ||
453 | 341 | [self.ui.on_credentials_error]) | ||
454 | 342 | self.assertEqual(self.ui.sso_backend._signals['AuthorizationDenied'], | ||
455 | 343 | [self.ui.on_authorization_denied]) | ||
456 | 344 | |||
457 | 345 | |||
458 | 346 | class OverwiewNetworkStatePanelTestCase(OverwiewPanelTestCase): | ||
459 | 347 | """The test suite for the overview panel regarding network state.""" | ||
460 | 348 | |||
461 | 349 | def test_network_state_is_created(self): | ||
462 | 350 | """The network state is created.""" | ||
463 | 351 | self.assertIsInstance(self.ui.network_manager_state, | ||
464 | 352 | gui.networkstate.NetworkManagerState) | ||
465 | 353 | self.assertEqual(self.ui.network_manager_state._kwargs['result_cb'], | ||
466 | 354 | self.ui.on_network_state_changed) | ||
467 | 355 | |||
468 | 356 | def test_network_state_is_queried_at_startup(self): | ||
469 | 357 | """The network state is asked to the NetworkManagerState.""" | ||
470 | 358 | self.assertTrue('find_online_state' in | ||
471 | 359 | self.ui.network_manager_state._called) | ||
472 | 360 | |||
473 | 361 | def test_state_online(self): | ||
474 | 362 | """Network connection is online.""" | ||
475 | 363 | self.ui.on_network_state_changed(gui.networkstate.ONLINE) | ||
476 | 364 | # all green, no warning | ||
477 | 365 | self.assertEqual(self.ui.warning_label.get_text(), '') | ||
478 | 366 | self.assertTrue(self.ui.get_sensitive()) | ||
479 | 367 | |||
480 | 368 | def test_state_offline(self): | ||
481 | 369 | """Network connection is offline.""" | ||
482 | 370 | self.ui.on_network_state_changed(gui.networkstate.OFFLINE) | ||
483 | 371 | msg = self.ui.NETWORK_OFFLINE % {'app_name': gui.U1_APP_NAME} | ||
484 | 372 | |||
485 | 373 | self.assert_warning_correct(self.ui.warning_label, msg) | ||
486 | 374 | self.assertFalse(self.ui.get_sensitive()) | ||
487 | 375 | |||
488 | 376 | def test_state_unknown(self): | ||
489 | 377 | """Network connection is unknown.""" | ||
490 | 378 | self.ui.on_network_state_changed(gui.networkstate.UNKNOWN) | ||
491 | 379 | |||
492 | 380 | self.assert_warning_correct(self.ui.warning_label, | ||
493 | 381 | self.ui.NETWORK_UNKNOWN) | ||
494 | 382 | self.assertFalse(self.ui.get_sensitive()) | ||
495 | 383 | |||
496 | 384 | |||
497 | 385 | class OverwiewPanelOnlineTestCase(OverwiewPanelTestCase): | ||
498 | 386 | """The test suite for the overview panel.""" | ||
499 | 387 | |||
500 | 388 | def setUp(self): | ||
501 | 389 | super(OverwiewPanelOnlineTestCase, self).setUp() | ||
502 | 390 | self.ui.on_network_state_changed(gui.networkstate.ONLINE) | ||
503 | 391 | |||
504 | 392 | def test_find_credentials_is_called(self): | ||
505 | 393 | """Credentials are asked to SSO backend.""" | ||
506 | 394 | self.assertFalse(self.ui._credentials_are_new) | ||
507 | 395 | self.assert_backend_called('find_credentials', (gui.U1_APP_NAME, {}), | ||
508 | 396 | backend=self.ui.sso_backend) | ||
509 | 397 | |||
510 | 398 | def test_on_credentials_found(self): | ||
511 | 399 | """Callback 'on_credentials_found' is correct.""" | ||
512 | 400 | self.ui.connect('credentials-found', self._set_called) | ||
513 | 401 | |||
514 | 402 | self.ui.on_credentials_found(gui.U1_APP_NAME, TOKEN) | ||
515 | 403 | |||
516 | 404 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | ||
517 | 405 | # assume credentials were in local keyring | ||
518 | 406 | self.assertEqual(self._called, ((self.ui, False, TOKEN), {})) | ||
519 | 407 | |||
520 | 408 | def test_on_credentials_found_when_creds_are_not_new(self): | ||
521 | 409 | """Callback 'on_credentials_found' distinguish if creds are new.""" | ||
522 | 410 | self.ui.connect('credentials-found', self._set_called) | ||
523 | 411 | |||
524 | 412 | # credentials weren't in the system | ||
525 | 413 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | ||
526 | 414 | # now they are! | ||
527 | 415 | self.ui.on_credentials_found(gui.U1_APP_NAME, TOKEN) | ||
528 | 416 | |||
529 | 417 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | ||
530 | 418 | # assume credentials were not in local keyring | ||
531 | 419 | self.assertEqual(self._called, ((self.ui, True, TOKEN), {})) | ||
532 | 420 | |||
533 | 421 | def test_on_credentials_not_found(self): | ||
534 | 422 | """Callback 'on_credentials_not_found' is correct.""" | ||
535 | 423 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | ||
536 | 424 | self.assertTrue(self.ui.get_visible()) | ||
537 | 425 | self.assertTrue(self.ui._credentials_are_new) | ||
538 | 426 | |||
539 | 427 | def test_on_credentials_error(self): | ||
540 | 428 | """Callback 'on_credentials_error' is correct.""" | ||
541 | 429 | self.ui.on_credentials_error(gui.U1_APP_NAME, {}) | ||
542 | 430 | self.assertTrue(self.ui.get_visible()) | ||
543 | 431 | self.assert_warning_correct(self.ui.warning_label, | ||
544 | 432 | self.ui.CREDENTIALS_ERROR) | ||
545 | 433 | |||
546 | 434 | def test_on_authorization_denied(self): | ||
547 | 435 | """Callback 'on_authorization_denied' is correct.""" | ||
548 | 436 | self.ui.on_authorization_denied(gui.U1_APP_NAME) | ||
549 | 437 | self.assertTrue(self.ui.get_visible()) | ||
550 | 438 | self.assert_warning_correct(self.ui.warning_label, | ||
551 | 439 | self.ui.AUTHORIZATION_DENIED) | ||
552 | 440 | |||
553 | 441 | |||
554 | 442 | class OverwiewPanelAppNameMismatchTestCase(OverwiewPanelTestCase): | ||
555 | 443 | """The test suite for the overview panel when the app_name won't match.""" | ||
556 | 444 | |||
557 | 445 | NOT_U1_APP = 'Not ' + gui.U1_APP_NAME | ||
558 | 446 | |||
559 | 447 | def test_filter_by_app_name(self): | ||
560 | 448 | """The filter_by_app_name decorator is correct.""" | ||
561 | 449 | f = gui.filter_by_app_name(self._set_called) | ||
562 | 450 | f(self.ui, self.NOT_U1_APP) | ||
563 | 451 | self.assertFalse(self._called) | ||
564 | 452 | self.assertTrue(self.memento.check_info('ignoring', self.NOT_U1_APP)) | ||
565 | 453 | |||
566 | 454 | args = ('test', object()) | ||
567 | 455 | kwargs = {'really': 'AWESOME'} | ||
568 | 456 | f(self.ui, gui.U1_APP_NAME, *args, **kwargs) | ||
569 | 457 | self.assertEqual(self._called, | ||
570 | 458 | ((self.ui, gui.U1_APP_NAME,) + args, kwargs)) | ||
571 | 459 | |||
572 | 460 | def test_on_credentials_found(self): | ||
573 | 461 | """Callback 'on_credentials_found' is not executed.""" | ||
574 | 462 | self.assert_function_decorated(gui.filter_by_app_name, | ||
575 | 463 | self.ui.on_credentials_found) | ||
576 | 464 | |||
577 | 465 | def test_on_credentials_not_found(self): | ||
578 | 466 | """Callback 'on_credentials_not_found' is not executed.""" | ||
579 | 467 | self.assert_function_decorated(gui.filter_by_app_name, | ||
580 | 468 | self.ui.on_credentials_not_found) | ||
581 | 469 | |||
582 | 470 | def test_on_credentials_error(self): | ||
583 | 471 | """Callback 'on_credentials_error' is not executed.""" | ||
584 | 472 | self.assert_function_decorated(gui.filter_by_app_name, | ||
585 | 473 | self.ui.on_credentials_error) | ||
586 | 474 | |||
587 | 475 | def test_on_authorization_denied(self): | ||
588 | 476 | """Callback 'on_authorization_denied' is not executed.""" | ||
589 | 477 | self.assert_function_decorated(gui.filter_by_app_name, | ||
590 | 478 | self.ui.on_authorization_denied) | ||
591 | 479 | |||
592 | 480 | |||
593 | 481 | class OverwiewPanelNoCredsTestCase(OverwiewPanelTestCase): | ||
594 | 482 | """The test suite for the overview panel when no credentials are found.""" | ||
595 | 483 | |||
596 | 484 | def setUp(self): | ||
597 | 485 | super(OverwiewPanelNoCredsTestCase, self).setUp() | ||
598 | 486 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | ||
599 | 487 | |||
600 | 488 | def test_startup_visibility(self): | ||
601 | 489 | """The widget is visible at startup.""" | ||
602 | 490 | self.assertTrue(self.ui.get_visible(), | ||
603 | 491 | 'must be visible at startup if credentials not found.') | ||
604 | 492 | |||
605 | 493 | def test_warning_label_is_hidden(self): | ||
606 | 494 | """The warning label is not shown by default.""" | ||
607 | 495 | self.assertEqual(self.ui.warning_label.get_text(), '') | ||
608 | 496 | |||
609 | 497 | def test_image_is_correct(self): | ||
610 | 498 | """There is an image attribute and is correct.""" | ||
611 | 499 | self.assert_image_equal(self.ui.image, 'overview.png') | ||
612 | 500 | |||
613 | 501 | def test_join_now_is_default_widget(self): | ||
614 | 502 | """The join now button is the default widget.""" | ||
615 | 503 | self.assertTrue(self.ui.join_now_button.get_property('can_default')) | ||
616 | 504 | |||
617 | 505 | def test_join_now_button_clicked(self): | ||
618 | 506 | """Test the 'join now' button callback.""" | ||
619 | 507 | self.kwargs['main_window'].show() # ensure parent window is realized | ||
620 | 508 | self.addCleanup(self.kwargs['main_window'].hide) | ||
621 | 509 | |||
622 | 510 | self.ui.join_now_button.clicked() | ||
623 | 511 | |||
624 | 512 | window_id = self.kwargs['main_window'].window.xid | ||
625 | 513 | args = (gui.U1_APP_NAME, | ||
626 | 514 | {gui.TC_URL_KEY: gui.U1_TC_URL, | ||
627 | 515 | gui.HELP_TEXT_KEY: gui.U1_DESCRIPTION, | ||
628 | 516 | gui.WINDOW_ID_KEY: str(window_id), | ||
629 | 517 | gui.PING_URL_KEY: gui.U1_PING_URL}) | ||
630 | 518 | self.assert_backend_called('register', args, | ||
631 | 519 | backend=self.ui.sso_backend) | ||
632 | 520 | |||
633 | 521 | def test_connect_button_clicked(self): | ||
634 | 522 | """Test the 'join now' button callback.""" | ||
635 | 523 | self.kwargs['main_window'].show() # ensure parent window is realized | ||
636 | 524 | self.addCleanup(self.kwargs['main_window'].hide) | ||
637 | 525 | |||
638 | 526 | self.ui.connect_button.clicked() | ||
639 | 527 | |||
640 | 528 | window_id = self.kwargs['main_window'].window.xid | ||
641 | 529 | args = (gui.U1_APP_NAME, | ||
642 | 530 | {gui.TC_URL_KEY: gui.U1_TC_URL, | ||
643 | 531 | gui.HELP_TEXT_KEY: gui.U1_DESCRIPTION, | ||
644 | 532 | gui.WINDOW_ID_KEY: str(window_id), | ||
645 | 533 | gui.PING_URL_KEY: gui.U1_PING_URL}) | ||
646 | 534 | self.assert_backend_called('login', args, | ||
647 | 535 | backend=self.ui.sso_backend) | ||
648 | 536 | |||
649 | 537 | def test_join_now_button_clicked_set_greyed(self): | ||
650 | 538 | """Clicking on 'join_now' self is greyed.""" | ||
651 | 539 | self.ui.join_now_button.clicked() | ||
652 | 540 | self.assertTrue(self.ui.get_property('greyed'), 'Must be greyed.') | ||
653 | 541 | |||
654 | 542 | def test_join_now_button_clicked_removes_warning(self): | ||
655 | 543 | """Clicking on 'join_now' the warnings are removed.""" | ||
656 | 544 | self.ui.on_authorization_denied(gui.U1_APP_NAME) # show warning | ||
657 | 545 | self.ui.join_now_button.clicked() | ||
658 | 546 | |||
659 | 547 | self.assertEqual(self.ui.warning_label.get_text(), '') | ||
660 | 548 | |||
661 | 549 | def test_connect_button_clicked_set_greyed(self): | ||
662 | 550 | """Clicking on 'connect' self is greyed.""" | ||
663 | 551 | self.ui.connect_button.clicked() | ||
664 | 552 | self.assertTrue(self.ui.get_property('greyed'), 'Must be greyed.') | ||
665 | 553 | |||
666 | 554 | def test_connect_button_clicked_removes_warning(self): | ||
667 | 555 | """Clicking on 'connect' the warnings are removed.""" | ||
668 | 556 | self.ui.on_authorization_denied(gui.U1_APP_NAME) # show warning | ||
669 | 557 | self.ui.connect_button.clicked() | ||
670 | 558 | |||
671 | 559 | self.assertEqual(self.ui.warning_label.get_text(), '') | ||
672 | 560 | |||
673 | 561 | def test_on_credentials_not_found_unset_greyed(self): | ||
674 | 562 | """Callback 'on_credentials_not_found' unsets the 'greyed' prop.""" | ||
675 | 563 | self.ui.connect_button.clicked() | ||
676 | 564 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | ||
677 | 565 | |||
678 | 566 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | ||
679 | 567 | |||
680 | 568 | def test_on_credentials_error_unset_greyed(self): | ||
681 | 569 | """Callback 'on_credentials_error' unsets the 'greyed' prop.""" | ||
682 | 570 | self.ui.connect_button.clicked() | ||
683 | 571 | self.ui.on_credentials_error(gui.U1_APP_NAME, {}) | ||
684 | 572 | |||
685 | 573 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | ||
686 | 574 | |||
687 | 575 | def test_on_authorization_denied_unset_greyed(self): | ||
688 | 576 | """Callback 'on_authorization_denied' unsets the 'greyed' prop.""" | ||
689 | 577 | self.ui.connect_button.clicked() | ||
690 | 578 | self.ui.on_authorization_denied(gui.U1_APP_NAME) | ||
691 | 579 | |||
692 | 580 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | ||
693 | 581 | |||
694 | 582 | def test_buttons_disabled_when_greyed(self): | ||
695 | 583 | """Buttons should be disabled when widget is greyed.""" | ||
696 | 584 | self.ui.set_sensitive(True) | ||
697 | 585 | self.ui.set_property('greyed', True) | ||
698 | 586 | |||
699 | 587 | self.assertFalse(self.ui.join_now_button.is_sensitive()) | ||
700 | 588 | self.assertFalse(self.ui.connect_button.is_sensitive()) | ||
701 | 589 | |||
702 | 590 | def test_buttons_enabled_when_not_greyed(self): | ||
703 | 591 | """Buttons should be enabled when widget is not greyed.""" | ||
704 | 592 | self.ui.set_sensitive(False) | ||
705 | 593 | self.ui.set_property('greyed', False) | ||
706 | 594 | |||
707 | 595 | self.assertTrue(self.ui.join_now_button.is_sensitive()) | ||
708 | 596 | self.assertTrue(self.ui.connect_button.is_sensitive()) | ||
709 | 597 | 39 | ||
710 | 598 | 40 | ||
711 | 599 | class DashboardTestCase(ControlPanelMixinTestCase): | 41 | class DashboardTestCase(ControlPanelMixinTestCase): |
712 | @@ -842,6 +284,35 @@ | |||
713 | 842 | self.assertEqual(self._called, | 284 | self.assertEqual(self._called, |
714 | 843 | ((None, gui.FILE_URI_PREFIX + ROOT['path']), {})) | 285 | ((None, gui.FILE_URI_PREFIX + ROOT['path']), {})) |
715 | 844 | 286 | ||
716 | 287 | def test_on_volumes_info_ready_with_music_folder(self): | ||
717 | 288 | """The volumes info is processed when ready.""" | ||
718 | 289 | info = [(u'', u'147852369', [ROOT] + [MUSIC_FOLDER])] | ||
719 | 290 | |||
720 | 291 | self.ui.on_volumes_info_ready(info) | ||
721 | 292 | |||
722 | 293 | treeiter = self.ui.volumes_store.get_iter_root() | ||
723 | 294 | row = self.ui.volumes_store.get(treeiter, *xrange(self.ui.MAX_COLS)) | ||
724 | 295 | |||
725 | 296 | # walk 'Mine' folders children | ||
726 | 297 | treeiter = self.ui.volumes_store.iter_children(treeiter) | ||
727 | 298 | |||
728 | 299 | # grab next row since first one is root | ||
729 | 300 | treeiter = self.ui.volumes_store.iter_next(treeiter) | ||
730 | 301 | row = self.ui.volumes_store.get(treeiter, *xrange(self.ui.MAX_COLS)) | ||
731 | 302 | |||
732 | 303 | volume = MUSIC_FOLDER | ||
733 | 304 | expected_path = volume['path'].replace(USER_HOME, '~') | ||
734 | 305 | expected_path = expected_path.replace(self.ui.MUSIC_REAL_PATH, | ||
735 | 306 | self.ui.MUSIC_DISPLAY_NAME) | ||
736 | 307 | self.assertEqual(row[0], expected_path) | ||
737 | 308 | self.assertEqual(row[1], bool(volume['subscribed'])) | ||
738 | 309 | self.assertEqual(row[2], self.ui.MUSIC_ICON_NAME) | ||
739 | 310 | self.assertTrue(row[3], 'toggle should be shown on child!') | ||
740 | 311 | self.assertTrue(row[4], 'toggle should be sensitive') | ||
741 | 312 | self.assertEqual(row[5], gui.gtk.ICON_SIZE_MENU) | ||
742 | 313 | self.assertEqual(row[6], volume['volume_id']) | ||
743 | 314 | self.assertEqual(row[7], volume['path']) | ||
744 | 315 | |||
745 | 845 | 316 | ||
746 | 846 | class VolumesSubscriptionTestCase(VolumesTestCase): | 317 | class VolumesSubscriptionTestCase(VolumesTestCase): |
747 | 847 | """The test suite for the volumes panel.""" | 318 | """The test suite for the volumes panel.""" |
748 | 848 | 319 | ||
749 | === added file 'ubuntuone/controlpanel/gtk/tests/test_gui_basic.py' | |||
750 | --- ubuntuone/controlpanel/gtk/tests/test_gui_basic.py 1970-01-01 00:00:00 +0000 | |||
751 | +++ ubuntuone/controlpanel/gtk/tests/test_gui_basic.py 2011-03-01 15:44:47 +0000 | |||
752 | @@ -0,0 +1,588 @@ | |||
753 | 1 | # -*- coding: utf-8 -*- | ||
754 | 2 | |||
755 | 3 | # Authors: Natalia B Bidart <natalia.bidart@canonical.com> | ||
756 | 4 | # | ||
757 | 5 | # Copyright 2010 Canonical Ltd. | ||
758 | 6 | # | ||
759 | 7 | # This program is free software: you can redistribute it and/or modify it | ||
760 | 8 | # under the terms of the GNU General Public License version 3, as published | ||
761 | 9 | # by the Free Software Foundation. | ||
762 | 10 | # | ||
763 | 11 | # This program is distributed in the hope that it will be useful, but | ||
764 | 12 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
765 | 13 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
766 | 14 | # PURPOSE. See the GNU General Public License for more details. | ||
767 | 15 | # | ||
768 | 16 | # You should have received a copy of the GNU General Public License along | ||
769 | 17 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
770 | 18 | |||
771 | 19 | """The test suite for the control panel user interface (basics).""" | ||
772 | 20 | |||
773 | 21 | from __future__ import division | ||
774 | 22 | |||
775 | 23 | from ubuntuone.controlpanel.gtk import gui | ||
776 | 24 | from ubuntuone.controlpanel.gtk.tests import BaseTestCase, FakedSSOBackend | ||
777 | 25 | from ubuntuone.controlpanel.tests import TOKEN | ||
778 | 26 | |||
779 | 27 | |||
780 | 28 | # Attribute 'yyy' defined outside __init__, access to a protected member | ||
781 | 29 | # pylint: disable=W0201, W0212 | ||
782 | 30 | |||
783 | 31 | |||
784 | 32 | class ControlPanelMixinTestCase(BaseTestCase): | ||
785 | 33 | """The test suite for the control panel widget.""" | ||
786 | 34 | |||
787 | 35 | klass = gui.ControlPanelMixin | ||
788 | 36 | ui_filename = None | ||
789 | 37 | |||
790 | 38 | def test_is_a_control_panel_mixin(self): | ||
791 | 39 | """Inherits from ControlPanelMixin.""" | ||
792 | 40 | self.assertIsInstance(self.ui, gui.ControlPanelMixin) | ||
793 | 41 | |||
794 | 42 | def test_ui_can_be_created(self): | ||
795 | 43 | """UI main class exists and can be created.""" | ||
796 | 44 | self.assertTrue(self.ui is not None) | ||
797 | 45 | |||
798 | 46 | |||
799 | 47 | class ControlPanelWindowTestCase(BaseTestCase): | ||
800 | 48 | """The test suite for the control panel window.""" | ||
801 | 49 | |||
802 | 50 | klass = gui.ControlPanelWindow | ||
803 | 51 | |||
804 | 52 | def test_is_a_window(self): | ||
805 | 53 | """Inherits from gtk.Window.""" | ||
806 | 54 | self.assertIsInstance(self.ui, gui.gtk.Window) | ||
807 | 55 | |||
808 | 56 | def test_startup_visibility(self): | ||
809 | 57 | """The widget is visible at startup.""" | ||
810 | 58 | self.assertTrue(self.ui.get_visible(), 'must be visible at startup.') | ||
811 | 59 | |||
812 | 60 | def test_main_start_gtk_main_loop(self): | ||
813 | 61 | """The GTK main loop is started when calling main().""" | ||
814 | 62 | self.patch(gui.gtk, 'main', self._set_called) | ||
815 | 63 | self.ui.main() | ||
816 | 64 | self.assertEqual(self._called, ((), {}), 'gtk.main was called.') | ||
817 | 65 | |||
818 | 66 | def test_closing_stops_the_main_lopp(self): | ||
819 | 67 | """The GTK main loop is stopped when closing the window.""" | ||
820 | 68 | self.patch(gui.gtk, 'main_quit', self._set_called) | ||
821 | 69 | self.ui.emit('delete-event', None) | ||
822 | 70 | self.assertEqual(self._called, ((), {}), 'gtk.main_quit was called.') | ||
823 | 71 | |||
824 | 72 | def test_title_is_correct(self): | ||
825 | 73 | """The window title is correct.""" | ||
826 | 74 | expected = self.ui.TITLE % {'app_name': gui.U1_APP_NAME} | ||
827 | 75 | self.assertEqual(self.ui.get_title(), expected) | ||
828 | 76 | |||
829 | 77 | def test_control_panel_is_the_only_child(self): | ||
830 | 78 | """The control panel is the window's content.""" | ||
831 | 79 | children = self.ui.get_children() | ||
832 | 80 | self.assertEqual(1, len(children)) | ||
833 | 81 | |||
834 | 82 | control_panel = self.ui.get_children()[0] | ||
835 | 83 | self.assertTrue(control_panel is self.ui.control_panel) | ||
836 | 84 | self.assertIsInstance(self.ui.control_panel, gui.ControlPanel) | ||
837 | 85 | self.assertTrue(self.ui.control_panel.get_visible()) | ||
838 | 86 | |||
839 | 87 | def test_main_window_is_passed_to_child(self): | ||
840 | 88 | """The child gets the main_window.""" | ||
841 | 89 | self.assertEqual(self.ui.control_panel.main_window, self.ui) | ||
842 | 90 | |||
843 | 91 | def test_icon_name_is_correct(self): | ||
844 | 92 | """The icon name is correct.""" | ||
845 | 93 | self.assertEqual(self.ui.get_icon_name(), 'ubuntuone') | ||
846 | 94 | |||
847 | 95 | def test_max_size(self): | ||
848 | 96 | """Max size is not bigger than 736x525 (LP: #645526, LP: #683164).""" | ||
849 | 97 | self.assertTrue(self.ui.get_size_request() <= (736, 525)) | ||
850 | 98 | |||
851 | 99 | |||
852 | 100 | class ControlPanelWindowParamsTestCase(ControlPanelWindowTestCase): | ||
853 | 101 | """The test suite for the control panel window when passing params.""" | ||
854 | 102 | |||
855 | 103 | kwargs = {'switch_to': 'devices'} | ||
856 | 104 | |||
857 | 105 | def test_switch_to(self): | ||
858 | 106 | """Can pass a 'switch_to' parameter to start on a particular tab.""" | ||
859 | 107 | actual = self.ui.control_panel.management.notebook.get_current_page() | ||
860 | 108 | self.assertEqual(actual, self.ui.control_panel.management.DEVICES_PAGE) | ||
861 | 109 | |||
862 | 110 | |||
863 | 111 | class ControlPanelWindowParamsNoneTestCase(ControlPanelWindowTestCase): | ||
864 | 112 | """The suite for the control panel window when passing None params.""" | ||
865 | 113 | |||
866 | 114 | kwargs = {'switch_to': None} | ||
867 | 115 | |||
868 | 116 | def test_switch_to(self): | ||
869 | 117 | """Can pass a 'switch_to' being None. Should default to dashboard.""" | ||
870 | 118 | actual = self.ui.control_panel.management.notebook.get_current_page() | ||
871 | 119 | expected = self.ui.control_panel.management.DASHBOARD_PAGE | ||
872 | 120 | self.assertEqual(actual, expected) | ||
873 | 121 | |||
874 | 122 | |||
875 | 123 | class ControlPanelWindowInvalidParamsTestCase(ControlPanelWindowTestCase): | ||
876 | 124 | """The suite for the control panel window when passing invalid params.""" | ||
877 | 125 | |||
878 | 126 | kwargs = {'switch_to': 'yadda-yadda'} | ||
879 | 127 | |||
880 | 128 | def test_switch_to(self): | ||
881 | 129 | """Can pass an invalid 'switch_to'. Should default to dashboard.""" | ||
882 | 130 | actual = self.ui.control_panel.management.notebook.get_current_page() | ||
883 | 131 | expected = self.ui.control_panel.management.DASHBOARD_PAGE | ||
884 | 132 | self.assertEqual(actual, expected) | ||
885 | 133 | |||
886 | 134 | |||
887 | 135 | class ControlPanelTestCase(BaseTestCase): | ||
888 | 136 | """The test suite for the control panel itself.""" | ||
889 | 137 | |||
890 | 138 | klass = gui.ControlPanel | ||
891 | 139 | kwargs = {'main_window': object()} | ||
892 | 140 | |||
893 | 141 | def assert_current_tab_correct(self, expected_tab): | ||
894 | 142 | """Check that the wiget 'expected_tab' is the current page.""" | ||
895 | 143 | actual = self.ui.get_nth_page(self.ui.get_current_page()) | ||
896 | 144 | self.assertTrue(expected_tab is actual) | ||
897 | 145 | |||
898 | 146 | def test_is_a_notebook(self): | ||
899 | 147 | """Inherits from gtk.VBox.""" | ||
900 | 148 | self.assertIsInstance(self.ui, gui.gtk.Notebook) | ||
901 | 149 | |||
902 | 150 | def test_startup_visibility(self): | ||
903 | 151 | """The widget is visible at startup.""" | ||
904 | 152 | self.assertTrue(self.ui.get_visible(), | ||
905 | 153 | 'must be visible at startup.') | ||
906 | 154 | |||
907 | 155 | def test_startup_props(self): | ||
908 | 156 | """The tabs and border are not shown.""" | ||
909 | 157 | self.assertFalse(self.ui.get_show_border(), 'must not show border.') | ||
910 | 158 | self.assertFalse(self.ui.get_show_tabs(), 'must not show tabs.') | ||
911 | 159 | |||
912 | 160 | def test_overview_is_shown_at_startup(self): | ||
913 | 161 | """The overview is shown at startup.""" | ||
914 | 162 | self.assertIsInstance(self.ui.overview, gui.OverviewPanel) | ||
915 | 163 | self.assert_current_tab_correct(self.ui.overview) | ||
916 | 164 | |||
917 | 165 | def test_main_window_is_passed_to_child(self): | ||
918 | 166 | """The child gets the main_window.""" | ||
919 | 167 | self.assertEqual(self.ui.overview.main_window, | ||
920 | 168 | self.kwargs['main_window']) | ||
921 | 169 | |||
922 | 170 | def test_on_show_management_panel(self): | ||
923 | 171 | """A ManagementPanel is shown when the callback is executed.""" | ||
924 | 172 | self.ui.on_show_management_panel() | ||
925 | 173 | self.assert_current_tab_correct(self.ui.management) | ||
926 | 174 | |||
927 | 175 | def test_on_show_management_panel_is_idempotent(self): | ||
928 | 176 | """Only one ManagementPanel is shown.""" | ||
929 | 177 | self.ui.on_show_management_panel() | ||
930 | 178 | self.ui.on_show_management_panel() | ||
931 | 179 | |||
932 | 180 | self.assert_current_tab_correct(self.ui.management) | ||
933 | 181 | |||
934 | 182 | def test_credentials_found_shows_dashboard_management_panel(self): | ||
935 | 183 | """On 'credentials-found' signal, the management panel is shown. | ||
936 | 184 | |||
937 | 185 | If first signal parameter is False, visible tab should be dashboard. | ||
938 | 186 | |||
939 | 187 | """ | ||
940 | 188 | self.patch(self.ui.management, 'load', self._set_called) | ||
941 | 189 | self.ui.overview.emit('credentials-found', False, object()) | ||
942 | 190 | |||
943 | 191 | self.assert_current_tab_correct(self.ui.management) | ||
944 | 192 | self.assertEqual(self.ui.management.notebook.get_current_page(), | ||
945 | 193 | self.ui.management.DASHBOARD_PAGE) | ||
946 | 194 | self.assertEqual(self._called, ((), {})) | ||
947 | 195 | |||
948 | 196 | def test_credentials_found_shows_volumes_management_panel(self): | ||
949 | 197 | """On 'credentials-found' signal, the management panel is shown. | ||
950 | 198 | |||
951 | 199 | If first signal parameter is True, visible tab should be volumes. | ||
952 | 200 | |||
953 | 201 | """ | ||
954 | 202 | a_token = object() | ||
955 | 203 | self.ui.overview.emit('credentials-found', True, a_token) | ||
956 | 204 | |||
957 | 205 | self.assert_current_tab_correct(self.ui.management) | ||
958 | 206 | self.assertEqual(self.ui.management.notebook.get_current_page(), | ||
959 | 207 | self.ui.management.VOLUMES_PAGE) | ||
960 | 208 | |||
961 | 209 | def test_local_device_removed_shows_overview_panel(self): | ||
962 | 210 | """On 'local-device-removed' signal, the overview panel is shown.""" | ||
963 | 211 | self.ui.overview.emit('credentials-found', True, object()) | ||
964 | 212 | self.ui.management.emit('local-device-removed') | ||
965 | 213 | |||
966 | 214 | self.assert_current_tab_correct(self.ui.overview) | ||
967 | 215 | |||
968 | 216 | |||
969 | 217 | class UbuntuOneBinTestCase(BaseTestCase): | ||
970 | 218 | """The test suite for a Ubuntu One panel.""" | ||
971 | 219 | |||
972 | 220 | klass = gui.UbuntuOneBin | ||
973 | 221 | kwargs = {'title': 'Something old, something new and something blue.'} | ||
974 | 222 | |||
975 | 223 | def test_is_a_vbox(self): | ||
976 | 224 | """Inherits from proper gtk widget.""" | ||
977 | 225 | self.assertIsInstance(self.ui, gui.gtk.VBox) | ||
978 | 226 | |||
979 | 227 | def test_startup_visibility(self): | ||
980 | 228 | """The widget is visible at startup.""" | ||
981 | 229 | self.assertTrue(self.ui.get_visible(), | ||
982 | 230 | 'must be visible at startup.') | ||
983 | 231 | for child in self.ui.get_children(): | ||
984 | 232 | self.assertTrue(child.get_visible()) | ||
985 | 233 | |||
986 | 234 | def test_title_is_a_panel_title(self): | ||
987 | 235 | """Title is the correct widget.""" | ||
988 | 236 | self.assertIsInstance(self.ui.title, gui.PanelTitle) | ||
989 | 237 | self.assertIn(self.ui.title, self.ui.get_children()) | ||
990 | 238 | |||
991 | 239 | def test_title_markup_is_correct(self): | ||
992 | 240 | """The title markup is correctly set when passed as argument.""" | ||
993 | 241 | self.assertEqual(self.ui.title.label.get_text(), self.kwargs['title']) | ||
994 | 242 | |||
995 | 243 | def test_title_is_correct(self): | ||
996 | 244 | """The title markup is correctly set when defined at class level.""" | ||
997 | 245 | ui = self.klass() # no title given | ||
998 | 246 | self.assertEqual(ui.title.label.get_text(), '') | ||
999 | 247 | |||
1000 | 248 | def test_message_is_a_label_loading(self): | ||
1001 | 249 | """Message is the correct widget.""" | ||
1002 | 250 | self.assertIsInstance(self.ui.message, gui.LabelLoading) | ||
1003 | 251 | self.assertIn(self.ui.message, self.ui.get_children()) | ||
1004 | 252 | |||
1005 | 253 | def test_on_success(self): | ||
1006 | 254 | """Callback to stop the Loading and clear messages.""" | ||
1007 | 255 | self.ui.on_success() | ||
1008 | 256 | self.assertEqual(self.ui.message.get_label(), '') | ||
1009 | 257 | self.assertFalse(self.ui.message.active) | ||
1010 | 258 | |||
1011 | 259 | def test_on_success_with_message(self): | ||
1012 | 260 | """Callback to stop the Loading and show a info message.""" | ||
1013 | 261 | msg = 'WOW! <i>this rocks</i>' | ||
1014 | 262 | self.ui.on_success(message=msg) | ||
1015 | 263 | self.assertEqual(self.ui.message.get_label(), msg) | ||
1016 | 264 | self.assertFalse(self.ui.message.active) | ||
1017 | 265 | |||
1018 | 266 | def test_on_error(self): | ||
1019 | 267 | """Callback to stop the Loading and clear messages.""" | ||
1020 | 268 | self.ui.on_error() | ||
1021 | 269 | self.assert_warning_correct(self.ui.message, gui.VALUE_ERROR) | ||
1022 | 270 | self.assertFalse(self.ui.message.active) | ||
1023 | 271 | |||
1024 | 272 | def test_on_error_with_message(self): | ||
1025 | 273 | """Callback to stop the Loading and show a info message.""" | ||
1026 | 274 | msg = 'WOW! <i>this does not rock</i> :-/' | ||
1027 | 275 | self.ui.on_error(message=msg) | ||
1028 | 276 | self.assert_warning_correct(self.ui.message, msg) | ||
1029 | 277 | self.assertFalse(self.ui.message.active) | ||
1030 | 278 | |||
1031 | 279 | def test_is_processing(self): | ||
1032 | 280 | """The flag 'is_processing' is False on start.""" | ||
1033 | 281 | self.assertFalse(self.ui.is_processing) | ||
1034 | 282 | self.assertTrue(self.ui.is_sensitive()) | ||
1035 | 283 | |||
1036 | 284 | def test_set_is_processing(self): | ||
1037 | 285 | """When setting 'is_processing', the spinner is shown.""" | ||
1038 | 286 | self.ui.is_processing = False | ||
1039 | 287 | self.ui.is_processing = True | ||
1040 | 288 | |||
1041 | 289 | self.assertTrue(self.ui.message.get_visible()) | ||
1042 | 290 | self.assertTrue(self.ui.message.active) | ||
1043 | 291 | self.assertFalse(self.ui.is_sensitive()) | ||
1044 | 292 | |||
1045 | 293 | def test_unset_is_processing(self): | ||
1046 | 294 | """When unsetting 'is_processing', the spinner is not shown.""" | ||
1047 | 295 | self.ui.is_processing = True | ||
1048 | 296 | self.ui.is_processing = False | ||
1049 | 297 | |||
1050 | 298 | self.assertTrue(self.ui.message.get_visible()) | ||
1051 | 299 | self.assertFalse(self.ui.message.active) | ||
1052 | 300 | self.assertTrue(self.ui.is_sensitive()) | ||
1053 | 301 | |||
1054 | 302 | |||
1055 | 303 | class OverwiewPanelTestCase(ControlPanelMixinTestCase): | ||
1056 | 304 | """The test suite for the overview panel.""" | ||
1057 | 305 | |||
1058 | 306 | klass = gui.OverviewPanel | ||
1059 | 307 | kwargs = {'main_window': gui.gtk.Window()} | ||
1060 | 308 | ui_filename = 'overview.ui' | ||
1061 | 309 | |||
1062 | 310 | def test_is_a_greyable_bin(self): | ||
1063 | 311 | """Inherits from GreyableBin.""" | ||
1064 | 312 | self.assertIsInstance(self.ui, gui.GreyableBin) | ||
1065 | 313 | |||
1066 | 314 | def test_inner_widget_is_packed(self): | ||
1067 | 315 | """The 'itself' vbox is packed into the widget.""" | ||
1068 | 316 | self.assertIn(self.ui.itself, self.ui.get_children()) | ||
1069 | 317 | |||
1070 | 318 | def test_join_now_is_default(self): | ||
1071 | 319 | """The 'join_now' button is the default widget.""" | ||
1072 | 320 | self.assertTrue(self.ui.join_now_button.get_property('can-default')) | ||
1073 | 321 | |||
1074 | 322 | def test_sso_backend(self): | ||
1075 | 323 | """Has a correct SSO backend.""" | ||
1076 | 324 | self.assertIsInstance(self.ui.sso_backend, FakedSSOBackend) | ||
1077 | 325 | |||
1078 | 326 | def test_sso_backend_signals(self): | ||
1079 | 327 | """The proper signals are connected to the backend.""" | ||
1080 | 328 | self.assertEqual(self.ui.sso_backend._signals['CredentialsFound'], | ||
1081 | 329 | [self.ui.on_credentials_found]) | ||
1082 | 330 | self.assertEqual(self.ui.sso_backend._signals['CredentialsNotFound'], | ||
1083 | 331 | [self.ui.on_credentials_not_found]) | ||
1084 | 332 | self.assertEqual(self.ui.sso_backend._signals['CredentialsError'], | ||
1085 | 333 | [self.ui.on_credentials_error]) | ||
1086 | 334 | self.assertEqual(self.ui.sso_backend._signals['AuthorizationDenied'], | ||
1087 | 335 | [self.ui.on_authorization_denied]) | ||
1088 | 336 | |||
1089 | 337 | |||
1090 | 338 | class OverwiewNetworkStatePanelTestCase(OverwiewPanelTestCase): | ||
1091 | 339 | """The test suite for the overview panel regarding network state.""" | ||
1092 | 340 | |||
1093 | 341 | def test_network_state_is_created(self): | ||
1094 | 342 | """The network state is created.""" | ||
1095 | 343 | self.assertIsInstance(self.ui.network_manager_state, | ||
1096 | 344 | gui.networkstate.NetworkManagerState) | ||
1097 | 345 | self.assertEqual(self.ui.network_manager_state._kwargs['result_cb'], | ||
1098 | 346 | self.ui.on_network_state_changed) | ||
1099 | 347 | |||
1100 | 348 | def test_network_state_is_queried_at_startup(self): | ||
1101 | 349 | """The network state is asked to the NetworkManagerState.""" | ||
1102 | 350 | self.assertTrue('find_online_state' in | ||
1103 | 351 | self.ui.network_manager_state._called) | ||
1104 | 352 | |||
1105 | 353 | def test_state_online(self): | ||
1106 | 354 | """Network connection is online.""" | ||
1107 | 355 | self.ui.on_network_state_changed(gui.networkstate.ONLINE) | ||
1108 | 356 | # all green, no warning | ||
1109 | 357 | self.assertEqual(self.ui.warning_label.get_text(), '') | ||
1110 | 358 | self.assertTrue(self.ui.get_sensitive()) | ||
1111 | 359 | |||
1112 | 360 | def test_state_offline(self): | ||
1113 | 361 | """Network connection is offline.""" | ||
1114 | 362 | self.ui.on_network_state_changed(gui.networkstate.OFFLINE) | ||
1115 | 363 | msg = self.ui.NETWORK_OFFLINE % {'app_name': gui.U1_APP_NAME} | ||
1116 | 364 | |||
1117 | 365 | self.assert_warning_correct(self.ui.warning_label, msg) | ||
1118 | 366 | self.assertFalse(self.ui.get_sensitive()) | ||
1119 | 367 | |||
1120 | 368 | def test_state_unknown(self): | ||
1121 | 369 | """Network connection is unknown.""" | ||
1122 | 370 | self.ui.on_network_state_changed(gui.networkstate.UNKNOWN) | ||
1123 | 371 | |||
1124 | 372 | self.assert_warning_correct(self.ui.warning_label, | ||
1125 | 373 | self.ui.NETWORK_UNKNOWN) | ||
1126 | 374 | self.assertFalse(self.ui.get_sensitive()) | ||
1127 | 375 | |||
1128 | 376 | |||
1129 | 377 | class OverwiewPanelOnlineTestCase(OverwiewPanelTestCase): | ||
1130 | 378 | """The test suite for the overview panel.""" | ||
1131 | 379 | |||
1132 | 380 | def setUp(self): | ||
1133 | 381 | super(OverwiewPanelOnlineTestCase, self).setUp() | ||
1134 | 382 | self.ui.on_network_state_changed(gui.networkstate.ONLINE) | ||
1135 | 383 | |||
1136 | 384 | def test_find_credentials_is_called(self): | ||
1137 | 385 | """Credentials are asked to SSO backend.""" | ||
1138 | 386 | self.assertFalse(self.ui._credentials_are_new) | ||
1139 | 387 | self.assert_backend_called('find_credentials', (gui.U1_APP_NAME, {}), | ||
1140 | 388 | backend=self.ui.sso_backend) | ||
1141 | 389 | |||
1142 | 390 | def test_on_credentials_found(self): | ||
1143 | 391 | """Callback 'on_credentials_found' is correct.""" | ||
1144 | 392 | self.ui.connect('credentials-found', self._set_called) | ||
1145 | 393 | |||
1146 | 394 | self.ui.on_credentials_found(gui.U1_APP_NAME, TOKEN) | ||
1147 | 395 | |||
1148 | 396 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | ||
1149 | 397 | # assume credentials were in local keyring | ||
1150 | 398 | self.assertEqual(self._called, ((self.ui, False, TOKEN), {})) | ||
1151 | 399 | |||
1152 | 400 | def test_on_credentials_found_when_creds_are_not_new(self): | ||
1153 | 401 | """Callback 'on_credentials_found' distinguish if creds are new.""" | ||
1154 | 402 | self.ui.connect('credentials-found', self._set_called) | ||
1155 | 403 | |||
1156 | 404 | # credentials weren't in the system | ||
1157 | 405 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | ||
1158 | 406 | # now they are! | ||
1159 | 407 | self.ui.on_credentials_found(gui.U1_APP_NAME, TOKEN) | ||
1160 | 408 | |||
1161 | 409 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | ||
1162 | 410 | # assume credentials were not in local keyring | ||
1163 | 411 | self.assertEqual(self._called, ((self.ui, True, TOKEN), {})) | ||
1164 | 412 | |||
1165 | 413 | def test_on_credentials_not_found(self): | ||
1166 | 414 | """Callback 'on_credentials_not_found' is correct.""" | ||
1167 | 415 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | ||
1168 | 416 | self.assertTrue(self.ui.get_visible()) | ||
1169 | 417 | self.assertTrue(self.ui._credentials_are_new) | ||
1170 | 418 | |||
1171 | 419 | def test_on_credentials_error(self): | ||
1172 | 420 | """Callback 'on_credentials_error' is correct.""" | ||
1173 | 421 | self.ui.on_credentials_error(gui.U1_APP_NAME, {}) | ||
1174 | 422 | self.assertTrue(self.ui.get_visible()) | ||
1175 | 423 | self.assert_warning_correct(self.ui.warning_label, | ||
1176 | 424 | self.ui.CREDENTIALS_ERROR) | ||
1177 | 425 | |||
1178 | 426 | def test_on_authorization_denied(self): | ||
1179 | 427 | """Callback 'on_authorization_denied' is correct.""" | ||
1180 | 428 | self.ui.on_authorization_denied(gui.U1_APP_NAME) | ||
1181 | 429 | self.assertTrue(self.ui.get_visible()) | ||
1182 | 430 | self.assert_warning_correct(self.ui.warning_label, | ||
1183 | 431 | self.ui.AUTHORIZATION_DENIED) | ||
1184 | 432 | |||
1185 | 433 | |||
1186 | 434 | class OverwiewPanelAppNameMismatchTestCase(OverwiewPanelTestCase): | ||
1187 | 435 | """The test suite for the overview panel when the app_name won't match.""" | ||
1188 | 436 | |||
1189 | 437 | NOT_U1_APP = 'Not ' + gui.U1_APP_NAME | ||
1190 | 438 | |||
1191 | 439 | def test_filter_by_app_name(self): | ||
1192 | 440 | """The filter_by_app_name decorator is correct.""" | ||
1193 | 441 | f = gui.filter_by_app_name(self._set_called) | ||
1194 | 442 | f(self.ui, self.NOT_U1_APP) | ||
1195 | 443 | self.assertFalse(self._called) | ||
1196 | 444 | self.assertTrue(self.memento.check_info('ignoring', self.NOT_U1_APP)) | ||
1197 | 445 | |||
1198 | 446 | args = ('test', object()) | ||
1199 | 447 | kwargs = {'really': 'AWESOME'} | ||
1200 | 448 | f(self.ui, gui.U1_APP_NAME, *args, **kwargs) | ||
1201 | 449 | self.assertEqual(self._called, | ||
1202 | 450 | ((self.ui, gui.U1_APP_NAME,) + args, kwargs)) | ||
1203 | 451 | |||
1204 | 452 | def test_on_credentials_found(self): | ||
1205 | 453 | """Callback 'on_credentials_found' is not executed.""" | ||
1206 | 454 | self.assert_function_decorated(gui.filter_by_app_name, | ||
1207 | 455 | self.ui.on_credentials_found) | ||
1208 | 456 | |||
1209 | 457 | def test_on_credentials_not_found(self): | ||
1210 | 458 | """Callback 'on_credentials_not_found' is not executed.""" | ||
1211 | 459 | self.assert_function_decorated(gui.filter_by_app_name, | ||
1212 | 460 | self.ui.on_credentials_not_found) | ||
1213 | 461 | |||
1214 | 462 | def test_on_credentials_error(self): | ||
1215 | 463 | """Callback 'on_credentials_error' is not executed.""" | ||
1216 | 464 | self.assert_function_decorated(gui.filter_by_app_name, | ||
1217 | 465 | self.ui.on_credentials_error) | ||
1218 | 466 | |||
1219 | 467 | def test_on_authorization_denied(self): | ||
1220 | 468 | """Callback 'on_authorization_denied' is not executed.""" | ||
1221 | 469 | self.assert_function_decorated(gui.filter_by_app_name, | ||
1222 | 470 | self.ui.on_authorization_denied) | ||
1223 | 471 | |||
1224 | 472 | |||
1225 | 473 | class OverwiewPanelNoCredsTestCase(OverwiewPanelTestCase): | ||
1226 | 474 | """The test suite for the overview panel when no credentials are found.""" | ||
1227 | 475 | |||
1228 | 476 | def setUp(self): | ||
1229 | 477 | super(OverwiewPanelNoCredsTestCase, self).setUp() | ||
1230 | 478 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | ||
1231 | 479 | |||
1232 | 480 | def test_startup_visibility(self): | ||
1233 | 481 | """The widget is visible at startup.""" | ||
1234 | 482 | self.assertTrue(self.ui.get_visible(), | ||
1235 | 483 | 'must be visible at startup if credentials not found.') | ||
1236 | 484 | |||
1237 | 485 | def test_warning_label_is_hidden(self): | ||
1238 | 486 | """The warning label is not shown by default.""" | ||
1239 | 487 | self.assertEqual(self.ui.warning_label.get_text(), '') | ||
1240 | 488 | |||
1241 | 489 | def test_image_is_correct(self): | ||
1242 | 490 | """There is an image attribute and is correct.""" | ||
1243 | 491 | self.assert_image_equal(self.ui.image, 'overview.png') | ||
1244 | 492 | |||
1245 | 493 | def test_join_now_is_default_widget(self): | ||
1246 | 494 | """The join now button is the default widget.""" | ||
1247 | 495 | self.assertTrue(self.ui.join_now_button.get_property('can_default')) | ||
1248 | 496 | |||
1249 | 497 | def test_join_now_button_clicked(self): | ||
1250 | 498 | """Test the 'join now' button callback.""" | ||
1251 | 499 | self.kwargs['main_window'].show() # ensure parent window is realized | ||
1252 | 500 | self.addCleanup(self.kwargs['main_window'].hide) | ||
1253 | 501 | |||
1254 | 502 | self.ui.join_now_button.clicked() | ||
1255 | 503 | |||
1256 | 504 | window_id = self.kwargs['main_window'].window.xid | ||
1257 | 505 | args = (gui.U1_APP_NAME, | ||
1258 | 506 | {gui.TC_URL_KEY: gui.U1_TC_URL, | ||
1259 | 507 | gui.HELP_TEXT_KEY: gui.U1_DESCRIPTION, | ||
1260 | 508 | gui.WINDOW_ID_KEY: str(window_id), | ||
1261 | 509 | gui.PING_URL_KEY: gui.U1_PING_URL}) | ||
1262 | 510 | self.assert_backend_called('register', args, | ||
1263 | 511 | backend=self.ui.sso_backend) | ||
1264 | 512 | |||
1265 | 513 | def test_connect_button_clicked(self): | ||
1266 | 514 | """Test the 'join now' button callback.""" | ||
1267 | 515 | self.kwargs['main_window'].show() # ensure parent window is realized | ||
1268 | 516 | self.addCleanup(self.kwargs['main_window'].hide) | ||
1269 | 517 | |||
1270 | 518 | self.ui.connect_button.clicked() | ||
1271 | 519 | |||
1272 | 520 | window_id = self.kwargs['main_window'].window.xid | ||
1273 | 521 | args = (gui.U1_APP_NAME, | ||
1274 | 522 | {gui.TC_URL_KEY: gui.U1_TC_URL, | ||
1275 | 523 | gui.HELP_TEXT_KEY: gui.U1_DESCRIPTION, | ||
1276 | 524 | gui.WINDOW_ID_KEY: str(window_id), | ||
1277 | 525 | gui.PING_URL_KEY: gui.U1_PING_URL}) | ||
1278 | 526 | self.assert_backend_called('login', args, | ||
1279 | 527 | backend=self.ui.sso_backend) | ||
1280 | 528 | |||
1281 | 529 | def test_join_now_button_clicked_set_greyed(self): | ||
1282 | 530 | """Clicking on 'join_now' self is greyed.""" | ||
1283 | 531 | self.ui.join_now_button.clicked() | ||
1284 | 532 | self.assertTrue(self.ui.get_property('greyed'), 'Must be greyed.') | ||
1285 | 533 | |||
1286 | 534 | def test_join_now_button_clicked_removes_warning(self): | ||
1287 | 535 | """Clicking on 'join_now' the warnings are removed.""" | ||
1288 | 536 | self.ui.on_authorization_denied(gui.U1_APP_NAME) # show warning | ||
1289 | 537 | self.ui.join_now_button.clicked() | ||
1290 | 538 | |||
1291 | 539 | self.assertEqual(self.ui.warning_label.get_text(), '') | ||
1292 | 540 | |||
1293 | 541 | def test_connect_button_clicked_set_greyed(self): | ||
1294 | 542 | """Clicking on 'connect' self is greyed.""" | ||
1295 | 543 | self.ui.connect_button.clicked() | ||
1296 | 544 | self.assertTrue(self.ui.get_property('greyed'), 'Must be greyed.') | ||
1297 | 545 | |||
1298 | 546 | def test_connect_button_clicked_removes_warning(self): | ||
1299 | 547 | """Clicking on 'connect' the warnings are removed.""" | ||
1300 | 548 | self.ui.on_authorization_denied(gui.U1_APP_NAME) # show warning | ||
1301 | 549 | self.ui.connect_button.clicked() | ||
1302 | 550 | |||
1303 | 551 | self.assertEqual(self.ui.warning_label.get_text(), '') | ||
1304 | 552 | |||
1305 | 553 | def test_on_credentials_not_found_unset_greyed(self): | ||
1306 | 554 | """Callback 'on_credentials_not_found' unsets the 'greyed' prop.""" | ||
1307 | 555 | self.ui.connect_button.clicked() | ||
1308 | 556 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | ||
1309 | 557 | |||
1310 | 558 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | ||
1311 | 559 | |||
1312 | 560 | def test_on_credentials_error_unset_greyed(self): | ||
1313 | 561 | """Callback 'on_credentials_error' unsets the 'greyed' prop.""" | ||
1314 | 562 | self.ui.connect_button.clicked() | ||
1315 | 563 | self.ui.on_credentials_error(gui.U1_APP_NAME, {}) | ||
1316 | 564 | |||
1317 | 565 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | ||
1318 | 566 | |||
1319 | 567 | def test_on_authorization_denied_unset_greyed(self): | ||
1320 | 568 | """Callback 'on_authorization_denied' unsets the 'greyed' prop.""" | ||
1321 | 569 | self.ui.connect_button.clicked() | ||
1322 | 570 | self.ui.on_authorization_denied(gui.U1_APP_NAME) | ||
1323 | 571 | |||
1324 | 572 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | ||
1325 | 573 | |||
1326 | 574 | def test_buttons_disabled_when_greyed(self): | ||
1327 | 575 | """Buttons should be disabled when widget is greyed.""" | ||
1328 | 576 | self.ui.set_sensitive(True) | ||
1329 | 577 | self.ui.set_property('greyed', True) | ||
1330 | 578 | |||
1331 | 579 | self.assertFalse(self.ui.join_now_button.is_sensitive()) | ||
1332 | 580 | self.assertFalse(self.ui.connect_button.is_sensitive()) | ||
1333 | 581 | |||
1334 | 582 | def test_buttons_enabled_when_not_greyed(self): | ||
1335 | 583 | """Buttons should be enabled when widget is not greyed.""" | ||
1336 | 584 | self.ui.set_sensitive(False) | ||
1337 | 585 | self.ui.set_property('greyed', False) | ||
1338 | 586 | |||
1339 | 587 | self.assertTrue(self.ui.join_now_button.is_sensitive()) | ||
1340 | 588 | self.assertTrue(self.ui.connect_button.is_sensitive()) |
+1