import pytest from pluggy import HookimplMarker from flaskbb.auth.services.registration import RegistrationService from flaskbb.core.auth.registration import (RegistrationFailureHandler, RegistrationPostProcessor, UserRegistrationInfo, UserValidator) from flaskbb.core.exceptions import (PersistenceError, StopValidation, ValidationError) from flaskbb.user.models import User pytestmark = pytest.mark.usefixtures('default_settings') class RaisingValidator(UserValidator): def validate(self, user_info): raise ValidationError('username', 'nope') class TestRegistrationService(object): fred = UserRegistrationInfo( username='Fred', password='Fred', email='fred@fred.com', language='fred', group=4 ) def test_raises_stop_validation_if_validators_fail( self, plugin_manager, database ): service = self._get_service(plugin_manager, database) plugin_manager.register(self.impls(validator=RaisingValidator())) with pytest.raises(StopValidation) as excinfo: service.register(self.fred) assert ('username', 'nope') in excinfo.value.reasons def test_calls_failure_handlers_if_validation_fails( self, plugin_manager, database, mocker ): service = self._get_service(plugin_manager, database) failure = mocker.MagicMock(spec=RegistrationFailureHandler) plugin_manager.register( self.impls(validator=RaisingValidator(), failure=failure) ) with pytest.raises(StopValidation) as excinfo: service.register(self.fred) failure.assert_called_once_with(self.fred, excinfo.value.reasons) def test_registers_user_if_everything_is_good( self, database, plugin_manager ): service = self._get_service(plugin_manager, database) service.register(self.fred) actual_fred = User.query.filter(User.username == 'Fred').one() assert actual_fred.id is not None def test_calls_post_processors_if_user_registration_works( self, database, plugin_manager, mocker ): service = self._get_service(plugin_manager, database) post_process = mocker.MagicMock(spec=RegistrationPostProcessor) plugin_manager.register(self.impls(post_process=post_process)) fred = service.register(self.fred) post_process.assert_called_once_with(fred) def test_raises_persistenceerror_if_saving_user_goes_wrong( self, database, plugin_manager, Fred ): service = self._get_service(plugin_manager, database) with pytest.raises(PersistenceError): service.register(self.fred) @staticmethod def _get_service(plugin_manager, db): return RegistrationService(plugins=plugin_manager, users=User, db=db) @staticmethod def impls(validator=None, failure=None, post_process=None): impl = HookimplMarker('flaskbb') class Impls: if validator is not None: @impl def flaskbb_gather_registration_validators(self): return [validator] if failure is not None: @impl def flaskbb_registration_failure_handler( self, user_info, failures ): failure(user_info, failures) if post_process is not None: @impl def flaskbb_registration_post_processor(self, user): post_process(user) return Impls()