Merge lp:~nataliabidart/magicicada-gui/bind-more-signals into lp:magicicada-gui

Proposed by Natalia Bidart
Status: Merged
Approved by: Facundo Batista
Approved revision: 24
Merged at revision: 20
Proposed branch: lp:~nataliabidart/magicicada-gui/bind-more-signals
Merge into: lp:magicicada-gui
Diff against target: 820 lines (+525/-96)
3 files modified
data/media/active.svg (+203/-0)
magicicada/__init__.py (+56/-50)
magicicada/tests/test_magicicada.py (+266/-46)
To merge this branch: bzr merge lp:~nataliabidart/magicicada-gui/bind-more-signals
Reviewer Review Type Date Requested Status
Facundo Batista Approve
Review via email: mp+25813@code.launchpad.net

Description of the change

Binding callbacks for started/stopped, connected/disconnected, online/offline. Binding methods start/quit and connect/disconnect.

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

Tweaks.

Revision history for this message
Facundo Batista (facundo) wrote :

Go forward!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'data/media/active-016.png'
2Binary files data/media/active-016.png 1970-01-01 00:00:00 +0000 and data/media/active-016.png 2010-05-22 03:21:24 +0000 differ
3=== added file 'data/media/active.svg'
4--- data/media/active.svg 1970-01-01 00:00:00 +0000
5+++ data/media/active.svg 2010-05-22 03:21:24 +0000
6@@ -0,0 +1,203 @@
7+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
8+<!-- Created with Inkscape (http://www.inkscape.org/) -->
9+
10+<svg
11+ xmlns:dc="http://purl.org/dc/elements/1.1/"
12+ xmlns:cc="http://creativecommons.org/ns#"
13+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
14+ xmlns:svg="http://www.w3.org/2000/svg"
15+ xmlns="http://www.w3.org/2000/svg"
16+ xmlns:xlink="http://www.w3.org/1999/xlink"
17+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
18+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
19+ width="425.71429"
20+ height="461.42856"
21+ id="svg2"
22+ sodipodi:version="0.32"
23+ inkscape:version="0.47 r22583"
24+ version="1.0"
25+ sodipodi:docname="active.svg"
26+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
27+ <defs
28+ id="defs4">
29+ <linearGradient
30+ id="linearGradient3250">
31+ <stop
32+ style="stop-color:#b8b8b8;stop-opacity:0;"
33+ offset="0"
34+ id="stop3252" />
35+ <stop
36+ id="stop3258"
37+ offset="0.40588239"
38+ style="stop-color:#b8b8b8;stop-opacity:1;" />
39+ <stop
40+ style="stop-color:#b8b8b8;stop-opacity:0;"
41+ offset="1"
42+ id="stop3254" />
43+ </linearGradient>
44+ <linearGradient
45+ id="linearGradient3224">
46+ <stop
47+ style="stop-color:#ffffff;stop-opacity:1;"
48+ offset="0"
49+ id="stop3226" />
50+ <stop
51+ style="stop-color:#c8c8c8;stop-opacity:1;"
52+ offset="1"
53+ id="stop3228" />
54+ </linearGradient>
55+ <linearGradient
56+ id="linearGradient3214">
57+ <stop
58+ style="stop-color:#3b3b3b;stop-opacity:1;"
59+ offset="0"
60+ id="stop3216" />
61+ <stop
62+ style="stop-color:#afafaf;stop-opacity:1;"
63+ offset="1"
64+ id="stop3218" />
65+ </linearGradient>
66+ <linearGradient
67+ id="linearGradient3176">
68+ <stop
69+ style="stop-color:#c1ffb6;stop-opacity:1;"
70+ offset="0"
71+ id="stop3178" />
72+ <stop
73+ id="stop3184"
74+ offset="0.40630153"
75+ style="stop-color:#00e632;stop-opacity:1;" />
76+ <stop
77+ style="stop-color:#1c3a4f;stop-opacity:1"
78+ offset="1"
79+ id="stop3180" />
80+ </linearGradient>
81+ <inkscape:perspective
82+ sodipodi:type="inkscape:persp3d"
83+ inkscape:vp_x="0 : 526.18109 : 1"
84+ inkscape:vp_y="0 : 1000 : 0"
85+ inkscape:vp_z="744.09448 : 526.18109 : 1"
86+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
87+ id="perspective10" />
88+ <inkscape:perspective
89+ id="perspective2390"
90+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
91+ inkscape:vp_z="744.09448 : 526.18109 : 1"
92+ inkscape:vp_y="0 : 1000 : 0"
93+ inkscape:vp_x="0 : 526.18109 : 1"
94+ sodipodi:type="inkscape:persp3d" />
95+ <radialGradient
96+ inkscape:collect="always"
97+ xlink:href="#linearGradient3176"
98+ id="radialGradient3182"
99+ cx="346.42856"
100+ cy="338.07645"
101+ fx="346.42856"
102+ fy="338.07645"
103+ r="165.71428"
104+ gradientUnits="userSpaceOnUse"
105+ gradientTransform="matrix(-1.2831103,0.3438084,-0.3438084,-1.2831103,907.16815,652.76078)" />
106+ <radialGradient
107+ inkscape:collect="always"
108+ xlink:href="#linearGradient3214"
109+ id="radialGradient3220"
110+ cx="317.60519"
111+ cy="539.41315"
112+ fx="317.60519"
113+ fy="539.41315"
114+ r="165.53342"
115+ gradientTransform="matrix(1,0,0,0.2054734,0,428.57808)"
116+ gradientUnits="userSpaceOnUse" />
117+ <radialGradient
118+ inkscape:collect="always"
119+ xlink:href="#linearGradient3224"
120+ id="radialGradient3230"
121+ cx="317.60394"
122+ cy="220.94547"
123+ fx="317.60394"
124+ fy="220.94547"
125+ r="164.06058"
126+ gradientTransform="matrix(1.0076229,0,0,0.1968921,-2.4553843,177.59098)"
127+ gradientUnits="userSpaceOnUse" />
128+ <linearGradient
129+ inkscape:collect="always"
130+ xlink:href="#linearGradient3250"
131+ id="linearGradient3256"
132+ x1="318.47412"
133+ y1="651.00037"
134+ x2="309.90268"
135+ y2="413.85742"
136+ gradientUnits="userSpaceOnUse"
137+ spreadMethod="pad" />
138+ <radialGradient
139+ inkscape:collect="always"
140+ xlink:href="#linearGradient3214"
141+ id="radialGradient3274"
142+ gradientUnits="userSpaceOnUse"
143+ gradientTransform="matrix(1,0,0,0.2054734,11.428571,428.57808)"
144+ cx="317.60519"
145+ cy="539.41315"
146+ fx="317.60519"
147+ fy="539.41315"
148+ r="165.53342" />
149+ <radialGradient
150+ inkscape:collect="always"
151+ xlink:href="#linearGradient3224"
152+ id="radialGradient3276"
153+ gradientUnits="userSpaceOnUse"
154+ gradientTransform="matrix(1.0076229,0,0,0.1922742,8.9731871,177.85367)"
155+ cx="317.60394"
156+ cy="220.94547"
157+ fx="317.60394"
158+ fy="220.94547"
159+ r="164.06058" />
160+ </defs>
161+ <sodipodi:namedview
162+ id="base"
163+ pagecolor="#ffffff"
164+ bordercolor="#666666"
165+ borderopacity="1.0"
166+ gridtolerance="10000"
167+ guidetolerance="10"
168+ objecttolerance="10"
169+ inkscape:pageopacity="0.0"
170+ inkscape:pageshadow="2"
171+ inkscape:zoom="0.70710678"
172+ inkscape:cx="577.43933"
173+ inkscape:cy="433.43027"
174+ inkscape:document-units="px"
175+ inkscape:current-layer="layer1"
176+ showgrid="false"
177+ inkscape:window-width="1250"
178+ inkscape:window-height="775"
179+ inkscape:window-x="0"
180+ inkscape:window-y="0"
181+ inkscape:window-maximized="1" />
182+ <metadata
183+ id="metadata7">
184+ <rdf:RDF>
185+ <cc:Work
186+ rdf:about="">
187+ <dc:format>image/svg+xml</dc:format>
188+ <dc:type
189+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
190+ </cc:Work>
191+ </rdf:RDF>
192+ </metadata>
193+ <g
194+ inkscape:label="Layer 1"
195+ inkscape:groupmode="layer"
196+ id="layer1"
197+ transform="translate(-105.61697,-158.14316)">
198+ <path
199+ sodipodi:type="arc"
200+ style="opacity:1;fill:url(#radialGradient3182);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
201+ id="path2396"
202+ sodipodi:cx="323.57144"
203+ sodipodi:cy="389.50504"
204+ sodipodi:rx="165.71428"
205+ sodipodi:ry="165.71428"
206+ d="m 489.28572,389.50504 c 0,91.52146 -74.19281,165.71427 -165.71428,165.71427 -91.52147,0 -165.71428,-74.19281 -165.71428,-165.71427 0,-91.52147 74.19281,-165.71428 165.71428,-165.71428 91.52147,0 165.71428,74.19281 165.71428,165.71428 z"
207+ transform="translate(5.643371,-11.272676)" />
208+ </g>
209+</svg>
210
211=== modified file 'magicicada/__init__.py'
212--- magicicada/__init__.py 2010-05-17 16:10:28 +0000
213+++ magicicada/__init__.py 2010-05-22 03:21:24 +0000
214@@ -28,8 +28,8 @@
215 from twisted.internet import gtk2reactor # for gtk-2.0
216 gtk2reactor.install()
217
218+from magicicada import syncdaemon
219 from magicicada.helpers import get_data_file, get_builder, NO_OP
220-from magicicada.syncdaemon import SyncDaemon
221
222 CONTENT_QUEUE = 'content'
223 META_QUEUE = 'meta'
224@@ -42,7 +42,8 @@
225 'online': _('Service reached Nirvana.'),
226 }
227
228- def __init__(self, launchpad_available=False, on_destroy=NO_OP):
229+ def __init__(self, launchpad_available=False, on_destroy=NO_OP,
230+ syncdaemon_class=syncdaemon.SyncDaemon):
231 """Init."""
232 self.builder = get_builder('gui.glade')
233 self.builder.connect_signals(self)
234@@ -59,8 +60,8 @@
235
236 animation_filename = get_data_file('media', 'loader-ball.gif')
237 self.loading_animation = gtk.gdk.PixbufAnimation(animation_filename)
238-
239- self.started = self.connected = self.online = False
240+ active_filename = get_data_file('media', 'active-016.png')
241+ self.active_indicator = gtk.gdk.pixbuf_new_from_file(active_filename)
242
243 widgets = (
244 'start', 'stop', 'connect', 'disconnect', # toolbar buttons
245@@ -81,16 +82,26 @@
246
247 self.main_window.show()
248
249- self.sd = SyncDaemon()
250+ self.sd = syncdaemon_class()
251+ self.sd.on_started_callback = self.on_started
252+ self.sd.on_stopped_callback = self.on_stopped
253+ self.sd.on_connected_callback = self.on_connected
254+ self.sd.on_disconnected_callback = self.on_disconnected
255+ self.sd.on_online_callback = self.on_online
256+ self.sd.on_offline_callback = self.on_offline
257+ self.sd.status_changed_callback = self.on_status_changed
258 self.sd.content_queue_changed_callback = self.on_content_queue_changed
259 self.sd.meta_queue_changed_callback = self.on_meta_queue_changed
260
261+ self.widget_enabled = lambda w: \
262+ w.get_property('visible') and w.is_sensitive()
263+
264 # GTK callbacks
265
266 def on_main_window_destroy(self, widget, data=None):
267 """Called when the MagicicadaWindow is closed."""
268 # Clean up code for saving application state should be added here.
269- if self.started:
270+ if self.widget_enabled(self.stop):
271 self.on_stop_clicked(self.stop)
272 self.sd.shutdown()
273 self.on_destroy()
274@@ -106,46 +117,39 @@
275
276 def on_start_clicked(self, widget, data=None):
277 """Start syncdaemon."""
278- self.started = True
279- self.connect.set_sensitive(True)
280+ self.sd.start()
281 self.start.hide()
282+ self.stop.set_sensitive(False)
283 self.stop.show()
284-
285- self.doing_something(self.is_started)
286+ self.start_loading(self.is_started)
287
288 def on_stop_clicked(self, widget, data=None):
289 """Stop syncdaemon."""
290- assert self.started
291-
292- if self.connected:
293+ if self.widget_enabled(self.disconnect):
294 self.on_disconnect_clicked(self.disconnect)
295 self.connect.set_sensitive(False)
296
297- self.started = False
298 self.start.show()
299+ self.start.set_sensitive(False)
300 self.stop.hide()
301
302- self.on_stopped()
303+ self.sd.quit()
304
305 def on_connect_clicked(self, widget, data=None):
306 """Connect syncdaemon."""
307- assert self.started
308- self.connected = True
309+ self.sd.connect()
310 self.connect.hide()
311+ self.disconnect.set_sensitive(False)
312 self.disconnect.show()
313-
314- self.on_started()
315- self.doing_something(self.is_connected)
316+ self.start_loading(self.is_connected)
317
318 def on_disconnect_clicked(self, widget, data=None):
319 """Disconnect syncdaemon."""
320- assert self.started
321- assert self.connected
322- self.connected = False
323 self.connect.show()
324+ self.connect.set_sensitive(False)
325 self.disconnect.hide()
326
327- self.on_disconnected()
328+ self.sd.disconnect()
329
330 def on_status_icon_activate(self, widget, data=None):
331 """Systray icon was clicked."""
332@@ -158,43 +162,45 @@
333
334 def on_started(self, *args, **kwargs):
335 """Callback'ed when syncadaemon is started."""
336- self.stop_doing_something(self.is_started)
337- self.status_label.set_text(self.STATUS['started'])
338+ self.stop.set_sensitive(True)
339+ self.activate_indicator(self.is_started)
340+ self.connect.set_sensitive(True)
341
342 def on_stopped(self, *args, **kwargs):
343 """Callback'ed when syncadaemon is stopped."""
344-
345- self.stop_doing_something(self.is_started, sensitive=False)
346-
347- self.is_started.set_sensitive(False)
348- self.is_connected.set_sensitive(False)
349- self.is_online.set_sensitive(False)
350+ self.start.set_sensitive(True)
351+
352+ self.activate_indicator(self.is_started, sensitive=False)
353+ self.activate_indicator(self.is_connected, sensitive=False)
354+ self.activate_indicator(self.is_online, sensitive=False)
355
356 def on_connected(self, *args, **kwargs):
357 """Callback'ed when syncadaemon is connected."""
358- self.is_connected.set_sensitive(True)
359- self.doing_something(self.is_online)
360- self.status_label.set_text(self.STATUS['connected'])
361+ self.disconnect.set_sensitive(True)
362+ self.activate_indicator(self.is_connected)
363+ self.start_loading(self.is_online)
364+ self.start_loading(self.is_online)
365
366 def on_disconnected(self, *args, **kwargs):
367 """Callback'ed when syncadaemon is disconnected."""
368-
369- self.stop_doing_something(self.is_connected, sensitive=False)
370-
371- self.is_connected.set_sensitive(False)
372- self.is_online.set_sensitive(False)
373+ self.connect.set_sensitive(True)
374+
375+ self.activate_indicator(self.is_connected, sensitive=False)
376+ self.activate_indicator(self.is_online, sensitive=False)
377
378 def on_online(self, *args, **kwargs):
379 """Callback'ed when syncadaemon is online."""
380- self.is_onlined.set_sensitive(True)
381- self.status_label.set_text(self.STATUS['online'])
382+ self.is_online.set_sensitive(True)
383+ self.activate_indicator(self.is_online)
384
385 def on_offline(self, *args, **kwargs):
386 """Callback'ed when syncadaemon is offline."""
387-
388- self.stop_doing_something(self.is_online, sensitive=False)
389-
390- self.is_online.set_sensitive(False)
391+ self.activate_indicator(self.is_online, sensitive=False)
392+
393+ def on_status_changed(self, name, description, is_error, is_connected,
394+ is_online, queues, connection):
395+ """Callback'ed when the SD status changed."""
396+ self.status_label.set_text(description)
397
398 def _on_queue_changed(self, queue_name, items, *args, **kwargs):
399 """Callback'ed when a queue changed."""
400@@ -218,12 +224,12 @@
401
402 # custom
403
404- def doing_something(self, what):
405+ def start_loading(self, what):
406 """Set a loader animation on 'what'."""
407 what.set_sensitive(True)
408 what.set_from_animation(self.loading_animation)
409
410- def stop_doing_something(self, what, sensitive=True):
411- """Set a loader animation on 'what'."""
412- what.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_BUTTON)
413+ def activate_indicator(self, what, sensitive=True):
414+ """Set ready pixbuf on 'what' and make it 'sensitive'."""
415 what.set_sensitive(sensitive)
416+ what.set_from_pixbuf(self.active_indicator)
417
418=== modified file 'magicicada/tests/test_magicicada.py'
419--- magicicada/tests/test_magicicada.py 2010-05-17 16:10:28 +0000
420+++ magicicada/tests/test_magicicada.py 2010-05-22 03:21:24 +0000
421@@ -26,9 +26,8 @@
422
423 from twisted.trial.unittest import TestCase
424
425-from magicicada import MagicicadaUI, CONTENT_QUEUE, META_QUEUE
426+from magicicada import MagicicadaUI, CONTENT_QUEUE, META_QUEUE, syncdaemon
427 from magicicada.helpers import get_builder, NO_OP
428-from magicicada.syncdaemon import SyncDaemon, QueueData
429
430 DEFAULT_TIMEOUT = 200
431
432@@ -47,8 +46,20 @@
433 """A faked syncdaemon."""
434
435 def __init__(self):
436+ self.on_started_callback = NO_OP
437+ self.on_stopped_callback = NO_OP
438+ self.on_connected_callback = NO_OP
439+ self.on_disconnected_callback = NO_OP
440+ self.on_online_callback = NO_OP
441+ self.on_offline_callback = NO_OP
442+ self.status_changed_callback = NO_OP
443 self.content_queue_changed_callback = NO_OP
444 self.meta_queue_changed_callback = NO_OP
445+ self.shutdown = NO_OP
446+ self.start = NO_OP
447+ self.quit = NO_OP
448+ self.connect = NO_OP
449+ self.disconnect = NO_OP
450
451
452 class MagicicadaUITestCase(TestCase):
453@@ -57,31 +68,50 @@
454 def setUp(self):
455 """Init."""
456 self.builder = get_builder('gui.glade')
457- self.ui = MagicicadaUI()
458+ self.ui = MagicicadaUI(syncdaemon_class=FakedSyncdaemon)
459 self._called = False
460+ self.set_called = lambda *_: setattr(self, '_called', True)
461
462 def tearDown(self):
463- """Clenaup."""
464+ """Cleanup."""
465 self.ui.on_main_window_destroy(self.ui.main_window)
466 self._called = False
467 self.builder = None
468
469+ def assert_indicator_disabled(self, indicator):
470+ """Test that 'indicator' is not sensitive."""
471+ self.assertFalse(indicator.is_sensitive(), 'indicator is not sensitive')
472+
473+ def assert_indicator_ready(self, indicator):
474+ """Test that 'indicator' is sensitive and green."""
475+ self.assertTrue(indicator.is_sensitive(), 'indicator is sensitive')
476+ expected = indicator.get_pixbuf() # a test on its own
477+ self.assertEqual(self.ui.active_indicator, expected,
478+ 'indicator is the correct pixbuf')
479+
480+ def assert_indicator_loading(self, indicator):
481+ """Test that 'indicator' is sensitive and loading."""
482+ self.assertTrue(indicator.is_sensitive(), 'indicator is sensitive')
483+ expected = indicator.get_animation() # a test on its own
484+ self.assertEqual(self.ui.loading_animation, expected,
485+ 'indicator is the correct animation')
486+
487+
488+class MagicicadaUIBasicTestCase(MagicicadaUITestCase):
489+ """UI test cases for basic state."""
490+
491 def test_init_creates_sd_instance(self):
492 """SyncDaemon instance is created at creation time."""
493- self.assertTrue(isinstance(self.ui.sd, SyncDaemon))
494+ self.assertTrue(self.ui.sd is not None)
495+ self.assertTrue(isinstance(self.ui.sd, FakedSyncdaemon))
496
497 def test_destroy_shutdowns_sd_instance(self):
498 """SyncDaemon instance is shutdown at destroy time."""
499- self.patch(self.ui.sd, 'shutdown',
500- lambda *_: setattr(self, '_called', True))
501+ self.patch(self.ui.sd, 'shutdown', self.set_called)
502 self.ui.on_main_window_destroy(self.ui.main_window)
503 self.assertTrue(self._called,
504 'syncdaemon.shutdown must be called at destroy time.')
505
506-
507-class MagicicadaUIStartupTestCase(MagicicadaUITestCase):
508- """UI test cases for startup state."""
509-
510 def test_main_window_is_visible(self):
511 """UI can be created."""
512 self.assertTrue(self.ui.main_window.get_property('visible'))
513@@ -99,52 +129,110 @@
514 self.assertFalse(self.ui.stop.get_property('visible'))
515 self.assertFalse(self.ui.disconnect.get_property('visible'))
516
517- def test_not_started_not_connected_not_online(self):
518- """Test default values for flags."""
519- self.assertFalse(self.ui.started)
520- self.assertFalse(self.ui.connected)
521- self.assertFalse(self.ui.online)
522-
523 def test_indicators_are_non_sensitive(self):
524 """Test default sensitivity for indicators."""
525- #import pdb; pdb.set_trace()
526 self.assertFalse(self.ui.is_started.is_sensitive())
527 self.assertFalse(self.ui.is_connected.is_sensitive())
528 self.assertFalse(self.ui.is_online.is_sensitive())
529
530+ def test_update_is_correct(self):
531+ """Update updates."""
532+ # XXX: TODO
533+
534
535 class MagicicadaUIClickedTestCase(MagicicadaUITestCase):
536 """UI test cases."""
537
538- def test_started_if_start_clicked(self):
539- """Test started if Start was clicked."""
540+ def test_on_start_clicked(self):
541+ """Test on_start_clicked."""
542 self.ui.on_start_clicked(self.ui.start)
543- self.assertTrue(self.ui.started)
544- self.assertFalse(self.ui.connected)
545- self.assertFalse(self.ui.online)
546
547- def test_can_connect_can_stop_if_start_clicked(self):
548- """Test Connect and Stop are enabled if Start was clicked."""
549- self.ui.on_start_clicked(self.ui.start)
550 self.assertFalse(self.ui.start.get_property('visible'))
551 self.assertTrue(self.ui.stop.get_property('visible'))
552- self.assertTrue(self.ui.connect.is_sensitive())
553-
554- def test_connected_if_connect_clicked(self):
555- """Test connected if Connect was clicked."""
556- self.ui.on_start_clicked(self.ui.start) # need to be started
557- self.ui.on_connect_clicked(self.ui.connect)
558-
559- self.assertTrue(self.ui.started)
560- self.assertTrue(self.ui.connected)
561- self.assertFalse(self.ui.online)
562-
563- def test_can_disconnect_if_connect_clicked(self):
564- """Test Disconnect is enabled if Connect was clicked."""
565- self.ui.on_start_clicked(self.ui.start) # need to be started
566- self.ui.on_connect_clicked(self.ui.connect)
567+ self.assertFalse(self.ui.stop.is_sensitive())
568+
569+ self.assert_indicator_loading(self.ui.is_started)
570+ self.assert_indicator_disabled(self.ui.is_connected)
571+ self.assert_indicator_disabled(self.ui.is_online)
572+
573+ def test_on_start_clicked_starts_syncdaemon(self):
574+ """Test on_start_clicked."""
575+ self.patch(self.ui.sd, 'start', self.set_called)
576+ self.ui.on_start_clicked(self.ui.start)
577+ self.assertTrue(self._called, 'syncdaemon.start was called.')
578+
579+ def test_on_connect_clicked(self):
580+ """Test on_connect_clicked."""
581+ self.ui.on_start_clicked(self.ui.start) # need to be started
582+ self.ui.on_started()
583+ self.ui.on_connect_clicked(self.ui.connect)
584+
585 self.assertFalse(self.ui.connect.get_property('visible'))
586 self.assertTrue(self.ui.disconnect.get_property('visible'))
587+ self.assertFalse(self.ui.disconnect.is_sensitive())
588+
589+ self.assert_indicator_ready(self.ui.is_started)
590+ self.assert_indicator_loading(self.ui.is_connected)
591+ self.assert_indicator_disabled(self.ui.is_online)
592+
593+ def test_on_connect_clicked_connects_syncdaemon(self):
594+ """Test on_connect_clicked."""
595+ self.patch(self.ui.sd, 'connect', self.set_called)
596+ self.ui.on_connect_clicked(self.ui.connect)
597+ self.assertTrue(self._called, 'syncdaemon.connect was called.')
598+
599+ def test_on_stop_clicked(self):
600+ """Test on_stop_clicked."""
601+ self.ui.on_start_clicked(self.ui.start)
602+ self.ui.on_started()
603+ assert not self.ui.widget_enabled(self.ui.disconnect)
604+ self.patch(self.ui, 'on_disconnect_clicked', self.set_called)
605+ self.ui.on_stop_clicked(self.ui.stop)
606+
607+ self.assertFalse(self._called, 'on_disconnect_clicked was not called.')
608+
609+ self.assertTrue(self.ui.start.get_property('visible'))
610+ self.assertFalse(self.ui.start.is_sensitive())
611+ self.assertFalse(self.ui.stop.get_property('visible'))
612+
613+ self.assertTrue(self.ui.connect.get_property('visible'))
614+ self.assertFalse(self.ui.connect.is_sensitive())
615+ self.assertFalse(self.ui.disconnect.get_property('visible'))
616+
617+ def test_on_stop_clicked_if_connected(self):
618+ """Test on_stop_clicked."""
619+ self.ui.on_start_clicked(self.ui.start)
620+ self.ui.on_started()
621+ self.ui.on_connect_clicked(self.ui.connect)
622+ self.ui.on_connected()
623+ self.patch(self.ui, 'on_disconnect_clicked', self.set_called)
624+ self.ui.on_stop_clicked(self.ui.stop)
625+
626+ self.assertTrue(self._called, 'on_disconnect_clicked was called.')
627+
628+ def test_on_stop_clicked_stops_syncdaemon(self):
629+ """Test on_stop_clicked."""
630+ self.patch(self.ui.sd, 'quit', self.set_called)
631+ self.ui.on_stop_clicked(self.ui.stop)
632+ self.assertTrue(self._called, 'syncdaemon.quit was called.')
633+
634+ def test_on_disconnect_clicked(self):
635+ """Test on_disconnect_clicked."""
636+ self.ui.on_start_clicked(self.ui.start)
637+ self.ui.on_started()
638+ self.ui.on_connect_clicked(self.ui.connect)
639+ self.ui.on_connected()
640+ self.ui.on_disconnect_clicked(self.ui.disconnect)
641+
642+ self.assertTrue(self.ui.connect.get_property('visible'))
643+ self.assertFalse(self.ui.connect.is_sensitive())
644+ self.assertFalse(self.ui.disconnect.get_property('visible'))
645+
646+ def test_on_disconnect_clicked_disconnects_syncdaemon(self):
647+ """Test on_disconnect_clicked."""
648+ self.patch(self.ui.sd, 'disconnect', self.set_called)
649+ self.ui.on_disconnect_clicked(self.ui.disconnect)
650+ self.assertTrue(self._called, 'syncdaemon.disconnect was called.')
651
652
653 class MagicicadaUISystrayIconTestCase(MagicicadaUITestCase):
654@@ -165,7 +253,7 @@
655
656
657 class _MagicicadaUIQueueTestCase(MagicicadaUITestCase):
658- """Abstratc UI test cases for a queue views."""
659+ """Abstratc UI test cases for queue tree views."""
660
661 queue = None
662
663@@ -183,8 +271,9 @@
664 """Build some data to pass to queue changed callback."""
665 items = []
666 for i in xrange(limit):
667- cq = QueueData(operation='operation %i' % i, path='path %i' % i,
668- node='node %i' % i, share='share %i' % i)
669+ cq = syncdaemon.QueueData(operation='operation %i' % i,
670+ path='path %i' % i, node='node %i' % i,
671+ share='share %i' % i)
672 items.append(cq)
673 return items
674
675@@ -242,12 +331,143 @@
676
677
678 class MagicicadaUIContentQueueTestCase(_MagicicadaUIQueueTestCase):
679- """UI test cases for content queue views."""
680+ """UI test cases for content queue view."""
681
682 queue = CONTENT_QUEUE
683
684
685 class MagicicadaUIMetaQueueTestCase(_MagicicadaUIQueueTestCase):
686- """UI test cases for meta queue views."""
687+ """UI test cases for meta queue view."""
688
689 queue = META_QUEUE
690+
691+
692+class MagicicadaUIStatusTestCase(MagicicadaUITestCase):
693+ """UI test cases for the status label."""
694+
695+ def setUp(self):
696+ """Init."""
697+ super(MagicicadaUIStatusTestCase, self).setUp()
698+
699+ def test_callback_is_connected(self):
700+ """Status callback is connected."""
701+ self.assertEqual(self.ui.sd.status_changed_callback,
702+ self.ui.on_status_changed,
703+ 'status_changed callback must be set')
704+
705+ def test_on_status_changed_updates_status_label(self):
706+ """On status changed the status label is updated."""
707+ kwargs = dict(name='test', description='the status for testing',
708+ is_error=False, is_connected=True, is_online=False,
709+ queues=None, connection=None)
710+ self.ui.on_status_changed(**kwargs)
711+ self.assertEqual(self.ui.status_label.get_text(), kwargs['description'])
712+
713+
714+class MagicicadaUIConnectionTestCase(MagicicadaUITestCase):
715+ """UI test cases for."""
716+
717+ def setUp(self):
718+ """Init."""
719+ super(MagicicadaUIConnectionTestCase, self).setUp()
720+
721+ def test_all_disabled_at_startup(self):
722+ """Indicators are all disabled at startup."""
723+ self.assert_indicator_disabled(self.ui.is_started)
724+ self.assert_indicator_disabled(self.ui.is_connected)
725+ self.assert_indicator_disabled(self.ui.is_online)
726+
727+ def test_callback_are_connected(self):
728+ """Connection callbacks are connected."""
729+ for callback in ('on_started', 'on_stopped',
730+ 'on_connected', 'on_disconnected',
731+ 'on_online', 'on_offline'):
732+ sd_cb = getattr(self.ui.sd, '%s_callback' % callback)
733+ ui_cb = getattr(self.ui, callback)
734+ self.assertEqual(sd_cb, ui_cb,
735+ '%s callback must be set' % callback)
736+
737+ def test_on_started_is_correct(self):
738+ """On SD started, the UI enables connect and indicator."""
739+ # must have click start first
740+ self.ui.on_start_clicked(self.ui.start)
741+ assert not self.ui.stop.is_sensitive()
742+ assert not self.ui.connect.is_sensitive()
743+
744+ self.ui.on_started()
745+
746+ self.assertTrue(self.ui.stop.is_sensitive())
747+ self.assertTrue(self.ui.connect.is_sensitive())
748+ self.assert_indicator_ready(self.ui.is_started)
749+ self.assert_indicator_disabled(self.ui.is_connected)
750+ self.assert_indicator_disabled(self.ui.is_online)
751+
752+ def test_on_connected_is_correct(self):
753+ """On SD connected, the UI enables indicator."""
754+ self.ui.on_start_clicked(self.ui.start)
755+ self.ui.on_started()
756+ self.ui.on_connect_clicked(self.ui.start)
757+ assert not self.ui.disconnect.is_sensitive()
758+
759+ self.ui.on_connected()
760+
761+ self.assertTrue(self.ui.disconnect.is_sensitive())
762+ self.assert_indicator_ready(self.ui.is_started)
763+ self.assert_indicator_ready(self.ui.is_connected)
764+ self.assert_indicator_loading(self.ui.is_online)
765+
766+ def test_on_online_is_correct(self):
767+ """On SD online, the UI enables indicator."""
768+ self.ui.on_start_clicked(self.ui.start)
769+ self.ui.on_started()
770+ self.ui.on_connect_clicked(self.ui.connect)
771+ self.ui.on_connected()
772+
773+ self.ui.on_online()
774+
775+ self.assert_indicator_ready(self.ui.is_started)
776+ self.assert_indicator_ready(self.ui.is_connected)
777+ self.assert_indicator_ready(self.ui.is_online)
778+
779+ def test_on_stopped_is_correct(self):
780+ """On SD stopped, the UI disables stop and indicator."""
781+ self.ui.on_start_clicked(self.ui.start)
782+ self.ui.on_started()
783+ self.ui.on_stop_clicked(self.ui.stop)
784+
785+ self.ui.on_stopped()
786+
787+ self.assertTrue(self.ui.start.is_sensitive())
788+ self.assertTrue(self.ui.start.get_property('visible'))
789+ self.assert_indicator_disabled(self.ui.is_started)
790+ self.assert_indicator_disabled(self.ui.is_connected)
791+ self.assert_indicator_disabled(self.ui.is_online)
792+
793+ def test_on_disconnected_is_correct(self):
794+ """On SD disconnected, the UI disables connect and indicator."""
795+ self.ui.on_start_clicked(self.ui.start)
796+ self.ui.on_started()
797+ self.ui.on_connect_clicked(self.ui.connect)
798+ self.ui.on_connected()
799+ self.ui.on_disconnect_clicked(self.ui.disconnect)
800+
801+ self.ui.on_disconnected()
802+
803+ self.assertTrue(self.ui.connect.is_sensitive())
804+ self.assert_indicator_ready(self.ui.is_started)
805+ self.assert_indicator_disabled(self.ui.is_connected)
806+ self.assert_indicator_disabled(self.ui.is_online)
807+
808+ def test_on_offline_is_correct(self):
809+ """On SD offline, the UI disables indicator."""
810+ self.ui.on_start_clicked(self.ui.start)
811+ self.ui.on_started()
812+ self.ui.on_connect_clicked(self.ui.connect)
813+ self.ui.on_connected()
814+
815+ self.ui.on_offline()
816+
817+ self.assert_indicator_ready(self.ui.is_started)
818+ self.assert_indicator_ready(self.ui.is_connected)
819+ self.assert_indicator_disabled(self.ui.is_online)
820+

Subscribers

People subscribed via source and target branches

to all changes: