Exemple #1
0
def test_uniqueness_of_request_keys(sql_alchemy_fixture,
                                    party_account_fixture):
    fixture = party_account_fixture

    system_account = fixture.new_system_account(activated=False)

    @stubclass(VerificationRequest)
    class VerificationRequestStub(VerificationRequest):
        __tablename__ = 'verificationrequeststub'
        __mapper_args__ = {'polymorphic_identity': 'verificationrequeststub'}
        id = Column(Integer,
                    ForeignKey(VerificationRequest.id),
                    primary_key=True)

        def generate_salt(self):
            self.salt = 'not unique'

    with sql_alchemy_fixture.persistent_test_classes(VerificationRequestStub):
        request1 = VerificationRequestStub()
        Session.add(request1)
        request2 = VerificationRequestStub()
        Session.add(request2)
        clashing_request = VerificationRequestStub()
        Session.add(clashing_request)
        assert request1.as_secret_key() != clashing_request.as_secret_key()
        assert request2.as_secret_key() != clashing_request.as_secret_key()
Exemple #2
0
def demo_setup(sql_alchemy_fixture):
    sql_alchemy_fixture.commit = True

    Session.add(Address(name='John Doe', email_address='*****@*****.**'))
    Session.add(
        Address(name='Jane Johnson', email_address='*****@*****.**'))
    Session.add(Address(name='Jack Black', email_address='*****@*****.**'))
Exemple #3
0
    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()
Exemple #4
0
def test_session_data_disappears_when_session_does(web_fixture):
    """When a UserSession is deleted, all associated SessionData disappear as well."""
    fixture = web_fixture

    UserSession.initialise_web_session_on(fixture.context)
    user_session = fixture.context.session
    ui_name = 'user_interface'
    channel_name = 'channel'

    session_data = SessionData(web_session=user_session,
                               view_path='/',
                               ui_name=ui_name,
                               channel_name=channel_name)
    Session.add(session_data)
    Session.flush()

    Session.delete(user_session)

    assert Session.query(SessionData).filter_by(
        id=session_data.id).count() == 0
    assert Session.query(UserSession).filter_by(
        id=user_session.id).count() == 0
Exemple #5
0
def test_session_keeps_living(web_fixture):
    """When SessionData is deleted, the associated UserSession is not affected."""
    fixture = web_fixture

    UserSession.initialise_web_session_on(fixture.context)
    user_session = fixture.context.session
    ui_name = 'user_interface'
    channel_name = 'channel'

    session_data = SessionData(web_session=user_session,
                               view_path='/',
                               ui_name=ui_name,
                               channel_name=channel_name)
    Session.add(session_data)
    Session.flush()

    Session.delete(session_data)

    assert Session.query(SessionData).filter_by(
        id=session_data.id).count() == 0
    assert Session.query(UserSession).filter_by(
        id=user_session.id).one() is user_session
def test_optimistic_concurrency(web_fixture, sql_alchemy_fixture,
                                concurrency_fixture):
    """A user is prompted to handle the situation where data would be overwritten when submitting a 
       form that was originally rendered based on older data.
    """
    fixture = concurrency_fixture

    with sql_alchemy_fixture.persistent_test_classes(fixture.ModelObject):
        model_object = fixture.model_object
        Session.add(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('/')

        # The form submit does not overwrite any data changed by other means
        assert not fixture.is_concurrency_error_displayed()

        browser.type(XPath.input_labelled('Some field'), 'something')
        fixture.make_concurrent_change_in_backend()

        browser.click(XPath.button_labelled('Submit'))

        assert fixture.is_concurrency_error_displayed()
        assert fixture.concurrent_change_is_present()

        # When presented with such an error, the user can click on a button to reset all inputs to the now-current values
        browser.click(XPath.button_labelled('Reset input'))
        assert not fixture.is_concurrency_error_displayed()
        assert browser.get_value(
            XPath.input_labelled('Some field')) == 'changed by someone else'

        browser.type(XPath.input_labelled('Some field'), 'final changed value')
        browser.click(XPath.button_labelled('Submit'))
        assert not fixture.is_concurrency_error_displayed()

        assert model_object.some_field == 'final changed value'
Exemple #7
0
    def deferred_action_times_out_with_shared_requirements(self, fixture):
        """If a DeferredAction times out, it will not nuke Requirements shared with another DeferredAction."""
 
        with fixture.persistent_test_classes(fixture.MyDeferredAction, fixture.SomeObject):
            requirements1 = [Requirement()]
            requirements2 = [Requirement(), Requirement()]
            deferred_action1 = fixture.MyDeferredAction(fixture.one_object,
                                                        requirements=requirements2,
                                                        deadline=fixture.future_time)
            Session.add(deferred_action1)
            deferred_action2 = fixture.MyDeferredAction(fixture.another_object,
                                                        requirements=requirements1+requirements2,
                                                        deadline=fixture.future_time)

            Session.add(deferred_action2)
            Session.flush()

            # If one DeferredAction times out, the remaining one and its Requirements are left intact
            deferred_action1.deadline=fixture.past_time

            ReahlEgg.do_daily_maintenance_for_egg('reahl-domain')
            vassert( fixture.one_object.deadline_flag )
            vassert( not fixture.another_object.deadline_flag )

            vassert( Session.query(Requirement).count() == 3 )
            vassert( Session.query(DeferredAction).count() == 1 )

            for requirement in requirements1+requirements2:
                vassert( set(requirement.deferred_actions) == {deferred_action2} )

            # When no more DeferredActions are held onto by Requirements, those Requirements are deleted
            deferred_action2.deadline=fixture.past_time
            ReahlEgg.do_daily_maintenance_for_egg('reahl-domain')

            vassert( fixture.one_object.deadline_flag )
            vassert( fixture.another_object.deadline_flag )

            vassert( Session.query(Requirement).count() == 0 )
            vassert( Session.query(DeferredAction).count() == 0 )
Exemple #8
0
    def register_help_pending(self, fixture):
        verification_requests = Session.query(VerifyEmailRequest)
        unactivated_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('//input[@name="email"]', unactivated_account.email)
        fixture.browser.click('//input[@value="Investigate"]')

        vassert( fixture.browser.location_path == '/a_ui/registerHelp/pending' )
        vassert( verification_requests.count() == 1 )
        fixture.mailer.reset()
        fixture.browser.click('//input[@value="Send"]')

        vassert( verification_requests.count() == 1 )
        vassert( fixture.mailer.mail_sent )
        vassert( fixture.browser.location_path == '/a_ui/registerHelp/pending/sent' )
Exemple #9
0
def test_activate_via_key(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)
    deferred_activation = ActivateAccount(system_account=system_account, requirements=[activation_request])
    Session.add(deferred_activation)
    account_management_interface = fixture.account_management_interface

    # Case where there is an email mismatch
    account_management_interface.email = '*****@*****.**'
    account_management_interface.secret = activation_request.as_secret_key()
    with expected(InvalidEmailException, test=assert_is_set_to_commit):
        account_management_interface.verify_email()
    assert not system_account.registration_activated

    # Case where there is a key mismatch
    account_management_interface.email = system_account.email
    account_management_interface.secret = 'a key that is invalid'
    with expected(KeyException):
        account_management_interface.verify_email()
    assert not system_account.registration_activated

    # Case where it works
    assert not system_account.registration_activated
    assert not system_account.account_enabled
    assert not system_account.registration_date
    account_management_interface.email = system_account.email
    account_management_interface.secret = activation_request.as_secret_key()
    account_management_interface.verify_email()
    assert system_account.registration_activated
    assert system_account.account_enabled
    assert_recent( system_account.registration_date )
    assert Session.query(VerifyEmailRequest).filter_by(id=activation_request.id).count() == 0
Exemple #10
0
    def deferred_action_times_out(self, fixture):
        """If all its Requirements are not fulfilled before its deadline has been reached, a DeferredAction executes its deadline action; then, it and its Requirements are deleted"""
        
        with fixture.persistent_test_classes(fixture.MyDeferredAction, fixture.SomeObject):
            requirements = [Requirement(), Requirement(), Requirement()]
            deferred_action = fixture.MyDeferredAction(fixture.one_object, requirements=requirements, deadline=fixture.future_time)
            Session.add(deferred_action)
            Session.flush()

            vassert( deferred_action.deadline == fixture.future_time )
            ReahlEgg.do_daily_maintenance_for_egg('reahl-domain')
            vassert( not fixture.one_object.deadline_flag )
            vassert( not fixture.another_object.deadline_flag )

            vassert( Session.query(Requirement).count() == 3 )
            vassert( Session.query(DeferredAction).count() == 1 )

            deferred_action.deadline = fixture.past_time
            ReahlEgg.do_daily_maintenance_for_egg('reahl-domain')
            vassert( fixture.one_object.deadline_flag )
            vassert( not fixture.another_object.deadline_flag )

            vassert( Session.query(Requirement).count() == 0 )
            vassert( Session.query(DeferredAction).count() == 0 )
def test_optimistic_concurrency_with_ajax(web_fixture, sql_alchemy_fixture,
                                          concurrency_fixture):
    """When a concurrent change happens after an Ajax refresh, it is ignored in subsequent Ajax refreshes, 
       but upon an eventual submit the user is prompted.
    """
    fixture = concurrency_fixture

    with sql_alchemy_fixture.persistent_test_classes(fixture.ModelObject):
        model_object = fixture.model_object
        Session.add(model_object)

        model_object.some_trigger_field = 'some value'
        model_object.some_field = 'some value'

        wsgi_app = web_fixture.new_wsgi_app(
            child_factory=fixture.MyForm.factory(), enable_js=True)
        web_fixture.reahl_server.set_app(wsgi_app)
        browser = web_fixture.driver_browser
        browser.open('/')

        # Trigger refreshing once so that we create construction_client_side_state which may influence subsequent refreshings
        browser.type(XPath.input_labelled('Some field'),
                     'something for the fun of it')
        with browser.refresh_expected_for('#myform', fixture.refresh_expected_for_form),\
             browser.refresh_expected_for('#inner_div', True):
            browser.type(XPath.input_labelled('Some trigger field'),
                         'something else')

        fixture.make_concurrent_change_in_backend()

        assert not fixture.is_concurrency_error_displayed()
        browser.type(XPath.input_labelled('Some trigger field'),
                     'something else again')
        assert not fixture.is_concurrency_error_displayed()
        browser.click(XPath.button_labelled('Submit'))
        assert fixture.is_concurrency_error_displayed()
Exemple #12
0
def test_reading_cookies_on_initialising_a_session(web_fixture):
    fixture = web_fixture

    # Case: session cookie not set in Request
    UserSession.initialise_web_session_on(fixture.context)
    assert not fixture.context.session.is_active()
    assert not fixture.context.session.is_secured()

    # Case: session cookie set in Request
    fixture.context.session = None
    user_session = UserSession()
    user_session.set_last_activity_time()
    Session.add(user_session)

    fixture.request.headers['Cookie'] = ascii_as_bytes_or_str(
        'reahl=%s' % user_session.as_key())
    UserSession.initialise_web_session_on(fixture.context)

    assert fixture.context.session is user_session
    assert fixture.context.session.is_active()
    assert not fixture.context.session.is_secured()

    # Case: session cookie set, secure cookie also set in Request, https
    fixture.request.scheme = 'https'
    fixture.context.session = None
    user_session = UserSession()
    user_session.set_last_activity_time()
    Session.add(user_session)

    fixture.request.headers['Cookie'] = ascii_as_bytes_or_str('reahl=%s , reahl_secure=%s' % \
                                        (user_session.as_key(), user_session.secure_salt))
    UserSession.initialise_web_session_on(fixture.context)

    assert fixture.context.session is user_session
    assert fixture.context.session.is_active()
    assert fixture.context.session.is_secured()

    # Case: session cookie set, secure cookie also set in Request, http
    fixture.request.scheme = 'http'
    fixture.context.session = None
    user_session = UserSession()
    user_session.set_last_activity_time()
    Session.add(user_session)
    fixture.request.headers['Cookie'] = ascii_as_bytes_or_str('reahl=%s , reahl_secure=%s' % \
                                        (user_session.as_key(), user_session.secure_salt))

    UserSession.initialise_web_session_on(fixture.context)

    assert fixture.context.session is user_session
    assert fixture.context.session.is_active()
    assert not fixture.context.session.is_secured()
Exemple #13
0
    def reserve(cls, email, password, party):
        cls.assert_email_unique(email)
        system_account = cls(owner=party, email=email)
        Session.add(system_account)
        system_account.set_new_password(email, password)
        verification_request = VerifyEmailRequest(email=email,
                                                  subject_config='accounts.activation_subject',
                                                  email_config='accounts.activation_email')
        Session.add(verification_request)
        Session.flush()
        deferred_activation = ActivateAccount(system_account=system_account, 
                                              requirements=[verification_request])
        Session.add(deferred_activation)
        system_account.send_activation_notification()

        return system_account
Exemple #14
0
 def callable_object():
     Session.add(TestObject(name='new object'))
     assert Session.query(TestObject).count() == 1
     return 'value returned from method'
 def save(self):
     self.added_date = datetime.now()
     Session.add(self)
Exemple #16
0
def test_exception_handling(reahl_system_fixture, web_fixture,
                            sql_alchemy_fixture):
    """When a DomainException happens during the handling of an Event:

       The database is rolled back.
       The browser is redirected to GET the original view again (not the target).
       The screen still displays the values the user initially typed, not those on the ModelObject.
    """

    fixture = web_fixture

    class ModelObject(Base):
        __tablename__ = 'test_event_handling_exception_handling'
        id = Column(Integer, primary_key=True)
        field_name = Column(Integer)

        def handle_event(self):
            self.field_name = 1
            raise DomainException()

        @exposed
        def events(self, events):
            events.an_event = Event(label='click me',
                                    action=Action(self.handle_event))

        @exposed
        def fields(self, fields):
            fields.field_name = IntegerField(default=3)

    with sql_alchemy_fixture.persistent_test_classes(ModelObject):
        model_object = ModelObject()
        Session.add(model_object)

        class MyForm(Form):
            def __init__(self, view, name, other_view):
                super(MyForm, self).__init__(view, name)
                self.define_event_handler(model_object.events.an_event,
                                          target=other_view)
                self.add_child(ButtonInput(self, model_object.events.an_event))
                self.add_child(TextInput(self, model_object.fields.field_name))

        class MainUI(UserInterface):
            def assemble(self):
                self.define_page(HTML5Page).use_layout(BasicPageLayout())
                home = self.define_view('/', title='Home page')
                other_view = self.define_view('/page2', title='Page 2')
                home.set_slot('main', MyForm.factory('myform', other_view))

        wsgi_app = fixture.new_wsgi_app(site_root=MainUI)

        browser = Browser(
            wsgi_app
        )  # Dont use a real browser, because it will also hit many other URLs for js and css which confuse the issue
        browser.open('/')

        assert not model_object.field_name
        browser.type("//input[@type='text']", '5')

        # any database stuff that happened when the form was submitted was rolled back
        #        with CallMonitor(reahl_system_fixture.system_control.orm_control.rollback) as monitor:
        #            browser.click(XPath.button_labelled('click me'))
        #        assert monitor.times_called == 1
        browser.click(XPath.button_labelled('click me'))

        # the value input by the user is still displayed on the form, NOT the actual value on the model object
        assert not model_object.field_name
        retained_value = browser.get_value("//input[@type='text']")
        assert retained_value == '5'

        # the browser is still on the page with the form which triggered the exception
        assert browser.current_url.path == '/'
Exemple #17
0
    def request_email_change(self, new_email):
        self.assert_account_live()
        self.assert_email_unique(new_email)

        Session.add(ChangeAccountEmail(self, new_email))
        self.send_email_change_mail()
Exemple #18
0
 def new_another_object(self):
     another = self.SomeObject(name='another')
     Session.add(another)
     return another
def test_invalid_non_trigger_input_corner_case(web_fixture, query_string_fixture, sql_alchemy_fixture):
    """If an invalid value was submitted via ajax for a non-trigger input, and a valid value is submitted for is with a 
       form, and a DomainException happens... then the non-trigger input must retain its new, valid value."""

    fixture = scenario

    class ModelObject(Base):
        __tablename__ = 'test_responsive_disclosure_recalculate_invalids'
        id = Column(Integer, primary_key=True)
        choice = Column(Integer, default=1)
        choice3 = Column(Integer, default=9)
        calculated_state = Column(Integer, default=0)

        def recalculate(self):
            self.calculated_state = self.choice * 10

        def submit(self):
            raise DomainException(message='An exception happened on submit')

        @exposed
        def events(self, events):
            events.choice_changed = Event(action=Action(self.recalculate))
            events.submit = Event(action=Action(self.submit))

        @exposed
        def fields(self, fields):
            fields.choice = ChoiceField([Choice(1, IntegerField(label='One')),
                                        Choice(2, IntegerField(label='Two')),
                                        Choice(3, IntegerField(label='Three'))],
                                        label='Choice')
            fields.choice3 = ChoiceField([Choice(7, IntegerField(label='Seven')),
                                        Choice(8, IntegerField(label='Eight')),
                                        Choice(9, IntegerField(label='Nine'))],
                                        label='Choice3')
            fields.calculated_state = IntegerField(label='Calculated', writable=Allowed(False))

    class MyForm(Form):
        def __init__(self, view, an_object):
            super(MyForm, self).__init__(view, 'myform')
            self.an_object = an_object
            self.enable_refresh(on_refresh=an_object.events.choice_changed)
            if self.exception:
                self.add_child(P(self.view, text=str(self.exception)))
            self.change_trigger_input = TextInput(self, an_object.fields.choice, refresh_widget=self)
            self.add_child(Label(view, for_input=self.change_trigger_input))
            self.add_child(self.change_trigger_input)
            self.add_child(P(self.view, text='My choice state is now %s' % an_object.choice))
            self.change3_non_trigger_input = TextInput(self, an_object.fields.choice3)
            self.add_child(Label(view, for_input=self.change3_non_trigger_input))
            self.add_child(self.change3_non_trigger_input)
            self.add_child(P(self.view, text='My calculated state is now %s' % an_object.calculated_state))
            self.define_event_handler(an_object.events.submit)
            self.add_child(ButtonInput(self, an_object.events.submit))

    class MainWidgetWithPersistentModelObject(Widget):
        def __init__(self, view):
            super(MainWidgetWithPersistentModelObject, self).__init__(view)
            an_object = fixture.model_object
            self.add_child(MyForm(view, an_object))


    with sql_alchemy_fixture.persistent_test_classes(ModelObject):

        fixture.model_object = ModelObject()
        Session.add(fixture.model_object)

        wsgi_app = web_fixture.new_wsgi_app(enable_js=True, child_factory=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_labelled_now, 'My choice state', 1)
        assert browser.wait_for(query_string_fixture.is_state_labelled_now, 'My calculated state', '10')

        browser.type(XPath.input_labelled('Choice3'), 'other invalid input')
        browser.type(XPath.input_labelled('Choice'), '2')
        browser.press_tab()
        assert browser.wait_for(query_string_fixture.is_state_labelled_now, 'My calculated state', '20')

        assert browser.is_element_value(XPath.input_labelled('Choice3'), 'other invalid input')
        browser.type(XPath.input_labelled('Choice3'), '8')
        browser.click(XPath.button_labelled('submit'))
        assert browser.is_element_present(XPath.paragraph().including_text('An exception happened on submit'))
        assert browser.is_element_value(XPath.input_labelled('Choice3'), '8')
Exemple #20
0
 def save(self):
     self.added_date = datetime.date.today()
     Session.add(self)
Exemple #21
0
 def new_user(self):
     user = User(name='John Doe', email_address='*****@*****.**')
     user.set_password(self.password)
     Session.add(user)
     return user
Exemple #22
0
 def new_party(self):
     party = Party()
     Session.add(party)
     Session.flush()
     return party
Exemple #23
0
 def new_queue(self, name=None):
     name = name or 'A queue'
     queue = Queue(name=name)
     Session.add(queue)
     return queue
Exemple #24
0
 def submit(self):
     Session.add(self)
Exemple #25
0
 def save(self):
     login_session = LoginSession.for_current_session()
     self.account = login_session.account
     Session.add(self)
Exemple #26
0
 def new_account(self):
     account = EmailAndPasswordSystemAccount(email='*****@*****.**')
     Session.add(account)
     account.set_new_password(account.email, self.password)
     account.activate()
     return account
Exemple #27
0
 def save(self):
     Session.add(self)
 def new_address_book(self, owner=None):
     owner = owner or self.account
     address_book = AddressBook(owner=owner)
     Session.add(address_book)
     return address_book
Exemple #29
0
 def submit(self):
     self.attach_uploaded_files()
     Session.add(self)
Exemple #30
0
 def new_one_object(self):
     one = self.SomeObject(name='one')
     Session.add(one)
     return one