unittest_registration.py 7.29 KB
Newer Older
Sylvain Thénault's avatar
Sylvain Thénault committed
1
import re, cgi, urlparse
2
from contextlib import contextmanager
3
4

from cubicweb import ValidationError
5
from cubicweb.crypto import encrypt, decrypt
6
from cubicweb.web import Redirect
Sylvain Thénault's avatar
Sylvain Thénault committed
7
from cubicweb.devtools.testlib import MAILBOX, CubicWebTC
8

9
from cubes.registration.views import RegistrationSendMailController
10
11


Sylvain Thénault's avatar
Sylvain Thénault committed
12
class RegistrationTC(CubicWebTC):
13

Florent's avatar
Florent committed
14
15
    captcha_value = u'captcha value'

16
    data = {'firstname-subject': u'Toto', 'surname-subject': u'Toto',
17
            'email_address-subject': u'toto@secondweb.fr',
18
19
20
            'login-subject': u'toto',
            'upassword-subject': 'toto',
            'upassword-subject-confirm': 'toto',
Florent's avatar
Florent committed
21
            'captcha': captcha_value}
22
23

    def setup_database(self):
24
        self.config.global_set_option('registration-cypher-seed', u'dummy cypher key')
25
26
        super(RegistrationTC, self).setup_database()

27
    def _check_user_not_created(self):
28
29
30
31
        with self.admin_access.repo_cnx() as cnx:
            rset = cnx.execute('CWUser X WHERE X login %(login)s',
                               {'login': self.data['login-subject']})
            self.assertFalse(rset)
32
33
34
35

    def _check_error(self, req, path,
                     expected_path='registration',
                     expected_errors=None,
36
                     expected_msg=None,
37
38
                     expected_formvalues=None):
        path, params = self.expect_redirect_publish(req, path)
Sylvain Thénault's avatar
Sylvain Thénault committed
39
        self.assertEqual(path, expected_path)
40
41
42
        if expected_msg:
            self.assertMessageEqual(req, params, expected_msg)
        forminfo = req.session.data.get('registration')
43
44
45
        if forminfo is None:
            self.failIf(expected_errors or expected_formvalues)
        else:
Sylvain Thénault's avatar
Sylvain Thénault committed
46
47
            self.assertEqual(forminfo['eidmap'], {})
            self.assertEqual(forminfo['values'], expected_formvalues or {})
48
            error = forminfo['error']
Sylvain Thénault's avatar
Sylvain Thénault committed
49
50
            self.assertEqual(error.entity, None)
            self.assertEqual(error.errors, expected_errors or {})
51
52
53
54
55
56
57
58
59

    def _posted_form(self, *skipkeys):
        data = self.data.copy()
        for key in skipkeys:
            data.pop(key, None)
        if not '__errorurl' in skipkeys:
            data['__errorurl'] = 'registration'
        return data

60
    def test_registration_form(self):
61
62
63
        with self.admin_access.web_request() as req:
            req.form = {'firstname-subject': u'Toto'}
            pageinfo = self.view('registration', req=req, rset=None)
64

65
        # check form field names
66
        names = pageinfo.etree.xpath('//form[@id="registrationForm"]//input[@type!="hidden"]/@name')
Sylvain Thénault's avatar
Sylvain Thénault committed
67
        self.assertEqual(set(names), set(self.data))
68

69
        # check form field value
70
        firstname = pageinfo.etree.xpath('//input[@name="firstname-subject"]/@value')
Sylvain Thénault's avatar
Sylvain Thénault committed
71
        self.assertEqual(firstname, [req.form['firstname-subject']])
72
73

    def test_send_mail_ok(self):
74
75
76
77
78
79
80
81
82
83
84
85
86
87
        with self.new_access(u'anon').web_request() as req:
            req.form = self._posted_form()
            req.session.data['captcha'] = self.captcha_value
            path, params = self.expect_redirect_publish(req, 'registration_sendmail')
            self.assertEqual(path, '')
            self.assertMessageEqual(req, params, 'Your registration email has been sent. Follow instructions in there to activate your account.')
            # check email contains activation url...
            URL_RE = re.compile('(%s[^.]+)$' % self.config['base-url'], re.M)
            text = MAILBOX[-1].message.get_payload(decode=True)
            url = URL_RE.search(text).group(1)
            # ... and the registration key contains all data
            key = dict(cgi.parse_qsl(urlparse.urlsplit(url)[3]))['key']
            d = self._posted_form('upassword-subject-confirm')
            self.assertDictEqual(decrypt(key, self.config['registration-cypher-seed']), d)
88
89

    def test_send_mail_failure(self):
90
91
92
        for param, msg, val in (('login-subject', 'required field', None),
                                ('captcha', 'required field', None),
                                ('captcha', 'incorrect captcha value', 'abc')):
93
94
95
96
97
98
99
100
101
102
103
104
105
106
            with self.admin_access.web_request() as req:
                if val is None:
                    req.form = self._posted_form(param)
                else:
                    req.form = self._posted_form()
                    req.form[param] = val
                req.session.data['captcha'] = self.captcha_value
                #expected
                self._check_error(req, 'registration_sendmail',
                                  expected_formvalues=req.form,
                                  expected_errors={param: msg})
                self.assertEqual(req.session.data.get('captcha'), None)

    @contextmanager
107
    def _confirm_req(self, key=None, overriden={}):
108
109
110
111
112
113
114
        with self.new_access(u'anon').web_request() as req:
            data = self._posted_form('upassword-subject-confirm')
            data.update(overriden)
            if key is None:
                key = encrypt(data, self.config['registration-cypher-seed'])
            req.form = {'key': key}
            yield req
115
116
    #self.vreg['controllers'].select('registration_confirm', req,
    #appli=self.app)
Florent's avatar
Florent committed
117
118

    def test_confirm_ok(self):
119
120
121
122
123
124
125
126
127
128
        with self._confirm_req() as req:
            path, params = self.expect_redirect_publish(req, 'registration_confirm')
            self.assertEqual(path, '')
            self.assertMessageEqual(req, params, 'Congratulations, your registration is complete. Welcome %(firstname-subject)s %(surname-subject)s !' % self.data)
        with self.admin_access.repo_cnx() as cnx:
            rset = cnx.execute('Any U WHERE U login %(login)s, U firstname %(firstname)s, '
                                'U surname %(surname)s, U use_email M, M address %(email_address)s',
                                dict((k.replace('-subject', ''), v)
                                     for k, v in self.data.items()))
            self.assertTrue(rset)
129

Florent's avatar
Florent committed
130
    def test_confirm_failure_login_already_used(self):
131
        # try to recreate a 'admin' user.
132
133
134
135
136
137
138
        with self._confirm_req(overriden={'login-subject': 'admin'}) as req:
            formvalues = self._posted_form('upassword-subject',
                                           'upassword-subject-confirm')
            formvalues['login-subject'] = 'admin'
            self._check_error(req, 'registration_confirm',
                              expected_formvalues=formvalues,
                              expected_errors={'login-subject': 'the value "admin" is already used, use another one'})
139
140

    def test_confirm_failure_invalid_data(self):
141
142
143
        with self._confirm_req('dummykey') as req:
            self._check_error(req, 'registration_confirm', 'register',
                              expected_msg='Invalid registration data. Please try registering again.')
Florent's avatar
Florent committed
144
145
146
        self._check_user_not_created()

    def test_confirm_failure_email_already_used(self):
147
148
149
150
151
152
153
        with self.admin_access.web_request() as req:
            self.create_user(req, 'test')
            req.execute('INSERT EmailAddress X: U use_email X, X address %(email_address)s '
                         'WHERE U login "test"', {'email_address': self.data['email_address-subject']})
            req.cnx.commit()
        with self._confirm_req() as req:
            req.form['__errorurl'] = 'registration'
Florent's avatar
Florent committed
154
        self._check_user_not_created()
Sylvain Thénault's avatar
Sylvain Thénault committed
155
156

if __name__ == '__main__':
Sylvain Thénault's avatar
Sylvain Thénault committed
157
    from logilab.common.testlib import unittest_main
Sylvain Thénault's avatar
Sylvain Thénault committed
158
    unittest_main()