Merge lp:~nataliabidart/ubuntuone-control-panel/autoupdate into lp:ubuntuone-control-panel

Proposed by Natalia Bidart on 2012-04-05
Status: Merged
Approved by: Natalia Bidart on 2012-04-05
Approved revision: 313
Merged at revision: 310
Proposed branch: lp:~nataliabidart/ubuntuone-control-panel/autoupdate
Merge into: lp:ubuntuone-control-panel
Diff against target: 255 lines (+130/-7)
5 files modified
ubuntuone/controlpanel/gui/__init__.py (+4/-0)
ubuntuone/controlpanel/gui/qt/gui.py (+26/-2)
ubuntuone/controlpanel/gui/qt/tests/__init__.py (+7/-0)
ubuntuone/controlpanel/gui/qt/tests/test_gui.py (+76/-5)
ubuntuone/controlpanel/gui/qt/tests/test_start.py (+17/-0)
To merge this branch: bzr merge lp:~nataliabidart/ubuntuone-control-panel/autoupdate
Reviewer Review Type Date Requested Status
Diego Sarmentero (community) Approve on 2012-04-05
Manuel de la Peña (community) 2012-04-05 Approve on 2012-04-05
Review via email: mp+100989@code.launchpad.net

Commit Message

- Check for updates when the main window is shown. On linux, this is a no
operation. On windows, this will check for new versions of the software and
will prompt the user for confirmation to install updates (LP: #971455).

To post a comment you must log in.
Manuel de la Peña (mandel) wrote :

Looks great!

review: Approve
Diego Sarmentero (diegosarmentero) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ubuntuone/controlpanel/gui/__init__.py'
2--- ubuntuone/controlpanel/gui/__init__.py 2012-03-29 16:56:35 +0000
3+++ ubuntuone/controlpanel/gui/__init__.py 2012-04-05 15:24:17 +0000
4@@ -247,6 +247,10 @@
5 VALUE_ERROR = _('Value could not be retrieved.')
6 UNKNOWN_ERROR = _('Unknown error')
7 USAGE_LABEL = _('%(used)s of %(total)s')
8+# TODO: mark the following strings translatable after precise is released
9+UPDATE_TITLE = APP_NAME
10+UPDATE_SOFTWARE = ('There is a new update available.'
11+ ' Would you like to install it?')
12 QUIT_LABEL = _('Quit Ubuntu One')
13
14 # pylint: enable=E0602
15
16=== modified file 'ubuntuone/controlpanel/gui/qt/gui.py'
17--- ubuntuone/controlpanel/gui/qt/gui.py 2012-03-29 19:05:02 +0000
18+++ ubuntuone/controlpanel/gui/qt/gui.py 2012-04-05 15:24:17 +0000
19@@ -18,9 +18,13 @@
20
21 from PyQt4 import QtGui, QtCore
22
23+from twisted.internet import defer
24+
25+from ubuntuone.controlpanel import utils
26+from ubuntuone.controlpanel.logger import setup_logging
27+from ubuntuone.controlpanel.gui import UPDATE_TITLE, UPDATE_SOFTWARE
28 from ubuntuone.controlpanel.gui.qt.systray import TrayIcon
29 from ubuntuone.controlpanel.gui.qt.ui import mainwindow_ui
30-from ubuntuone.controlpanel.utils import add_to_autostart
31
32 # pylint: disable=E0611
33 try:
34@@ -30,6 +34,8 @@
35 USE_LIBUNITY = False
36 # pylint: enable=E0611
37
38+logger = setup_logging('qt.gui')
39+
40 U1_DOTDESKTOP = "ubuntuone-installer.desktop"
41
42
43@@ -49,7 +55,7 @@
44 self.installer = installer
45 if installer:
46 self.ui.control_panel.start_from_license()
47- add_to_autostart()
48+ utils.add_to_autostart()
49 if USE_LIBUNITY:
50 self.entry = Unity.LauncherEntry.get_for_desktop_id(U1_DOTDESKTOP)
51 else:
52@@ -87,6 +93,23 @@
53
54 # pylint: enable=C0103
55
56+ @defer.inlineCallbacks
57+ def check_updates(self):
58+ """Offer the user to update if there are updates available."""
59+ logger.debug('Checking for updates.')
60+ are_present = yield utils.are_updates_present()
61+ logger.info('Updates available? %r', are_present)
62+ if are_present:
63+ buttons = QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
64+ result = QtGui.QMessageBox.question(self, UPDATE_TITLE,
65+ UPDATE_SOFTWARE,
66+ buttons, QtGui.QMessageBox.Yes)
67+ if result == QtGui.QMessageBox.Yes:
68+ logger.info('Performing auto-update.')
69+ utils.perform_update()
70+ else:
71+ logger.info('User do not want to update.')
72+
73
74 def start(close_callback, minimized=False, with_icon=False, installer=False):
75 """Show the UI elements."""
76@@ -102,6 +125,7 @@
77 QtCore.Qt.LeftToRight, QtCore.Qt.AlignCenter,
78 window.size(), app.desktop().availableGeometry())
79 window.setGeometry(style)
80+ window.check_updates()
81 window.show()
82 else:
83 window = None
84
85=== modified file 'ubuntuone/controlpanel/gui/qt/tests/__init__.py'
86--- ubuntuone/controlpanel/gui/qt/tests/__init__.py 2012-03-28 12:06:28 +0000
87+++ ubuntuone/controlpanel/gui/qt/tests/__init__.py 2012-04-05 15:24:17 +0000
88@@ -210,6 +210,13 @@
89 cls.kwargs = kw
90 return cls.response
91
92+ @classmethod
93+ def question(cls, *a, **kw):
94+ """Simulate a question message."""
95+ cls.args = a
96+ cls.kwargs = kw
97+ return cls.response
98+
99 # Invalid name "setDetailedText", "setDefaultButton"
100 # pylint: disable=C0103
101
102
103=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_gui.py'
104--- ubuntuone/controlpanel/gui/qt/tests/test_gui.py 2012-03-26 13:30:07 +0000
105+++ ubuntuone/controlpanel/gui/qt/tests/test_gui.py 2012-04-05 15:24:17 +0000
106@@ -1,8 +1,6 @@
107 # -*- coding: utf-8 -*-
108-
109-# Authors: Alejandro J. Cura <alecu@canonical.com>
110 #
111-# Copyright 2011 Canonical Ltd.
112+# Copyright 2011-2012 Canonical Ltd.
113 #
114 # This program is free software: you can redistribute it and/or modify it
115 # under the terms of the GNU General Public License version 3, as published
116@@ -21,7 +19,7 @@
117 from twisted.internet import defer
118
119 from ubuntuone.controlpanel.gui.qt import gui
120-from ubuntuone.controlpanel.gui.qt.tests import BaseTestCase
121+from ubuntuone.controlpanel.gui.qt.tests import BaseTestCase, FakedDialog
122
123
124 class FakeEntry(object):
125@@ -119,13 +117,86 @@
126 self.assertEqual(entry.called, (('urgent', "foo"), {}))
127
128
129+class CheckUpdatesNoUpdatesTestCase(MainWindowTestCase):
130+ """Test the check_updates method when there are no updates."""
131+
132+ updates_available = False
133+
134+ @defer.inlineCallbacks
135+ def setUp(self):
136+ """Set the different tests."""
137+ yield super(CheckUpdatesNoUpdatesTestCase, self).setUp()
138+ self.patch(gui.utils, 'are_updates_present',
139+ lambda: defer.succeed(self.updates_available))
140+ self.patch(gui.utils, 'perform_update',
141+ lambda: defer.fail(ValueError()))
142+
143+ @defer.inlineCallbacks
144+ def test_update_confirmation_dialog(self):
145+ """The confirmation dialog is not shown."""
146+ yield self.ui.check_updates()
147+ self.assertEqual(None, FakedDialog.args)
148+ self.assertEqual(None, FakedDialog.kwargs)
149+
150+ @defer.inlineCallbacks
151+ def test_perform_update(self):
152+ """The perform_update method is not called."""
153+ yield self.ui.check_updates()
154+ self.assertFalse(self._called)
155+
156+
157+class CheckUpdatesUserSaysNoTestCase(CheckUpdatesNoUpdatesTestCase):
158+ """Test check_updates when there are updates and user rejects them."""
159+
160+ updates_available = True
161+ user_response = gui.QtGui.QMessageBox.No
162+
163+ @defer.inlineCallbacks
164+ def setUp(self):
165+ """Set the different tests."""
166+ yield super(CheckUpdatesUserSaysNoTestCase, self).setUp()
167+ self.patch(FakedDialog, 'response', self.user_response)
168+
169+ @defer.inlineCallbacks
170+ def test_update_confirmation_dialog(self):
171+ """The confirmation dialog is shown with correct params."""
172+ yield self.ui.check_updates()
173+ args = (self.ui, gui.UPDATE_TITLE, gui.UPDATE_SOFTWARE,
174+ gui.QtGui.QMessageBox.Yes | gui.QtGui.QMessageBox.No,
175+ gui.QtGui.QMessageBox.Yes)
176+ self.assertEqual(args, FakedDialog.args)
177+ self.assertEqual({}, FakedDialog.kwargs)
178+
179+
180+class CheckUpdatesUserSaysYesTestCase(CheckUpdatesUserSaysNoTestCase):
181+ """Test check_updates when there are updates and user accepts them."""
182+
183+ user_response = gui.QtGui.QMessageBox.Yes
184+
185+ @defer.inlineCallbacks
186+ def setUp(self):
187+ """Set the different tests."""
188+ self.updated = defer.Deferred()
189+ yield super(CheckUpdatesUserSaysYesTestCase, self).setUp()
190+ self.patch(gui.utils, 'perform_update',
191+ lambda *a, **kw: self.updated.callback((a, kw)))
192+
193+ @defer.inlineCallbacks
194+ def test_perform_update(self):
195+ """The perform_update method is called."""
196+ yield self.ui.check_updates()
197+ result = yield self.updated # perform_update will fire this deferred
198+
199+ self.assertEqual(result, ((), {}))
200+
201+
202 class AutoStartTestCase(MainWindowTestCase):
203 """Test the add_to_autostart call."""
204
205 @defer.inlineCallbacks
206 def setUp(self):
207 # Be sure to patch add_to_autostart *before* class_ui creation occurs.
208- self.patch(gui, "add_to_autostart", self._set_called)
209+ self.patch(gui.utils, "add_to_autostart", self._set_called)
210 yield super(AutoStartTestCase, self).setUp()
211
212 def test_add_to_autostart(self):
213
214=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_start.py'
215--- ubuntuone/controlpanel/gui/qt/tests/test_start.py 2012-03-20 19:13:28 +0000
216+++ ubuntuone/controlpanel/gui/qt/tests/test_start.py 2012-04-05 15:24:17 +0000
217@@ -34,6 +34,7 @@
218
219 def __init__(self):
220 self.args = []
221+ self.updates_checked = defer.Deferred()
222
223 def __call__(self, *args, **kwargs):
224 self.args.append((args, kwargs))
225@@ -50,10 +51,17 @@
226 """Save the new geometry."""
227 self.style = style
228
229+ def check_updates(self):
230+ """Fake the check updates call."""
231+ self.updates_checked.callback(None)
232+ return self.updates_checked
233+
234
235 class StartTestCase(TestCase):
236 """Test the qt control panel."""
237
238+ timeout = 2
239+
240 @defer.inlineCallbacks
241 def setUp(self):
242 yield super(StartTestCase, self).setUp()
243@@ -106,3 +114,12 @@
244 gui.QtCore.Qt.AlignCenter, self.main_window.size(),
245 app.desktop().availableGeometry())
246 self.assertEqual(self.main_window.style, expected)
247+
248+ @defer.inlineCallbacks
249+ def test_updates_are_checked(self):
250+ """When creating the window, updates are checked."""
251+ gui.start(close_callback=self.close_cb)
252+
253+ # a timeout in this test means that the check_updates method
254+ # was not called
255+ yield self.main_window.updates_checked

Subscribers

People subscribed via source and target branches