~elopio/ubuntu-sso-client/autopilot

« back to all changes in this revision

Viewing changes to ubuntu_sso/tests/acceptance/test_ubuntu_sso_client.py

  • Committer: leo.arias at canonical
  • Date: 2013-02-25 04:10:49 UTC
  • Revision ID: leo.arias@canonical.com-20130225041049-mi589bnvwmr394qz
Second pass to the autopilot acceptance test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import time
1
2
import os
2
 
 
3
 
from autopilot import testcase, introspection
 
3
import uuid
 
4
 
 
5
import dbus
 
6
from dbus.mainloop.glib import DBusGMainLoop
 
7
 
 
8
from autopilot import introspection, testcase
 
9
from autopilot.emulators import X11
 
10
from testtools.matchers import Equals, Contains
 
11
 
 
12
 
 
13
# This should be an emulator. But it seems that the only way to make an
 
14
# emulator is if the application's bus has well-known name.
 
15
# TODO ask on #qa.
 
16
class Page(object):
 
17
 
 
18
    def __init__(self, application, page_type):
 
19
        self.application = application
 
20
        self.page = self.application.select_single(page_type)
 
21
        self.keyboard = X11.Keyboard()
 
22
        self.mouse = X11.Mouse()
 
23
 
 
24
    def wait_for_action_to_complete(self):
 
25
        """Wait for the last action to complete.
 
26
 
 
27
        This method waits for the loading overlay to dissapear.
 
28
 
 
29
        """
 
30
        # If autopilot executes too fast, we might look for the loading overlay
 
31
        # before it is shown. We should wait a little to give it time to
 
32
        # appear, but it's not possible to wait for it, because if autopilot
 
33
        # executes too slow, we might look for it after it dissapears.
 
34
        # Thus, the only solution that comes to mind is a sleep. -- Leo
 
35
        time.sleep(3)
 
36
        loading_overlay = self.application.select_single('LoadingOverlay')
 
37
        loading_overlay.visible.wait_for(False)
 
38
 
 
39
    # TODO propose this to autopilot.
 
40
    def get_child_by_type(self, desired_type, **kwargs):
 
41
        children = self.page.get_children_by_type(desired_type, **kwargs)
 
42
        assert len(children) > 0, 'No child found.'
 
43
        assert len(children) == 1, 'More than one child found.'
 
44
        return children[0]
 
45
 
 
46
 
 
47
class SignUpPage(Page):
 
48
 
 
49
    def __init__(self, application):
 
50
        super(SignUpPage, self).__init__(application, 'SetupAccountPage')
 
51
 
 
52
    def go_to_log_in(self):
 
53
        sign_in_label = self.get_child_by_type(
 
54
            'QLabel', objectName='sign_in_label')
 
55
        self.mouse.move_to_object(sign_in_label)
 
56
        self.mouse.click()
 
57
        self.wait_for_action_to_complete()
 
58
        return LogInPage(self.application)
 
59
 
 
60
 
 
61
class LogInPage(Page):
 
62
 
 
63
    def __init__(self, application):
 
64
        super(LogInPage, self).__init__(application, 'CurrentUserSignInPage')
 
65
 
 
66
    def log_in_with_successful_authentication(self, email, password):
 
67
        self._log_in(email, password)
 
68
        assert self.get_form_errors() is None
 
69
        return SuccessPage(self.application)
 
70
 
 
71
    def _log_in(self, email, password):
 
72
        self._fill_log_in_form(email, password)
 
73
        sign_in_button = self.get_child_by_type(
 
74
            'QPushButton', objectName='sign_in_button')
 
75
        self.mouse.move_to_object(sign_in_button)
 
76
        self.mouse.click()
 
77
        self.wait_for_action_to_complete()
 
78
 
 
79
    def log_in_with_failed_authentication(self, email, password):
 
80
        self._log_in(email, password)
 
81
        return self.page
 
82
 
 
83
    def _fill_log_in_form(self, email, password):
 
84
        email_edit = self.get_child_by_type(
 
85
            'QLineEdit', objectName='email_edit')
 
86
        self.mouse.move_to_object(email_edit)
 
87
        self.mouse.click()
 
88
        self.keyboard.type(email)
 
89
        password_edit = self.get_child_by_type(
 
90
            'QLineEdit', objectName='password_edit')
 
91
        self.mouse.move_to_object(password_edit)
 
92
        self.mouse.click()
 
93
        self.keyboard.type(password)
 
94
 
 
95
    def get_form_errors(self):
 
96
        form_errors = self.get_child_by_type(
 
97
            'QLabel', objectName='form_errors')
 
98
        if form_errors.visible:
 
99
            return form_errors.text
 
100
        else:
 
101
            return None
 
102
 
 
103
 
 
104
class SuccessPage(Page):
 
105
 
 
106
    def __init__(self, application):
 
107
        super(SuccessPage, self).__init__(application, 'SuccessPage')
 
108
 
 
109
    def get_message(self):
 
110
        label = self.get_child_by_type(
 
111
            'QLabel', objectName='success_message_body')
 
112
        return label.text
 
113
 
 
114
    def finish(self):
 
115
        # TODO when we have the emulator, this should be on the wizard, not the
 
116
        # page.
 
117
        # TODO file a bug to QWizard because the buttons don't have objectName.
 
118
        finish_button = self.application.select_single(
 
119
            'QPushButton', text='&Finish')
 
120
        self.mouse.move_to_object(finish_button)
 
121
        self.mouse.click()
4
122
 
5
123
 
6
124
class NoEnvironmentIntrospectionTestMixin(
9
127
    def prepare_environment(self, app_path, arguments):
10
128
        return app_path, arguments
11
129
 
 
130
 
12
131
class TestUbuntuSSOClient(
13
132
        testcase.AutopilotTestCase, NoEnvironmentIntrospectionTestMixin):
14
133
 
15
134
    def setUp(self):
16
135
        super(TestUbuntuSSOClient, self).setUp()
17
136
        os.environ['TESTABILITY'] = '1'
18
 
        # TODO launch the app connected to staging.
 
137
        # TODO we shouldn't start the application this way. We should call
 
138
        # the register or login method through dbus.
 
139
        # There are two problems with this. First, the TESTABILITY variable
 
140
        # is not passed as True. Second, I haven't found an easy way to get
 
141
        # the autopilot dbus proxy.
 
142
        self.app_name = 'App {0}'.format(str(uuid.uuid1()))
19
143
        self.application = self.launch_test_application(
20
144
            'bin/ubuntu-sso-login-qt',
21
 
            '--app_name="Test"')
22
 
 
23
 
    def test(self):
24
 
        loading_overlay = self.application.select_single('LoadingOverlay')
25
 
        loading_overlay.visible.wait_for(True)
26
 
        loading_overlay.visible.wait_for(False)
27
 
        sign_in_label = self.application.select_single(
28
 
            'QLabel', objectName='sign_in_label')
29
 
        self.mouse.move_to_object(sign_in_label)
30
 
        self.mouse.click()
31
 
        sign_in_page = self.application.select_single('CurrentUserSignInPage')
32
 
        # TODO why isn't there a single email_edit?
33
 
        email_edit = sign_in_page.select_many(
34
 
            'QLineEdit', objectName='email_edit')[0]
35
 
        self.mouse.move_to_object(email_edit)
36
 
        self.mouse.click()
37
 
        self.keyboard.type("test@canonical.com")
38
 
        # TODO why isn't there a single password_edit?
39
 
        password_edit = sign_in_page.select_many(
40
 
            'QLineEdit', objectName='password_edit')[1]
41
 
        self.mouse.move_to_object(password_edit)
42
 
        self.mouse.click()
43
 
        self.keyboard.type('password')
44
 
        sign_in_button = sign_in_page.select_single(
45
 
            'QPushButton', objectName='sign_in_button')
46
 
        self.mouse.move_to_object(sign_in_button)
47
 
        self.mouse.click()
48
 
        loading_overlay.visible.wait_for(True)
49
 
        loading_overlay.visible.wait_for(False)
50
 
        # TODO wait for the application to be closed.
 
145
            '--app_name={0}'.format(self.app_name))
 
146
 
 
147
    def _clear_credentials(self):
 
148
        DBusGMainLoop(set_as_default=True)
 
149
        session_bus = dbus.SessionBus()
 
150
        proxy = session_bus.get_object(
 
151
            'com.ubuntu.sso', '/com/ubuntu/sso/credentials')
 
152
        interface = dbus.Interface(
 
153
            proxy, dbus_interface='com.ubuntu.sso.CredentialsManagement')
 
154
        interface.clear_credentials(self.app_name, {})
 
155
 
 
156
    def _log_in_with_successful_authentication(self, email, password):
 
157
        log_in_page = self._go_to_log_in_page()
 
158
        return log_in_page.log_in_with_successful_authentication(
 
159
            email, password)
 
160
 
 
161
    def _go_to_log_in_page(self):
 
162
        sign_up_page = SignUpPage(self.application)
 
163
        sign_up_page.wait_for_action_to_complete()
 
164
        return sign_up_page.go_to_log_in()
 
165
 
 
166
    def _log_in_with_failed_authentication(self, email, password):
 
167
        log_in_page = self._go_to_log_in_page()
 
168
        log_in_page.log_in_with_failed_authentication(email, password)
 
169
        self.assertTrue(log_in_page.page.visible)
 
170
        return log_in_page
 
171
 
 
172
    def test_authentication_failed(self):
 
173
        log_in_page = self._log_in_with_failed_authentication(
 
174
            'wrong-email@canonical.com', 'wrong password')
 
175
        self.assertThat(
 
176
            log_in_page.get_form_errors(),
 
177
            Contains('The authentication failed.'))
 
178
 
 
179
    def test_successful_log_in(self):
 
180
        self.skipTest('This is a public project, so we need a way to store '
 
181
                      'real user credentials on a private way.')
 
182
        self.addCleanup(self._clear_credentials)
 
183
        success_page = self._log_in_with_successful_authentication(
 
184
            'u1test+sso@canonical.com', 'some-password')
 
185
        self.assertThat(
 
186
            success_page.get_message(),
 
187
            Equals('You are now logged into {0}.'.format(self.app_name)))
 
188
        success_page.finish()
 
189
        # TODO assert that the application is closed.