''' 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'), ]) @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 == {} 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 # 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(app_config): ''' 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 == {} 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 def test_reset_password_form_processing_cancel(): ''' 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)