Merge lp:~ralsina/ubuntuone-windows-installer/ui-come-back-to-installer into lp:ubuntuone-windows-installer

Proposed by Roberto Alsina
Status: Merged
Approved by: Natalia Bidart
Approved revision: 50
Merged at revision: 25
Proposed branch: lp:~ralsina/ubuntuone-windows-installer/ui-come-back-to-installer
Merge into: lp:ubuntuone-windows-installer
Diff against target: 1027 lines (+379/-370)
12 files modified
bin/ubuntuone-installer-qt (+0/-3)
data/qt/local_folders.ui (+63/-33)
ubuntuone_installer/gui/qt/currentuser.py (+55/-0)
ubuntuone_installer/gui/qt/embedded_sso.py (+0/-61)
ubuntuone_installer/gui/qt/forgotten.py (+34/-34)
ubuntuone_installer/gui/qt/gui.py (+24/-2)
ubuntuone_installer/gui/qt/local_folders.py (+7/-2)
ubuntuone_installer/gui/qt/main/tests/test_main.py (+0/-97)
ubuntuone_installer/gui/qt/main/windows.py (+21/-29)
ubuntuone_installer/gui/qt/sync_now_or_later.py (+44/-44)
ubuntuone_installer/gui/qt/tests/test_currentuser.py (+90/-0)
ubuntuone_installer/gui/qt/tests/test_gui.py (+41/-65)
To merge this branch: bzr merge lp:~ralsina/ubuntuone-windows-installer/ui-come-back-to-installer
Reviewer Review Type Date Requested Status
Natalia Bidart (community) Approve
Diego Sarmentero (community) Approve
Review via email: mp+70015@code.launchpad.net

Commit message

Moved the wizard UI from ussoc's process, back into the installer process.

Added one u1cp widget (the add folder button) to test that this fixes the problems embedding u1cp UI into the installer.

Added check to skip pages if there are credentials in the system.

Description of the change

Moved the wizard UI from ussoc's process, back into the installer process.

Added one u1cp widget (the add folder button) to test that this fixes the problems embedding u1cp UI into the installer.

Added check to skip pages if there are credentials in the system.

To post a comment you must log in.
Revision history for this message
Diego Sarmentero (diegosarmentero) wrote :

+1

review: Approve
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

There are no test for the new module currentuser.

review: Needs Fixing
37. By Roberto Alsina

added tests for the currentuser module.

38. By Roberto Alsina

better docstrings.

39. By Roberto Alsina

merge

40. By Roberto Alsina

 test fix

41. By Roberto Alsina

merge

42. By Roberto Alsina

no need for embedded_sso anymore

Revision history for this message
Roberto Alsina (ralsina) wrote :

> There are no test for the new module currentuser.

Tests added.

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

* Can you please unify these two imports into one?

from ubuntuone.platform.credentials import (
    APP_NAME,
    TC_URL,
)
from ubuntuone.platform.credentials import CredentialsManagementTool

* We need a blank line between these two:

import sys
from PyQt4 import QtGui

* The code inside the try-except in currentuser.py should not be this:

+ print e, type(e), repr(e)

but a call to logger.exception.

* Four double quotes instead of 3:

""""Fake the wizard() method of QWizardPage.""

* The faked credentialsmanagementtool should return a fired deferred with an empty dict, to simulate the absence of credentials.

review: Needs Fixing
43. By Roberto Alsina

Use a successful deferred

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Seems like a test is not passing:

Traceback (most recent call last):
  File "E:\u1\windows-installer\review_ui-come-back-to-installer\ubuntuone_installer\gui\qt\tests\test_gui.py", line 464, in test_total_size
    u"Space (1337)")
twisted.trial.unittest.FailTest: not equal:
a = u'Space (1.3 KiB)'
b = u'Space (1337)'

review: Needs Fixing
44. By Roberto Alsina

fixes

45. By Roberto Alsina

fixes

46. By Roberto Alsina

fix race condition in test

47. By Roberto Alsina

fixes

48. By Roberto Alsina

log credential exceptions

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

I'm getting these lint issues:

ubuntuone_installer/gui/qt/gui.py:
    28: [W0611] Unused import returnValue
    28: [W0611] Unused import inlineCallbacks

ubuntuone_installer/gui/qt/tests/test_gui.py:
    382: [E0102, MainWindowTestCase.test_license_next] method already defined line 378
    395: [W0201, FakeSignal.connect] Attribute 'target' defined outside __init__
    27: [W0611] Unused import reactor
    36: [W0611] Unused import ubuntu_sso
    31: [W0611] Unused import TC_URL

review: Needs Fixing
49. By Roberto Alsina

lint fixes

50. By Roberto Alsina

fixes

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Looks great now!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/ubuntuone-installer-qt'
2--- bin/ubuntuone-installer-qt 2011-07-13 20:21:48 +0000
3+++ bin/ubuntuone-installer-qt 2011-08-02 20:49:39 +0000
4@@ -27,8 +27,6 @@
5
6 from optparse import OptionParser
7
8-from twisted.internet import reactor
9-
10 from ubuntuone_installer import TRANSLATION_DOMAIN
11
12 gettext.textdomain(TRANSLATION_DOMAIN)
13@@ -48,4 +46,3 @@
14 parser = parser_options()
15 (options, args) = parser.parse_args(sys.argv)
16 main.main()
17- reactor.run()
18
19=== modified file 'data/qt/local_folders.ui'
20--- data/qt/local_folders.ui 2011-06-28 15:46:02 +0000
21+++ data/qt/local_folders.ui 2011-08-02 20:49:39 +0000
22@@ -17,11 +17,11 @@
23 <item>
24 <widget class="QLabel" name="label">
25 <property name="text">
26- <string>Ok! Now it's time to choose wich folder sync to the cloud from this computer.
27-We started by suggesting a few</string>
28+ <string>Let's get started! First choose which folder you want to sync to your Ubuntu One personal cloud from this computer.
29+To help you get going we have suggested a few.</string>
30 </property>
31 <property name="textFormat">
32- <enum>Qt::RichText</enum>
33+ <enum>Qt::PlainText</enum>
34 </property>
35 <property name="wordWrap">
36 <bool>true</bool>
37@@ -50,23 +50,28 @@
38 </property>
39 </spacer>
40 </item>
41- <item>
42- <widget class="QPushButton" name="pushButton_2">
43- <property name="text">
44- <string>Add a folder</string>
45- </property>
46- </widget>
47- </item>
48 </layout>
49 </item>
50 <item>
51 <widget class="QTreeWidget" name="folder_list">
52+ <property name="indentation">
53+ <number>0</number>
54+ </property>
55+ <property name="rootIsDecorated">
56+ <bool>false</bool>
57+ </property>
58+ <property name="uniformRowHeights">
59+ <bool>true</bool>
60+ </property>
61+ <property name="allColumnsShowFocus">
62+ <bool>true</bool>
63+ </property>
64 <attribute name="headerStretchLastSection">
65 <bool>false</bool>
66 </attribute>
67 <column>
68 <property name="text">
69- <string>My Folders</string>
70+ <string>Sync these folders on my computer</string>
71 </property>
72 </column>
73 <column>
74@@ -74,26 +79,44 @@
75 <string>Space (Total)</string>
76 </property>
77 </column>
78- <column>
79- <property name="text">
80- <string>Remove</string>
81- </property>
82- </column>
83- </widget>
84- </item>
85- <item>
86- <widget class="QCheckBox" name="checkBox">
87- <property name="text">
88- <string>Connect automatically when computer starts</string>
89- </property>
90- </widget>
91- </item>
92- <item>
93- <widget class="QCheckBox" name="checkBox_2">
94- <property name="text">
95- <string>Automatically sync all selected folders from this computer to the cloud</string>
96- </property>
97- </widget>
98+ </widget>
99+ </item>
100+ <item>
101+ <layout class="QHBoxLayout" name="horizontalLayout_3">
102+ <item>
103+ <spacer name="horizontalSpacer_4">
104+ <property name="orientation">
105+ <enum>Qt::Horizontal</enum>
106+ </property>
107+ <property name="sizeHint" stdset="0">
108+ <size>
109+ <width>40</width>
110+ <height>20</height>
111+ </size>
112+ </property>
113+ </spacer>
114+ </item>
115+ <item>
116+ <widget class="AddFolderButton" name="add_folder_button">
117+ <property name="text">
118+ <string>Add a folder</string>
119+ </property>
120+ </widget>
121+ </item>
122+ <item>
123+ <spacer name="horizontalSpacer_5">
124+ <property name="orientation">
125+ <enum>Qt::Horizontal</enum>
126+ </property>
127+ <property name="sizeHint" stdset="0">
128+ <size>
129+ <width>40</width>
130+ <height>20</height>
131+ </size>
132+ </property>
133+ </spacer>
134+ </item>
135+ </layout>
136 </item>
137 <item>
138 <widget class="QFrame" name="offer_frame">
139@@ -113,7 +136,7 @@
140 <item>
141 <widget class="QLabel" name="offer_label">
142 <property name="text">
143- <string>The folders you have selected to sync take over your 2GB space. You can remove some folders or add some extra space</string>
144+ <string>The folders you have selected to sync take over your 5GB storage space by 6.5GB. You can remove some folders or add some extra storage now.</string>
145 </property>
146 <property name="wordWrap">
147 <bool>true</bool>
148@@ -138,7 +161,7 @@
149 <item>
150 <widget class="QPushButton" name="pushButton">
151 <property name="text">
152- <string>add more space</string>
153+ <string>Add more storage</string>
154 </property>
155 </widget>
156 </item>
157@@ -162,6 +185,13 @@
158 </item>
159 </layout>
160 </widget>
161+ <customwidgets>
162+ <customwidget>
163+ <class>AddFolderButton</class>
164+ <extends>QPushButton</extends>
165+ <header>ubuntuone.controlpanel.gui.qt.addfolder</header>
166+ </customwidget>
167+ </customwidgets>
168 <resources/>
169 <connections/>
170 </ui>
171
172=== added file 'ubuntuone_installer/gui/qt/currentuser.py'
173--- ubuntuone_installer/gui/qt/currentuser.py 1970-01-01 00:00:00 +0000
174+++ ubuntuone_installer/gui/qt/currentuser.py 2011-08-02 20:49:39 +0000
175@@ -0,0 +1,55 @@
176+# -*- coding: utf-8 -*-
177+
178+# Authors: Roberto Alsina <roberto.alsina@canonical.com>
179+#
180+# Copyright 2011 Canonical Ltd.
181+#
182+# This program is free software: you can redistribute it and/or modify it
183+# under the terms of the GNU General Public License version 3, as published
184+# by the Free Software Foundation.
185+#
186+# This program is distributed in the hope that it will be useful, but
187+# WITHOUT ANY WARRANTY; without even the implied warranties of
188+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
189+# PURPOSE. See the GNU General Public License for more details.
190+#
191+# You should have received a copy of the GNU General Public License along
192+# with this program. If not, see <http://www.gnu.org/licenses/>.
193+
194+"""Custom controller for current user page."""
195+
196+from twisted.internet.defer import inlineCallbacks
197+
198+from ubuntu_sso.qt import controllers
199+
200+from ubuntuone.platform.credentials import (
201+ CredentialsManagementTool,
202+ CredentialsError,
203+)
204+
205+from ubuntuone_installer.logger import setup_logging
206+
207+# Invalid name logger
208+# pylint: disable=C0103
209+logger = setup_logging('qt.currentuser')
210+# pylint: enable=C0103
211+
212+
213+class CurrentUserController(controllers.CurrentUserController):
214+ """Custom controller for current user page."""
215+
216+ @inlineCallbacks
217+ def login(self, *args):
218+ """Perform the login using the self.backend."""
219+ email = unicode(self.view.ui.email_edit.text())
220+ password = unicode(self.view.ui.password_edit.text())
221+ credtool = CredentialsManagementTool()
222+ try:
223+ d = yield credtool.login_email_password(
224+ email=email,
225+ password=password,
226+ )
227+ self.on_logged_in(self.view.wizard().app_name, d)
228+ except CredentialsError, e:
229+ logger.exception("Error getting credentials:")
230+ self.on_login_error(e.args[0])
231
232=== removed file 'ubuntuone_installer/gui/qt/embedded_sso.py'
233--- ubuntuone_installer/gui/qt/embedded_sso.py 2011-07-27 14:53:56 +0000
234+++ ubuntuone_installer/gui/qt/embedded_sso.py 1970-01-01 00:00:00 +0000
235@@ -1,61 +0,0 @@
236-# -*- coding: utf-8 -*-
237-
238-# Authors: Roberto Alsina <roberto.alsina@canonical.com>
239-#
240-# Copyright 2011 Canonical Ltd.
241-#
242-# This program is free software: you can redistribute it and/or modify it
243-# under the terms of the GNU General Public License version 3, as published
244-# by the Free Software Foundation.
245-#
246-# This program is distributed in the hope that it will be useful, but
247-# WITHOUT ANY WARRANTY; without even the implied warranties of
248-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
249-# PURPOSE. See the GNU General Public License for more details.
250-#
251-# You should have received a copy of the GNU General Public License along
252-# with this program. If not, see <http://www.gnu.org/licenses/>.
253-
254-"""The user interface for the Ubuntu One Installer's SSO client."""
255-
256-import ubuntu_sso.qt.gui as sso_gui
257-
258-from ubuntuone_installer.gui.qt.gui import MainWindow
259-
260-
261-class UbuntuSSOClientGUI(object):
262- """A custom Client GUI for SSO."""
263-
264- def __init__(self, app_name, tc_url, help_text,
265- window_id=0, login_only=False):
266- """Create a new instance."""
267-
268- # create the controller and the ui, then set the cb and call the show
269- # method so that we can work
270- self.controller = sso_gui.UbuntuSSOWizardController(
271- app_name,
272- user_cancellation_callback=self._user_cancellation_callback)
273- self.view = MainWindow()
274-
275- self.login_success_callback = lambda x, y: None
276- self.registration_success_callback = lambda x, y: None
277- self.user_cancellation_callback = lambda x: None
278-
279- self.view.loginSuccess.connect(self._login_success_callback)
280- self.view.registrationSuccess.connect(
281- self._registration_success_callback)
282- self.view.userCancellation.connect(self._user_cancellation_callback)
283-
284- self.view.show()
285-
286- def _login_success_callback(self, app_name, email):
287- """Call the real callback, set by the Credentials object"""
288- self.login_success_callback(str(app_name), str(email))
289-
290- def _registration_success_callback(self, app_name, email):
291- """Call the real callback, set by the Credentials object"""
292- self.registration_success_callback(str(app_name), str(email))
293-
294- def _user_cancellation_callback(self, app_name):
295- """Call the real callback, set by the Credentials object"""
296- self.user_cancellation_callback(str(app_name))
297
298=== modified file 'ubuntuone_installer/gui/qt/forgotten.py'
299--- ubuntuone_installer/gui/qt/forgotten.py 2011-07-19 21:06:06 +0000
300+++ ubuntuone_installer/gui/qt/forgotten.py 2011-08-02 20:49:39 +0000
301@@ -1,34 +1,34 @@
302-# -*- coding: utf-8 -*-
303-
304-# Authors: Roberto Alsina <roberto.alsina@canonical.com>
305-#
306-# Copyright 2011 Canonical Ltd.
307-#
308-# This program is free software: you can redistribute it and/or modify it
309-# under the terms of the GNU General Public License version 3, as published
310-# by the Free Software Foundation.
311-#
312-# This program is distributed in the hope that it will be useful, but
313-# WITHOUT ANY WARRANTY; without even the implied warranties of
314-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
315-# PURPOSE. See the GNU General Public License for more details.
316-#
317-# You should have received a copy of the GNU General Public License along
318-# with this program. If not, see <http://www.gnu.org/licenses/>.
319-
320-"""Custom forgotten password controller."""
321-
322-from ubuntu_sso.qt import controllers
323-
324-
325-class ForgottenPasswordController(controllers.ForgottenPasswordController):
326- """A custom forgotten password controller.
327-
328- This controller hides the overlay as needed.
329- """
330-
331- def on_password_reset_error(self, app_name, error):
332- """Hide the overlay, then do as the default controller does."""
333- self.view.wizard().overlay.hide()
334- super(ForgottenPasswordController,
335- self).on_password_reset_error(app_name, error)
336+# -*- coding: utf-8 -*-
337+
338+# Authors: Roberto Alsina <roberto.alsina@canonical.com>
339+#
340+# Copyright 2011 Canonical Ltd.
341+#
342+# This program is free software: you can redistribute it and/or modify it
343+# under the terms of the GNU General Public License version 3, as published
344+# by the Free Software Foundation.
345+#
346+# This program is distributed in the hope that it will be useful, but
347+# WITHOUT ANY WARRANTY; without even the implied warranties of
348+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
349+# PURPOSE. See the GNU General Public License for more details.
350+#
351+# You should have received a copy of the GNU General Public License along
352+# with this program. If not, see <http://www.gnu.org/licenses/>.
353+
354+"""Custom forgotten password controller."""
355+
356+from ubuntu_sso.qt import controllers
357+
358+
359+class ForgottenPasswordController(controllers.ForgottenPasswordController):
360+ """A custom forgotten password controller.
361+
362+ This controller hides the overlay as needed.
363+ """
364+
365+ def on_password_reset_error(self, app_name, error):
366+ """Hide the overlay, then do as the default controller does."""
367+ self.view.wizard().overlay.hide()
368+ super(ForgottenPasswordController,
369+ self).on_password_reset_error(app_name, error)
370
371=== modified file 'ubuntuone_installer/gui/qt/gui.py'
372--- ubuntuone_installer/gui/qt/gui.py 2011-08-02 14:12:22 +0000
373+++ ubuntuone_installer/gui/qt/gui.py 2011-08-02 20:49:39 +0000
374@@ -45,7 +45,6 @@
375 from ubuntu_sso.qt.reset_password_ui import Ui_ResetPasswordPage
376 from ubuntu_sso.qt.controllers import (
377 ChooseSignInController,
378- CurrentUserController,
379 EmailVerificationController,
380 ErrorController,
381 ResetPasswordController,
382@@ -58,6 +57,7 @@
383
384 from ubuntuone.platform.credentials import (
385 APP_NAME,
386+ CredentialsManagementTool,
387 TC_URL,
388 )
389
390@@ -75,6 +75,7 @@
391 # pylint: enable=W0611
392
393 from ubuntuone_installer.gui.qt.are_you_sure import AreYouSure
394+from ubuntuone_installer.gui.qt.currentuser import CurrentUserController
395 from ubuntuone_installer.gui.qt.forgotten import ForgottenPasswordController
396 from ubuntuone_installer.gui.qt.local_folders import LocalFoldersPage
397 from ubuntuone_installer.gui.qt.sync_now_or_later import SyncNowOrLaterPage
398@@ -101,6 +102,7 @@
399 super(LicensePage, self).__init__(parent)
400 self.ui = license_ui.Ui_Form()
401 self.ui.setupUi(self)
402+ self._next_id = None
403
404 # Invalid names of Qt-inherited methods
405 # pylint: disable=C0103
406@@ -146,6 +148,12 @@
407 printer.setPageSize(QtGui.QPrinter.A4)
408 document.print_(printer)
409
410+ def nextId(self):
411+ """Return next page's ID."""
412+ if self._next_id is None:
413+ return super(LicensePage, self).nextId()
414+ return self._next_id
415+
416
417 class SignInPage(QtGui.QWizardPage):
418 """Wizard Page that lets the user Sign into Ubuntu One."""
419@@ -330,7 +338,9 @@
420 # PyQt doesn't support the (int, page) version of addPage, so
421 # Add the pages in the right order
422 # pylint: disable=C0103
423- self.LICENSE_PAGE = self.addPage(LicensePage())
424+
425+ self.LICENSE_PAGE = LicensePage()
426+ self.LICENSE_PAGE_ID = self.addPage(self.LICENSE_PAGE)
427
428 #SSO Pages
429 title_page = TITLE_STYLE % SIGN_IN
430@@ -424,10 +434,22 @@
431 # Apply font to the entire application
432 QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-R.ttf')
433 QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-B.ttf')
434+ credtool = CredentialsManagementTool()
435+ d = credtool.find_credentials()
436+ d.addCallback(self.creds_cb)
437+ d.addErrback(lambda exc: logger.error(
438+ 'Error while getting the credentials: %r', exc))
439
440 # Invalid name "closeEvent"
441 # pylint: disable=C0103
442
443+ def creds_cb(self, token):
444+ """Change wizard flow if we have credentials."""
445+ if not token:
446+ self.LICENSE_PAGE._next_id = self.SIGNIN_PAGE
447+ else:
448+ self.LICENSE_PAGE._next_id = self.local_folders_page_id
449+
450 def critical(self, *args, **kwargs):
451 """Wrapper for QMessageBox.critical that hides the overlay."""
452 self.overlay.hide()
453
454=== modified file 'ubuntuone_installer/gui/qt/local_folders.py'
455--- ubuntuone_installer/gui/qt/local_folders.py 2011-07-22 16:32:35 +0000
456+++ ubuntuone_installer/gui/qt/local_folders.py 2011-08-02 20:49:39 +0000
457@@ -103,8 +103,13 @@
458 # Special Folder "My Documents"
459 dll = ctypes.windll.shell32
460 buf = ctypes.create_string_buffer(300)
461- dll.SHGetSpecialFolderPathA(None, buf, 0x0005, False)
462- result = [buf.value, ]
463+ dll.SHGetSpecialFolderPathA(None, buf, 5, False)
464+ docs = buf.value
465+ dll.SHGetSpecialFolderPathA(None, buf, 13, False)
466+ music = buf.value
467+ dll.SHGetSpecialFolderPathA(None, buf, 39, False)
468+ pictures = buf.value
469+ return [docs, music, pictures]
470 else:
471 result = ['To be implemented']
472 return result
473
474=== removed file 'ubuntuone_installer/gui/qt/main/tests/test_main.py'
475--- ubuntuone_installer/gui/qt/main/tests/test_main.py 2011-07-27 15:09:28 +0000
476+++ ubuntuone_installer/gui/qt/main/tests/test_main.py 1970-01-01 00:00:00 +0000
477@@ -1,97 +0,0 @@
478-# -*- coding: utf-8 -*-
479-
480-# Authors: Roberto Alsina <roberto.alsina@canonical.com>
481-#
482-# Copyright 2011 Canonical Ltd.
483-#
484-# This program is free software: you can redistribute it and/or modify it
485-# under the terms of the GNU General Public License version 3, as published
486-# by the Free Software Foundation.
487-#
488-# This program is distributed in the hope that it will be useful, but
489-# WITHOUT ANY WARRANTY; without even the implied warranties of
490-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
491-# PURPOSE. See the GNU General Public License for more details.
492-#
493-# You should have received a copy of the GNU General Public License along
494-# with this program. If not, see <http://www.gnu.org/licenses/>.
495-
496-"""The test suite for the Qt UI of the Ubuntu One Installer."""
497-
498-from ubuntuone_installer.tests import TestCase
499-
500-import ubuntuone_installer.gui.qt.main.windows as main_module
501-
502-# pylint: disable=W0212
503-
504-from ubuntuone.platform.credentials import (
505- APP_NAME,
506- DESCRIPTION,
507- TC_URL,
508-)
509-
510-
511-class FakeSSOCred(object):
512- """A fake sso_cred."""
513-
514- _registered_to_signal = False
515- _login_args = ()
516- on_credentials_found = None
517-
518- def register_to_signals(self):
519- """Fake method."""
520- self._registered_to_signal = True
521-
522- def login_or_register_to_get_credentials(self, *args, **kwargs):
523- """Fake method."""
524- self._login_args = (args, kwargs)
525-
526-
527-class FakeSSOClient(object):
528-
529- """Fake UbuntuSSOClient."""
530-
531- sso_cred = FakeSSOCred()
532- testcase = None
533-
534- def connect(self):
535- """Fake method."""
536- self.testcase._connected = True
537- return self
538-
539-
540-class MainTestCase(TestCase):
541-
542- """Tests for the main() function."""
543-
544- _connected = False
545-
546- def setUp(self):
547- """Prepare tests."""
548- self.patch(main_module, "UbuntuSSOClient", FakeSSOClient)
549- main_module.UbuntuSSOClient.testcase = self
550-
551- def test_connect(self):
552- """Test that we instantiate the SSO Client and connect."""
553- main_module.main()
554- self.assertEqual(FakeSSOClient.testcase._connected, True)
555-
556- def test_credentials_found_cb(self):
557- """Test that the credentials found signal is connected."""
558- main_module.main()
559- self.assertEqual(
560- FakeSSOClient.sso_cred.on_credentials_found_cb.__name__,
561- "stop")
562-
563- def test_registered(self):
564- """Test that the credentials registers to signals."""
565- main_module.main()
566- self.assertEqual(FakeSSOClient.sso_cred._registered_to_signal,
567- True)
568-
569- def test_check_register_args(self):
570- """Test that the credentials registers to signals."""
571- main_module.main()
572- self.assertEqual(FakeSSOClient.sso_cred._login_args,
573- ((APP_NAME, TC_URL, DESCRIPTION, 0),
574- {'ui_module': 'ubuntuone_installer.gui.qt.embedded_sso'}))
575
576=== modified file 'ubuntuone_installer/gui/qt/main/windows.py'
577--- ubuntuone_installer/gui/qt/main/windows.py 2011-07-27 14:53:56 +0000
578+++ ubuntuone_installer/gui/qt/main/windows.py 2011-08-02 20:49:39 +0000
579@@ -19,34 +19,26 @@
580
581 # pylint: disable=E1101, F0401, W0404
582
583-from twisted.internet.defer import inlineCallbacks
584-from ubuntu_sso.main.windows import UbuntuSSOClient
585-
586-from ubuntuone.platform.credentials import (
587- APP_NAME,
588- DESCRIPTION,
589- TC_URL,
590-)
591-
592-
593-@inlineCallbacks
594+import sys
595+
596+from PyQt4 import QtGui
597+
598+
599+def stop(*args):
600+ """End the process."""
601+ from twisted.internet import reactor
602+ reactor.stop()
603+
604+
605 def main():
606 """Perform a client request to be logged in."""
607- client = UbuntuSSOClient()
608- client = yield client.connect()
609-
610- @inlineCallbacks
611- def stop(*args):
612- """End the process."""
613- from twisted.internet import reactor
614- yield client.sso_cred.unregister_to_signals()
615- reactor.stop()
616-
617- client.sso_cred.on_credentials_found_cb = stop
618- client.sso_cred.on_authorization_denied_cb = stop
619- client.sso_cred.on_credentials_error_cb = stop
620- yield client.sso_cred.register_to_signals()
621- yield client.sso_cred.login_or_register_to_get_credentials(APP_NAME,
622- TC_URL,
623- DESCRIPTION, 0,
624- ui_module="ubuntuone_installer.gui.qt.embedded_sso")
625+
626+ app = QtGui.QApplication(sys.argv)
627+ import qtreactor.qt4reactor
628+ qtreactor.qt4reactor.install()
629+ from ubuntuone_installer.gui.qt.gui import MainWindow
630+ from twisted.internet import reactor
631+ window = MainWindow(close_callback=stop)
632+ app.window = window
633+ window.show()
634+ reactor.run()
635
636=== modified file 'ubuntuone_installer/gui/qt/sync_now_or_later.py'
637--- ubuntuone_installer/gui/qt/sync_now_or_later.py 2011-06-29 11:44:23 +0000
638+++ ubuntuone_installer/gui/qt/sync_now_or_later.py 2011-08-02 20:49:39 +0000
639@@ -1,44 +1,44 @@
640-# -*- coding: utf-8 -*-
641-
642-# Authors: Roberto Alsina <roberto.alsina@canonical.com>
643-#
644-# Copyright 2011 Canonical Ltd.
645-#
646-# This program is free software: you can redistribute it and/or modify it
647-# under the terms of the GNU General Public License version 3, as published
648-# by the Free Software Foundation.
649-#
650-# This program is distributed in the hope that it will be useful, but
651-# WITHOUT ANY WARRANTY; without even the implied warranties of
652-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
653-# PURPOSE. See the GNU General Public License for more details.
654-#
655-# You should have received a copy of the GNU General Public License along
656-# with this program. If not, see <http://www.gnu.org/licenses/>.
657-
658-"""The user interface for the Ubuntu One Installer."""
659-
660-from PyQt4 import QtGui
661-
662-from ubuntuone_installer.gui.qt.ui import sync_now_or_later_ui
663-
664-
665-class SyncNowOrLaterPage(QtGui.QWizardPage):
666- """User can choose whether to sync now, later, or selectively"""
667-
668- def __init__(self, parent=None):
669- QtGui.QWizardPage.__init__(self, parent)
670- self.ui = sync_now_or_later_ui.Ui_Form()
671- self.ui.setupUi(self)
672- self.registerField("sync_now", self.ui.sync_now)
673- self.registerField("sync_later", self.ui.sync_later)
674- self.registerField("sync_custom", self.ui.sync_custom)
675-
676- # Invalid names of Qt-inherited methods
677- # pylint: disable=C0103
678-
679- def initializePage(self):
680- """Setup UI details"""
681- self.wizard().setOption(QtGui.QWizard.HaveCustomButton1, False)
682- self.wizard().setOption(QtGui.QWizard.NoCancelButton, True)
683- self.wizard()._next_id = None
684+# -*- coding: utf-8 -*-
685+
686+# Authors: Roberto Alsina <roberto.alsina@canonical.com>
687+#
688+# Copyright 2011 Canonical Ltd.
689+#
690+# This program is free software: you can redistribute it and/or modify it
691+# under the terms of the GNU General Public License version 3, as published
692+# by the Free Software Foundation.
693+#
694+# This program is distributed in the hope that it will be useful, but
695+# WITHOUT ANY WARRANTY; without even the implied warranties of
696+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
697+# PURPOSE. See the GNU General Public License for more details.
698+#
699+# You should have received a copy of the GNU General Public License along
700+# with this program. If not, see <http://www.gnu.org/licenses/>.
701+
702+"""The user interface for the Ubuntu One Installer."""
703+
704+from PyQt4 import QtGui
705+
706+from ubuntuone_installer.gui.qt.ui import sync_now_or_later_ui
707+
708+
709+class SyncNowOrLaterPage(QtGui.QWizardPage):
710+ """User can choose whether to sync now, later, or selectively"""
711+
712+ def __init__(self, parent=None):
713+ QtGui.QWizardPage.__init__(self, parent)
714+ self.ui = sync_now_or_later_ui.Ui_Form()
715+ self.ui.setupUi(self)
716+ self.registerField("sync_now", self.ui.sync_now)
717+ self.registerField("sync_later", self.ui.sync_later)
718+ self.registerField("sync_custom", self.ui.sync_custom)
719+
720+ # Invalid names of Qt-inherited methods
721+ # pylint: disable=C0103
722+
723+ def initializePage(self):
724+ """Setup UI details"""
725+ self.wizard().setOption(QtGui.QWizard.HaveCustomButton1, False)
726+ self.wizard().setOption(QtGui.QWizard.NoCancelButton, True)
727+ self.wizard()._next_id = None
728
729=== added file 'ubuntuone_installer/gui/qt/tests/test_currentuser.py'
730--- ubuntuone_installer/gui/qt/tests/test_currentuser.py 1970-01-01 00:00:00 +0000
731+++ ubuntuone_installer/gui/qt/tests/test_currentuser.py 2011-08-02 20:49:39 +0000
732@@ -0,0 +1,90 @@
733+# -*- coding: utf-8 -*-
734+
735+# Authors: Roberto Alsina <roberto.alsina@canonical.com>
736+#
737+# Copyright 2011 Canonical Ltd.
738+#
739+# This program is free software: you can redistribute it and/or modify it
740+# under the terms of the GNU General Public License version 3, as published
741+# by the Free Software Foundation.
742+#
743+# This program is distributed in the hope that it will be useful, but
744+# WITHOUT ANY WARRANTY; without even the implied warranties of
745+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
746+# PURPOSE. See the GNU General Public License for more details.
747+#
748+# You should have received a copy of the GNU General Public License along
749+# with this program. If not, see <http://www.gnu.org/licenses/>.
750+
751+"""Tests for the CurrentUserController."""
752+
753+from ubuntuone_installer.gui.qt import currentuser
754+from ubuntuone_installer.gui.qt.tests import BaseTestCase
755+
756+
757+class FakeView(object):
758+
759+ """A Fake view for the controller."""
760+
761+ def __init__(self):
762+ """Setup."""
763+ self.view = self
764+ self.ui = self
765+ self.email_edit = self
766+ self.password_edit = self
767+ self.app_name = "APP"
768+
769+ def text(self):
770+ """Return some text."""
771+ return "text"
772+
773+ def wizard(self):
774+ """Fake the wizard() method of QWizardPage."""
775+ return self
776+
777+
778+class FakeCredentialsManagementToolSuccess(object):
779+
780+ """A fake CredentialsManagementTool where login succeeds."""
781+
782+ def login_email_password(self, *args, **kwargs):
783+ """Fake credentials."""
784+ return {"x": "y"}
785+
786+
787+class FakeCredentialsManagementToolFailure(object):
788+
789+ """A fake CredentialsManagementTool where login fails."""
790+
791+ def login_email_password(self, *args, **kwargs):
792+ """Raises a credentials exception."""
793+ raise currentuser.CredentialsError("Failure")
794+
795+
796+class CurrentUserTestCase(BaseTestCase):
797+
798+ """Test the CurrentUserController."""
799+
800+ class_ui = FakeView
801+
802+ def setUp(self):
803+ """Initialize this test instance."""
804+ self.controller = currentuser.CurrentUserController()
805+ self.controller.view = FakeView()
806+ super(CurrentUserTestCase, self).setUp()
807+
808+ def test_login_success(self):
809+ """Check that login works correctly."""
810+ self.patch(currentuser, 'CredentialsManagementTool',
811+ FakeCredentialsManagementToolSuccess)
812+ self.patch(self.controller, 'on_logged_in', self._set_called)
813+ self.controller.login()
814+ self.assertEqual(self._called, (('APP', {'x': 'y'}), {}))
815+
816+ def test_login_failure(self):
817+ """Check that login fails correctly."""
818+ self.patch(currentuser, 'CredentialsManagementTool',
819+ FakeCredentialsManagementToolFailure)
820+ self.patch(self.controller, 'on_login_error', self._set_called)
821+ self.controller.login()
822+ self.assertEqual(self._called, (('Failure',), {}))
823
824=== modified file 'ubuntuone_installer/gui/qt/tests/test_gui.py'
825--- ubuntuone_installer/gui/qt/tests/test_gui.py 2011-08-02 14:12:22 +0000
826+++ ubuntuone_installer/gui/qt/tests/test_gui.py 2011-08-02 20:49:39 +0000
827@@ -24,18 +24,14 @@
828 import shutil
829 import tempfile
830
831+from twisted.internet import defer
832+
833 from PyQt4 import QtCore
834
835-from ubuntuone.platform.credentials import (
836- APP_NAME,
837- TC_URL,
838-)
839-
840-import ubuntu_sso
841+from ubuntuone.platform.credentials import APP_NAME
842
843 from ubuntuone_installer.gui.qt import gui
844 from ubuntuone_installer.gui.qt.tests import BaseTestCase
845-from ubuntuone_installer.gui.qt import embedded_sso
846 from ubuntuone_installer.gui.qt import forgotten
847 from ubuntuone_installer.gui.qt import local_folders
848 from ubuntuone_installer.gui.qt import setup_account
849@@ -51,6 +47,15 @@
850 u'token_secret': u'qFYImEtlczPbsCnYyuwLoPDlPEnvNcIktZphPQklAWrvyfFMV'}
851
852
853+class FakeFailureCredentialsManagementTool(object):
854+
855+ """A fake CredentialsManagementTool that fails."""
856+
857+ def find_credentials(self):
858+ """Return a deferred that never triggers callback."""
859+ return defer.succeed({})
860+
861+
862 class FakeController(object):
863
864 """A fake controller for the tests."""
865@@ -99,6 +104,9 @@
866 """Fake hide."""
867 self.hide_counter += 1
868
869+ def resize(self, *args):
870+ """Fake resize."""
871+
872
873 class MainWindowTestCase(BaseTestCase):
874 """Test the qt main window."""
875@@ -118,6 +126,8 @@
876 self.patch(gui, "ResetPasswordController", FakeController)
877 self.patch(gui, "AreYouSure", FakeAreYouSure)
878 self.patch(gui, "LoadingOverlay", FakeOverlay)
879+ self.patch(gui, "CredentialsManagementTool",
880+ FakeFailureCredentialsManagementTool)
881 super(MainWindowTestCase, self).setUp()
882
883 def test_critical(self):
884@@ -291,7 +301,7 @@
885
886 def test_stage_progression_1(self):
887 """Check that each page in the wizard sets the correct stage."""
888- self.ui.on_currentIdChanged(self.ui.LICENSE_PAGE)
889+ self.ui.on_currentIdChanged(self.ui.LICENSE_PAGE_ID)
890 self.assertEqual(self.ui.sideWidget().stage, 0)
891
892 def test_stage_progression_2(self):
893@@ -360,11 +370,25 @@
894 QtCore.QCoreApplication.instance().processEvents()
895 self.assertEqual(self.ui.result(), self.ui.Rejected)
896
897+ def test_license_next(self):
898+ """Test what's the license page's nextID."""
899+ self.assertEqual(self.ui.LICENSE_PAGE.nextId(), self.ui.SIGNIN_PAGE)
900+
901+ def test_license_next_with_creds(self):
902+ """Test what's the license page's nextID."""
903+ self.ui.creds_cb("fakecreds")
904+ self.assertEqual(self.ui.LICENSE_PAGE.nextId(),
905+ self.ui.local_folders_page_id)
906+
907
908 class FakeSignal(object):
909
910 """A fake PyQt signal."""
911
912+ def __init__(self, *args, **kwargs):
913+ """Initialize."""
914+ self.target = lambda *args: None
915+
916 def connect(self, target):
917 """Fake connect."""
918 self.target = target
919@@ -388,51 +412,6 @@
920 self.shown = True
921
922
923-class SSOGuiTestCase(BaseTestCase):
924- """Test the custom SSO GUI."""
925-
926- class_ui = embedded_sso.UbuntuSSOClientGUI
927-
928- def setUp(self):
929- """Initialize this test instance."""
930- self.kwargs = {
931- 'app_name': APP_NAME,
932- 'tc_url': TC_URL,
933- 'help_text': '',
934- }
935- self.patch(embedded_sso, "MainWindow", FakeMainWindow)
936- super(SSOGuiTestCase, self).setUp()
937-
938- def test_sso_client_gui(self):
939- """Ensure the class instantiates correctly."""
940- self.assertIsInstance(
941- self.ui.controller,
942- ubuntu_sso.qt.controllers.UbuntuSSOWizardController)
943- self.assertIsInstance(self.ui.view, FakeMainWindow)
944-
945- def test_login_callback(self):
946- """Test that the login success callback is correctly handled."""
947- self.ui.login_success_callback = self._set_called
948- self.ui.view.loginSuccess.emit("app", "email")
949- self.assertEqual(self._called, (('app', 'email'), {}))
950-
951- def test_registration_callback(self):
952- """Test that the registration success callback is correctly handled."""
953- self.ui.registration_success_callback = self._set_called
954- self.ui.view.registrationSuccess.emit("app", "email")
955- self.assertEqual(self._called, (('app', 'email'), {}))
956-
957- def test_cancellation_callback(self):
958- """Test that the cancellation callback is called right."""
959- self.ui.user_cancellation_callback = self._set_called
960- self.ui.view.userCancellation.emit("app")
961- self.assertEqual(self._called, (('app',), {}))
962-
963- def test_view_is_shown(self):
964- """Test that the view is actually shown."""
965- self.assertTrue(self.ui.view.shown)
966-
967-
968 class LocalFoldersTestCase(BaseTestCase):
969 """Test the LocalFoldersPage code."""
970
971@@ -465,16 +444,10 @@
972 self.assertEqual(path, self.tmpdir)
973 self.assertEqual(size, 1337)
974
975- def test_item_addition_removal(self):
976+ def test_item_addition(self):
977 """Add an item (plus the default one), then remove them."""
978 self.ui.add_folder(self.tmpdir)
979- self.assertEqual(2, self.ui.ui.folder_list.topLevelItemCount())
980- self.ui.on_folder_list_itemClicked(
981- self.ui.ui.folder_list.topLevelItem(0), 2)
982- self.ui.on_folder_list_itemClicked(
983- self.ui.ui.folder_list.topLevelItem(0), 2)
984- self.assertEqual(0, self.ui.ui.folder_list.topLevelItemCount())
985- self.assertEqual({}, self.ui.items)
986+ self.assertEqual(4, self.ui.ui.folder_list.topLevelItemCount())
987
988 def test_total_size(self):
989 """Test that the header reflects the change in item sizes."""
990@@ -484,6 +457,8 @@
991 self.assertEqual(0, self.ui.ui.folder_list.topLevelItemCount())
992 item = self.ui.add_folder(self.tmpdir)
993 item.size = 1337
994+ item.thread.run()
995+ item.thread.join()
996 self.ui.update_sizes()
997 self.assertEqual(unicode(self.ui.ui.folder_list.headerItem().text(1)),
998 u"Space (1337)")
999@@ -515,6 +490,7 @@
1000 item = self.ui.add_folder(os.path.join("xyzzy", "xyzzy", "xyzzy"))
1001 self.assertEqual(1, self.ui.ui.folder_list.topLevelItemCount())
1002 item.thread.run()
1003+ item.thread.join()
1004 self.ui.update_sizes()
1005 self.assertEqual(0, item.size)
1006 # world did not explode
1007@@ -758,16 +734,16 @@
1008 self.ui.on_currentIdChanged(self.ui.LICENSE_PAGE)
1009 self.assertEqual(
1010 True,
1011- sideWidget().ui.states_frame.isVisible())
1012+ self.ui.sideWidget().ui.states_frame.isVisible())
1013 self.ui.on_currentIdChanged(self.ui.SIGNIN_PAGE)
1014 self.assertEqual(
1015 True,
1016- sideWidget().ui.states_frame.isVisible())
1017+ self.ui.sideWidget().ui.states_frame.isVisible())
1018 self.ui.on_currentIdChanged(self.ui.local_folders_page_id)
1019 self.assertEqual(
1020 True,
1021- sideWidget().ui.states_frame.isVisible())
1022+ self.ui.sideWidget().ui.states_frame.isVisible())
1023 self.ui.on_currentIdChanged(self.ui.CONGRATULATIONS_PAGE)
1024 self.assertEqual(
1025 True,
1026- sideWidget().ui.states_frame.isVisible())
1027+ self.ui.sideWidget().ui.states_frame.isVisible())

Subscribers

People subscribed via source and target branches