You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
559 lines
18 KiB
559 lines
18 KiB
''' Tests for ordr2.views.account ''' |
|
|
|
import deform |
|
import pytest |
|
|
|
from pyramid.httpexceptions import HTTPFound |
|
from pyramid.testing import DummyRequest, DummyResource |
|
from pyramid_mailer import get_mailer |
|
from webob.multidict import MultiDict |
|
|
|
from .. import app_config, dbsession, get_user, create_users, set_deform_data |
|
|
|
|
|
REGISTRATION_FORM_DATA = MultiDict([ |
|
('username', 'AmyMcDonald'), |
|
('first_name', 'Amy'), |
|
('last_name', 'McDonald'), |
|
('email', 'mcdonald@example.com'), |
|
('__start__', 'password:mapping'), |
|
('password', 'Amy'), |
|
('password-confirm', 'Amy'), |
|
('__end__', 'password:mapping'), |
|
]) |
|
|
|
PASSWORD_RESET_FORM_DATA = MultiDict([ |
|
('__start__', 'password:mapping'), |
|
('password', 'Nudge'), |
|
('password-confirm', 'Nudge'), |
|
('__end__', 'password:mapping'), |
|
]) |
|
|
|
SETTINGS_FORM_DATA = MultiDict([ |
|
('__start__', 'general:mapping'), |
|
('username', 'TerryGilliam'), |
|
('first_name', 'Terry'), |
|
('last_name', 'Gilliam'), |
|
('email', 'gilliam@example.com'), |
|
('role', 'USER'), |
|
('__end__', 'general:mapping'), |
|
('__start__', 'change_password:mapping'), |
|
('__start__', 'new_password:mapping'), |
|
('new_password', 'Amy'), |
|
('new_password-confirm', 'Amy'), |
|
('__end__', 'new_password:mapping'), |
|
('__end__', 'change_password:mapping'), |
|
('__start__', 'confirm_changes:mapping'), |
|
('password', 'Terry'), |
|
('__end__', 'confirm_changes:mapping') |
|
]) |
|
|
|
|
|
|
|
@pytest.mark.parametrize('rolename', ['user', 'purchaser', 'admin']) |
|
def test_account_login_active_users(dbsession, rolename): |
|
''' login ok for active users ''' |
|
from ordr2.views.account import login |
|
create_users(dbsession) |
|
|
|
user = get_user(rolename) |
|
request = DummyRequest( |
|
dbsession=dbsession, |
|
post={ |
|
'username': user.username, |
|
'password': user.first_name |
|
} |
|
) |
|
result = login(None, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com//orders' |
|
|
|
|
|
@pytest.mark.parametrize('rolename', ['unvalidated', 'new', 'inactive']) |
|
def test_account_login_fails_inactive_users(dbsession, rolename): |
|
''' login fails for inactive users ''' |
|
from ordr2.views.account import login |
|
create_users(dbsession) |
|
|
|
user = get_user(rolename) |
|
request = DummyRequest( |
|
dbsession=dbsession, |
|
post={ |
|
'username': user.username, |
|
'password': user.first_name |
|
} |
|
) |
|
result = login(None, request) |
|
|
|
assert result == {} |
|
|
|
|
|
@pytest.mark.parametrize( |
|
'username, password', [ |
|
('EricIdle', 'wrong password'), |
|
('unknown user', 'Eric'), |
|
('unknown user', 'wrong password'), |
|
('', '') |
|
] |
|
) |
|
def test_account_login_fails_wrong_credentials(dbsession, username, password): |
|
''' login fails for unknown or wrong credentials ''' |
|
from ordr2.views.account import login |
|
create_users(dbsession) |
|
|
|
request = DummyRequest( |
|
dbsession=dbsession, |
|
post={ |
|
'username': username, |
|
'password': password |
|
} |
|
) |
|
result = login(None, request) |
|
|
|
assert result == {} |
|
assert request.session.pop_flash('error') == [ |
|
'You entered the wrong username or password' |
|
] |
|
|
|
|
|
|
|
def test_logout(app_config): |
|
''' logout works ''' |
|
from ordr2.views.account import logout |
|
user = get_user('admin') |
|
|
|
request = DummyRequest(user=user) |
|
result = logout(None, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com//' |
|
|
|
|
|
# tests for the registration form |
|
|
|
def test_registration_form(app_config): |
|
''' registration form ''' |
|
from ordr2.views.account import registration_form |
|
|
|
request = DummyRequest() |
|
context = DummyResource() |
|
result = registration_form(context, request) |
|
|
|
assert isinstance(result['form'], deform.Form) |
|
|
|
|
|
def test_registration_form_processing_ok(dbsession): |
|
''' registration form processing with valid data''' |
|
from ordr2.models.account import User, Role, TokenSubject |
|
from ordr2.views.account import registration_form_processing |
|
|
|
user = get_user('user') # intentionally not added to database |
|
context = DummyResource(model=user) |
|
request = DummyRequest(dbsession=dbsession, context=context) |
|
set_deform_data(request, REGISTRATION_FORM_DATA) |
|
result = registration_form_processing(context, request) |
|
|
|
# return value of function call |
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com/registered' |
|
|
|
# user should be added to database |
|
user = dbsession.query(User).first() |
|
assert user.username == REGISTRATION_FORM_DATA['username'] |
|
assert user.first_name == REGISTRATION_FORM_DATA['first_name'] |
|
assert user.last_name == REGISTRATION_FORM_DATA['last_name'] |
|
assert user.email == REGISTRATION_FORM_DATA['email'] |
|
assert user.check_password(REGISTRATION_FORM_DATA['password']) |
|
assert user.role == Role.UNVALIDATED |
|
|
|
# a token should be created |
|
token = user.tokens[0] |
|
assert token.subject == TokenSubject.USER_REGISTRATION |
|
|
|
# warning about a short password |
|
assert request.session.pop_flash('warning') == [ |
|
'You should really consider a longer password' |
|
] |
|
|
|
# and a verification email should be sent |
|
# this is tested in the functional test since request.registry.notify |
|
# doesn't know about event subscribers in the unittest |
|
|
|
|
|
def test_registration_form_processing_cancel(dbsession): |
|
''' canceling registration form processing ''' |
|
from ordr2.models.account import User, Role, TokenSubject |
|
from ordr2.views.account import registration_form_processing |
|
|
|
user = get_user('user') # intentionally not added to database |
|
context = DummyResource(model=user) |
|
request = DummyRequest(dbsession=dbsession, context=context) |
|
set_deform_data(request, REGISTRATION_FORM_DATA, {'Cancel': 'Cancel'}) |
|
result = registration_form_processing(context, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com//' |
|
|
|
|
|
@pytest.mark.parametrize( |
|
'key,value', [ |
|
('username', ''), |
|
('username', 'TerryGilliam'), |
|
('first_name', ''), |
|
('last_name', ''), |
|
('email', ''), |
|
('email', 'no email'), |
|
('email', 'gilliam@example.com'), |
|
('password', ''), |
|
('password-confirm', ''), |
|
('password-confirm', 'no match') |
|
] |
|
) |
|
def test_registration_form_processing_validation_error(dbsession, key, value): |
|
''' registration form processing with valid data''' |
|
from ordr2.models.account import User, Role, TokenSubject |
|
from ordr2.views.account import registration_form_processing |
|
|
|
admin = get_user('user') |
|
dbsession.add(admin) |
|
context = DummyResource(model=get_user('admin')) |
|
request = DummyRequest(dbsession=dbsession, context=context) |
|
set_deform_data(request, REGISTRATION_FORM_DATA, {key: value}) |
|
result = registration_form_processing(context, request) |
|
|
|
assert isinstance(result['form'], deform.Form) |
|
|
|
|
|
def test_registration_confirmation(): |
|
''' registration, awaiting confirmation of email address ''' |
|
from ordr2.views.account import registration_confirmation |
|
|
|
result = registration_confirmation(None, None) |
|
|
|
assert result == {} |
|
|
|
|
|
def test_registration_completed(dbsession): |
|
''' registration, confirmation of email address successful ''' |
|
from ordr2.models.account import User, Role, Token, TokenSubject |
|
from ordr2.views.account import registration_completed |
|
|
|
request = DummyRequest(dbsession=dbsession) |
|
user = get_user('unvalidated') |
|
user.issue_token(request, TokenSubject.USER_REGISTRATION) |
|
dbsession.add(user) |
|
dbsession.flush() |
|
token = user.tokens[0] |
|
context = DummyResource(model=token) |
|
result = registration_completed(context, request) |
|
|
|
assert result == {} |
|
assert user.role == Role.NEW |
|
assert dbsession.query(Token).count() == 0 |
|
assert dbsession.query(User).count() == 1 |
|
|
|
|
|
# tests for password reset |
|
|
|
def test_forgot_password_form(): |
|
''' display the forgot password form ''' |
|
from ordr2.views.account import forgot_password_form |
|
|
|
result = forgot_password_form(None, None) |
|
|
|
assert result == {} |
|
|
|
|
|
@pytest.mark.parametrize('who', ['TerryGilliam', 'gilliam@example.com']) |
|
def test_forgot_password_form_processing_ok(dbsession, who): |
|
''' process the forgot password form ''' |
|
from ordr2.views.account import forgot_password_form_processing |
|
|
|
dbsession.add(get_user('user')) |
|
request = DummyRequest( |
|
dbsession=dbsession, |
|
POST={'username_or_email': who} |
|
) |
|
result = forgot_password_form_processing(None, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com//forgot-password-email' |
|
|
|
|
|
def test_forgot_password_form_processing_cancel(dbsession): |
|
''' forgot password form was canceled ''' |
|
from ordr2.views.account import forgot_password_form_processing |
|
|
|
dbsession.add(get_user('user')) |
|
request = DummyRequest( |
|
dbsession=dbsession, |
|
POST={'username_or_email': 'gilliam@example.com', 'cancel': 'Cancel'} |
|
) |
|
result = forgot_password_form_processing(None, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com//' |
|
|
|
|
|
@pytest.mark.parametrize( |
|
'who', |
|
['unknown user', 'unknown@example.com', ''] |
|
) |
|
def test_forgot_password_form_processing_error(dbsession, who): |
|
''' process the forgot password form ''' |
|
from ordr2.views.account import forgot_password_form_processing |
|
|
|
dbsession.add(get_user('user')) |
|
request = DummyRequest( |
|
dbsession=dbsession, |
|
POST = {'username_or_email': who} |
|
) |
|
result = forgot_password_form_processing(None, request) |
|
|
|
assert result == {} |
|
assert request.session.pop_flash('error') == [ |
|
'Username or email address unknown' |
|
] |
|
|
|
|
|
def test_forgot_password_email_sent(): |
|
''' message that a password reset link was sent ''' |
|
from ordr2.views.account import forgot_password_email_sent |
|
|
|
result = forgot_password_email_sent(None, None) |
|
|
|
assert result == {} |
|
|
|
|
|
def test_reset_password_form(): |
|
''' reset password form display ''' |
|
from ordr2.views.account import reset_password_form |
|
|
|
request = DummyRequest() |
|
result = reset_password_form(None, request) |
|
|
|
assert isinstance(result['form'], deform.Form) |
|
|
|
|
|
def test_reset_password_form_processing_ok(dbsession): |
|
''' reset password form processing is ok ''' |
|
from ordr2.models.account import Token, TokenSubject, User |
|
from ordr2.views.account import reset_password_form_processing |
|
|
|
request = DummyRequest(dbsession=dbsession) |
|
set_deform_data(request, REGISTRATION_FORM_DATA) |
|
account = get_user('user') |
|
token = account.issue_token(request, TokenSubject.RESET_PASSWORD) |
|
dbsession.add(account) |
|
dbsession.flush() |
|
context = DummyResource(model=token) |
|
result = reset_password_form_processing(context, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com//login' |
|
assert account.check_password(REGISTRATION_FORM_DATA['password']) |
|
assert dbsession.query(Token).count() == 0 |
|
assert dbsession.query(User).count() == 1 |
|
assert request.session.pop_flash('warning') == [ |
|
'You should really consider a longer password' |
|
] |
|
assert request.session.pop_flash('success') == [ |
|
'Your password was changed' |
|
] |
|
|
|
|
|
def test_reset_password_form_processing_cancel(dbsession): |
|
''' reset password form processing is canceled ''' |
|
from ordr2.views.account import reset_password_form_processing |
|
|
|
request = DummyRequest(dbsession=dbsession, POST={'Cancel': 'cancel'}) |
|
result = reset_password_form_processing(None, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com//' |
|
|
|
|
|
@pytest.mark.parametrize( |
|
'pw, confirm', [ |
|
('', ''), |
|
('no', 'match'), |
|
('one is empty', ''), |
|
('', 'one is empty'), |
|
] |
|
) |
|
def test_reset_password_form_processing_invalid(pw, confirm): |
|
''' validation error in reset password form ''' |
|
from ordr2.views.account import reset_password_form_processing |
|
|
|
request = DummyRequest(dbsession=dbsession) |
|
modifier = {'password': pw, 'password-confim': confirm} |
|
set_deform_data(request, REGISTRATION_FORM_DATA, modifier) |
|
result = reset_password_form_processing(None, request) |
|
|
|
assert isinstance(result['form'], deform.Form) |
|
|
|
|
|
# settings |
|
|
|
def test_settings_form(dbsession): |
|
''' settings form display ''' |
|
from ordr2.views.account import settings_form |
|
|
|
user = get_user('user') |
|
context = DummyResource(model=user) |
|
request = DummyRequest() |
|
result = settings_form(context, request) |
|
|
|
assert isinstance(result['form'], deform.Form) |
|
|
|
|
|
def test_settings_form_processing_cancel(dbsession): |
|
''' settings form processing is canceled ''' |
|
from ordr2.views.account import settings_form_processing |
|
|
|
user = get_user('user') |
|
context = DummyResource(model=user) |
|
request = DummyRequest(dbsession=dbsession, POST={'Cancel': 'cancel'}) |
|
result = settings_form_processing(None, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com//' |
|
|
|
|
|
def test_settings_form_processing_change_name(dbsession): |
|
''' settings form processing change name only ''' |
|
from ordr2.views.account import settings_form_processing |
|
|
|
user = get_user('user') |
|
dbsession.add(user) |
|
context = DummyResource(model=user) |
|
request = DummyRequest(dbsession=dbsession, user=user, context=context) |
|
changes = { |
|
'username': 'AmyMcDonald', |
|
'first_name': 'Amy', |
|
'last_name': 'McDonald', |
|
'role': 'ADMIN', |
|
'new_password': '', |
|
'new_password-confirm': '', |
|
} |
|
set_deform_data(request, SETTINGS_FORM_DATA, changes) |
|
result = settings_form_processing(context, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com//' |
|
assert user.username == 'TerryGilliam' |
|
assert user.first_name == 'Amy' |
|
assert user.last_name == 'McDonald' |
|
assert user.email == 'gilliam@example.com' |
|
assert user.check_password('Terry') |
|
|
|
|
|
def test_settings_form_processing_change_password(dbsession): |
|
''' settings form processing change name only ''' |
|
from ordr2.views.account import settings_form_processing |
|
|
|
user = get_user('user') |
|
context = DummyResource(model=user) |
|
request = DummyRequest(dbsession=dbsession, user=user, context=context) |
|
changes = { |
|
'new_password': 'Amy', |
|
'new_password-confirm': 'Amy', |
|
} |
|
set_deform_data(request, SETTINGS_FORM_DATA, changes) |
|
result = settings_form_processing(context, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com//' |
|
assert user.check_password('Amy') |
|
assert request.session.pop_flash('warning') == [ |
|
'You should really consider a longer password' |
|
] |
|
assert request.session.pop_flash('success') == [ |
|
'Password updated sucessfully' |
|
] |
|
|
|
|
|
def test_settings_change_email(dbsession): |
|
''' settings form processing change name only ''' |
|
from ordr2.views.account import settings_form_processing |
|
from ordr2.models.account import TokenSubject |
|
|
|
user = get_user('user') |
|
dbsession.add(user) |
|
context = DummyResource(model=user) |
|
request = DummyRequest(dbsession=dbsession, user=user, context=context) |
|
changes = { |
|
'email': 'amy@example.com', |
|
} |
|
set_deform_data(request, SETTINGS_FORM_DATA, changes) |
|
result = settings_form_processing(context, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com/verify-new-email' |
|
token = user.tokens[0] |
|
assert token.subject == TokenSubject.CHANGE_EMAIL |
|
assert token.payload == {'new_email': 'amy@example.com'} |
|
assert user.email == 'gilliam@example.com' |
|
|
|
|
|
@pytest.mark.parametrize( |
|
'key, value', [ |
|
('first_name', ''), |
|
('last_name', ''), |
|
('email', ''), |
|
('email', 'not an email address'), |
|
('email', 'jones@example.com'), |
|
('password', ''), |
|
('password', 'wrong password'), |
|
] |
|
) |
|
def test_settings_form_processing_validation_error(dbsession, key, value): |
|
''' settings form processing with validation error ''' |
|
from ordr2.views.account import settings_form_processing |
|
|
|
admin = get_user('admin') |
|
user = get_user('user') |
|
dbsession.add(admin) |
|
dbsession.add(user) |
|
context = DummyResource(model=user) |
|
request = DummyRequest(dbsession=dbsession, user=user, context=context) |
|
set_deform_data(request, SETTINGS_FORM_DATA, {key: value}) |
|
result = settings_form_processing(context, request) |
|
|
|
assert isinstance(result['form'], deform.Form) |
|
|
|
|
|
def test_email_confirmation(): |
|
''' awaiting confirmation of new email address ''' |
|
from ordr2.views.account import email_confirmation |
|
|
|
result = email_confirmation(None, None) |
|
|
|
assert result == {} |
|
|
|
|
|
def test_email_change_confirmed(dbsession): |
|
''' new email address is verified ''' |
|
from ordr2.views.account import email_change_confirmed |
|
from ordr2.models.account import User, Token, TokenSubject |
|
|
|
|
|
user = get_user('user') |
|
token = user.issue_token( |
|
DummyRequest(dbsession=dbsession), |
|
TokenSubject.CHANGE_EMAIL, |
|
{'new_email': 'amy@example.com'} |
|
) |
|
dbsession.add(user) |
|
dbsession.flush() |
|
context = DummyResource(model=token) |
|
request = DummyRequest(dbsession=dbsession, context=context) |
|
|
|
result = email_change_confirmed(context, request) |
|
|
|
assert isinstance(result, HTTPFound) |
|
assert result.location == 'http://example.com//' |
|
assert user.email == 'amy@example.com' |
|
assert dbsession.query(Token).count() == 0 |
|
assert request.session.pop_flash('success') == ['Email change sucessful']
|
|
|