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()