1
# -*- coding: utf-8 -*-
3
# Copyright (C) 2008 Matthew Good <trac@matt-good.net>
5
# "THE BEER-WARE LICENSE" (Revision 42):
6
# <trac@matt-good.net> wrote this file. As long as you retain this notice you
7
# can do whatever you want with this stuff. If we meet some day, and you think
8
# this stuff is worth it, you can buy me a beer in return. Matthew Good
10
# Author: Pedro Algarvio <ufs@ufsoft.org>
14
from trac.tests.notification import parse_smtp_message
16
from acct_mgr.tests.functional import *
19
class TestFormLoginAdmin(FunctionalTwillTestCaseSetup):
21
"""Login with test user 'admin'"""
22
self._tester.login('admin')
25
class TestFormLoginUser(FunctionalTwillTestCaseSetup):
27
"""Login with test user 'user'"""
28
self._tester.login('user')
31
class TestRegisterNewUser(FunctionalTestCaseSetup):
33
"""Register 'testuser'"""
34
self._tester.register('testuser')
36
class TestLoginNewUser(FunctionalTestCaseSetup):
38
"""Login just registered 'testuser'"""
39
self._tester.login('testuser')
43
class TestFailRegisterPasswdConfirmNotPassed(FunctionalTestCaseSetup):
45
"""Fail if no password confirmation is passed"""
46
reg_form_name = 'acctmgr_registerform'
47
username = 'testuser1'
50
tc.formvalue(reg_form_name, 'user', username)
51
tc.formvalue(reg_form_name, 'password', username)
53
tc.find("The passwords must match.")
55
class TestFailRegisterDuplicateUsername(FunctionalTestCaseSetup):
57
"""Fail if username exists"""
58
reg_form_name = 'acctmgr_registerform'
62
tc.formvalue(reg_form_name, 'user', username)
63
tc.formvalue(reg_form_name, 'password', username)
64
tc.formvalue(reg_form_name, 'password_confirm', username)
66
tc.find("Another account with that name already exists.")
68
class TestNewAccountNotification(FunctionalTestCaseSetup):
70
"""Send out notification on new account registrations"""
72
address_to_notify = 'admin@testenv%s.tld' % self._testenv.port
74
new_username_email = "foo@%s" % address_to_notify.split('@')[1]
76
env = self._testenv.get_trac_environment()
77
env.config.set('account-manager', 'account_changes_notify_addresses',
79
env.config.set('account-manager', 'notify_actions', 'new,change,delete')
80
env.config.set('account-manager', 'force_passwd_change', 'true')
82
self._tester.register(new_username, new_username_email)
84
headers, body = parse_smtp_message(self._smtpd.get_message())
86
self.assertEqual(self._smtpd.get_recipients(), [address_to_notify])
87
self.assertEqual(headers['Subject'],
88
'[%s] New user registration: %s' % (
89
'testenv%s' % self._testenv.port,
91
self.assertEqual(headers['X-URL'], self._testenv.url)
93
class TestNewAccountEmailVerification(FunctionalTestCaseSetup):
95
"""User is shown info that he needs to verify his address"""
96
user_email = "foo@testenv%s.tld" % self._testenv.port
97
self._tester.login("foo")
99
tc.find('<strong>Notice:</strong> <span>An email has been sent to '
100
'%s with a token to <a href="/verify_email">verify your new '
101
'email address</a></span>' % user_email)
102
self._tester.go_to_front()
103
tc.find('<strong>Warning:</strong> <span>Your permissions have been '
104
'limited until you <a href="/verify_email">verify your email '
105
'address</a></span>')
107
class VerifyNewAccountEmailAddress(FunctionalTestCaseSetup):
109
"""User confirms his address with mailed token"""
110
headers, body = parse_smtp_message(self._smtpd.get_message())
111
blines = base64.decodestring(body).splitlines()
112
token = [l.split() for l in blines if 'Verification Token' in l][0][-1]
114
tc.find('Logout') # User is logged in from previous test
115
self._tester.go_to_front()
116
tc.find('<strong>Warning:</strong> <span>Your permissions have been '
117
'limited until you <a href="/verify_email">verify your email '
118
'address</a></span>')
119
tc.go(self._testenv.url + '/verify_email')
121
reg_form_name = 'acctmgr_verify_email'
122
tc.formvalue(reg_form_name, 'token', token)
125
tc.notfind('<strong>Warning:</strong> <span>Your permissions have been '
126
'limited until you <a href="/verify_email">verify your email'
127
' address</a></span>')
128
tc.find('Thank you for verifying your email address')
129
self._tester.go_to_front()
132
class PasswdResetsNotifiesAdmin(FunctionalTestCaseSetup):
134
"""User password resets notifies admin by mail"""
135
self._tester.logout()
136
self._smtpd.full_reset() # Clean all previous sent emails
141
# Do we have the Forgot passwd link
142
tc.find('Forgot your password?')
143
tc.follow('Forgot your password?')
146
email_addr = "foo@testenv%s.tld" % self._testenv.port
148
reset_form_name = 'acctmgr_passwd_reset'
149
tc.formvalue(reset_form_name, 'username', username)
150
tc.formvalue(reset_form_name, 'email', email_addr)
153
headers, body = parse_smtp_message(
154
self._smtpd.get_message('admin@testenv%s.tld' % self._testenv.port))
155
self.assertEqual(headers['Subject'],
156
'[%s] Password reset for user: %s' % (
157
'testenv%s' % self._testenv.port,
159
self.assertEqual(headers['X-URL'], self._testenv.url)
162
class PasswdResetsNotifiesUser(FunctionalTestCaseSetup):
164
"""Password reset sends new password to user by mail"""
166
email_addr = "foo@testenv%s.tld" % self._testenv.port
167
headers, self.body = parse_smtp_message(self._smtpd.get_message(email_addr))
168
self.assertEqual(headers['Subject'],
169
'[%s] Trac password reset for user: %s' % (
170
'testenv%s' % self._testenv.port,
173
class UserLoginWithMailedPassword(PasswdResetsNotifiesUser):
175
"""User is able to login with the new password"""
176
PasswdResetsNotifiesUser.runTest(self)
177
# Does it include a new password
178
body = base64.decodestring(self.body)
180
self.assertTrue('Username: %s' % username in body)
181
self.assertTrue('Password:' in body)
183
passwd = [l.split(':')[1].strip() for l in
184
body.splitlines() if 'Password:' in l][0]
186
self._tester.login(username, passwd)
188
class UserIsForcedToChangePassword(FunctionalTestCaseSetup):
190
"""User is forced to change password after resets"""
192
tc.find("You are required to change password because of a recent "
193
"password change request.")
196
class UserCantBrowseUntilPasswdChange(PasswdResetsNotifiesUser):
198
"""User can't navigate out of '/prefs/account' before password change"""
199
PasswdResetsNotifiesUser.runTest(self)
201
forced_passwd_change_url = '^%s/prefs/account$' % self._tester.url
203
tc.url(forced_passwd_change_url)
204
tc.follow('View Tickets')
205
tc.url(forced_passwd_change_url)
206
tc.follow('New Ticket')
207
tc.url(forced_passwd_change_url)
208
tc.follow('Browse Source')
209
tc.url(forced_passwd_change_url)
211
# Now, let's change his password
212
body = base64.decodestring(self.body)
213
passwd = [l.split(':')[1].strip() for l in
214
body.splitlines() if 'Password:' in l][0]
216
change_passwd_form = 'userprefs'
217
tc.formvalue(change_passwd_form, 'old_password', passwd)
218
tc.formvalue(change_passwd_form, 'password', username)
219
tc.formvalue(change_passwd_form, 'password_confirm', username)
222
tc.notfind("You are required to change password because of a recent "
223
"password change request.")
224
tc.find("Thank you for taking the time to update your password.")
226
# We can now browse away from /prefs/accounts
228
tc.url(self._tester.url + '/roadmap')
229
# Clear the mailstore
230
self._smtpd.full_reset()
232
class DeleteAccountNotifiesAdmin(FunctionalTestCaseSetup):
234
"""Delete account notifies admin"""
235
tc.find("Logout") # We're logged-in from previous post
236
tc.follow("Preferences")
238
tc.url(self._testenv.url + '/prefs/account')
240
delete_account_form_name = 'acctmgr_delete_account'
241
tc.formvalue(delete_account_form_name, 'password', 'foo')
243
tc.find("Login") # We're logged out when we delete our account
244
headers, _ = parse_smtp_message(self._smtpd.get_message())
245
self.assertEqual(headers['Subject'],
246
'[%s] Deleted User: %s' % (
247
'testenv%s' % self._testenv.port, 'foo'))
249
class UserNoLongerLogins(FunctionalTestCaseSetup):
251
"""Deleted user can't login"""
253
login_form_name = 'acctmgr_loginform'
254
tc.formvalue(login_form_name, 'user', 'foo')
255
tc.formvalue(login_form_name, 'password', 'foo')
257
tc.find("Invalid username or password")
260
class UserIsAbleToRegisterWithSameUserName(FunctionalTestCaseSetup):
262
"""Register with deleted username (session and session_attributes clean)"""
263
self._tester.register('foo')
264
self._tester.login('foo')
265
self._tester.logout()
266
self._smtpd.full_reset()
268
class NoEmailVerificationForAnonymousUsers(FunctionalTestCaseSetup):
270
"""Anonymous users don't get their email address verified"""
272
tc.follow("Preferences")
273
form_name = 'userprefs'
274
email_address = 'anonyous.user@fakedomain.tld'
275
tc.formvalue(form_name, 'email', email_address)
277
tc.notfind('<strong>Notice:</strong> <span>An email has been sent to '
278
'%s with a token to <a href="/verify_email">verify your new '
279
'email address</a></span>' % email_address)
280
self._tester.go_to_front()
281
tc.notfind('<strong>Warning:</strong> <span>Your permissions have been '
282
'limited until you <a href="/verify_email">verify your email '
283
'address</a></span>')
287
suite = FunctionalTestSuite()
288
suite.addTest(TestFormLoginAdmin())
289
suite.addTest(TestFormLoginUser())
290
suite.addTest(TestRegisterNewUser())
291
suite.addTest(TestLoginNewUser())
292
suite.addTest(TestFailRegisterPasswdConfirmNotPassed())
293
suite.addTest(TestFailRegisterDuplicateUsername())
294
suite.addTest(TestNewAccountNotification())
295
suite.addTest(TestNewAccountEmailVerification())
296
suite.addTest(VerifyNewAccountEmailAddress())
297
suite.addTest(PasswdResetsNotifiesAdmin())
298
suite.addTest(PasswdResetsNotifiesUser())
299
suite.addTest(UserLoginWithMailedPassword())
300
suite.addTest(UserIsForcedToChangePassword())
301
suite.addTest(UserCantBrowseUntilPasswdChange())
302
suite.addTest(DeleteAccountNotifiesAdmin())
303
suite.addTest(UserNoLongerLogins())
304
suite.addTest(UserIsAbleToRegisterWithSameUserName())
305
suite.addTest(NoEmailVerificationForAnonymousUsers())
309
if __name__ == '__main__':
310
unittest.main(defaultTest='suite')