28
28
from twisted.trial.unittest import TestCase, FailTest
30
30
from contrib.testing.testcase import MementoHandler
31
from ubuntu_sso import credentials, gui
31
from ubuntu_sso import credentials
32
32
from ubuntu_sso.credentials import (APP_NAME_KEY, HELP_TEXT_KEY, NO_OP,
33
PING_URL_KEY, TC_URL_KEY, WINDOW_ID_KEY, ERROR_KEY, ERROR_DETAIL_KEY)
34
from ubuntu_sso.tests import (APP_NAME, EMAIL, HELP_TEXT, PING_URL, TC_URL,
33
PING_URL_KEY, TC_URL_KEY, UI_CLASS_KEY, UI_MODULE_KEY, WINDOW_ID_KEY,
34
ERROR_KEY, ERROR_DETAIL_KEY)
35
from ubuntu_sso.tests import (APP_NAME, EMAIL, GTK_GUI_CLASS, GTK_GUI_MODULE,
36
HELP_TEXT, PING_URL, TC_URL, TOKEN, WINDOW_ID)
38
39
# Access to a protected member of a client class
48
49
HELP_TEXT_KEY: HELP_TEXT,
49
50
WINDOW_ID_KEY: WINDOW_ID,
50
51
PING_URL_KEY: PING_URL,
52
UI_MODULE_KEY: 'ubuntu_sso.tests.test_credentials',
53
UI_CLASS_KEY: 'FakedClientGUI',
57
APP_NAME_KEY: APP_NAME,
59
HELP_TEXT_KEY: HELP_TEXT,
60
WINDOW_ID_KEY: WINDOW_ID,
63
SIG_LOGIN_SUCCEEDED = '1'
64
SIG_REGISTRATION_SUCCEEDED = '2'
65
SIG_USER_CANCELATION = '3'
68
class SampleMiscException(Exception):
69
"""An error to be used while testing."""
72
class FailingClientGUI(object):
73
"""Fake a failing SSO GUI."""
75
def __init__(self, *args, **kwargs):
76
raise SampleMiscException('A failing GUI class.')
79
class FakedClientGUI(object):
82
def __init__(self, *args, **kwargs):
87
self.connect = lambda *a: self.signals.append(a)
89
def finish_success(self):
90
"""Fake the success finish."""
91
self.methods.append('finish_success')
93
def finish_error(self, error):
94
"""Fake the error finish."""
95
self.methods.append(('finish_error', error))
54
98
class BasicTestCase(TestCase):
80
124
super(CredentialsTestCase, self).setUp()
86
class FakedUbuntuSSOClientGUI(object):
89
# Method should have 'self' as first argument
90
# pylint: disable=E0213
92
def __init__(sself, *args, **kwargs):
95
sself.connect = lambda *a: self.signals.append(a)
97
def finish_success(sself):
98
"""Fake the success finish."""
99
self.methods.append('finish_success')
101
def finish_error(sself, error):
102
"""Fake the error finish."""
103
self.methods.append(('finish_error', error))
105
self.patch(gui, 'UbuntuSSOClientGUI', FakedUbuntuSSOClientGUI)
106
125
self.obj = credentials.Credentials(success_cb=self.success,
107
126
error_cb=self.error,
108
127
denial_cb=self.denial,
192
211
self.assertEqual(getattr(self.obj, PING_URL_KEY), None)
213
def test_ui_class_defaults_to_gtk(self):
214
"""The ui class defaults to gtk."""
215
newkw = KWARGS.copy()
216
newkw.pop(UI_CLASS_KEY)
217
self.obj = credentials.Credentials(**newkw)
219
self.assertEqual(getattr(self.obj, UI_CLASS_KEY), GTK_GUI_CLASS)
221
def test_ui_module_defaults_to_gtk(self):
222
"""The ui module defaults to gtk."""
223
newkw = KWARGS.copy()
224
newkw.pop(UI_MODULE_KEY)
225
self.obj = credentials.Credentials(**newkw)
227
self.assertEqual(getattr(self.obj, UI_MODULE_KEY), GTK_GUI_MODULE)
194
229
def test_success_cb_gui_none(self):
195
230
"""Success callback calls the caller but not the GUI."""
196
231
self.obj.gui = None
199
234
self.assertEqual(self._called, (('success', APP_NAME, TOKEN), {}),
200
235
'caller _success_cb was called.')
201
self.assertEqual(self.methods, [],
202
'GUI finish_success was not called.')
204
237
def test_success_cb_gui_not_none(self):
205
238
"""Success callback calls the caller and finish the GUI."""
206
self.obj.gui = gui.UbuntuSSOClientGUI(APP_NAME)
239
self.obj.gui = ui = FakedClientGUI(APP_NAME)
207
240
self.obj.success_cb(creds=TOKEN)
209
242
self.assertEqual(self._called, (('success', APP_NAME, TOKEN), {}),
210
243
'caller _success_cb was called.')
211
self.assertEqual(self.methods, ['finish_success'],
244
self.assertEqual(ui.methods, ['finish_success'],
212
245
'GUI finish_success was called.')
213
246
self.assertTrue(self.obj.gui is None, 'gui is reset to None.')
221
254
self.assertEqual(self._called, (('error', APP_NAME, error_dict), {}),
222
255
'caller _error_cb was called.')
223
self.assertEqual(self.methods, [],
224
'GUI finish_error was not called.')
226
257
def test_error_cb_gui_not_none(self):
227
258
"""Error callback calls the caller and finish the GUI."""
228
self.obj.gui = gui.UbuntuSSOClientGUI(APP_NAME)
259
self.obj.gui = ui = FakedClientGUI(APP_NAME)
229
260
error_dict = {'foo': 'bar'}
230
261
self.obj.error_cb(error_dict=error_dict)
232
263
self.assertEqual(self._called, (('error', APP_NAME, error_dict), {}),
233
264
'caller _error_cb was called.')
234
self.assertEqual(self.methods, [('finish_error', error_dict)],
265
self.assertEqual(ui.methods, [('finish_error', error_dict)],
235
266
'GUI finish_error was called.')
236
267
self.assertTrue(self.obj.gui is None, 'gui is reset to None.')
341
372
self.assertEqual(self._called, (('success', APP_NAME, TOKEN), {}))
344
class CredentialsLoginErrorTestCase(CredentialsTestCase):
345
"""Test suite for the Credentials login error callback."""
347
def test_login_error_cb(self):
348
"""On login/register error, self.error_cb is called."""
349
self.obj._login_error_cb(dialog=None, app_name=APP_NAME, error='Bla')
350
self.assert_error_cb_called(msg='Bla')
353
375
class CredentialsAuthDeniedTestCase(CredentialsTestCase):
354
376
"""Test suite for the Credentials auth denied callback."""
356
378
def test_auth_denial_cb(self):
357
379
"""On auth denied, self.denial_cb is called."""
380
self.obj.gui = ui = FakedClientGUI(APP_NAME)
358
381
self.obj._auth_denial_cb(dialog=None, app_name=APP_NAME)
359
382
self.assertEqual(self._called, (('denial', APP_NAME), {}))
360
self.assertEqual(self.methods, [], 'no GUI method was called.')
383
self.assertEqual(ui.methods, [], 'no GUI method was called.')
363
386
class PingUrlTestCase(CredentialsTestCase):
420
443
self.assertTrue(self.memento.check_exception(FailTest, error))
423
class SampleMiscException(Exception):
424
"""An error to be used while testing."""
427
446
class FindCredentialsTestCase(CredentialsTestCase):
428
447
"""Test suite for the find_credentials method."""
492
511
operation = 'register'
493
512
login_only = False
515
super(RegisterTestCase, self).setUp()
516
self.ui_kwargs = UI_KWARGS.copy()
517
self.ui_kwargs['login_only'] = self.login_only
496
520
def test_with_existent_token(self):
497
521
"""The operation returns the credentials if already in keyring."""
511
535
yield getattr(self.obj, self.operation)()
513
expected = KWARGS.copy()
514
expected.pop(PING_URL_KEY)
515
expected['login_only'] = self.login_only
516
self.assertEqual(expected, self.kwargs)
537
self.assertEqual(self.obj.gui.kwargs, self.ui_kwargs)
519
540
def test_with_exception_on_credentials(self):
533
554
"""The operation calls the error callback if a GUI exception occurs."""
534
555
self.patch(credentials.Keyring, 'get_credentials',
535
556
lambda kr, app: defer.succeed(None))
537
self.patch(gui, 'UbuntuSSOClientGUI', lambda *a, **kw: self.fail(err))
557
err = 'A failing GUI class.'
558
self.obj.ui_class = 'FailingClientGUI'
539
560
yield getattr(self.obj, self.operation)()
541
562
msg = 'Problem opening the Ubuntu SSO user interface'
542
self.assert_error_cb_called(msg=msg, detailed_error=FailTest(err))
543
self.assertTrue(self.memento.check_exception(FailTest, err))
563
self.assert_error_cb_called(msg=msg,
564
detailed_error=SampleMiscException(err))
565
self.assertTrue(self.memento.check_exception(SampleMiscException, err))
546
568
def test_connects_gui_signals(self):
549
571
lambda kr, app: defer.succeed(None))
552
(gui.SIG_LOGIN_SUCCEEDED, self.obj._login_success_cb),
553
(gui.SIG_LOGIN_FAILED, self.obj._login_error_cb),
554
(gui.SIG_REGISTRATION_SUCCEEDED, self.obj._login_success_cb),
555
(gui.SIG_REGISTRATION_FAILED, self.obj._login_error_cb),
556
(gui.SIG_USER_CANCELATION, self.obj._auth_denial_cb),
574
(SIG_LOGIN_SUCCEEDED, self.obj._login_success_cb),
575
(SIG_REGISTRATION_SUCCEEDED, self.obj._login_success_cb),
576
(SIG_USER_CANCELATION, self.obj._auth_denial_cb),
558
578
yield getattr(self.obj, self.operation)()
559
self.assertEqual(self.signals, expected)
579
self.assertEqual(self.obj.gui.signals, expected)
562
582
def test_gui_is_created(self):
567
587
yield getattr(self.obj, self.operation)()
569
self.assertIsInstance(self.obj.gui, gui.UbuntuSSOClientGUI)
570
self.assertEqual(self.args, ())
572
expected = KWARGS.copy()
573
expected.pop(PING_URL_KEY)
574
expected['login_only'] = self.login_only
575
self.assertEqual(self.kwargs, expected)
589
self.assertIsInstance(self.obj.gui, FakedClientGUI)
590
self.assertEqual(self.obj.gui.args, ())
591
self.assertEqual(self.obj.gui.kwargs, self.ui_kwargs)
578
594
class LoginTestCase(RegisterTestCase):