Merge lp:~nataliabidart/ubuntu-sso-client/stable-3-0-update-2.99.5 into lp:ubuntu-sso-client/stable-3-0

Proposed by Natalia Bidart
Status: Merged
Approved by: Natalia Bidart
Approved revision: 827
Merged at revision: 826
Proposed branch: lp:~nataliabidart/ubuntu-sso-client/stable-3-0-update-2.99.5
Merge into: lp:ubuntu-sso-client/stable-3-0
Diff against target: 2716 lines (+888/-321)
46 files modified
data/qt/resources.qrc (+10/-0)
data/qt/setup_account.ui (+35/-2)
data/qt/stylesheet.qss (+119/-0)
run-tests (+1/-1)
setup.py (+0/-39)
ubuntu_sso/credentials.py (+3/-1)
ubuntu_sso/gtk/gui.py (+14/-16)
ubuntu_sso/gtk/tests/test_gui.py (+57/-53)
ubuntu_sso/keyring/tests/test_linux.py (+2/-3)
ubuntu_sso/main/__init__.py (+1/-1)
ubuntu_sso/main/linux.py (+2/-3)
ubuntu_sso/main/qt.py (+23/-3)
ubuntu_sso/main/tests/test_common.py (+15/-22)
ubuntu_sso/main/tests/test_qt.py (+69/-0)
ubuntu_sso/qt/__init__.py (+0/-10)
ubuntu_sso/qt/common.py (+1/-0)
ubuntu_sso/qt/current_user_sign_in_page.py (+18/-8)
ubuntu_sso/qt/email_verification_page.py (+6/-1)
ubuntu_sso/qt/enhanced_check_box.py (+5/-2)
ubuntu_sso/qt/forgotten_password_page.py (+18/-4)
ubuntu_sso/qt/gui.py (+13/-7)
ubuntu_sso/qt/main.py (+13/-1)
ubuntu_sso/qt/network_detection_page.py (+8/-8)
ubuntu_sso/qt/reset_password_page.py (+11/-2)
ubuntu_sso/qt/setup_account_page.py (+18/-10)
ubuntu_sso/qt/sign_in_page.py (+2/-4)
ubuntu_sso/qt/tests/__init__.py (+22/-2)
ubuntu_sso/qt/tests/test_current_user_sign_in_page.py (+32/-22)
ubuntu_sso/qt/tests/test_email_verification.py (+9/-11)
ubuntu_sso/qt/tests/test_enhanced_check_box.py (+0/-7)
ubuntu_sso/qt/tests/test_forgotten_password.py (+31/-9)
ubuntu_sso/qt/tests/test_network_detection.py (+2/-4)
ubuntu_sso/qt/tests/test_reset_password.py (+77/-31)
ubuntu_sso/qt/tests/test_setup_account.py (+50/-3)
ubuntu_sso/qt/tests/test_sign_in_page.py (+2/-2)
ubuntu_sso/qt/tests/test_ubuntu_sso_wizard.py (+2/-2)
ubuntu_sso/qt/ubuntu_sso_wizard.py (+1/-0)
ubuntu_sso/tests/__init__.py (+8/-8)
ubuntu_sso/utils/__init__.py (+9/-3)
ubuntu_sso/utils/runner/glib.py (+11/-2)
ubuntu_sso/utils/runner/tests/test_glib.py (+132/-0)
ubuntu_sso/utils/runner/tests/test_qt.py (+9/-1)
ubuntu_sso/utils/runner/tests/test_runner.py (+9/-7)
ubuntu_sso/utils/runner/tx.py (+9/-1)
ubuntu_sso/utils/tests/test_common.py (+1/-2)
ubuntu_sso/utils/ui.py (+8/-3)
To merge this branch: bzr merge lp:~nataliabidart/ubuntu-sso-client/stable-3-0-update-2.99.5
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Review via email: mp+94066@code.launchpad.net

Commit message

- Updating from trunk up to revno 882:

[ Diego Sarmentero <email address hidden> ]
  - Fixed: Captcha is failing for the Qt UI (LP: #933679).
  - Add stylesheets for the Qt UI.
  - Fixed: Qt UI: must call the backend passing reply_handler
    and error_handler (LP: #931452).

[ Natalia B. Bidart <email address hidden> ]
  - Make gettext return unicode strings. Also, transform arguments passed to
    the GLib spawnner to bytes (LP: #933632).
  - Fix lint issue on nightlies build (LP: #934488).
  - Try to load the qt main/ implementation when possible, if not default
    to the glib (LP: #933534).
  - Make the bin_dir discoverable when running from the system installation
    (LP: #933039).

[ Roberto Alsina <email address hidden> ]
  - Implement timeout_func for the Qt frontend (LP: #933758).

To post a comment you must log in.
Revision history for this message
Roberto Alsina (ralsina) wrote :

+1

review: Approve
Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (64.0 KiB)

The attempt to merge lp:~nataliabidart/ubuntu-sso-client/stable-3-0-update-2.99.5 into lp:ubuntu-sso-client/stable-3-0 failed. Below is the output from the failed tests.

*** Running GTK test suite for ubuntu_sso ***
twisted.trial.unittest
  TestCase
    runTest ... [OK]
ubuntu_sso.keyring.tests.test_common
  TestGetHostname
    test_get_hostname ... [OK]
    test_get_hostname_uses_filesystem_encoding ... [OK]
  TestTokenNameBuilder
    test_get_complex_token_name_for_app_name ... [OK]
    test_get_complex_token_name_for_hostname ... [OK]
    test_get_simple_token_name ... [OK]
    test_get_unicode_appname_token_name ... [OK]
    test_get_utf8_hostname_token_name ... [OK]
twisted.trial.unittest
  TestCase
    runTest ... [OK]
ubuntu_sso.keyring.tests.test_linux
  TestKeyring
    test_delete_credentials ... [OK]
    test_get_credentials ... [OK]
    test_get_credentials_migrating_token ... [OK]
    test_get_old_cred_found ... [OK]
    test_get_old_cred_found_but_not_asked_for ... [OK]
    test_get_old_cred_not_found ... [OK]
    test_set_credentials ... [OK]
ubuntu_sso.networkstate.tests.test_linux
  NetworkManagerStateErrorsTestCase
    test_dbus_problem ... [OK]
    test_nm_not_running ... [OK]
  NetworkManagerStateTestCase
    test_nm_connecting_then_offline ... [OK]
    test_nm_connecting_then_offline_old ... [OK]
    test_nm_connecting_then_online ... [OK]
    test_nm_connecting_then_online_old ... [OK]
    test_nm_offline ... [OK]
    test_nm_offline_local ... [OK]
    test_nm_offline_old ... [OK]
    test_nm_offline_site ... [OK]
    test_nm_online_global ... [OK]
    test_nm_online_old ... [OK]
ubuntu_sso.tests
  TestCase
    runTest ... [OK]
ubuntu_sso.networkstate.tests.test_linux
  TestConnection
    test_is_machine_connected_nm_state_connected_global ... [OK]
    test_is_machine_connected_nm_state_connected_old ... [OK]
    test_is_machine_defer_error ... [OK]
    test_is_machine_disconnected_n...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'data/Ubuntu-B.ttf'
2Binary files data/Ubuntu-B.ttf 1970-01-01 00:00:00 +0000 and data/Ubuntu-B.ttf 2012-02-21 23:01:20 +0000 differ
3=== added file 'data/Ubuntu-R.ttf'
4Binary files data/Ubuntu-R.ttf 1970-01-01 00:00:00 +0000 and data/Ubuntu-R.ttf 2012-02-21 23:01:20 +0000 differ
5=== added file 'data/balloon_shape.png'
6Binary files data/balloon_shape.png 1970-01-01 00:00:00 +0000 and data/balloon_shape.png 2012-02-21 23:01:20 +0000 differ
7=== added file 'data/password_hint_ok.png'
8Binary files data/password_hint_ok.png 1970-01-01 00:00:00 +0000 and data/password_hint_ok.png 2012-02-21 23:01:20 +0000 differ
9=== added file 'data/password_hint_warning.png'
10Binary files data/password_hint_warning.png 1970-01-01 00:00:00 +0000 and data/password_hint_warning.png 2012-02-21 23:01:20 +0000 differ
11=== added file 'data/qt/resources.qrc'
12--- data/qt/resources.qrc 1970-01-01 00:00:00 +0000
13+++ data/qt/resources.qrc 2012-02-21 23:01:20 +0000
14@@ -0,0 +1,10 @@
15+<RCC>
16+ <qresource prefix="/">
17+ <file>../password_hint_ok.png</file>
18+ <file>../password_hint_warning.png</file>
19+ <file>../Ubuntu-R.ttf</file>
20+ <file>../Ubuntu-B.ttf</file>
21+ <file>../balloon_shape.png</file>
22+ <file>stylesheet.qss</file>
23+ </qresource>
24+</RCC>
25
26=== modified file 'data/qt/setup_account.ui'
27--- data/qt/setup_account.ui 2012-02-02 15:44:18 +0000
28+++ data/qt/setup_account.ui 2012-02-21 23:01:20 +0000
29@@ -221,6 +221,22 @@
30 <number>3</number>
31 </property>
32 <item>
33+ <spacer name="verticalSpacer_4">
34+ <property name="orientation">
35+ <enum>Qt::Vertical</enum>
36+ </property>
37+ <property name="sizeType">
38+ <enum>QSizePolicy::Fixed</enum>
39+ </property>
40+ <property name="sizeHint" stdset="0">
41+ <size>
42+ <width>20</width>
43+ <height>10</height>
44+ </size>
45+ </property>
46+ </spacer>
47+ </item>
48+ <item>
49 <widget class="QLabel" name="password_label">
50 <property name="font">
51 <font>
52@@ -283,6 +299,22 @@
53 <number>3</number>
54 </property>
55 <item>
56+ <spacer name="verticalSpacer_5">
57+ <property name="orientation">
58+ <enum>Qt::Vertical</enum>
59+ </property>
60+ <property name="sizeType">
61+ <enum>QSizePolicy::Fixed</enum>
62+ </property>
63+ <property name="sizeHint" stdset="0">
64+ <size>
65+ <width>20</width>
66+ <height>10</height>
67+ </size>
68+ </property>
69+ </spacer>
70+ </item>
71+ <item>
72 <widget class="QLabel" name="confirm_password_label">
73 <property name="font">
74 <font>
75@@ -576,7 +608,7 @@
76 <item row="6" column="1" rowspan="2">
77 <widget class="QLabel" name="password_assistance">
78 <property name="sizePolicy">
79- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
80+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
81 <horstretch>0</horstretch>
82 <verstretch>0</verstretch>
83 </sizepolicy>
84@@ -584,7 +616,7 @@
85 <property name="minimumSize">
86 <size>
87 <width>220</width>
88- <height>0</height>
89+ <height>100</height>
90 </size>
91 </property>
92 <property name="maximumSize">
93@@ -663,5 +695,6 @@
94 </item>
95 </layout>
96 </widget>
97+ <resources/>
98 <connections/>
99 </ui>
100
101=== added file 'data/qt/stylesheet.qss'
102--- data/qt/stylesheet.qss 1970-01-01 00:00:00 +0000
103+++ data/qt/stylesheet.qss 2012-02-21 23:01:20 +0000
104@@ -0,0 +1,119 @@
105+QWidget {
106+ font-family: "Ubuntu";
107+ color: #333333;
108+}
109+
110+QWizard,
111+QDialog {
112+ background-color: white;
113+}
114+
115+QLabel#password_assistance {
116+ border-image: url(":/balloon_shape.png");
117+}
118+
119+QLineEdit {
120+ border: 1px solid #aea79f;
121+}
122+
123+QPushButton {
124+ border-radius: 5px;
125+ border-style: solid;
126+ padding: 6px;
127+ padding-left: 20px;
128+ padding-right: 20px;
129+ border-width: 1px;
130+ height: 14px;
131+}
132+
133+QPushButton[default="true"] {
134+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
135+ stop: 0 #fe9e84,stop: 1.0 #dd4814);
136+ color: white;
137+ border-color: #999999;
138+}
139+
140+QPushButton:hover[default="true"] {
141+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
142+ stop: 0 #ffb19c,stop: 1.0 #dd4814);
143+ color: white;
144+ border-color: #999999;
145+}
146+
147+QPushButton:pressed[default="true"] {
148+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
149+ stop: 0 #b93f14,stop: 1.0 #dd4814);
150+ color: white;
151+ border-color: #999999;
152+}
153+
154+QPushButton[default="false"] {
155+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
156+ stop: 0 #ffffff,stop: 1.0 #e6e6e6);
157+ color: #333333;
158+ border-color: #999999;
159+}
160+
161+QPushButton:hover[default="false"] {
162+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
163+ stop: 0 #ffffff,stop: 1.0 #ededed);
164+ color: #333333;
165+ border-color: #999999;
166+}
167+
168+QPushButton:pressed[default="false"] {
169+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
170+ stop: 0 #d9d9d9,stop: 1.0 #fefefe);
171+ color: #333333;
172+ border-color: #999999;
173+}
174+
175+QPushButton[DisabledState="true"] {
176+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
177+ stop: 0 #eaeaea, stop: 1.0 #cacaca);
178+ color: #595959;
179+ border-color: #939389;
180+}
181+
182+QPushButton[DisabledState="false"] {
183+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
184+ stop: 0 #fe9e84,stop: 1.0 #dd4814);
185+ color: white;
186+ border-color: #999999;
187+}
188+
189+QPushButton:hover[DisabledState="false"] {
190+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
191+ stop: 0 #ffb19c,stop: 1.0 #dd4814);
192+ color: white;
193+ border-color: #999999;
194+}
195+
196+QPushButton:pressed[DisabledState="false"] {
197+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
198+ stop: 0 #b93f14,stop: 1.0 #dd4814);
199+ color: white;
200+ border-color: #999999;
201+}
202+
203+QFrame#frm_box {
204+ background: #ffffff;
205+ border-radius: 5px;
206+ border-style: solid;
207+ border-color: #939389;
208+ border-width: 1px;
209+ color: white;
210+ min-height: 100px;
211+}
212+
213+QFrame#frm_box > QLabel {
214+ font-size: 20px;
215+}
216+
217+QLabel#title_label {
218+ font-size: 20px;
219+}
220+
221+QFrame#header {
222+ padding: 10px;
223+}
224
225=== modified file 'run-tests'
226--- run-tests 2012-02-09 22:19:31 +0000
227+++ run-tests 2012-02-21 23:01:20 +0000
228@@ -47,7 +47,7 @@
229 fi
230
231 echo "*** Running GTK test suite for ""$MODULE"" ***"
232-$XVFB_CMDLINE u1trial --reactor=gi --gui -p "$QT_TESTS_PATH" -i "test_windows.py" "$MODULE"
233+$XVFB_CMDLINE u1trial --reactor=gi --gui -p "$QT_TESTS_PATH" -i "test_windows.py,test_qt.py" "$MODULE"
234 rm -rf _trial_temp
235
236 # hack to avoid:
237
238=== modified file 'setup.py'
239--- setup.py 2012-02-15 16:32:29 +0000
240+++ setup.py 2012-02-21 23:01:20 +0000
241@@ -153,11 +153,6 @@
242
243 def run(self):
244 """Execute the command."""
245- # pylint: disable=W0703
246- try:
247- self._wrapuic()
248- except Exception, e:
249- self.warn("Error wrapping uic to use gettext: %s" % e)
250 basepath = os.path.join('data', 'qt')
251 # TODO: build the resource files so that we can include them
252 #self.build_rc(os.path.join(basepath, 'icons_rc.py'),
253@@ -172,40 +167,6 @@
254
255 build_extra.build_extra.run(self)
256
257- # pylint: disable=E1002
258- _wrappeduic = False
259-
260- @classmethod
261- def _wrapuic(cls):
262- """Wrap uic to use gettext's _() in place of tr()"""
263- if cls._wrappeduic:
264- return
265-
266- from PyQt4.uic.Compiler import compiler, qtproxies, indenter
267-
268- # pylint: disable=C0103
269- class _UICompiler(compiler.UICompiler):
270- """Speciallized compiler for qt .ui files."""
271- def createToplevelWidget(self, classname, widgetname):
272- o = indenter.getIndenter()
273- o.level = 0
274- o.write('from gettext import gettext as _')
275- return super(_UICompiler, self).createToplevelWidget(classname,
276- widgetname)
277- compiler.UICompiler = _UICompiler
278-
279- class _i18n_string(qtproxies.i18n_string):
280- """Provide a translated text."""
281-
282- def __str__(self):
283- return "_('%s')" % self.string.encode('string-escape')
284-
285- qtproxies.i18n_string = _i18n_string
286-
287- cls._wrappeduic = True
288- # pylint: enable=C0103
289- # pylint: enable=E1002
290-
291
292 class SSOClean(DistUtilsExtra.auto.clean_build_tree):
293 """Class to clean up after the build."""
294
295=== modified file 'ubuntu_sso/credentials.py'
296--- ubuntu_sso/credentials.py 2012-02-11 19:25:01 +0000
297+++ ubuntu_sso/credentials.py 2012-02-21 23:01:20 +0000
298@@ -148,7 +148,9 @@
299 value = getattr(self, arg)
300 if value:
301 args.append('--%s' % arg)
302- args.append("%s" % str(value))
303+ if not isinstance(value, basestring):
304+ value = str(value)
305+ args.append(value)
306
307 if login_only:
308 args.append('--login_only')
309
310=== modified file 'ubuntu_sso/gtk/gui.py'
311--- ubuntu_sso/gtk/gui.py 2012-02-11 19:25:01 +0000
312+++ ubuntu_sso/gtk/gui.py 2012-02-21 23:01:20 +0000
313@@ -111,6 +111,7 @@
314 # To be replaced by values from the theme (LP: #616526)
315 HELP_TEXT_COLOR = parse_color("#bfbfbf")
316 WARNING_TEXT_COLOR = parse_color("red")
317+LARGE_MARKUP = u'<span size="x-large">%s</span>'
318
319
320 def log_call(f):
321@@ -173,9 +174,9 @@
322
323 def get_text(self):
324 """Get text only if it's not the label nor empty."""
325- result = super(LabeledEntry, self).get_text()
326+ result = super(LabeledEntry, self).get_text().decode('utf8')
327 if result == self.label or result.isspace():
328- result = ''
329+ result = u''
330 return result
331
332 def set_warning(self, warning_msg):
333@@ -209,10 +210,10 @@
334 self._done = False # whether the whole process was completed or not
335
336 self.app_name = app_name
337- self.app_label = '<b>%s</b>' % self.app_name
338- self.ping_url = kwargs.get('ping_url', '')
339- self.tc_url = kwargs.get('tc_url', '')
340- self.help_text = kwargs.get('help_text', '')
341+ self.app_label = u'<b>%s</b>' % self.app_name
342+ self.ping_url = kwargs.get('ping_url', u'')
343+ self.tc_url = kwargs.get('tc_url', u'')
344+ self.help_text = kwargs.get('help_text', u'')
345 self.login_only = kwargs.get('login_only', False)
346 window_id = kwargs.get('window_id', 0)
347 self.close_callback = kwargs.get('close_callback', NO_OP)
348@@ -338,15 +339,14 @@
349 def success_vbox(self):
350 """The success page."""
351 message = SUCCESS % {'app_name': self.app_name}
352- message = '<span size="x-large">%s</span>' % message
353+ message = LARGE_MARKUP % message
354 self.finish_vbox.label.set_markup(message)
355 return self.finish_vbox
356
357 @property
358 def error_vbox(self):
359 """The error page."""
360- self.finish_vbox.label.set_markup('<span size="x-large">%s</span>' %
361- ERROR)
362+ self.finish_vbox.label.set_markup(LARGE_MARKUP % ERROR)
363 return self.finish_vbox
364
365 # helpers
366@@ -362,7 +362,7 @@
367 result = f(app_name, *args, **kwargs)
368 else:
369 logger.info('%s: ignoring call since received app_name '\
370- '"%s" (expected "%s")',
371+ '%r (expected %r)',
372 f.__name__, app_name, self.app_name)
373 return result
374
375@@ -459,8 +459,7 @@
376
377 def _set_header(self, header):
378 """Set 'header' as the window title and header."""
379- markup = '<span size="x-large">%s</span>'
380- self.header_label.set_markup(markup % header)
381+ self.header_label.set_markup(LARGE_MARKUP % header)
382 self.window.set_title(self.header_label.get_text()) # avoid markup
383
384 def _set_current_page(self, current_page, warning_text=None):
385@@ -792,9 +791,8 @@
386 f = self.backend.register_user
387 error_handler = partial(self._handle_error, f,
388 self.on_user_registration_error)
389- f(unicode(self.app_name), email1.decode('utf8'),
390- password1.decode('utf8'), name.decode('utf8'),
391- unicode(self._captcha_id), captcha_solution.decode('utf8'),
392+ f(self.app_name, self.user_email, self.user_password, name,
393+ self._captcha_id, captcha_solution,
394 reply_handler=NO_OP, error_handler=error_handler)
395
396 def on_verify_token_button_clicked(self, *args, **kwargs):
397@@ -1035,7 +1033,7 @@
398 """Captcha image has been generated and is available to be shown."""
399 if captcha_id is None:
400 logger.warning('on_captcha_generated: captcha_id is None for '
401- 'app_name "%s".', app_name)
402+ 'app_name %r.', app_name)
403 self._captcha_id = captcha_id
404 self._set_captcha_image()
405
406
407=== modified file 'ubuntu_sso/gtk/tests/test_gui.py'
408--- ubuntu_sso/gtk/tests/test_gui.py 2012-02-11 01:51:57 +0000
409+++ ubuntu_sso/gtk/tests/test_gui.py 2012-02-21 23:01:20 +0000
410@@ -165,7 +165,7 @@
411 tmp = Gdk.RGBA()
412 assert tmp.parse(gdk_color.to_string())
413
414- msg = 'Text color must be "%s" (got "%s" instead).'
415+ msg = 'Text color must be %r (got %r instead).'
416 self.assertEqual(rgba_color, tmp, msg % (rgba_color, tmp))
417
418 def assert_backend_called(self, method, *args, **kwargs):
419@@ -211,7 +211,7 @@
420 def assert_correct_label(self):
421 """Check that the entry has the correct label."""
422 # text content is correct
423- msg = 'Text content must be "%s" (got "%s" instead).'
424+ msg = 'Text content must be %r (got %r instead).'
425 expected = self.label
426 actual = super(gui.LabeledEntry, self.entry).get_text()
427 self.assertEqual(expected, actual, msg % (expected, actual))
428@@ -231,7 +231,7 @@
429
430 def test_tooltip(self):
431 """Entry have the correct tooltip."""
432- msg = 'Tooltip must be "%s" (got "%s" instead).'
433+ msg = 'Tooltip must be %r (got %r instead).'
434 expected = self.label
435 actual = self.entry.get_tooltip_text()
436 # tooltip is correct
437@@ -404,7 +404,7 @@
438
439 def assert_entries_are_packed_to_ui(self, container_name, entries):
440 """Every entry is properly packed in the ui 'container_name'."""
441- msg = 'Entry "%s" must be packed in "%s" but is not.'
442+ msg = 'Entry %r must be packed in %r but is not.'
443 container = getattr(self.ui, container_name)
444 for kind in entries:
445 name = '%s_entry' % kind
446@@ -414,7 +414,7 @@
447
448 def assert_warnings_visibility(self, visible=False):
449 """Every warning label should be 'visible'."""
450- msg = '"%s" should have %sempty content.'
451+ msg = '%r should have %sempty content.'
452 for name in self.ui.widgets:
453 widget = getattr(self.ui, name)
454 if 'warning' in name:
455@@ -429,7 +429,7 @@
456 self.assertTrue(label.get_property('visible'))
457
458 # warning content is correct
459- actual = label.get_text()
460+ actual = label.get_text().decode('utf-8')
461 self.assertEqual(actual, message)
462
463 # content color is correct
464@@ -547,7 +547,7 @@
465
466 def test_initial_text_for_entries(self):
467 """Entries have the correct text at startup."""
468- msg = 'Text for "%s" must be "%s" (got "%s" instead).'
469+ msg = 'Text for %r must be %r (got %r instead).'
470 for name in self.ui.entries:
471 entry = getattr(self.ui, name)
472 expected = getattr(gui.utils.ui, name.upper())
473@@ -557,14 +557,14 @@
474
475 def test_entries_activates_default(self):
476 """Entries have the activates default prop set."""
477- msg = '"%s" must have activates_default set to True.'
478+ msg = '%r must have activates_default set to True.'
479 for name in self.ui.entries:
480 entry = getattr(self.ui, name)
481 self.assertTrue(entry.get_activates_default(), msg % (name,))
482
483 def test_password_fields_are_password(self):
484 """Password fields have the is_password flag set."""
485- msg = '"%s" should be a password LabeledEntry instance.'
486+ msg = '%r should be a password LabeledEntry instance.'
487 passwords = filter(lambda name: 'password' in name,
488 self.ui.entries)
489 for name in passwords:
490@@ -578,7 +578,7 @@
491 def test_cancel_buttons_close_window(self):
492 """Every cancel button should close the window when clicked."""
493 self.patch(self.ui.backend, 'disconnect_from_signal', lambda *a: None)
494- msg = '"%s" should close the window when clicked.'
495+ msg = '%r should close the window when clicked.'
496 buttons = filter(lambda name: 'cancel_button' in name or
497 'close_button' in name, self.ui.widgets)
498 for name in buttons:
499@@ -597,15 +597,16 @@
500 self.ui.finish_success()
501 self.assert_pages_visibility(finish=True)
502 self.assertEqual(gui.SUCCESS % {'app_name': APP_NAME},
503- self.ui.finish_vbox.label.get_text())
504- result = self.ui.finish_vbox.label.get_text()
505+ self.ui.finish_vbox.label.get_text().decode('utf8'))
506+ result = self.ui.finish_vbox.label.get_text().decode('utf8')
507 self.assertTrue(self.ui.app_name in result)
508
509 def test_finish_error_shows_error_page(self):
510 """When calling 'finish_error' the error page is shown."""
511 self.ui.finish_error()
512 self.assert_pages_visibility(finish=True)
513- self.assertEqual(gui.ERROR, self.ui.finish_vbox.label.get_text())
514+ self.assertEqual(gui.ERROR,
515+ self.ui.finish_vbox.label.get_text().decode('utf8'))
516
517
518 class SetTransientForTestCase(UbuntuSSOClientTestCase):
519@@ -649,9 +650,9 @@
520
521 def test_initial_text_for_header_label(self):
522 """The header must have the correct text at startup."""
523- msg = 'Text for the header must be "%s" (got "%s" instead).'
524+ msg = 'Text for the header must be %r (got %r instead).'
525 expected = gui.JOIN_HEADER_LABEL % {'app_name': APP_NAME}
526- actual = self.ui.header_label.get_text()
527+ actual = self.ui.header_label.get_text().decode('utf8')
528 # text content is correct
529 self.assertEqual(expected, actual, msg % (expected, actual))
530
531@@ -670,26 +671,26 @@
532
533 def test_initial_texts_for_checkbuttons(self):
534 """Check buttons have the correct text at startup."""
535- msg = 'Text for "%s" must be "%s" (got "%s" instead).'
536+ msg = 'Text for %r must be %r (got %r instead).'
537 expected = gui.YES_TO_UPDATES % {'app_name': APP_NAME}
538- actual = self.ui.yes_to_updates_checkbutton.get_label()
539+ actual = self.ui.yes_to_updates_checkbutton.get_label().decode('utf8')
540 self.assertEqual(expected, actual, msg % ('yes_to_updates_checkbutton',
541 expected, actual))
542 expected = gui.YES_TO_TC % {'app_name': APP_NAME}
543- actual = self.ui.yes_to_tc_checkbutton.get_label()
544+ actual = self.ui.yes_to_tc_checkbutton.get_label().decode('utf8')
545 self.assertEqual(expected, actual,
546 msg % ('yes_to_tc_checkbutton', expected, actual))
547
548 def test_checkbutton_is_checked_at_startup(self):
549 """Checkbuttons are checked by default."""
550- msg = '"%s" is checked by default.'
551+ msg = '%r is checked by default.'
552 name = 'yes_to_updates_checkbutton'
553 widget = getattr(self.ui, name)
554 self.assertTrue(widget.get_active(), msg % name)
555
556 def test_checkbutton_isnt_checked_at_startup(self):
557 """Checkbuttons are checked by default."""
558- msg = '"%s" is checked by default.'
559+ msg = '%r is checked by default.'
560 name = 'yes_to_tc_checkbutton'
561 widget = getattr(self.ui, name)
562 self.assertFalse(widget.get_active(), msg % name)
563@@ -732,7 +733,8 @@
564 'the processing spinner should be active.')
565 self.assertTrue(label.get_property('visible'),
566 'the processing label should be visible.')
567- self.assertEqual(label.get_text(), gui.ONE_MOMENT_PLEASE,
568+ self.assertEqual(label.get_text().decode('utf8'),
569+ gui.ONE_MOMENT_PLEASE,
570 'the processing label text must be correct.')
571
572 def test_captcha_image_is_not_visible_at_startup(self):
573@@ -775,7 +777,7 @@
574 'the captcha_loading spinner should be active.')
575 self.assertTrue(label.get_property('visible'),
576 'the captcha_loading label should be visible.')
577- self.assertEqual(label.get_text(), gui.LOADING,
578+ self.assertEqual(label.get_text().decode('utf8'), gui.LOADING,
579 'the captcha_loading label text must be correct.')
580
581 def test_join_ok_button_is_disabled_until_captcha_is_available(self):
582@@ -814,7 +816,7 @@
583 def test_on_captcha_generated_logs_captcha_id_when_none(self):
584 """If the captcha id is None, a warning is logged."""
585 self.ui.on_captcha_generated(app_name=APP_NAME, captcha_id=None)
586- self.assertTrue(self.memento.check(logging.WARNING, APP_NAME))
587+ self.assertTrue(self.memento.check(logging.WARNING, repr(APP_NAME)))
588 self.assertTrue(self.memento.check(logging.WARNING,
589 'captcha_id is None'))
590
591@@ -837,7 +839,7 @@
592
593 def test_login_button_has_correct_wording(self):
594 """The sign in button has the proper wording."""
595- actual = self.ui.login_button.get_label()
596+ actual = self.ui.login_button.get_label().decode('utf8')
597 self.assertEqual(gui.LOGIN_BUTTON_LABEL, actual)
598
599 def test_join_ok_button_does_nothing_if_clicked_but_disabled(self):
600@@ -870,7 +872,7 @@
601 """When captcha was retrieved after error, the warning is removed."""
602 self.ui.on_captcha_generation_error(APP_NAME, error=self.error)
603 self.ui.on_captcha_generated(app_name=APP_NAME, captcha_id=CAPTCHA_ID)
604- self.assertEqual(self.ui.warning_label.get_text(), '')
605+ self.assertEqual(self.ui.warning_label.get_text().decode('utf8'), '')
606
607
608 class NoTermsAndConditionsTestCase(UbuntuSSOClientTestCase):
609@@ -953,12 +955,13 @@
610
611 def test_tc_button_has_the_proper_wording(self):
612 """Terms & Conditions has the proper wording."""
613- self.assertEqual(self.ui.tc_button.get_label(), gui.TC_BUTTON)
614+ self.assertEqual(self.ui.tc_button.get_label().decode('utf8'),
615+ gui.TC_BUTTON)
616
617 def test_tc_has_no_help_text(self):
618 """The help text is removed."""
619 self.ui.on_tc_browser_notify_load_status(self.browser)
620- self.assertEqual('', self.ui.help_label.get_text())
621+ self.assertEqual('', self.ui.help_label.get_text().decode('utf8'))
622
623 def test_tc_browser_opens_the_proper_url(self):
624 """Terms & Conditions browser shows the proper uri."""
625@@ -1115,8 +1118,8 @@
626
627 def test_help_label_display_correct_wording(self):
628 """The help_label display VERIFY_EMAIL_LABEL."""
629- msg = 'help_label must read "%s" (got "%s" instead).'
630- actual = self.ui.help_label.get_label()
631+ msg = 'help_label must read %r (got %r instead).'
632+ actual = self.ui.help_label.get_label().decode('utf8')
633 expected = gui.VERIFY_EMAIL_LABEL % {'app_name': APP_NAME,
634 'email': EMAIL}
635 self.assertEqual(expected, actual, msg % (expected, actual))
636@@ -1160,7 +1163,7 @@
637 """On email validated the help text is not removed."""
638 self.ui.on_email_validated(app_name=APP_NAME, email=EMAIL)
639 self.assertEqual(self.ui.verify_email_vbox.help_text,
640- self.ui.help_label.get_label())
641+ self.ui.help_label.get_label().decode('utf8'))
642
643 def test_on_email_validation_error_verify_email_is_shown(self):
644 """On email validation error, the verify_email page is shown."""
645@@ -1186,16 +1189,16 @@
646 def test_success_label_is_correct(self):
647 """The success message is correct."""
648 self.assertEqual(gui.SUCCESS % {'app_name': APP_NAME},
649- self.ui.success_vbox.label.get_text())
650- markup = self.ui.success_vbox.label.get_label()
651+ self.ui.success_vbox.label.get_text().decode('utf8'))
652+ markup = self.ui.success_vbox.label.get_label().decode('utf8')
653 self.assertTrue('<span size="x-large">' in markup)
654 self.assertTrue(self.ui.app_name in markup)
655
656 def test_error_label_is_correct(self):
657 """The error message is correct."""
658 self.assertEqual(gui.ERROR,
659- self.ui.error_vbox.label.get_text())
660- markup = self.ui.error_vbox.label.get_label()
661+ self.ui.error_vbox.label.get_text().decode('utf8'))
662+ markup = self.ui.error_vbox.label.get_label().decode('utf8')
663 self.assertTrue('<span size="x-large">' in markup)
664
665 def test_on_finish_close_button_clicked_closes_window(self):
666@@ -1346,7 +1349,7 @@
667 """Password help text is correctly displayed."""
668 self.assertTrue(self.ui.password_help_label.get_property('visible'),
669 'password help text is visible.')
670- self.assertEqual(self.ui.password_help_label.get_text(),
671+ self.assertEqual(self.ui.password_help_label.get_text().decode('utf8'),
672 gui.PASSWORD_HELP)
673 self.assertNotIn('register_user', self.ui.backend._called)
674
675@@ -1436,16 +1439,16 @@
676
677 def test_initial_text_for_header_label(self):
678 """The header must have the correct text when logging in."""
679- msg = 'Text for the header must be "%s" (got "%s" instead).'
680+ msg = 'Text for the header must be %r (got %r instead).'
681 expected = gui.LOGIN_HEADER_LABEL % {'app_name': APP_NAME}
682- actual = self.ui.header_label.get_text()
683+ actual = self.ui.header_label.get_text().decode('utf8')
684 self.assertEqual(expected, actual, msg % (expected, actual))
685
686 def test_initial_text_for_help_label(self):
687 """The help must have the correct text at startup."""
688- msg = 'Text for the help must be "%s" (got "%s" instead).'
689+ msg = 'Text for the help must be %r (got %r instead).'
690 expected = gui.CONNECT_HELP_LABEL % {'app_name': APP_NAME}
691- actual = self.ui.help_label.get_text()
692+ actual = self.ui.help_label.get_text().decode('utf8')
693 self.assertEqual(expected, actual, msg % (expected, actual))
694
695 def test_entries_are_packed_to_ui_for_login(self):
696@@ -1628,23 +1631,23 @@
697
698 def test_forgotten_password_button_has_the_proper_wording(self):
699 """The forgotten_password_button has the proper wording."""
700- self.assertEqual(self.ui.forgotten_password_button.get_label(),
701- gui.FORGOTTEN_PASSWORD_BUTTON)
702+ actual = self.ui.forgotten_password_button.get_label()
703+ self.assertEqual(actual.decode('utf8'), gui.FORGOTTEN_PASSWORD_BUTTON)
704
705 def test_on_forgotten_password_button_clicked_help_text(self):
706 """Clicking forgotten_password_button the help is properly changed."""
707 wanted = gui.REQUEST_PASSWORD_TOKEN_LABEL % {'app_name': APP_NAME}
708- self.assertEqual(self.ui.help_label.get_text(), wanted)
709+ self.assertEqual(self.ui.help_label.get_text().decode('utf8'), wanted)
710
711 def test_on_forgotten_password_button_clicked_header_label(self):
712 """Clicking forgotten_password_button the title is properly changed."""
713- self.assertEqual(self.ui.header_label.get_text(),
714+ self.assertEqual(self.ui.header_label.get_text().decode('utf8'),
715 gui.RESET_PASSWORD)
716
717 def test_on_forgotten_password_button_clicked_ok_button(self):
718 """Clicking forgotten_password_button the ok button reads 'Next'."""
719- self.assertEqual(self.ui.request_password_token_ok_button.get_label(),
720- gui.NEXT)
721+ actual = self.ui.request_password_token_ok_button.get_label()
722+ self.assertEqual(actual.decode('utf8'), gui.NEXT)
723
724 def test_on_forgotten_password_button_clicked_morphs_window(self):
725 """Clicking forgotten_password_button the proper page is shown."""
726@@ -1691,7 +1694,7 @@
727 self.click_request_password_token_with_valid_data()
728 self.ui.on_password_reset_token_sent(app_name=APP_NAME, email=EMAIL)
729
730- self.assertEqual(self.ui.help_label.get_text(),
731+ self.assertEqual(self.ui.help_label.get_text().decode('utf8'),
732 gui.SET_NEW_PASSWORD_LABEL % {'email': EMAIL})
733
734 def test_on_password_reset_token_sent_ok_button(self):
735@@ -1699,8 +1702,8 @@
736 self.click_request_password_token_with_valid_data()
737 self.ui.on_password_reset_token_sent(app_name=APP_NAME, email=EMAIL)
738
739- self.assertEqual(self.ui.set_new_password_ok_button.get_label(),
740- gui.RESET_PASSWORD)
741+ actual = self.ui.set_new_password_ok_button.get_label()
742+ self.assertEqual(actual.decode('utf8'), gui.RESET_PASSWORD)
743
744 def test_on_password_reset_error_shows_login_page(self):
745 """When reset token wasn't successfuly sent the login page is shown."""
746@@ -1872,8 +1875,8 @@
747 """Password help text is correctly displayed."""
748 visible = self.ui.reset_password_help_label.get_property('visible')
749 self.assertTrue(visible, 'password help text is visible.')
750- self.assertEqual(self.ui.reset_password_help_label.get_text(),
751- gui.PASSWORD_HELP)
752+ actual = self.ui.reset_password_help_label.get_text()
753+ self.assertEqual(actual.decode('utf8'), gui.PASSWORD_HELP)
754 self.assertNotIn('set_new_password', self.ui.backend._called)
755
756 def test_warning_is_shown_if_password_mismatch(self):
757@@ -1951,7 +1954,7 @@
758 """Callbacks do nothing but logging when app_name doesn't match."""
759 mismatch_app_name = self.ui.app_name * 2
760 for method in self.ui._signals.itervalues():
761- msgs = ('ignoring', method.__name__, mismatch_app_name)
762+ msgs = ('ignoring', method.__name__, repr(mismatch_app_name))
763 method(mismatch_app_name, 'dummy')
764 self.assertTrue(self.memento.check(logging.INFO, *msgs))
765 self.memento.records = []
766@@ -2068,7 +2071,8 @@
767
768 def test_help_text_is_used(self):
769 """The passed help_text is used."""
770- self.assertEqual(self.ui.help_label.get_text(), HELP_TEXT)
771+ self.assertEqual(self.ui.help_label.get_text().decode('utf8'),
772+ HELP_TEXT)
773
774
775 class ReturnCodeTestCase(UbuntuSSOClientTestCase):
776@@ -2087,7 +2091,7 @@
777 def test_every_cancel_calls_proper_callback(self):
778 """When any cancel button is clicked, USER_CANCELLATION is called."""
779 self.patch(self.ui.backend, 'disconnect_from_signal', lambda *a: None)
780- msg = 'USER_CANCELLATION should be returned when "%s" is clicked.'
781+ msg = 'USER_CANCELLATION should be returned when %r is clicked.'
782 buttons = filter(lambda name: 'cancel_button' in name, self.ui.widgets)
783 for name in buttons:
784 widget = getattr(self.ui, name)
785
786=== modified file 'ubuntu_sso/keyring/tests/test_linux.py'
787--- ubuntu_sso/keyring/tests/test_linux.py 2012-01-26 15:34:16 +0000
788+++ ubuntu_sso/keyring/tests/test_linux.py 2012-02-21 23:01:20 +0000
789@@ -26,7 +26,6 @@
790
791 from ubuntu_sso import keyring as common_keyring
792 from ubuntu_sso.keyring import linux as keyring
793-from ubuntu_sso.tests import APP_NAME
794
795
796 class MockItem(object):
797@@ -168,9 +167,9 @@
798 sample_creds = {"name": "sample creds name"}
799 kr = keyring.Keyring()
800 self.patch(keyring, "get_token_name", keyring.get_old_token_name)
801- yield kr.set_credentials(APP_NAME, sample_creds)
802+ yield kr.set_credentials("app name", sample_creds)
803
804- result = yield kr.get_credentials(APP_NAME)
805+ result = yield kr.get_credentials("app name")
806 self.assertEqual(result, sample_creds)
807
808 @inlineCallbacks
809
810=== modified file 'ubuntu_sso/main/__init__.py'
811--- ubuntu_sso/main/__init__.py 2012-02-11 01:51:57 +0000
812+++ ubuntu_sso/main/__init__.py 2012-02-21 23:01:20 +0000
813@@ -318,7 +318,7 @@
814 def CredentialsFound(self, app_name, credentials):
815 """Signal thrown when the credentials are found."""
816 self.ref_count -= 1
817- logger.info('%s: emitting CredentialsFound with app_name "%s".',
818+ logger.info('%s: emitting CredentialsFound with app_name %r.',
819 self.__class__.__name__, app_name)
820 self.proxy.CredentialsFound(app_name, credentials)
821
822
823=== modified file 'ubuntu_sso/main/linux.py'
824--- ubuntu_sso/main/linux.py 2012-02-14 21:53:58 +0000
825+++ ubuntu_sso/main/linux.py 2012-02-21 23:01:20 +0000
826@@ -25,7 +25,6 @@
827
828 """
829
830-import os
831 import signal
832
833 import dbus
834@@ -439,10 +438,10 @@
835 return defer.succeed(result)
836
837
838-if os.environ.get('USE_QT_MAINLOOP'):
839+try:
840 from ubuntu_sso.main import qt
841 source = qt
842-else:
843+except ImportError: # no PyQt4.QtCore in the system
844 from ubuntu_sso.main import glib
845 source = glib
846
847
848=== modified file 'ubuntu_sso/main/qt.py'
849--- ubuntu_sso/main/qt.py 2012-01-26 14:54:13 +0000
850+++ ubuntu_sso/main/qt.py 2012-02-21 23:01:20 +0000
851@@ -22,10 +22,30 @@
852
853 from PyQt4 import QtCore
854
855-
856-def timeout_func(*a, **kw):
857+TIMERS = set()
858+
859+
860+def timeout_func(interval, callback, *a, **kw):
861 """Delay import of dynamic bindings to avoid crashes."""
862- # use a QTimer to simulate a looping call
863+
864+ # QTimers don't support priorities
865+ kw.pop("priority", None)
866+
867+ timer = QtCore.QTimer()
868+ TIMERS.add(timer)
869+
870+ def _callback():
871+ """Call the real callback, with arguments, until it returns False."""
872+ if timer in TIMERS:
873+ result = callback(*a, **kw)
874+ if not result:
875+ timer.stop()
876+ TIMERS.remove(timer)
877+ # Probably overkill
878+ timer.deleteLater()
879+
880+ timer.timeout.connect(_callback)
881+ timer.start(interval)
882
883
884 def shutdown_func(*a, **kw):
885
886=== modified file 'ubuntu_sso/main/tests/test_common.py'
887--- ubuntu_sso/main/tests/test_common.py 2012-02-10 17:18:22 +0000
888+++ ubuntu_sso/main/tests/test_common.py 2012-02-21 23:01:20 +0000
889@@ -919,7 +919,8 @@
890 @defer.inlineCallbacks
891 def setUp(self):
892 yield super(CredentialsManagementOpsTestCase, self).setUp()
893- self.args = dict((k, str(v)) for k, v in self.base_args.iteritems())
894+ self.args = dict(self.base_args)
895+ self.args[WINDOW_ID_KEY] = str(self.args[WINDOW_ID_KEY])
896 self.cred_args = self.base_args.copy()
897
898 def test_register(self):
899@@ -955,12 +956,16 @@
900 class CredentialsManagementSignalsTestCase(CredentialsManagementTestCase):
901 """Tests for the CredentialsManagement DBus signals."""
902
903+ def assert_signal_logged(self, signal, *args):
904+ """Check that signal info was properly logged."""
905+ signal(APP_NAME, *args)
906+ msgs = [self.obj.__class__.__name__,
907+ signal.__name__, repr(APP_NAME)]
908+ self.assertTrue(self.memento.check_info(*msgs))
909+
910 def test_credentials_found(self):
911 """The CredentialsFound signal."""
912- self.obj.CredentialsFound(APP_NAME, TOKEN)
913- msgs = (self.obj.__class__.__name__,
914- self.obj.CredentialsFound.__name__, APP_NAME)
915- self.assertTrue(self.memento.check_info(*msgs))
916+ self.assert_signal_logged(self.obj.CredentialsFound, TOKEN)
917
918 msg = 'credentials must not be logged (found %r in log).'
919 for val in TOKEN.itervalues():
920@@ -968,24 +973,15 @@
921
922 def test_credentials_not_found(self):
923 """The CredentialsNotFound signal."""
924- self.obj.CredentialsNotFound(APP_NAME)
925- msgs = (self.obj.__class__.__name__,
926- self.obj.CredentialsNotFound.__name__, APP_NAME)
927- self.assertTrue(self.memento.check_info(*msgs))
928+ self.assert_signal_logged(self.obj.CredentialsNotFound)
929
930 def test_credentials_cleared(self):
931 """The CredentialsCleared signal."""
932- self.obj.CredentialsCleared(APP_NAME)
933- msgs = (self.obj.__class__.__name__,
934- self.obj.CredentialsCleared.__name__, APP_NAME)
935- self.assertTrue(self.memento.check_info(*msgs))
936+ self.assert_signal_logged(self.obj.CredentialsCleared)
937
938 def test_credentials_stored(self):
939 """The CredentialsStored signal."""
940- self.obj.CredentialsStored(APP_NAME)
941- msgs = (self.obj.__class__.__name__,
942- self.obj.CredentialsStored.__name__, APP_NAME)
943- self.assertTrue(self.memento.check_info(*msgs))
944+ self.assert_signal_logged(self.obj.CredentialsStored)
945
946 def test_credentials_error(self):
947 """The CredentialsError signal."""
948@@ -993,15 +989,12 @@
949 self.obj.CredentialsError(APP_NAME, error)
950 msgs = (self.obj.__class__.__name__,
951 self.obj.CredentialsError.__name__,
952- APP_NAME, str(error))
953+ repr(APP_NAME), repr(error))
954 self.assertTrue(self.memento.check_error(*msgs))
955
956 def test_authorization_denied(self):
957 """The AuthorizationDenied signal."""
958- self.obj.AuthorizationDenied(APP_NAME)
959- msgs = (self.obj.__class__.__name__,
960- self.obj.AuthorizationDenied.__name__, APP_NAME)
961- self.assertTrue(self.memento.check_info(*msgs))
962+ self.assert_signal_logged(self.obj.AuthorizationDenied)
963
964
965 class UbuntuSSOServiceTestCase(BaseTestCase):
966
967=== added file 'ubuntu_sso/main/tests/test_qt.py'
968--- ubuntu_sso/main/tests/test_qt.py 1970-01-01 00:00:00 +0000
969+++ ubuntu_sso/main/tests/test_qt.py 2012-02-21 23:01:20 +0000
970@@ -0,0 +1,69 @@
971+# -*- coding: utf-8 -*-
972+#
973+# Copyright 2012 Canonical Ltd.
974+#
975+# This program is free software: you can redistribute it and/or modify it
976+# under the terms of the GNU General Public License version 3, as published
977+# by the Free Software Foundation.
978+#
979+# This program is distributed in the hope that it will be useful, but
980+# WITHOUT ANY WARRANTY; without even the implied warranties of
981+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
982+# PURPOSE. See the GNU General Public License for more details.
983+#
984+# You should have received a copy of the GNU General Public License along
985+# with this program. If not, see <http://www.gnu.org/licenses/>.
986+"""Qt specific tests for the main module."""
987+
988+# pylint: disable=F0401
989+from PyQt4 import QtCore
990+from twisted.internet import defer
991+
992+from ubuntu_sso.main import qt
993+from ubuntu_sso.tests import TestCase
994+
995+
996+class MiscTestCase(TestCase):
997+ """Tests for module level misc functions."""
998+
999+ def clean_timers(self):
1000+ """Remove all timers."""
1001+ qt.TIMERS = set()
1002+
1003+ @defer.inlineCallbacks
1004+ def setUp(self):
1005+ yield super(MiscTestCase, self).setUp()
1006+ self.addCleanup(self.clean_timers)
1007+
1008+ def test_timeout_func_ignores_priority(self):
1009+ """Should not pass priority as argument."""
1010+ qt.timeout_func(0, self._set_called, priority="crazy")
1011+ QtCore.QCoreApplication.instance().processEvents()
1012+ self.assertEqual(self._called, ((), {}))
1013+
1014+ def test_timeout_func_keeps_reference(self):
1015+ """Should keep a reference to the timer created."""
1016+ self.assertEqual(len(qt.TIMERS), 0)
1017+ qt.timeout_func(0, self._set_called, priority="crazy")
1018+ self.assertEqual(len(qt.TIMERS), 1)
1019+
1020+ def test_timeout_func_removes_reference(self):
1021+ """Remove reference to timer when callback returns False."""
1022+ self.assertEqual(len(qt.TIMERS), 0)
1023+ qt.timeout_func(0, self._set_called, priority="crazy")
1024+ self.assertEqual(len(qt.TIMERS), 1)
1025+ QtCore.QCoreApplication.instance().processEvents()
1026+ self.assertEqual(len(qt.TIMERS), 0)
1027+
1028+ def test_timeout_func_timer_activation(self):
1029+ """The timer should be activated with the right period."""
1030+ self.assertEqual(len(qt.TIMERS), 0)
1031+ qt.timeout_func(1337, self._set_called, priority="crazy")
1032+ self.assertEqual(len(qt.TIMERS), 1)
1033+ self.assertEqual(list(qt.TIMERS)[0].interval(), 1337)
1034+
1035+ def test_timeout_func_argument_passing(self):
1036+ """The right arguments should be passed to the callback."""
1037+ qt.timeout_func(0, self._set_called, 1, name="a")
1038+ QtCore.QCoreApplication.instance().processEvents()
1039+ self.assertEqual(self._called, ((1,), {"name": "a"}))
1040
1041=== modified file 'ubuntu_sso/qt/__init__.py'
1042--- ubuntu_sso/qt/__init__.py 2012-02-09 18:28:40 +0000
1043+++ ubuntu_sso/qt/__init__.py 2012-02-21 23:01:20 +0000
1044@@ -16,21 +16,11 @@
1045
1046 """The Qt graphical interface for the Ubuntu Single Sign On Client."""
1047
1048-import gettext
1049 import collections
1050
1051
1052-_ = gettext.gettext
1053-
1054 ERROR_ALL = '__all__'
1055 ERROR_MESSAGE = 'message'
1056-LOCAL_FOLDERS_TITLE = _("Syncing your computer with the cloud")
1057-LOCAL_FOLDERS_SPACE_HEADER = _("Space (%s)")
1058-LOCAL_FOLDERS_OFFER_LABEL = _("The folders you have selected to sync "
1059- "take over your %(quota)s space. You can remove some folders or add "
1060- "some extra space")
1061-LOCAL_FOLDERS_CALCULATING = _("Calculating")
1062-NEXT = _("Next")
1063
1064
1065 # Based on the gtk implementation
1066
1067=== modified file 'ubuntu_sso/qt/common.py'
1068--- ubuntu_sso/qt/common.py 2012-02-09 19:21:09 +0000
1069+++ ubuntu_sso/qt/common.py 2012-02-21 23:01:20 +0000
1070@@ -18,6 +18,7 @@
1071 """Common functionality used by the UI modules."""
1072
1073 import re
1074+
1075 from ubuntu_sso.utils.ui import (
1076 PASSWORD_DIGIT,
1077 PASSWORD_LENGTH,
1078
1079=== modified file 'ubuntu_sso/qt/current_user_sign_in_page.py'
1080--- ubuntu_sso/qt/current_user_sign_in_page.py 2012-02-13 20:27:48 +0000
1081+++ ubuntu_sso/qt/current_user_sign_in_page.py 2012-02-21 23:01:20 +0000
1082@@ -16,15 +16,17 @@
1083
1084 """Page to allow the user to login into Ubuntu Single Sign On."""
1085
1086-import gettext
1087+from functools import partial
1088
1089 from PyQt4 import QtGui, QtCore
1090 from twisted.internet import defer
1091
1092+from ubuntu_sso import NO_OP
1093 from ubuntu_sso.qt import build_general_error_message
1094 from ubuntu_sso.qt.gui import SSOWizardPage
1095 from ubuntu_sso.logger import setup_logging
1096 from ubuntu_sso.utils.ui import (
1097+ CANCEL_BUTTON,
1098 EMAIL_LABEL,
1099 FORGOTTEN_PASSWORD_BUTTON,
1100 is_correct_email,
1101@@ -33,10 +35,10 @@
1102 )
1103
1104
1105-FORGOTTEN_PASSWORD_LINK_STYLE = '<a href="#">{forgotten_text}</a>'
1106-
1107-
1108-_ = gettext.gettext
1109+FORGOTTEN_PASSWORD_LINK_STYLE = ('<a href="#" style="color:#dd4814;">'
1110+ '{forgotten_text}</a>')
1111+
1112+
1113 logger = setup_logging('ubuntu_sso.current_user_sign_in_page')
1114
1115
1116@@ -85,8 +87,7 @@
1117
1118 def initializePage(self):
1119 """Setup UI details."""
1120- self.setButtonText(QtGui.QWizard.CancelButton,
1121- _("Cancel"))
1122+ self.setButtonText(QtGui.QWizard.CancelButton, CANCEL_BUTTON)
1123 # Layout without custom button 1,
1124 # without finish button
1125 self.wizard().setButtonLayout([
1126@@ -103,6 +104,10 @@
1127 self.ui.sign_in_button.style().polish(
1128 self.ui.sign_in_button)
1129
1130+ def cleanupPage(self):
1131+ """Reset the wizard buttons."""
1132+ self.wizard().setButtonLayout([QtGui.QWizard.Stretch])
1133+
1134 def _set_translated_strings(self):
1135 """Set the translated strings."""
1136 logger.debug('CurrentUserSignInPage._set_translated_strings')
1137@@ -147,19 +152,24 @@
1138 args = args + (self.ping_url,)
1139 else:
1140 f = self.backend.login
1141- f(*args)
1142+
1143+ self.overlay.show()
1144+ error_handler = partial(self._handle_error, f, self.on_login_error)
1145+ f(*args, reply_handler=NO_OP, error_handler=error_handler)
1146
1147 def on_login_error(self, app_name, error):
1148 """There was an error when login in."""
1149 # let the user know
1150 logger.error('Got error when login %s, error: %s',
1151 self.app_name, error)
1152+ self.overlay.hide()
1153 self.message_box.critical(self, self.app_name,
1154 build_general_error_message(error))
1155
1156 def on_logged_in(self, app_name, result):
1157 """We managed to log in."""
1158 logger.info('Logged in for %s', app_name)
1159+ self.overlay.hide()
1160 email = unicode(self.ui.email_edit.text())
1161 self.userLoggedIn.emit(app_name, email)
1162 logger.debug('Wizard.loginSuccess emitted.')
1163
1164=== modified file 'ubuntu_sso/qt/email_verification_page.py'
1165--- ubuntu_sso/qt/email_verification_page.py 2012-02-13 14:04:27 +0000
1166+++ ubuntu_sso/qt/email_verification_page.py 2012-02-21 23:01:20 +0000
1167@@ -16,9 +16,12 @@
1168
1169 """Email Verification page UI."""
1170
1171+from functools import partial
1172+
1173 from PyQt4 import QtCore
1174 from twisted.internet import defer
1175
1176+from ubuntu_sso import NO_OP
1177 from ubuntu_sso.qt import build_general_error_message
1178 from ubuntu_sso.qt.gui import SSOWizardPage
1179 from ubuntu_sso.logger import setup_logging
1180@@ -115,7 +118,9 @@
1181 logger.info('Calling validate_email with email %r, password <hidden>, '
1182 'app_name %r and email_token %r.', self.email,
1183 self.app_name, code)
1184- f(*args)
1185+ error_handler = partial(self._handle_error, f,
1186+ self.on_email_validation_error)
1187+ f(*args, reply_handler=NO_OP, error_handler=error_handler)
1188
1189 def on_email_validated(self, app_name, *args, **kwargs):
1190 """Signal thrown after the email is validated."""
1191
1192=== modified file 'ubuntu_sso/qt/enhanced_check_box.py'
1193--- ubuntu_sso/qt/enhanced_check_box.py 2012-02-02 15:57:02 +0000
1194+++ ubuntu_sso/qt/enhanced_check_box.py 2012-02-21 23:01:20 +0000
1195@@ -18,7 +18,7 @@
1196
1197 """Customized Check Box to support links."""
1198
1199-from PyQt4 import QtGui
1200+from PyQt4 import QtGui, QtCore
1201
1202
1203 class EnhancedCheckBox(QtGui.QCheckBox):
1204@@ -28,9 +28,12 @@
1205 QtGui.QCheckBox.__init__(self)
1206 hbox = QtGui.QHBoxLayout()
1207 self.text_label = QtGui.QLabel(text)
1208+ self.text_label.setAlignment(QtCore.Qt.AlignTop)
1209 self.text_label.setOpenExternalLinks(True)
1210 padding = self.iconSize().width()
1211- self.text_label.setStyleSheet("padding-left: {0}px;".format(padding))
1212+ self.text_label.setStyleSheet("margin-top: -3px;"
1213+ "padding-left: {0}px;".format(padding))
1214+ hbox.setContentsMargins(padding, 0, 0, 0)
1215 hbox.addWidget(self.text_label)
1216 self.setLayout(hbox)
1217
1218
1219=== modified file 'ubuntu_sso/qt/forgotten_password_page.py'
1220--- ubuntu_sso/qt/forgotten_password_page.py 2012-02-13 21:50:16 +0000
1221+++ ubuntu_sso/qt/forgotten_password_page.py 2012-02-21 23:01:20 +0000
1222@@ -16,9 +16,12 @@
1223
1224 """Forgotten Password page UI."""
1225
1226+from functools import partial
1227+
1228 from PyQt4 import QtCore
1229 from twisted.internet import defer
1230
1231+from ubuntu_sso import NO_OP
1232 from ubuntu_sso.qt.gui import SSOWizardEnhancedEditPage
1233 from ubuntu_sso.utils.ui import (
1234 EMAIL_LABEL,
1235@@ -139,12 +142,21 @@
1236 def _connect_ui(self):
1237 """Connect the diff signals from the Ui."""
1238 self.email_address_line_edit.textChanged.connect(self._validate)
1239- self.send_button.clicked.connect(
1240- lambda: self.backend.request_password_reset_token(
1241- self.app_name,
1242- self.email_address))
1243+
1244+ self.send_button.clicked.connect(self.request_new_password)
1245 self.try_again_button.clicked.connect(self.on_try_again)
1246
1247+ def request_new_password(self):
1248+ """Send the request password operation."""
1249+ args = (self.app_name, self.email_address)
1250+ f = self.backend.request_password_reset_token
1251+
1252+ error_handler = partial(self._handle_error, f,
1253+ self.on_password_reset_error)
1254+
1255+ self.overlay.show()
1256+ f(*args, reply_handler=NO_OP, error_handler=error_handler)
1257+
1258 def _validate(self):
1259 """Validate that we have an email."""
1260 email = unicode(self.email_address_line_edit.text())
1261@@ -163,12 +175,14 @@
1262 def on_password_reset_token_sent(self, app_name, result):
1263 """Action taken when we managed to get the password reset done."""
1264 # ignore the result and move to the reset page
1265+ self.overlay.hide()
1266 self.passwordResetTokenSent.emit()
1267 # pylint: enable=W0212
1268
1269 def on_password_reset_error(self, app_name, error):
1270 """Action taken when there was an error requesting the reset."""
1271 # set the error message
1272+ self.overlay.hide()
1273 msg = REQUEST_PASSWORD_TOKEN_TECH_ERROR
1274 if error['errtype'] == 'ResetPasswordTokenError':
1275 # the account provided is wrong, lets tell the user to try
1276
1277=== modified file 'ubuntu_sso/qt/gui.py'
1278--- ubuntu_sso/qt/gui.py 2012-02-13 16:16:03 +0000
1279+++ ubuntu_sso/qt/gui.py 2012-02-21 23:01:20 +0000
1280@@ -15,7 +15,6 @@
1281 # with this program. If not, see <http://www.gnu.org/licenses/>.
1282 """Qt implementation of the UI."""
1283
1284-import gettext
1285 from functools import wraps
1286
1287 # pylint: disable=F0401,E0611
1288@@ -23,8 +22,8 @@
1289 from PyQt4.QtCore import Qt
1290 from PyQt4.QtGui import (
1291 QApplication,
1292- QWidget,
1293 QCursor,
1294+ QFrame,
1295 QHBoxLayout,
1296 QVBoxLayout,
1297 QMessageBox,
1298@@ -37,18 +36,19 @@
1299 from ubuntu_sso import main
1300 from ubuntu_sso.qt.loadingoverlay import LoadingOverlay
1301 from ubuntu_sso.logger import setup_logging
1302-
1303-
1304-_ = gettext.gettext
1305+from ubuntu_sso.utils.ui import GENERIC_BACKEND_ERROR
1306+
1307+
1308 logger = setup_logging('ubuntu_sso.gui')
1309
1310
1311-class Header(QWidget):
1312+class Header(QFrame):
1313 """Header Class for Title and Subtitle in all wizard pages."""
1314
1315 def __init__(self):
1316 """Create a new instance."""
1317- QWidget.__init__(self)
1318+ super(Header, self).__init__()
1319+ self.setObjectName('header')
1320 vbox = QVBoxLayout(self)
1321 vbox.setContentsMargins(0, 0, 0, 10)
1322 self.title_label = QLabel()
1323@@ -149,6 +149,12 @@
1324 match = self.backend.connect_to_signal(signal, method)
1325 self._signals_receivers[signal] = match
1326
1327+ def _handle_error(self, remote_call, handler, error):
1328+ """Handle any error when calling the remote backend."""
1329+ logger.error('Remote call %r failed with: %r', remote_call, error)
1330+ errordict = {'message': GENERIC_BACKEND_ERROR}
1331+ handler(self.app_name, errordict)
1332+
1333
1334 class EnhancedLineEdit(object):
1335 """Represents and enhanced lineedit.
1336
1337=== modified file 'ubuntu_sso/qt/main.py'
1338--- ubuntu_sso/qt/main.py 2012-02-13 15:43:59 +0000
1339+++ ubuntu_sso/qt/main.py 2012-02-21 23:01:20 +0000
1340@@ -18,14 +18,26 @@
1341
1342 import sys
1343
1344-from PyQt4 import QtGui
1345+from PyQt4 import QtGui, QtCore
1346
1347+# Module used to include the resources into this file
1348+# Unused import resources_rc, pylint: disable=W0611
1349+from ubuntu_sso.qt.ui import resources_rc
1350+# pylint: enable=W0611
1351 from ubuntu_sso.qt.ubuntu_sso_wizard import UbuntuSSOClientGUI
1352
1353
1354 def main(**kwargs):
1355 """Start the QT mainloop and open the main window."""
1356 app = QtGui.QApplication(sys.argv)
1357+
1358+ QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-R.ttf')
1359+ QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-B.ttf')
1360+
1361+ # Apply Style Sheet -- The windows version may be different
1362+ qss = QtCore.QResource(":/stylesheet.qss")
1363+ app.setStyleSheet(qss.data())
1364+
1365 # Unused variable 'ui', pylint: disable=W0612
1366 ui = UbuntuSSOClientGUI(close_callback=app.exit, **kwargs)
1367 app.exec_()
1368
1369=== modified file 'ubuntu_sso/qt/network_detection_page.py'
1370--- ubuntu_sso/qt/network_detection_page.py 2012-02-13 20:27:48 +0000
1371+++ ubuntu_sso/qt/network_detection_page.py 2012-02-21 23:01:20 +0000
1372@@ -16,17 +16,17 @@
1373
1374 """Pages from SSO."""
1375
1376-
1377-import gettext
1378-
1379 from twisted.internet import defer
1380 from PyQt4 import QtGui
1381
1382 from ubuntu_sso import networkstate
1383
1384 from ubuntu_sso.qt.ui import network_detection_ui
1385-
1386-_ = gettext.gettext
1387+from ubuntu_sso.utils.ui import (
1388+ CLOSE_AND_SETUP_LATER,
1389+ NETWORK_DETECTION_TITLE,
1390+ TRY_AGAIN_BUTTON,
1391+)
1392
1393
1394 class NetworkDetectionPage(QtGui.QWizardPage):
1395@@ -35,7 +35,7 @@
1396
1397 def __init__(self, banner_pixmap=None, parent=None):
1398 super(NetworkDetectionPage, self).__init__(parent)
1399- self.setTitle(_("Network detection"))
1400+ self.setTitle(NETWORK_DETECTION_TITLE)
1401 self.ui = network_detection_ui.Ui_Form()
1402 self.ui.setupUi(self)
1403 if banner_pixmap is not None:
1404@@ -47,9 +47,9 @@
1405 """Set UI details."""
1406 self.wizard()._next_id = None
1407
1408- self.setButtonText(QtGui.QWizard.CustomButton1, _("Try again"))
1409+ self.setButtonText(QtGui.QWizard.CustomButton1, TRY_AGAIN_BUTTON)
1410 self.setButtonText(QtGui.QWizard.CancelButton,
1411- _("Close window and set up later"))
1412+ CLOSE_AND_SETUP_LATER)
1413 self.wizard().setButtonLayout([
1414 QtGui.QWizard.Stretch,
1415 QtGui.QWizard.CustomButton1,
1416
1417=== modified file 'ubuntu_sso/qt/reset_password_page.py'
1418--- ubuntu_sso/qt/reset_password_page.py 2012-02-10 21:09:38 +0000
1419+++ ubuntu_sso/qt/reset_password_page.py 2012-02-21 23:01:20 +0000
1420@@ -16,11 +16,14 @@
1421
1422 """Reset Password page UI."""
1423
1424+from functools import partial
1425+
1426 from PyQt4.QtCore import SIGNAL
1427 from PyQt4.QtCore import pyqtSignal
1428 from PyQt4.QtGui import QApplication
1429 from twisted.internet import defer
1430
1431+from ubuntu_sso import NO_OP
1432 from ubuntu_sso.qt import build_general_error_message
1433 from ubuntu_sso.qt.gui import SSOWizardEnhancedEditPage
1434 from ubuntu_sso.qt import common
1435@@ -175,14 +178,15 @@
1436
1437 def on_password_changed(self, app_name, result):
1438 """Let user know that the password was changed."""
1439+ self.overlay.hide()
1440 email = unicode(self.wizard().forgotten.ui.email_line_edit.text())
1441- self.overlay.hide()
1442 self.passwordChanged.emit(email)
1443
1444 def on_password_change_error(self, app_name, error):
1445 """Let the user know that there was an error."""
1446 logger.error('Got error changing password for %s, error: %s',
1447 self.app_name, error)
1448+ self.overlay.hide()
1449 self.message_box.critical(self, self.app_name,
1450 build_general_error_message(error))
1451
1452@@ -193,7 +197,12 @@
1453 password = unicode(self.ui.password_line_edit.text())
1454 logger.info('Setting new password for %r and email %r with code %r',
1455 self.app_name, email, code)
1456- self.backend.set_new_password(self.app_name, email, code, password)
1457+ args = (self.app_name, email, code, password)
1458+ f = self.backend.set_new_password
1459+ error_handler = partial(self._handle_error, f,
1460+ self.on_password_change_error)
1461+ self.overlay.show()
1462+ f(*args, reply_handler=NO_OP, error_handler=error_handler)
1463
1464 def is_correct_password_confirmation(self, password):
1465 """Return if the password is correct."""
1466
1467=== modified file 'ubuntu_sso/qt/setup_account_page.py'
1468--- ubuntu_sso/qt/setup_account_page.py 2012-02-13 20:27:48 +0000
1469+++ ubuntu_sso/qt/setup_account_page.py 2012-02-21 23:01:20 +0000
1470@@ -19,6 +19,7 @@
1471 import StringIO
1472 import tempfile
1473 import os
1474+from functools import partial
1475
1476 # pylint: disable=F0401
1477 try:
1478@@ -30,6 +31,7 @@
1479 from PyQt4 import QtGui, QtCore
1480 from twisted.internet import defer
1481
1482+from ubuntu_sso import NO_OP
1483 from ubuntu_sso.qt import build_general_error_message
1484 from ubuntu_sso.qt import common
1485 from ubuntu_sso.qt.gui import SSOWizardEnhancedEditPage
1486@@ -53,7 +55,6 @@
1487 is_min_required_password,
1488 is_correct_email,
1489 JOIN_HEADER_LABEL,
1490- NAME,
1491 NAME_ENTRY,
1492 NAME_INVALID,
1493 PASSWORD,
1494@@ -123,8 +124,8 @@
1495 privacy_policy=privacy_policy_link)
1496
1497 self.terms_checkbox = enhanced_check_box.EnhancedCheckBox(terms)
1498+ self.ui.hlayout_check.addWidget(self.terms_checkbox)
1499 self.terms_checkbox.setVisible(bool(toc_link or policy_link))
1500- self.ui.hlayout_check.addWidget(self.terms_checkbox)
1501
1502 self.set_up_button = None
1503 self.captcha_received = False
1504@@ -175,7 +176,7 @@
1505 self.set_up_button.clicked.connect(self.set_next_validation)
1506 self.set_up_button.setEnabled(False)
1507
1508- self.ui.name_label.setText(NAME)
1509+ self.ui.name_label.setText(NAME_ENTRY)
1510 self.ui.email_label.setText(EMAIL)
1511 self.ui.confirm_email_label.setText(RETYPE_EMAIL)
1512 self.ui.password_label.setText(PASSWORD)
1513@@ -198,7 +199,7 @@
1514 #pylint: enable=C0103
1515
1516 def _set_translated_strings(self):
1517- """Set the different gettext translated strings."""
1518+ """Set the strings."""
1519 logger.debug('SetUpAccountPage._set_translated_strings')
1520 # set the translated string
1521 self.ui.name_label.setText(NAME_ENTRY)
1522@@ -259,7 +260,7 @@
1523 captcha_solution = unicode(self.ui.captcha_solution_edit.text())
1524
1525 # Check for len(name) > 0 to ensure that a bool is assigned to enabled
1526- if self.terms_checkbox.isVisible():
1527+ if not self.terms_checkbox.isVisible():
1528 checkbox_terms = True
1529 else:
1530 checkbox_terms = self.terms_checkbox.isChecked()
1531@@ -281,10 +282,14 @@
1532 # lets clean behind us, do we have the old file arround?
1533 if self.captcha_file and os.path.exists(self.captcha_file):
1534 os.unlink(self.captcha_file)
1535- fd = tempfile.TemporaryFile(mode='r')
1536+ fd = tempfile.NamedTemporaryFile()
1537 file_name = fd.name
1538 self.captcha_file = file_name
1539- self.backend.generate_captcha(self.app_name, file_name)
1540+ args = (self.app_name, file_name)
1541+ f = self.backend.generate_captcha
1542+ error_handler = partial(self._handle_error, f,
1543+ self.on_captcha_generation_error)
1544+ f(*args, reply_handler=NO_OP, error_handler=error_handler)
1545 self.on_captcha_refreshing()
1546
1547 def _set_titles(self):
1548@@ -393,9 +398,12 @@
1549 # validate the current info of the form, try to perform the action
1550 # to register the user, and then move foward
1551 if self.validate_form():
1552- self.backend.register_user(self.app_name, email,
1553- password, name, captcha_id,
1554- captcha_solution)
1555+ args = (self.app_name, email, password, name, captcha_id,
1556+ captcha_solution)
1557+ f = self.backend.register_user
1558+ error_handler = partial(self._handle_error, f,
1559+ self.on_user_registration_error)
1560+ f(*args, reply_handler=NO_OP, error_handler=error_handler)
1561 # Update validation page's title, which contains the email
1562 self.userRegistered.emit(email, password)
1563 # pylint: enable=W0212
1564
1565=== modified file 'ubuntu_sso/qt/sign_in_page.py'
1566--- ubuntu_sso/qt/sign_in_page.py 2012-02-13 20:27:48 +0000
1567+++ ubuntu_sso/qt/sign_in_page.py 2012-02-21 23:01:20 +0000
1568@@ -16,19 +16,17 @@
1569
1570 """Page to allow the user to sign in."""
1571
1572-import gettext
1573-
1574 from PyQt4 import QtGui, QtCore
1575
1576 from ubuntu_sso.qt.gui import SSOWizardPage
1577 from ubuntu_sso.logger import setup_logging
1578 from ubuntu_sso.utils.ui import (
1579+ CLOSE_AND_SETUP_LATER,
1580 EXISTING_ACCOUNT_CHOICE_BUTTON,
1581 SET_UP_ACCOUNT_CHOICE_BUTTON,
1582 )
1583
1584
1585-_ = gettext.gettext
1586 logger = setup_logging('ubuntu_sso.sing_in_page')
1587
1588
1589@@ -76,7 +74,7 @@
1590
1591 def initializePage(self):
1592 """Setup UI details."""
1593- self.ui.cancel_button.setText(_("Close window and setup later"))
1594+ self.ui.cancel_button.setText(CLOSE_AND_SETUP_LATER)
1595 self.ui.cancel_button.clicked.connect(self.singInCanceled.emit)
1596 # Layout without custom button 1,
1597 # without finish button
1598
1599=== modified file 'ubuntu_sso/qt/tests/__init__.py'
1600--- ubuntu_sso/qt/tests/__init__.py 2012-02-09 18:28:40 +0000
1601+++ ubuntu_sso/qt/tests/__init__.py 2012-02-21 23:01:20 +0000
1602@@ -21,7 +21,10 @@
1603 from twisted.trial.unittest import TestCase
1604 from ubuntu_sso.qt import loadingoverlay
1605
1606-from ubuntu_sso import main
1607+from ubuntu_sso import (
1608+ main,
1609+ NO_OP,
1610+)
1611
1612
1613 class FakedObject(object):
1614@@ -29,7 +32,7 @@
1615
1616 next_result = None
1617 exposed_methods = ['connect_to_signal',
1618- 'generate_captcha']
1619+ 'generate_captcha', 'request_password_reset_token']
1620
1621 def __init__(self, *args, **kwargs):
1622 self._args = args
1623@@ -384,6 +387,23 @@
1624 """Store 'args' and 'kwargs' for test assertions."""
1625 self._called = (args, kwargs)
1626
1627+ # pylint: disable=E1101, W0212
1628+ def assert_backend_called(self, method, *args, **kwargs):
1629+ """Check that 'method(*args, **kwargs)' was called in the backend."""
1630+ self.assertIn(method, self.ui.backend._called)
1631+
1632+ call = self.ui.backend._called[method]
1633+ self.assertEqual(call[0], args)
1634+
1635+ reply_handler = call[1].pop('reply_handler')
1636+ self.assertEqual(reply_handler, NO_OP)
1637+
1638+ error_handler = call[1].pop('error_handler')
1639+ self.assertEqual(error_handler.func, self.ui._handle_error)
1640+
1641+ self.assertEqual(call[1], kwargs)
1642+ # pylint: enable=E1101, W0212
1643+
1644
1645 class BaseTestCaseUI(TestCase):
1646 """Base Test Case."""
1647
1648=== modified file 'ubuntu_sso/qt/tests/test_current_user_sign_in_page.py'
1649--- ubuntu_sso/qt/tests/test_current_user_sign_in_page.py 2012-02-13 17:19:05 +0000
1650+++ ubuntu_sso/qt/tests/test_current_user_sign_in_page.py 2012-02-21 23:01:20 +0000
1651@@ -25,6 +25,7 @@
1652 BaseTestCase,
1653 FakedBackend,
1654 FakedObject,
1655+ FakeOverlay,
1656 FakePageUiStyle,
1657 FakeSignal,
1658 FakeWizard,
1659@@ -40,6 +41,7 @@
1660 @defer.inlineCallbacks
1661 def setUp(self):
1662 yield super(CurrentUserSignInTestCase, self).setUp()
1663+ self.patch(gui, "LoadingOverlay", FakeOverlay)
1664 self.patch(gui.main, "get_sso_client", FakedBackend)
1665 self.signals_results = []
1666 self.patch(current_user_sign_in_page.CurrentUserSignInPage,
1667@@ -48,18 +50,20 @@
1668 "passwordForgotten", FakeSignal())
1669 self.patch(current_user_sign_in_page.CurrentUserSignInPage,
1670 "userNotValidated", FakeSignal())
1671+ self.app_name = 'my_app'
1672 self.ui = current_user_sign_in_page.CurrentUserSignInPage(
1673 current_user_sign_in_ui.Ui_CurrentUserSignInPage(),
1674 '',
1675+ app_name=self.app_name,
1676 parent=None)
1677 self.wizard = FakeWizard()
1678 self.patch(self.ui, 'wizard', lambda: self.wizard)
1679
1680 def test_init(self):
1681 """Test the construction of the object."""
1682- self.assertTrue('LoggedIn' in self.ui._signals)
1683- self.assertTrue('LoginError' in self.ui._signals)
1684- self.assertTrue('UserNotValidated' in self.ui._signals)
1685+ self.assertIn('LoggedIn', self.ui._signals)
1686+ self.assertIn('LoginError', self.ui._signals)
1687+ self.assertIn('UserNotValidated', self.ui._signals)
1688 self.assertTrue(callable(self.ui._signals['LoggedIn']))
1689 self.assertTrue(callable(self.ui._signals['LoginError']))
1690 self.assertTrue(callable(self.ui._signals['UserNotValidated']))
1691@@ -81,9 +85,9 @@
1692 self.patch(self.ui, "_connect_ui",
1693 faked_object._connect_ui)
1694 self.ui.setup_page()
1695- self.assertTrue('_set_translated_strings' in faked_object._called)
1696- self.assertTrue('_setup_signals' in faked_object._called)
1697- self.assertTrue('_connect_ui' in faked_object._called)
1698+ self.assertIn('_set_translated_strings', faked_object._called)
1699+ self.assertIn('_setup_signals', faked_object._called)
1700+ self.assertIn('_connect_ui', faked_object._called)
1701 # pylint: enable=E1101
1702
1703 def test_on_user_not_validated(self):
1704@@ -98,7 +102,7 @@
1705 self.signals_results.append((email, password))
1706 self.ui.userNotValidated.connect(slot)
1707 self.ui.on_user_not_validated()
1708- self.assertTrue((email, password) in self.signals_results)
1709+ self.assertIn((email, password), self.signals_results)
1710
1711 def test_initialize_page(self):
1712 """Test the initialization method."""
1713@@ -110,8 +114,8 @@
1714 self.ui.initializePage()
1715 self.assertEqual(wizard.buttons_text[QtGui.QWizard.CancelButton],
1716 "Cancel")
1717- self.assertTrue(('setButtonLayout',
1718- (([QtGui.QWizard.BackButton, QtGui.QWizard.Stretch],), {})) in
1719+ self.assertIn(('setButtonLayout',
1720+ (([QtGui.QWizard.BackButton, QtGui.QWizard.Stretch],), {})),
1721 wizard.called)
1722 self.assertTrue(button.properties['default'])
1723 self.assertFalse(button.isEnabled())
1724@@ -178,12 +182,14 @@
1725 self.patch(FakedObject, "exposed_methods", exposed_methods)
1726 faked_object = FakedObject()
1727 self.patch(self.ui, "backend", faked_object)
1728- self.ui.ui.email_edit.setText('valid@email')
1729- self.ui.ui.password_edit.setText('123456')
1730+ email = 'valid@email'
1731+ password = '123456'
1732+ self.ui.ui.email_edit.setText(email)
1733+ self.ui.ui.password_edit.setText(password)
1734 self.ui.login()
1735- self.assertTrue('login_and_ping' in self.ui.backend._called)
1736- self.assertEqual(self.ui.backend._called['login_and_ping'],
1737- ((None, u'valid@email', u'123456', ping), {}))
1738+ self.assertEqual(self.ui.overlay.show_counter, 1)
1739+ self.assert_backend_called('login_and_ping',
1740+ self.app_name, email, password, ping)
1741
1742 def test_login_without_ping(self):
1743 """Test the login method."""
1744@@ -192,12 +198,14 @@
1745 self.patch(FakedObject, "exposed_methods", exposed_methods)
1746 faked_object = FakedObject()
1747 self.patch(self.ui, "backend", faked_object)
1748- self.ui.ui.email_edit.setText('valid@email')
1749- self.ui.ui.password_edit.setText('123456')
1750+ email = 'valid@email'
1751+ password = '123456'
1752+ self.ui.ui.email_edit.setText(email)
1753+ self.ui.ui.password_edit.setText(password)
1754 self.ui.login()
1755- self.assertTrue('login' in self.ui.backend._called)
1756- self.assertEqual(self.ui.backend._called['login'],
1757- ((None, u'valid@email', u'123456'), {}))
1758+ self.assertEqual(self.ui.overlay.show_counter, 1)
1759+ self.assert_backend_called('login',
1760+ self.app_name, email, password)
1761
1762 def test_on_login_error(self):
1763 """Test the on_login_error method."""
1764@@ -206,6 +214,7 @@
1765 self.ui.app_name = app_name
1766 error = {'errtype': 'UserNotValidated'}
1767 self.ui.on_login_error(app_name, error)
1768+ self.assertEqual(self.ui.overlay.hide_counter, 2)
1769 expected = ((self.ui, 'my_app', ''), {})
1770 self.assertTrue(expected, self._called)
1771
1772@@ -221,7 +230,8 @@
1773 self.signals_results.append((app, email))
1774 self.ui.userLoggedIn.connect(slot)
1775 self.ui.on_logged_in(app_name, None)
1776- self.assertTrue((app_name, email) in self.signals_results)
1777+ self.assertEqual(self.ui.overlay.hide_counter, 2)
1778+ self.assertIn((app_name, email), self.signals_results)
1779
1780 def test_on_forgotten_password(self):
1781 """Test the on_forgotten_password method."""
1782@@ -231,7 +241,7 @@
1783 self.signals_results.append(1)
1784 self.ui.passwordForgotten.connect(slot)
1785 self.ui.on_forgotten_password()
1786- self.assertTrue(1 in self.signals_results)
1787+ self.assertIn(1, self.signals_results)
1788
1789 def test_on_forgotten_password_link_clicked(self):
1790 """Test the on_forgotten_password method."""
1791@@ -241,4 +251,4 @@
1792 self.signals_results.append(1)
1793 self.ui.passwordForgotten.connect(slot)
1794 self.ui.ui.forgot_password_label.linkActivated.emit("link")
1795- self.assertTrue(1 in self.signals_results)
1796+ self.assertIn(1, self.signals_results)
1797
1798=== modified file 'ubuntu_sso/qt/tests/test_email_verification.py'
1799--- ubuntu_sso/qt/tests/test_email_verification.py 2012-02-13 14:04:27 +0000
1800+++ ubuntu_sso/qt/tests/test_email_verification.py 2012-02-21 23:01:20 +0000
1801@@ -51,8 +51,8 @@
1802
1803 def test_init(self):
1804 """Test the construction of the object."""
1805- self.assertTrue('EmailValidated' in self.ui._signals)
1806- self.assertTrue('EmailValidationError' in self.ui._signals)
1807+ self.assertIn('EmailValidated', self.ui._signals)
1808+ self.assertIn('EmailValidationError', self.ui._signals)
1809 self.assertTrue(callable(self.ui._signals['EmailValidated']))
1810 self.assertTrue(callable(self.ui._signals['EmailValidationError']))
1811 self.assertEqual(self.ui.backend, FakedBackend.sso_login)
1812@@ -70,8 +70,8 @@
1813 self.patch(self.ui, "_connect_ui_elements",
1814 faked_object._connect_ui_elements)
1815 self.ui.setup_page()
1816- self.assertTrue('_setup_signals' in faked_object._called)
1817- self.assertTrue('_connect_ui_elements' in faked_object._called)
1818+ self.assertIn('_setup_signals', faked_object._called)
1819+ self.assertIn('_connect_ui_elements', faked_object._called)
1820 # pylint: enable=E1101
1821
1822 def test_verification_code(self):
1823@@ -166,7 +166,7 @@
1824 self.signals_results.append((app, email))
1825 self.ui.registrationSuccess.connect(slot)
1826 self.ui.on_email_validated(app_name)
1827- self.assertTrue((app_name, email) in self.signals_results)
1828+ self.assertIn((app_name, email), self.signals_results)
1829
1830 def test_validate_email_with_ping(self):
1831 """Test the login method."""
1832@@ -185,9 +185,8 @@
1833 faked_object = FakedObject()
1834 self.patch(self.ui, "backend", faked_object)
1835 self.ui.validate_email()
1836- self.assertTrue('validate_email_and_ping' in self.ui.backend._called)
1837- self.assertEqual(self.ui.backend._called['validate_email_and_ping'],
1838- ((app_name, email, password, code, ping), {}))
1839+ self.assert_backend_called('validate_email_and_ping',
1840+ app_name, email, password, code, ping)
1841
1842 def test_validate_email_without_ping(self):
1843 """Test the login method."""
1844@@ -206,6 +205,5 @@
1845 faked_object = FakedObject()
1846 self.patch(self.ui, "backend", faked_object)
1847 self.ui.validate_email()
1848- self.assertTrue('validate_email' in self.ui.backend._called)
1849- self.assertEqual(self.ui.backend._called['validate_email'],
1850- ((app_name, email, password, code), {}))
1851+ self.assert_backend_called('validate_email',
1852+ app_name, email, password, code)
1853
1854=== modified file 'ubuntu_sso/qt/tests/test_enhanced_check_box.py'
1855--- ubuntu_sso/qt/tests/test_enhanced_check_box.py 2012-02-02 15:57:02 +0000
1856+++ ubuntu_sso/qt/tests/test_enhanced_check_box.py 2012-02-21 23:01:20 +0000
1857@@ -1,6 +1,4 @@
1858 # -*- coding: utf-8 -*-
1859-
1860-# Authors: Diego Sarmentero <diego.sarmentero@canonical.com>
1861 #
1862 # Copyright 2011 Canonical Ltd.
1863 #
1864@@ -18,8 +16,6 @@
1865
1866 """Tests for the EnhancedCheckBox widget."""
1867
1868-import re
1869-
1870 from PyQt4 import QtCore
1871
1872 from ubuntu_sso.qt import enhanced_check_box
1873@@ -34,9 +30,6 @@
1874 check = enhanced_check_box.EnhancedCheckBox("text")
1875 self.assertEqual(check.text(), "text")
1876 self.assertTrue(check.text_label.openExternalLinks())
1877- style_sheet = unicode(check.text_label.styleSheet())
1878- size = re.sub("\D", "", style_sheet)
1879- self.assertEqual(check.iconSize().width(), int(size))
1880 self.assertEqual(check.receivers(
1881 QtCore.SIGNAL('stateChanged(int)')), 1)
1882
1883
1884=== modified file 'ubuntu_sso/qt/tests/test_forgotten_password.py'
1885--- ubuntu_sso/qt/tests/test_forgotten_password.py 2012-02-13 21:50:16 +0000
1886+++ ubuntu_sso/qt/tests/test_forgotten_password.py 2012-02-21 23:01:20 +0000
1887@@ -25,6 +25,7 @@
1888 BaseTestCase,
1889 FakedBackend,
1890 FakedObject,
1891+ FakeOverlay,
1892 FakePageUiStyle,
1893 FakeSignal,
1894 FakeWizard,
1895@@ -40,23 +41,36 @@
1896 def setUp(self):
1897 yield super(ForgottenPasswordTestCase, self).setUp()
1898 self.signals_results = []
1899+ self.patch(gui, "LoadingOverlay", FakeOverlay)
1900+ self.patch(gui.main, "get_sso_client", FakedBackend)
1901 self.patch(forgotten_password_page.ForgottenPasswordPage,
1902 "passwordResetTokenSent", FakeSignal())
1903- self.patch(gui.main, "get_sso_client", FakedBackend)
1904+ self.app_name = 'my_app'
1905 self.ui = forgotten_password_page.ForgottenPasswordPage(
1906 forgotten_password_ui.Ui_ForgottenPasswordPage(),
1907- parent=None)
1908+ app_name=self.app_name, parent=None)
1909 self.wizard = FakeWizard()
1910 self.patch(self.ui, 'wizard', lambda: self.wizard)
1911
1912 def test_init(self):
1913 """Test the construction of the object."""
1914- self.assertTrue('PasswordResetTokenSent' in self.ui._signals)
1915- self.assertTrue('PasswordResetError' in self.ui._signals)
1916+ self.assertIn('PasswordResetTokenSent', self.ui._signals)
1917+ self.assertIn('PasswordResetError', self.ui._signals)
1918 self.assertTrue(callable(self.ui._signals['PasswordResetTokenSent']))
1919 self.assertTrue(callable(self.ui._signals['PasswordResetError']))
1920 self.assertEqual(self.ui.backend, FakedBackend.sso_login)
1921
1922+ def test_request_new_password(self):
1923+ """Test the request_new_password function."""
1924+ app_name = 'my_app'
1925+ email = 'email@example.com'
1926+ self.ui.app_name = app_name
1927+ self.ui.ui.email_line_edit.setText(email)
1928+ self.ui.request_new_password()
1929+ self.assertEqual(self.ui.overlay.show_counter, 1)
1930+ self.assert_backend_called('request_password_reset_token',
1931+ app_name, email)
1932+
1933 def test_setup_page(self):
1934 """Test that the backend is received and the methods are called."""
1935 exposed_methods = [
1936@@ -78,11 +92,11 @@
1937 self.patch(self.ui, "_register_fields",
1938 faked_object._register_fields)
1939 self.ui.setup_page()
1940- self.assertTrue('_setup_signals' in faked_object._called)
1941- self.assertTrue('_set_translated_strings' in faked_object._called)
1942- self.assertTrue('_connect_ui' in faked_object._called)
1943- self.assertTrue('_set_enhanced_line_edit' in faked_object._called)
1944- self.assertTrue('_register_fields' in faked_object._called)
1945+ self.assertIn('_setup_signals', faked_object._called)
1946+ self.assertIn('_set_translated_strings', faked_object._called)
1947+ self.assertIn('_connect_ui', faked_object._called)
1948+ self.assertIn('_set_enhanced_line_edit', faked_object._called)
1949+ self.assertIn('_register_fields', faked_object._called)
1950
1951 def test_email_widget(self):
1952 """Test the email_widget property."""
1953@@ -120,6 +134,12 @@
1954 self.assertEqual(value, self.ui.ui.send_button)
1955 self.assertTrue(isinstance(value, QtGui.QPushButton))
1956
1957+ def test_send_button_clicked(self):
1958+ """Test the send_button property."""
1959+ self.ui.send_button.clicked.emit(True)
1960+ self.assert_backend_called('request_password_reset_token',
1961+ self.app_name, '')
1962+
1963 def test_try_again_widget(self):
1964 """Test the try_again_widget property."""
1965 value = self.ui.try_again_widget
1966@@ -211,6 +231,7 @@
1967 self.signals_results.append(1)
1968 self.ui.passwordResetTokenSent.connect(slot)
1969 self.ui.on_password_reset_token_sent('app_name', {})
1970+ self.assertEqual(self.ui.overlay.hide_counter, 2)
1971 self.assertTrue(1 in self.signals_results)
1972
1973 def test_on_password_reset_error(self):
1974@@ -227,6 +248,7 @@
1975 self.assertFalse(self.ui.email_widget.isVisible())
1976 self.assertFalse(self.ui.forgotted_password_intro_label.isVisible())
1977 self.assertTrue(self.ui.try_again_widget.isVisible())
1978+ self.assertEqual(self.ui.overlay.hide_counter, 2)
1979
1980 def test_on_password_reset_error_with_token_error(self):
1981 """Test on_password_reset_error method."""
1982
1983=== modified file 'ubuntu_sso/qt/tests/test_network_detection.py'
1984--- ubuntu_sso/qt/tests/test_network_detection.py 2012-02-02 15:44:18 +0000
1985+++ ubuntu_sso/qt/tests/test_network_detection.py 2012-02-21 23:01:20 +0000
1986@@ -60,10 +60,8 @@
1987 "wizard", FakeWizardButtonStyle)
1988 self.network_detection.initializePage()
1989 self.assertTrue(self.network_detection.btn_try_again.isDefault())
1990- self.assertTrue(
1991- 'polish' in self.network_detection.btn_try_again.data)
1992- self.assertTrue(
1993- 'unpolish' in self.network_detection.btn_try_again.data)
1994+ self.assertIn('polish', self.network_detection.btn_try_again.data)
1995+ self.assertIn('unpolish', self.network_detection.btn_try_again.data)
1996 self.assertEqual(
1997 self.network_detection.btn_try_again.data['polish'],
1998 self.network_detection.btn_try_again)
1999
2000=== modified file 'ubuntu_sso/qt/tests/test_reset_password.py'
2001--- ubuntu_sso/qt/tests/test_reset_password.py 2012-02-09 18:09:29 +0000
2002+++ ubuntu_sso/qt/tests/test_reset_password.py 2012-02-21 23:01:20 +0000
2003@@ -19,7 +19,6 @@
2004
2005 from PyQt4 import QtGui, QtCore
2006 from twisted.internet import defer
2007-from twisted.trial.unittest import TestCase
2008
2009 from ubuntu_sso.utils.ui import (
2010 PASSWORD1_ENTRY,
2011@@ -33,7 +32,12 @@
2012 RESET_TITLE,
2013 )
2014 from ubuntu_sso.qt.ui.reset_password_ui import Ui_ResetPasswordPage
2015-from ubuntu_sso.qt.tests import FakedBackend
2016+from ubuntu_sso.qt.tests import (
2017+ BaseTestCase,
2018+ FakedBackend,
2019+ FakedObject,
2020+ FakeWizard,
2021+)
2022
2023
2024 class FakePasswordAssistance(object):
2025@@ -50,52 +54,76 @@
2026 FakePasswordAssistance._called = False
2027
2028
2029-class ResetPasswordTestCase(TestCase):
2030+# We need this Fake until a future refactor.
2031+class FakeForgottenPage(object):
2032+
2033+ """Fake Forgotten Page."""
2034+
2035+ def __init__(self):
2036+ self.ui = self
2037+ self.email_line_edit = self
2038+ self.line_text = ''
2039+
2040+ # pylint: disable=C0103
2041+ def setText(self, text):
2042+ """Fake setText for Line edit."""
2043+ self.line_text = text
2044+ # pylint: enable=C0103
2045+
2046+ def text(self):
2047+ """Fake text for line edit."""
2048+ return self.line_text
2049+
2050+
2051+class ResetPasswordTestCase(BaseTestCase):
2052 """Test the ResetPasswordPage code."""
2053
2054 @defer.inlineCallbacks
2055 def setUp(self):
2056 yield super(ResetPasswordTestCase, self).setUp()
2057 self.patch(gui.main, "get_sso_client", FakedBackend)
2058- self.page = ResetPasswordPage(Ui_ResetPasswordPage(),
2059- 'app_name',
2060- None)
2061+ self.app_name = 'my_app'
2062+ self.ui = ResetPasswordPage(Ui_ResetPasswordPage(),
2063+ app_name=self.app_name,
2064+ parent=None)
2065+ self.wizard = FakeWizard()
2066+ self.patch(self.ui, 'wizard', lambda: self.wizard)
2067 self.fake = FakePasswordAssistance()
2068
2069 def test_init(self):
2070 """Check the initial state of ResetPassword."""
2071- self.assertEqual(self.page.ui.password_line_edit.receivers(
2072+ self.assertEqual(self.ui.ui.password_line_edit.receivers(
2073 QtCore.SIGNAL('textEdited(QString)')), 1)
2074- self.assertEqual(self.page.ui.confirm_password_line_edit.receivers(
2075+ self.assertEqual(self.ui.ui.confirm_password_line_edit.receivers(
2076 QtCore.SIGNAL('textEdited(QString)')), 1)
2077
2078 def test_initialize(self):
2079 """Check the Title and Subtitle."""
2080- self.page.show()
2081- self.page.initializePage()
2082- self.addCleanup(self.page.hide)
2083- self.assertEqual(self.page.header.title_label.text(), RESET_TITLE)
2084- self.assertEqual(self.page.header.subtitle_label.text(),
2085+ self.ui.show()
2086+ self.ui.initializePage()
2087+ self.addCleanup(self.ui.hide)
2088+ self.assertEqual(self.ui.header.title_label.text(), RESET_TITLE)
2089+ self.assertEqual(self.ui.header.subtitle_label.text(),
2090 RESET_SUBTITLE)
2091- self.assertEqual(self.page.ui.password_label.text(), PASSWORD1_ENTRY)
2092- self.assertEqual(self.page.ui.confirm_password_label.text(),
2093+ self.assertEqual(self.ui.ui.password_label.text(), PASSWORD1_ENTRY)
2094+ self.assertEqual(self.ui.ui.confirm_password_label.text(),
2095 PASSWORD2_ENTRY)
2096- self.assertEqual(self.page.ui.reset_code.text(), RESET_CODE_ENTRY)
2097+ self.assertEqual(self.ui.ui.reset_code.text(), RESET_CODE_ENTRY)
2098
2099 def test_focus_changed_password_visibility(self):
2100 """Check visibility changes when focus_changed() is executed."""
2101- self.page.show()
2102- self.addCleanup(self.page.hide)
2103- self.page.focus_changed(None, self.page.ui.password_line_edit)
2104- self.assertTrue(self.page.ui.password_assistance.isVisible())
2105+ self.ui.show()
2106+ self.addCleanup(self.ui.hide)
2107+ self.ui.focus_changed(None, self.ui.ui.password_line_edit)
2108+ self.assertTrue(self.ui.ui.password_assistance.isVisible())
2109
2110 def test_show_hide_event(self):
2111 """Check connections to focusChanged on show and hide event."""
2112- self.page.show()
2113- self.addCleanup(self.page.hide)
2114+ self.ui.show()
2115+ self.addCleanup(self.ui.hide)
2116 self.assertEqual(QtGui.QApplication.instance().receivers(
2117 QtCore.SIGNAL("focusChanged(QWidget*, QWidget*)")), 1)
2118- self.page.hide()
2119+ self.ui.hide()
2120 self.assertEqual(QtGui.QApplication.instance().receivers(
2121 QtCore.SIGNAL("focusChanged(QWidget*, QWidget*)")), 0)
2122
2123@@ -105,22 +133,40 @@
2124 """Check functions execution when focus_changed() is executed."""
2125 self.patch(common, 'password_default_assistance', self.fake.call)
2126 self.addCleanup(self.fake.clenaup)
2127- self.page.show()
2128- self.addCleanup(self.page.hide)
2129+ self.ui.show()
2130+ self.addCleanup(self.ui.hide)
2131 self.assertFalse(FakePasswordAssistance._called)
2132- self.page.focus_changed(None, self.page.ui.password_line_edit)
2133- self.assertTrue(self.page.ui.password_assistance.isVisible())
2134+ self.ui.focus_changed(None, self.ui.ui.password_line_edit)
2135+ self.assertTrue(self.ui.ui.password_assistance.isVisible())
2136 self.assertTrue(FakePasswordAssistance._called)
2137
2138 def test_focus_changed_2(self):
2139 """Check functions execution when focus_changed() is executed."""
2140 self.patch(common, 'password_check_match', self.fake.call)
2141 self.addCleanup(self.fake.clenaup)
2142- self.page.show()
2143- self.addCleanup(self.page.hide)
2144+ self.ui.show()
2145+ self.addCleanup(self.ui.hide)
2146 self.assertFalse(FakePasswordAssistance._called)
2147- self.page.focus_changed(None, self.page.ui.confirm_password_line_edit)
2148- self.assertTrue(self.page.ui.password_assistance.isVisible())
2149+ self.ui.focus_changed(None, self.ui.ui.confirm_password_line_edit)
2150+ self.assertTrue(self.ui.ui.password_assistance.isVisible())
2151 self.assertTrue(FakePasswordAssistance._called)
2152
2153 # pylint: enable=W0212
2154+
2155+ def test_set_new_password(self):
2156+ """Test set_new_password method."""
2157+ email = 'email@example.com'
2158+ code = 'code'
2159+ password = 'password'
2160+ forgotten = FakeForgottenPage()
2161+ forgotten.setText(email)
2162+ self.patch(self.wizard, "forgotten", forgotten)
2163+ exposed_methods = ['set_new_password']
2164+ self.patch(FakedObject, "exposed_methods", exposed_methods)
2165+ faked_object = FakedObject()
2166+ self.patch(self.ui, "backend", faked_object)
2167+ self.ui.ui.reset_code_line_edit.setText(code)
2168+ self.ui.ui.password_line_edit.setText(password)
2169+ self.ui.set_new_password()
2170+ self.assert_backend_called('set_new_password',
2171+ self.app_name, email, code, password)
2172
2173=== modified file 'ubuntu_sso/qt/tests/test_setup_account.py'
2174--- ubuntu_sso/qt/tests/test_setup_account.py 2012-02-10 21:09:38 +0000
2175+++ ubuntu_sso/qt/tests/test_setup_account.py 2012-02-21 23:01:20 +0000
2176@@ -44,11 +44,13 @@
2177 self.signals_results = []
2178 self.patch(setup_account_page.SetupAccountPage,
2179 "userRegistered", FakeSignal())
2180+ self.app_name = 'my_app'
2181 self.ui = setup_account_page.SetupAccountPage(
2182 setup_account_ui.Ui_SetUpAccountPage(),
2183 'subtitle',
2184 'toc_link',
2185 'policy_link',
2186+ app_name=self.app_name,
2187 parent=None)
2188 self.wizard = FakeWizard()
2189 self.patch(self.ui, 'wizard', lambda: self.wizard)
2190@@ -75,6 +77,41 @@
2191 setup_account_page.ERROR % setup_account_page.EMPTY_NAME)
2192 self.ui.hide()
2193
2194+ def test_enable_setup_button_with_visible_check(self):
2195+ """Test _enable_setup_button method with terms check visible."""
2196+ self.ui.ui.name_edit.setText('name')
2197+ email = 'email@example.com'
2198+ self.ui.ui.email_edit.setText(email)
2199+ self.ui.ui.confirm_email_edit.setText(email)
2200+ password = 'T3st3rqwe'
2201+ self.ui.ui.password_edit.setText(password)
2202+ self.ui.ui.confirm_password_edit.setText(password)
2203+ self.ui.ui.captcha_solution_edit.setText('captcha solution')
2204+ self.ui.terms_checkbox.setChecked(True)
2205+
2206+ self.ui.show()
2207+ self.addCleanup(self.ui.hide)
2208+ self.ui.terms_checkbox.setVisible(True)
2209+ self.ui.ui.captcha_solution_edit.textEdited.emit('')
2210+ self.assertTrue(self.ui.set_up_button.isEnabled())
2211+
2212+ def test_enable_setup_button_without_visible_check(self):
2213+ """Test _enable_setup_button method with terms check not visible."""
2214+ self.ui.ui.name_edit.setText('name')
2215+ email = 'email@example.com'
2216+ self.ui.ui.email_edit.setText(email)
2217+ self.ui.ui.confirm_email_edit.setText(email)
2218+ password = 'T3st3rqwe'
2219+ self.ui.ui.password_edit.setText(password)
2220+ self.ui.ui.confirm_password_edit.setText(password)
2221+ self.ui.ui.captcha_solution_edit.setText('captcha solution')
2222+
2223+ self.ui.show()
2224+ self.addCleanup(self.ui.hide)
2225+ self.ui.terms_checkbox.setVisible(False)
2226+ self.ui.ui.captcha_solution_edit.textEdited.emit('')
2227+ self.assertTrue(self.ui.set_up_button.isEnabled())
2228+
2229 def test_password_default_assistance(self):
2230 """Status when the password line edit receive focus and shows popup.
2231
2232@@ -155,7 +192,10 @@
2233 self.signals_results.append((email, password))
2234 self.ui.userRegistered.connect(slot)
2235 self.ui.set_next_validation()
2236- self.assertTrue((email, password) in self.signals_results)
2237+ self.assertIn((email, password), self.signals_results)
2238+ self.assert_backend_called('register_user',
2239+ self.app_name, email, password, name, captcha_id,
2240+ captcha_solution)
2241
2242 def test_set_next_validation(self):
2243 """Test on_user_registered method."""
2244@@ -169,7 +209,13 @@
2245 self.signals_results.append((email, password))
2246 self.ui.userRegistered.connect(slot)
2247 self.ui.on_user_registered('app_name', None)
2248- self.assertTrue((email, password) in self.signals_results)
2249+ self.assertIn((email, password), self.signals_results)
2250+
2251+ def test_captcha_image_is_requested_as_startup(self):
2252+ """The captcha image is requested at startup."""
2253+ # assert generate_captcha was called
2254+ self.assert_backend_called('generate_captcha',
2255+ self.app_name, self.ui.captcha_file)
2256
2257
2258 class SetupAccountFakeWizardTestCase(BaseTestCase):
2259@@ -221,7 +267,8 @@
2260 self.assertFalse(self.ui.captcha_received)
2261
2262 # labels
2263- self.assertEqual(self.ui.ui.name_label.text(), setup_account_page.NAME)
2264+ self.assertEqual(self.ui.ui.name_label.text(),
2265+ setup_account_page.NAME_ENTRY)
2266 self.assertEqual(self.ui.ui.email_label.text(),
2267 setup_account_page.EMAIL)
2268 self.assertEqual(self.ui.ui.confirm_email_label.text(),
2269
2270=== modified file 'ubuntu_sso/qt/tests/test_sign_in_page.py'
2271--- ubuntu_sso/qt/tests/test_sign_in_page.py 2012-02-10 21:09:38 +0000
2272+++ ubuntu_sso/qt/tests/test_sign_in_page.py 2012-02-21 23:01:20 +0000
2273@@ -55,7 +55,7 @@
2274 self.signals_results.append(1)
2275 self.ui.existingAccountSelected.connect(slot)
2276 self.ui._set_next_existing()
2277- self.assertTrue(1 in self.signals_results)
2278+ self.assertIn(1, self.signals_results)
2279
2280 def test_set_next_new(self):
2281 """Test _set_next_existing method."""
2282@@ -65,5 +65,5 @@
2283 self.signals_results.append(1)
2284 self.ui.newAccountSelected.connect(slot)
2285 self.ui._set_next_new()
2286- self.assertTrue(1 in self.signals_results)
2287+ self.assertIn(1, self.signals_results)
2288 # pylint: enable=W0212
2289
2290=== modified file 'ubuntu_sso/qt/tests/test_ubuntu_sso_wizard.py'
2291--- ubuntu_sso/qt/tests/test_ubuntu_sso_wizard.py 2012-02-13 20:37:57 +0000
2292+++ ubuntu_sso/qt/tests/test_ubuntu_sso_wizard.py 2012-02-21 23:01:20 +0000
2293@@ -89,6 +89,6 @@
2294 self.ui.show()
2295 self.addCleanup(self.ui.hide)
2296 self.ui.sign_in_page.ui.cancel_button.clicked.emit(True)
2297- self.assertTrue('close' in faked_object._called)
2298- self.assertTrue('reject' not in faked_object._called)
2299+ self.assertIn('close', faked_object._called)
2300+ self.assertNotIn('reject', faked_object._called)
2301 # pylint: enable=W0212, E1101
2302
2303=== modified file 'ubuntu_sso/qt/ubuntu_sso_wizard.py'
2304--- ubuntu_sso/qt/ubuntu_sso_wizard.py 2012-02-14 18:42:00 +0000
2305+++ ubuntu_sso/qt/ubuntu_sso_wizard.py 2012-02-21 23:01:20 +0000
2306@@ -151,6 +151,7 @@
2307 self.setWizardStyle(QWizard.ModernStyle)
2308 self.button(QWizard.CancelButton).clicked.connect(
2309 self.on_user_cancelation)
2310+ self.resize(550, 500)
2311
2312 # pylint: disable=C0103
2313 def nextId(self):
2314
2315=== modified file 'ubuntu_sso/tests/__init__.py'
2316--- ubuntu_sso/tests/__init__.py 2012-02-10 17:18:22 +0000
2317+++ ubuntu_sso/tests/__init__.py 2012-02-21 23:01:20 +0000
2318@@ -26,20 +26,20 @@
2319
2320 from ubuntu_sso.keyring import get_token_name
2321
2322-APP_NAME = u'The Super App!'
2323+APP_NAME = u'I ♥ Ubuntu'
2324 CAPTCHA_ID = u'test ñiña'
2325 CAPTCHA_PATH = os.path.abspath(os.path.join(os.curdir, 'ubuntu_sso', 'tests',
2326 'files', 'captcha.png'))
2327 CAPTCHA_SOLUTION = u'william Byrd ñandú'
2328 EMAIL = u'test@example.com'
2329-EMAIL_TOKEN = u'B2Pgtf'
2330+EMAIL_TOKEN = u'B2P☺ gtf'
2331 GTK_GUI_EXE = 'ubuntu-sso-login-gtk'
2332-HELP_TEXT = """Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed
2333-lorem nibh. Suspendisse gravida nulla non nunc suscipit pulvinar tempus ut
2334-augue. Morbi consequat, ligula a elementum pretium, dolor nulla tempus metus,
2335-sed viverra nisi risus non velit."""
2336-NAME = u'Juanito Pérez'
2337-PASSWORD = u'h3lloWorld'
2338+HELP_TEXT = u'☛ Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' \
2339+'Nam sed lorem nibh. Suspendisse gravida nulla non nunc suscipit pulvinar ' \
2340+'tempus ut augue. Morbi consequat, ligula a elementum pretium, ' \
2341+'dolor nulla tempus metus, sed viverra nisi risus non velit.'
2342+NAME = u'Juanito ☀ Pérez'
2343+PASSWORD = u'h3lloWorld☑ '
2344 PING_URL = u'http://localhost/ping-me/'
2345 POLICY_URL = u'http://localhost/policy/'
2346 RESET_PASSWORD_TOKEN = u'8G5Wtq'
2347
2348=== modified file 'ubuntu_sso/utils/__init__.py'
2349--- ubuntu_sso/utils/__init__.py 2012-02-11 19:25:01 +0000
2350+++ ubuntu_sso/utils/__init__.py 2012-02-21 23:01:20 +0000
2351@@ -54,9 +54,11 @@
2352
2353 # otherwise, try to load 'dir_constant' from installation path
2354 try:
2355+ # Unused variable 'ubuntu_sso', pylint: disable=W0612, F0401, E0611
2356+ import ubuntu_sso.constants
2357 module = sys.modules.get('ubuntu_sso.constants')
2358 return getattr(module, dir_constant)
2359- except AttributeError:
2360+ except (ImportError, AttributeError):
2361 msg = '_get_dir: can not build a valid path. Giving up. ' \
2362 '__file__ is %r, constants module not available.'
2363 logger.error(msg, __file__)
2364@@ -69,7 +71,9 @@
2365 found, return the value of the PROJECT_DIR.
2366
2367 """
2368- return _get_dir(dir_name=DATA_SUFFIX, dir_constant='PROJECT_DIR')
2369+ result = _get_dir(dir_name=DATA_SUFFIX, dir_constant='PROJECT_DIR')
2370+ assert result is not None, '%r dir can not be None.' % DATA_SUFFIX
2371+ return result
2372
2373
2374 def get_data_file(*args):
2375@@ -84,7 +88,9 @@
2376 found, return the value of the BIN_DIR.
2377
2378 """
2379- return _get_dir(dir_name=BIN_SUFFIX, dir_constant='BIN_DIR')
2380+ result = _get_dir(dir_name=BIN_SUFFIX, dir_constant='BIN_DIR')
2381+ assert result is not None, '%r dir can not be None.' % BIN_SUFFIX
2382+ return result
2383
2384
2385 class RequestHead(urllib2.Request):
2386
2387=== modified file 'ubuntu_sso/utils/runner/glib.py'
2388--- ubuntu_sso/utils/runner/glib.py 2012-02-10 17:03:56 +0000
2389+++ ubuntu_sso/utils/runner/glib.py 2012-02-21 23:01:20 +0000
2390@@ -27,7 +27,7 @@
2391 logger = setup_logging("ubuntu_sso.utils.runner.glib")
2392
2393
2394-NO_SUCH_FILE_OR_DIR = '(No such file or directory)'
2395+NO_SUCH_FILE_OR_DIR = 'No such file or directory'
2396
2397
2398 def spawn_program(args, reply_handler, error_handler):
2399@@ -66,8 +66,17 @@
2400 GLib.SpawnFlags.STDOUT_TO_DEV_NULL | \
2401 GLib.SpawnFlags.STDERR_TO_DEV_NULL
2402 pid = None
2403+
2404+ bytes_args = []
2405+ for arg in args:
2406+ if isinstance(arg, unicode):
2407+ arg = arg.encode('utf-8')
2408+ if not isinstance(arg, basestring):
2409+ arg = str(arg)
2410+ bytes_args.append(arg)
2411+
2412 try:
2413- pid, _, _, _ = GLib.spawn_async(argv=args, flags=flags)
2414+ pid, _, _, _ = GLib.spawn_async(argv=bytes_args, flags=flags)
2415 except GLib.GError, e:
2416 handle_error(e)
2417 else:
2418
2419=== added file 'ubuntu_sso/utils/runner/tests/test_glib.py'
2420--- ubuntu_sso/utils/runner/tests/test_glib.py 1970-01-01 00:00:00 +0000
2421+++ ubuntu_sso/utils/runner/tests/test_glib.py 2012-02-21 23:01:20 +0000
2422@@ -0,0 +1,132 @@
2423+# -*- coding: utf-8 -*-
2424+#
2425+# Copyright 2012 Canonical Ltd.
2426+#
2427+# This program is free software: you can redistribute it and/or modify it
2428+# under the terms of the GNU General Public License version 3, as published
2429+# by the Free Software Foundation.
2430+#
2431+# This program is distributed in the hope that it will be useful, but
2432+# WITHOUT ANY WARRANTY; without even the implied warranties of
2433+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2434+# PURPOSE. See the GNU General Public License for more details.
2435+#
2436+# You should have received a copy of the GNU General Public License along
2437+# with this program. If not, see <http://www.gnu.org/licenses/>.
2438+
2439+"""Tests for the glib runner helper module."""
2440+
2441+import subprocess
2442+
2443+# pylint: disable=E0611
2444+from gi.repository import GLib
2445+# pylint: enable=E0611
2446+from twisted.internet import defer
2447+
2448+from ubuntu_sso.utils import runner
2449+from ubuntu_sso.utils.runner import glib
2450+from ubuntu_sso.utils.runner.tests.test_runner import SpawnProgramTestCase
2451+
2452+
2453+class FakedSignal(object):
2454+ """Fake a glib signal."""
2455+
2456+ def __init__(self, name):
2457+ self.name = name
2458+ self._handlers = []
2459+
2460+ def connect(self, handler):
2461+ """Connect 'handler' with this signal."""
2462+ self._handlers.append(handler)
2463+
2464+ def emit(self, *args, **kwargs):
2465+ """Emit this signal."""
2466+ for handler in self._handlers:
2467+ handler(*args, **kwargs)
2468+
2469+
2470+class FakedProcess(object):
2471+ """Fake a glib Process."""
2472+
2473+ _argv = _flags = None
2474+ _pid = 123456
2475+ _pids = []
2476+ _status_code = 0
2477+
2478+ SpawnFlags = GLib.SpawnFlags
2479+ GError = GLib.GError
2480+
2481+ def __init__(self):
2482+ self.pid = lambda: self._pid
2483+ self.started = FakedSignal('started')
2484+ self.finished = FakedSignal('finished')
2485+ self.error = FakedSignal('error')
2486+
2487+ def spawn_async(self, argv, flags):
2488+ """Spwan a process."""
2489+ if 'None' in argv:
2490+ exc = GLib.GError()
2491+ exc.message = str('Can not handle None')
2492+ exc.code = 24
2493+ raise exc
2494+
2495+ self._argv = argv
2496+ self._flags = flags
2497+
2498+ try:
2499+ subprocess.call(argv)
2500+ except Exception, e:
2501+ exc = GLib.GError()
2502+ exc.message = str(e)
2503+ exc.code = 42
2504+ raise exc
2505+
2506+ self._pids.append(self._pid)
2507+ return (self._pid, None, None, None)
2508+
2509+ def child_watch_add(self, pid, child_watch):
2510+ """Addd a child watch."""
2511+ if pid in self._pids:
2512+ child_watch(pid, self._status_code)
2513+
2514+ def spawn_close_pid(self, pid):
2515+ """Close the 'pid'."""
2516+ self._pids.remove(pid)
2517+
2518+
2519+class GLibSpawnProgramTestCase(SpawnProgramTestCase):
2520+ """The test suite for the spawn_program method (using GLib)."""
2521+
2522+ use_reactor = False
2523+
2524+ @defer.inlineCallbacks
2525+ def setUp(self):
2526+ yield super(GLibSpawnProgramTestCase, self).setUp()
2527+ # Since we can't mix plan glib runner and the gireactor, we patch
2528+ # GLib.spawn_async and fake the conditions so the glib runner is chosen
2529+ self.process = FakedProcess()
2530+ self.patch(glib, 'GLib', self.process)
2531+ self.patch(runner, 'is_twisted_reactor_installed', lambda: False)
2532+ self.patch(runner, 'is_qt4_main_loop_installed', lambda: False)
2533+
2534+ # Access to a protected member _flags, _argv of a client class
2535+ # pylint: disable=W0212
2536+
2537+ @defer.inlineCallbacks
2538+ def test_flags_are_correct(self):
2539+ """The flags are the correct ones."""
2540+ yield self.spawn_fn(self.args)
2541+
2542+ flags = GLib.SpawnFlags.DO_NOT_REAP_CHILD | \
2543+ GLib.SpawnFlags.SEARCH_PATH | \
2544+ GLib.SpawnFlags.STDOUT_TO_DEV_NULL | \
2545+ GLib.SpawnFlags.STDERR_TO_DEV_NULL
2546+ self.assertEqual(self.process._flags, flags)
2547+
2548+ @defer.inlineCallbacks
2549+ def test_argv_is_bytes(self):
2550+ """The argv parameter is converted to bytes."""
2551+ yield self.spawn_fn(self.args)
2552+
2553+ bytes_args = [a.encode('utf-8') for a in self.args]
2554+ self.assertEqual(self.process._argv, bytes_args)
2555
2556=== modified file 'ubuntu_sso/utils/runner/tests/test_qt.py'
2557--- ubuntu_sso/utils/runner/tests/test_qt.py 2012-02-10 15:44:28 +0000
2558+++ ubuntu_sso/utils/runner/tests/test_qt.py 2012-02-21 23:01:20 +0000
2559@@ -64,8 +64,16 @@
2560 self.started.emit()
2561
2562 args = (program,) + tuple(arguments)
2563+
2564+ # subprocess expects bytes
2565+ bytes_args = []
2566+ for arg in args:
2567+ if isinstance(arg, unicode):
2568+ arg = arg.encode('utf-8')
2569+ bytes_args.append(arg)
2570+
2571 try:
2572- subprocess.call(args)
2573+ subprocess.call(bytes_args)
2574 except OSError, e:
2575 if e.errno == 2:
2576 self.error.emit(self.FailedToStart)
2577
2578=== modified file 'ubuntu_sso/utils/runner/tests/test_runner.py'
2579--- ubuntu_sso/utils/runner/tests/test_runner.py 2012-02-08 02:13:03 +0000
2580+++ ubuntu_sso/utils/runner/tests/test_runner.py 2012-02-21 23:01:20 +0000
2581@@ -24,21 +24,23 @@
2582 from ubuntu_sso.utils import runner
2583
2584
2585-TEST_ME_DIR = 'test-me'
2586+TEST_ME_DIR = u'test-me-more-♥'
2587+TEST_ME_DIR_BYTES = TEST_ME_DIR.encode('utf-8')
2588
2589
2590 class SpawnProgramTestCase(TestCase):
2591 """The test suite for the spawn_program method."""
2592
2593 timeout = 3
2594- args = ('python', '-c', 'import os; os.system("mkdir %s")' % TEST_ME_DIR)
2595+ args = (u'python', u'-c',
2596+ u'import os; os.system("mkdir %s")' % TEST_ME_DIR)
2597
2598 @defer.inlineCallbacks
2599 def setUp(self):
2600 yield super(SpawnProgramTestCase, self).setUp()
2601- assert not os.path.exists(TEST_ME_DIR)
2602- self.addCleanup(lambda: os.path.exists(TEST_ME_DIR) and
2603- os.rmdir(TEST_ME_DIR))
2604+ assert not os.path.exists(TEST_ME_DIR_BYTES)
2605+ self.addCleanup(lambda: os.path.exists(TEST_ME_DIR_BYTES) and
2606+ os.rmdir(TEST_ME_DIR_BYTES))
2607
2608 def spawn_fn(self, args):
2609 """The target function to test."""
2610@@ -46,8 +48,8 @@
2611
2612 def assert_command_was_run(self):
2613 """The spawnned commnad was correctly run."""
2614- self.assertTrue(os.path.exists(TEST_ME_DIR))
2615- self.assertTrue(os.path.isdir(TEST_ME_DIR))
2616+ self.assertTrue(os.path.exists(TEST_ME_DIR_BYTES))
2617+ self.assertTrue(os.path.isdir(TEST_ME_DIR_BYTES))
2618
2619 @defer.inlineCallbacks
2620 def test_program_is_spawned(self):
2621
2622=== modified file 'ubuntu_sso/utils/runner/tx.py'
2623--- ubuntu_sso/utils/runner/tx.py 2012-02-08 18:29:39 +0000
2624+++ ubuntu_sso/utils/runner/tx.py 2012-02-21 23:01:20 +0000
2625@@ -68,6 +68,14 @@
2626 program = args[0]
2627 argv = args[1:]
2628
2629+ bytes_args = []
2630+ for arg in argv:
2631+ if isinstance(arg, unicode):
2632+ arg = arg.encode('utf-8')
2633+ if not isinstance(arg, basestring):
2634+ arg = str(arg)
2635+ bytes_args.append(arg)
2636+
2637 if program and not os.access(program, os.X_OK):
2638 # handle searching the executable in the PATH, since
2639 # twisted will not solve that for us :-/
2640@@ -81,7 +89,7 @@
2641 break
2642
2643 try:
2644- d = utils.getProcessOutputAndValue(program, argv, env=os.environ)
2645+ d = utils.getProcessOutputAndValue(program, bytes_args, env=os.environ)
2646 except OSError, e:
2647 error_handler(msg=e, failed_to_start=True)
2648 except Exception, e:
2649
2650=== modified file 'ubuntu_sso/utils/tests/test_common.py'
2651--- ubuntu_sso/utils/tests/test_common.py 2012-02-11 19:25:01 +0000
2652+++ ubuntu_sso/utils/tests/test_common.py 2012-02-21 23:01:20 +0000
2653@@ -124,8 +124,7 @@
2654 self.patch(utils.os.path, 'exists', lambda path: False)
2655 sys.modules[CONSTANTS_MODULE] = None
2656
2657- result = self.get_dir()
2658- self.assertTrue(result is None)
2659+ self.assertRaises(AssertionError, self.get_dir)
2660 msg = 'get_dir: can not build a valid path.'
2661 self.assertTrue(self.memento.check_error(msg))
2662
2663
2664=== modified file 'ubuntu_sso/utils/ui.py'
2665--- ubuntu_sso/utils/ui.py 2012-02-13 20:27:48 +0000
2666+++ ubuntu_sso/utils/ui.py 2012-02-21 23:01:20 +0000
2667@@ -21,11 +21,12 @@
2668
2669 from ubuntu_sso.logger import setup_logging
2670
2671+
2672+gettext.install('ubuntu-sso-client', unicode=True)
2673 logger = setup_logging('ubuntu_sso.utils.ui')
2674
2675
2676-gettext.textdomain('ubuntu-sso-client')
2677-_ = gettext.gettext
2678+# Undefined variable '_', pylint: disable=E0602
2679
2680 # all the text that is used in the gui
2681 AGREE_TO_PRIVACY_POLICY = _('By signing up to {app_name} you agree to '
2682@@ -33,11 +34,13 @@
2683 AGREE_TO_TERMS = _('By signing up to {app_name} you agree to '
2684 'our {terms_and_conditions}')
2685 AGREE_TO_TERMS_AND_PRIVACY_POLICY = AGREE_TO_TERMS + _(' and {privacy_policy}')
2686+CANCEL_BUTTON = _('Cancel')
2687 CAPTCHA_SOLUTION_ENTRY = _('Type the characters above')
2688 CAPTCHA_LOAD_ERROR = _('There was a problem getting the captcha, '
2689 'reloading...')
2690 CAPTCHA_RELOAD_TOOLTIP = _('Reload')
2691 CAPTCHA_REQUIRED_ERROR = _('The captcha is a required field')
2692+CLOSE_AND_SETUP_LATER = _('Close window and setup later')
2693 CONGRATULATIONS = _("Congratulations, {app_name} is installed!")
2694 PROXY_CREDS_DIALOG_TITLE = _('Add proxy settings')
2695 PROXY_CREDS_HEADER = _('You are connecting through a proxy.')
2696@@ -76,10 +79,10 @@
2697 LOGIN_HEADER_LABEL = _('Connect to %(app_name)s')
2698 LOGIN_PASSWORD_ENTRY = _('Password')
2699 LOGIN_PASSWORD_LABEL = LOGIN_PASSWORD_ENTRY
2700-NAME = _("Name")
2701 NAME_ENTRY = _('Name')
2702 NAME_INVALID = _('The name must not be empty.')
2703 NEXT = _('Next')
2704+NETWORK_DETECTION_TITLE = _('Network detection')
2705 ONE_MOMENT_PLEASE = _('One moment please...')
2706 PASSWORD = _("Create a password")
2707 PASSWORD_CHANGED = _('Your password was successfully changed.')
2708@@ -140,6 +143,8 @@
2709 YES_TO_TC = _('I agree with the %(app_name)s terms and conditions')
2710 YES_TO_UPDATES = _('Yes! Email me %(app_name)s tips and updates.')
2711
2712+# pylint: enable=E0602
2713+
2714
2715 def get_password_strength(password):
2716 """Return the strength of the password.

Subscribers

People subscribed via source and target branches