def test_set_new_password(party_account_fixture): fixture = party_account_fixture system_account = fixture.system_account new_password_request = NewPasswordRequest(system_account=system_account) Session.add(new_password_request) new_password = system_account.password * 2 account_management_interface = AccountManagementInterface() Session.add(account_management_interface) # Case: the key is invalid invalid_key = 'in va lid key which is also too long and contains spaces' account_management_interface.email = system_account.email account_management_interface.secret = invalid_key account_management_interface.password = new_password with expected(KeyException): account_management_interface.choose_new_password() # Case: the email is invalid invalid_email = 'i am not a valid email' account_management_interface.email = invalid_email account_management_interface.secret = new_password_request.as_secret_key() account_management_interface.password = new_password with expected(InvalidEmailException): account_management_interface.choose_new_password() # Case: the key is valid account_management_interface.email = system_account.email account_management_interface.secret = new_password_request.as_secret_key() account_management_interface.password = new_password account_management_interface.choose_new_password() system_account.authenticate(new_password) # Should not raise exception
def test_send_activation_mail(reahl_system_fixture, party_account_fixture): fixture = party_account_fixture system_account = fixture.new_system_account(email='*****@*****.**', activated=False) activation_request = VerifyEmailRequest( email=system_account.email, subject_config='accounts.activation_subject', email_config='accounts.activation_email') Session.add(activation_request) activation_action = ActivateAccount(system_account=system_account, requirements=[activation_request]) Session.add(activation_action) mailer_stub = fixture.mailer fixture.account_management_interface.email = system_account.email fixture.account_management_interface.password = system_account.password # Case: the first send fixture.account_management_interface.send_activation_notification() assert mailer_stub.mail_recipients == [system_account.email] assert mailer_stub.mail_sender == reahl_system_fixture.config.accounts.admin_email substitutions = { 'email': system_account.email, 'secret_key': activation_request.as_secret_key() } expected_subject = Template( reahl_system_fixture.config.accounts.activation_subject).substitute( substitutions) assert mailer_stub.mail_subject == expected_subject expected_message = Template( reahl_system_fixture.config.accounts.activation_email).substitute( substitutions) assert mailer_stub.mail_message == expected_message
def test_expire_stale_requests(reahl_system_fixture, party_account_fixture): fixture = party_account_fixture old_email = '*****@*****.**' recent_email = '*****@*****.**' password = '******' mailer_stub = fixture.mailer EmailAndPasswordSystemAccount.mailer = mailer_stub longago = datetime.now() - timedelta( reahl_system_fixture.config.accounts.request_verification_timeout) old_account_management_interface = AccountManagementInterface() old_account_management_interface.email = old_email old_account_management_interface.password = password old_account_management_interface.register() old_system_account = EmailAndPasswordSystemAccount.by_email(old_email) old_activation_request = Session.query(VerifyEmailRequest).one() old_activation_request.deferred_actions[0].deadline = longago new_account_management_interface = AccountManagementInterface() new_account_management_interface.email = recent_email new_account_management_interface.password = password new_account_management_interface.register() recent_system_account = EmailAndPasswordSystemAccount.by_email( recent_email) ReahlEgg.do_daily_maintenance_for_egg('reahl-domain') assert Session.query(EmailAndPasswordSystemAccount).filter_by( id=old_system_account.id).count() == 0 assert Session.query(EmailAndPasswordSystemAccount).filter_by( id=recent_system_account.id).count() == 1
def get_or_create_domain_object(self): domain_objects = Session.query(MyDomainObject).all() if len(domain_objects) == 0: domain_object = MyDomainObject() Session.add(domain_object) return domain_object return domain_objects[0]
def test_reahl_additions(): ExecutionContext().install() try: metadata.bind = 'sqlite:///:memory:' metadata.create_all() address = Address() Session.add(address) email_field = address.fields.email_address # While a programmer would not usually write code like this, # it is useful to show how the framework can use Fields and Events # to obtain more information about a certain Field/Event: assert email_field.label == 'Email' # Fields are used (amongst other things) to validate user input: with expected(Exception): email_field.from_input('invalid email address') with expected(NoException): assert address.email_address == None email_field.from_input('*****@*****.**') assert address.email_address == '*****@*****.**' # After input was given, the field is set on the object it belongs to: # (The value set is a marshalled version of the user input. In this case it is just # a string again, but it could have been, for example an EmailAddress object, # and Integer, or a Date.) assert address.email_address == '*****@*****.**' finally: metadata.bind = None
def test_cascade_removal_of_user_session(sql_alchemy_fixture, session_scoped_fixture): """ If a user session is deleted, all session scoped objects are deleted as well. """ fixture = session_scoped_fixture @session_scoped class MySessionScoped(Base): __tablename__ = 'my_session_scoped' id = Column(Integer, primary_key=True) with sql_alchemy_fixture.persistent_test_classes(MySessionScoped): user_session = fixture.create_user_session() assert Session.query(MySessionScoped).count() == 0 session_object = MySessionScoped.for_current_session() assert Session.query(MySessionScoped).one() is session_object assert session_object.user_session is user_session if fixture.cascade: Session.delete(user_session) else: Session.delete(session_object) Session.flush() assert Session.query(MySessionScoped).count() == 0 assert Session.query( UserSession).count() == fixture.expected_user_session_after_delete
def save_for(cls, view, form=None, **kwargs): assert (not form) or (form.view is view) channel_name = form.channel_name if form else None web_session = ExecutionContext.get_context().session instance = cls(web_session=web_session, view_path=view.full_path, ui_name=view.user_interface.name, channel_name=channel_name, **kwargs) Session.add(instance) return instance
def test_input_validation_cues_javascript_interaction(web_fixture, sql_alchemy_fixture, javascript_validation_scenario): """The visual cues rendered server-side can subsequently be manipulated via javascript.""" fixture = javascript_validation_scenario web_fixture.reahl_server.set_app(web_fixture.new_wsgi_app(child_factory=fixture.Form.factory(), enable_js=False)) browser = fixture.browser with sql_alchemy_fixture.persistent_test_classes(fixture.ModelObject): fixture.domain_object = fixture.ModelObject() Session.add(fixture.domain_object) browser.open('/') browser.type(XPath.input_labelled('Some input'), '') browser.click(XPath.button_labelled('Submit')) assert ['is-invalid'] == fixture.get_form_group_highlight_marks(browser, index=0) [error] = fixture.get_form_group_errors(browser, index=0) assert error.text == 'Some input is required' web_fixture.reahl_server.set_app(web_fixture.new_wsgi_app(child_factory=fixture.Form.factory(), enable_js=True)) browser.open('/') browser.click(XPath.button_labelled('Submit')) assert ['is-invalid'] == fixture.get_form_group_highlight_marks(browser, index=0) [error] = fixture.get_form_group_errors(browser, index=0) assert error.text == 'Some input is required' browser.type(XPath.input_labelled('Some input'), 'valid value', trigger_blur=False, wait_for_ajax=False) browser.press_tab() def form_group_is_marked_success(index): return ['is-valid'] == fixture.get_form_group_highlight_marks(browser, index=index) assert web_fixture.driver_browser.wait_for(form_group_is_marked_success, 0) assert not fixture.get_form_group_errors(browser, index=0)
def test_input_validation_cues(sql_alchemy_fixture, validation_scenarios): """Visible cues are inserted to indicate the current validation state and possible validation error messages to a user. """ fixture = validation_scenarios browser = fixture.browser with sql_alchemy_fixture.persistent_test_classes(fixture.ModelObject): fixture.domain_object = fixture.ModelObject() Session.add(fixture.domain_object) browser.open('/') assert not fixture.get_form_group_highlight_marks(browser, index=0) assert not fixture.get_form_group_errors(browser, index=0) browser.type(XPath.input_labelled('Some input'), '') browser.click(XPath.button_labelled('Submit')) assert ['is-invalid' ] == fixture.get_form_group_highlight_marks(browser, index=0) [error] = fixture.get_form_group_errors(browser, index=0) assert error.text == 'Some input is required' browser.type(XPath.input_labelled('Some input'), 'valid value') browser.click(XPath.button_labelled('Submit')) assert ['is-valid'] == fixture.get_form_group_highlight_marks(browser, index=0) assert not fixture.get_form_group_errors(browser, index=0) browser.type(XPath.input_labelled('Another input'), 'valid value') browser.click(XPath.button_labelled('Submit')) assert not fixture.get_form_group_highlight_marks(browser, index=0) assert not fixture.get_form_group_errors(browser, index=0)
def test_verify_from_menu(web_fixture, party_account_fixture, accounts_web_fixture): fixture = accounts_web_fixture account = party_account_fixture.new_system_account(activated=False) activation_request = VerifyEmailRequest( email=account.email, subject_config='accounts.activation_subject', email_config='accounts.activation_email') Session.add(activation_request) deferred_activation = ActivateAccount(system_account=account, requirements=[activation_request]) Session.add(deferred_activation) secret_key = activation_request.as_secret_key() assert not account.status.is_active() fixture.browser.open('/a_ui/verify') fixture.browser.type(XPath.input_labelled('Email'), account.email) fixture.browser.type(XPath.input_labelled('Secret key'), secret_key) fixture.browser.type(XPath.input_labelled('Password'), account.password) fixture.browser.click(XPath.button_labelled('Verify')) assert fixture.browser.current_url.path == '/a_ui/thanks' assert account.status.is_active()
def test_register_help_pending(web_fixture, party_account_fixture, accounts_web_fixture): fixture = accounts_web_fixture verification_requests = Session.query(VerifyEmailRequest) unactivated_account = party_account_fixture.new_system_account( email='*****@*****.**', activated=False) activation_request = VerifyEmailRequest( email=unactivated_account.email, subject_config='accounts.activation_subject', email_config='accounts.activation_email') Session.add(activation_request) deferred_activation = ActivateAccount(system_account=unactivated_account, requirements=[activation_request]) Session.add(deferred_activation) fixture.browser.open('/a_ui/registerHelp') fixture.browser.type(XPath.input_labelled('Email'), unactivated_account.email) fixture.browser.click(XPath.button_labelled('Investigate')) assert fixture.browser.current_url.path == '/a_ui/registerHelp/pending' assert verification_requests.count() == 1 party_account_fixture.mailer.reset() fixture.browser.click(XPath.button_labelled('Send')) assert verification_requests.count() == 1 assert party_account_fixture.mailer.mail_sent assert fixture.browser.current_url.path == '/a_ui/registerHelp/pending/sent'
def test_verify_from_menu(web_fixture, party_account_fixture, accounts_web_fixture): fixture = accounts_web_fixture account = party_account_fixture.new_system_account(activated=False) activation_request = VerifyEmailRequest( email=account.email, subject_config='accounts.activation_subject', email_config='accounts.activation_email') Session.add(activation_request) deferred_activation = ActivateAccount(system_account=account, requirements=[activation_request]) Session.add(deferred_activation) secret_key = activation_request.as_secret_key() assert not account.status.is_active() fixture.browser.open('/a_ui/verify') fixture.browser.type('//form[@id="verify"]//*[@name="verify-email"]', account.email) fixture.browser.type('//form[@id="verify"]//*[@name="verify-secret"]', secret_key) fixture.browser.type('//form[@id="verify"]//*[@name="verify-password"]', account.password) fixture.browser.click('//form[@id="verify"]//*[@value="Verify"]') assert fixture.browser.current_url.path == '/a_ui/thanks' assert account.status.is_active()
def test_request_email_change(reahl_system_fixture, party_account_fixture): fixture = party_account_fixture system_account = fixture.new_system_account(activated=False) mailer_stub = fixture.mailer new_email = '*****@*****.**' account_management_interface = fixture.new_account_management_interface( system_account=system_account) # Case where the user account has not been activated assert isinstance(system_account.status, AccountNotActivated) account_management_interface.new_email = new_email with expected(AccountNotActiveException): account_management_interface.request_email_change() system_account.activate() system_account.disable() # Case where the user account is disabled for another reason assert isinstance(system_account.status, AccountDisabled) account_management_interface.new_email = new_email with expected(AccountNotActiveException): account_management_interface.request_email_change() system_account.enable() # Case where the user account is active and enabled, but a clashing email name is requested other_party = Party() clashing_new_email = '*****@*****.**' clashing_system_account = fixture.new_system_account( party=other_party, email=clashing_new_email, activated=True) account_management_interface.new_email = clashing_new_email with expected(NotUniqueException): account_management_interface.request_email_change() # Case where the user account is active and enabled, and a new unique email name is requested assert Session.query(ChangeAccountEmail).count() == 0 account_management_interface.new_email = new_email account_management_interface.request_email_change() new_email_request = Session.query(ChangeAccountEmail).filter_by( system_account=system_account).one().verify_email_request assert mailer_stub.mail_recipients == [new_email] assert mailer_stub.mail_sender == reahl_system_fixture.config.accounts.admin_email substitutions = { 'email': new_email, 'secret_key': new_email_request.as_secret_key() } expected_subject = Template( reahl_system_fixture.config.accounts.email_change_subject).substitute( substitutions) assert mailer_stub.mail_subject == expected_subject expected_message = Template( reahl_system_fixture.config.accounts.email_change_email).substitute( substitutions) assert mailer_stub.mail_message == expected_message # Case where a email name is requested which matches an already pending one account_management_interface.new_email = new_email with expected(NotUniqueException): account_management_interface.request_email_change()
def test_verify_email_change(party_account_fixture): fixture = party_account_fixture system_account = fixture.system_account new_email = '*****@*****.**' change_email_action = ChangeAccountEmail(system_account, new_email) Session.add(change_email_action) request = change_email_action.verify_email_request account_management_interface = fixture.account_management_interface # Case where there is a password mismatch account_management_interface.email = new_email account_management_interface.password = '******' account_management_interface.secret = request.as_secret_key() with expected(InvalidPasswordException, test=assert_is_set_to_commit): account_management_interface.verify_email() assert system_account.email != new_email # Case where there is a key mismatch account_management_interface.email = new_email account_management_interface.password = system_account.password account_management_interface.secret = 'invalid key' with expected(KeyException): account_management_interface.verify_email() assert system_account.email != new_email # Case where it works assert system_account.email != new_email account_management_interface.email = new_email account_management_interface.password = system_account.password account_management_interface.secret = request.as_secret_key() account_management_interface.verify_email() assert Session.query(VerifyEmailRequest).filter_by( id=request.id).count() == 0 assert system_account.email == new_email
def do_demo_setup(self): Session.add(Address(name='John Doe', email_address='*****@*****.**')) Session.add(Address(name='Jane Johnson', email_address='*****@*****.**')) Session.add(Address(name='Jack Black', email_address='*****@*****.**')) Session.flush() Session.commit()
def test_clear_form_inputs_on_optimistic_concurrency(web_fixture, sql_alchemy_fixture, concurrency_fixture, scenario): """A concurrency error is detected upon submit after an exception. When a user resets inputs upon such a concurrency error, previous form exceptions and input data are cleared. """ fixture = concurrency_fixture with sql_alchemy_fixture.persistent_test_classes(fixture.ModelObject): Session.add(fixture.model_object) wsgi_app = web_fixture.new_wsgi_app( child_factory=fixture.MyForm.factory()) web_fixture.reahl_server.set_app(wsgi_app) browser = web_fixture.driver_browser browser.open('/') # Concurrency error is detected on submit after an exception scenario.cause_exception_on_submit(browser) assert fixture.is_any_error_displayed() assert not fixture.is_concurrency_error_displayed() fixture.make_concurrent_change_in_backend() browser.type(XPath.input_labelled('Some field'), 'valid input') browser.click(XPath.button_labelled('Submit')) assert fixture.is_concurrency_error_displayed() # Previous error and inputs are cleared browser.click(XPath.button_labelled('Reset input')) assert browser.get_value( XPath.input_labelled('Some field')) == 'changed by someone else' assert not fixture.is_any_error_displayed()
def request_new_password(self): self.assert_account_live() existing_requests = Session.query(NewPasswordRequest).filter_by( system_account=self) if existing_requests.count() == 0: Session.add(NewPasswordRequest(system_account=self)) self.send_new_password_mail()
def clear_all_view_data(cls, view): web_session = ExecutionContext.get_context().session items = Session.query(cls).filter_by(web_session=web_session, view_path=view.full_path, ui_name=view.user_interface.name) for stale in items: Session.delete(stale)
def start_transaction(self): if not self.commit: # The tests run in a nested transaction inside a real transaction, and both are rolled back # This is done because finalise_session (real code) is run as part of the test, and it # checks for the nested transaction and behaves differently to make testing possible. # Session.begin() - this happens implicitly Session.begin_nested()
def new_task(self, title=None, queue=None): title = title or 'A task' queue = queue or self.queue task = Task(title=title, queue=queue) Session.add(task) Session.flush() return task
def test_recalculate_on_refresh(web_fixture, query_string_fixture, sql_alchemy_fixture, scenario): """You can make a widget recalculate domain values upon refresh by adding an Event to enable_refresh().""" fixture = scenario with sql_alchemy_fixture.persistent_test_classes(fixture.ModelObject): Session.add(fixture.model_object) wsgi_app = web_fixture.new_wsgi_app(enable_js=True, child_factory=scenario.MainWidgetWithPersistentModelObject.factory()) web_fixture.reahl_server.set_app(wsgi_app) browser = web_fixture.driver_browser browser.open('/') assert browser.wait_for(query_string_fixture.is_state_now, 1) scenario.check_widget_value(browser, 10) browser.type(XPath.input_labelled('Choice'), '2') # Case: values are recalculated after ajax assert browser.wait_for(query_string_fixture.is_state_now, 2) scenario.check_widget_value(browser, 20) # Case: values stay recalculated after submit with exception browser.click(XPath.button_labelled('submit')) assert browser.is_element_present(XPath.paragraph().including_text('An exception happened on submit')) scenario.check_widget_value(browser, 20)
def test_login_queries(party_account_fixture, web_fixture): """""" context = ExecutionContext.get_context() config = context.config user_session = context.session login_session = LoginSession.for_session(context.session) system_account = party_account_fixture.system_account web_fixture.request.scheme = 'https' context.request.cookies[ config.web.secure_key_name] = user_session.secure_salt assert config.web.idle_secure_lifetime < config.web.idle_lifetime assert config.web.idle_lifetime < config.web.idle_lifetime_max # Case: user logs in user_session.last_activity = None login_session.set_as_logged_in(system_account, False) assert login_session.is_logged_in() assert login_session.is_logged_in(secured=True) # Case: user logs out login_session.log_out() assert not login_session.is_logged_in() assert not login_session.is_logged_in(secured=True) # Case: user activity is older than secure lifetime assert (config.web.idle_lifetime - config.web.idle_secure_lifetime) > 50 login_session.set_as_logged_in(system_account, False) user_session.last_activity = datetime.now() - timedelta( seconds=config.web.idle_secure_lifetime + 50) assert login_session.is_logged_in() assert not login_session.is_logged_in(secured=True) # Case: user activity is older than all lifetimes assert (config.web.idle_lifetime - config.web.idle_secure_lifetime) > 50 login_session.set_as_logged_in(system_account, False) user_session.last_activity = datetime.now() - timedelta( seconds=config.web.idle_lifetime + 50) assert not login_session.is_logged_in() assert not login_session.is_logged_in(secured=True) # Case: user activity is older than non-secure lifetime, but keep_me_logged_in is set assert (config.web.idle_lifetime - config.web.idle_secure_lifetime) > 50 assert (config.web.idle_lifetime_max - config.web.idle_lifetime) > 50 login_session.set_as_logged_in(system_account, True) user_session.last_activity = datetime.now() - timedelta( seconds=config.web.idle_lifetime + 50) assert login_session.is_logged_in() assert not login_session.is_logged_in(secured=True) # Case: user activity is older than non-secure lifetime max, but keep_me_logged_in is set assert (config.web.idle_lifetime - config.web.idle_secure_lifetime) > 50 assert (config.web.idle_lifetime_max - config.web.idle_lifetime) > 50 login_session.set_as_logged_in(system_account, True) Session.flush() user_session.last_activity = datetime.now() - timedelta( seconds=config.web.idle_lifetime_max + 50) assert not login_session.is_logged_in() assert not login_session.is_logged_in(secured=True)
def destroy_test_tables(self, *entities): # Session.flush() Session.expunge_all() for entity in entities: if hasattr(entity, '__table__'): entity.__table__.metadata.remove(entity.__table__) if entity.__name__ in entity._decl_class_registry: del entity._decl_class_registry[entity.__name__]
def do_demo_setup(self): self.address_book self.account self.other_account self.other_address_book Session.flush() Session.commit()
def new_account_management_interface(self, system_account=None): system_account = system_account or self.system_account account_management_interface = AccountManagementInterface() account_management_interface.password = system_account.password account_management_interface.email = system_account.email Session.add(account_management_interface) Session.flush() return account_management_interface
def edit_address_in_other_address_book(self): address = Address(address_book=self.other_address_book, email_address='*****@*****.**', name='Friend') address.save() Session.flush() self.url = '/edit_address/%s' % address.id self.get = True
def do_demo_setup(self): self.address_book john = self.account jane = self.new_account(email='*****@*****.**') jane_book = self.new_address_book(owner=jane) someone = self.new_account(email='*****@*****.**') someone_book = self.new_address_book(owner=someone) someone_else = self.new_account(email='*****@*****.**') someone_else_book = self.new_address_book(owner=someone_else) jane_book.allow(john, can_add_addresses=True, can_edit_addresses=True) someone_book.allow(john, can_add_addresses=False, can_edit_addresses=True) someone_else_book.allow(john, can_add_addresses=False, can_edit_addresses=False) Address(address_book=jane_book, email_address='*****@*****.**', name='Friend1').save() Address(address_book=jane_book, email_address='*****@*****.**', name='Friend2').save() Address(address_book=jane_book, email_address='*****@*****.**', name='Friend3').save() Address(address_book=jane_book, email_address='*****@*****.**', name='Friend4').save() Address(address_book=someone_book, email_address='*****@*****.**', name='Friend11').save() Address(address_book=someone_book, email_address='*****@*****.**', name='Friend12').save() Address(address_book=someone_book, email_address='*****@*****.**', name='Friend13').save() Address(address_book=someone_book, email_address='*****@*****.**', name='Friend14').save() Address(address_book=someone_else_book, email_address='*****@*****.**', name='Friend21').save() Address(address_book=someone_else_book, email_address='*****@*****.**', name='Friend22').save() Address(address_book=someone_else_book, email_address='*****@*****.**', name='Friend23').save() Address(address_book=someone_else_book, email_address='*****@*****.**', name='Friend24').save() Session.flush() Session.commit()
def new_objects(self): objects = [ self.MyObject(name='B'), self.MyObject(name='A'), self.MyObject(name='C') ] for o in objects: Session.add(o) return objects
def do_demo_setup(self): Address(email_address='*****@*****.**', name='Friend1').save() Address(email_address='*****@*****.**', name='Friend2').save() Address(email_address='*****@*****.**', name='Friend3').save() Address(email_address='*****@*****.**', name='Friend4').save() Session.flush() Session.commit()
def __init__(self, view): super(AddressBookPanel, self).__init__(view) self.add_child(H(view, 1, text=_.ngettext('Address', 'Addresses', Session.query(Address).count()))) for address in Session.query(Address).all(): self.add_child(AddressBox(view, address)) self.add_child(AddAddressForm(view))