Ejemplo n.º 1
0
def test_query_string_prepopulates_form(web_fixture, value_scenarios):
    """Widget query string arguments can be used on forms to pre-populate inputs based on the query string."""

    fixture = value_scenarios

    class ModelObject:
        @exposed
        def fields(self, fields):
            fields.arg_on_other_object = fixture.field

    class FormWithQueryArguments(Form):
        def __init__(self, view):
            self.model_object = ModelObject()
            super().__init__(view, 'name')
            self.use_layout(FormLayout())
            self.layout.add_input(TextInput(self, self.model_object.fields.arg_on_other_object))

        @exposed
        def query_fields(self, fields):
            fields.arg_on_other_object = self.model_object.fields.arg_on_other_object

    wsgi_app = web_fixture.new_wsgi_app(enable_js=True, child_factory=FormWithQueryArguments.factory())
    browser = Browser(wsgi_app)

    browser.open('/?%s' % fixture.field_on_query_string.format(field_name='name-arg_on_other_object'))
    assert browser.get_value(XPath.input_labelled('field')) == fixture.field_value_as_string
Ejemplo n.º 2
0
def test_email_retained(web_fixture, session_scope_fixture):
    """The email address used when last logged in is always pre-populated on the Log in page."""

    browser = Browser(web_fixture.new_wsgi_app(site_root=SessionScopeUI))
    user = session_scope_fixture.user

    browser.open('/')
    browser.click(XPath.link().with_text('Log in'))

    browser.type(XPath.input_labelled('Email'), '*****@*****.**')
    browser.type(XPath.input_labelled('Password'), 'topsecret')
    browser.click(XPath.button_labelled('Log in'))

    # Go away from the page, then back
    browser.click(XPath.link().with_text('Home'))
    browser.click(XPath.link().with_text('Log in'))

    # .. then the email is still pre-populated
    typed_value = browser.get_value(XPath.input_labelled('Email'))
    assert typed_value == '*****@*****.**'
Ejemplo n.º 3
0
def test_form_preserves_user_input_after_validation_exceptions_multichoice(
        web_fixture):
    """When a form is submitted and validation fails on the server, the user
     is presented with the values that were originally entered (even if they were invalid)."""

    fixture = web_fixture

    class ModelObject(object):
        @exposed
        def events(self, events):
            events.an_event = Event(label='click me')

        @exposed
        def fields(self, fields):
            choices = [
                Choice(1, IntegerField(label='One')),
                Choice(2, IntegerField(label='Two')),
                Choice(3, IntegerField(label='Three'))
            ]
            fields.no_validation_exception_field = MultiChoiceField(
                choices, label='Make your invalid choice', default=[])
            fields.validation_exception_field = MultiChoiceField(
                choices, label='Make your choice', default=[], required=True)

    model_object = ModelObject()

    class MyForm(Form):
        def __init__(self, view):
            super(MyForm, self).__init__(view, 'my_form')
            self.define_event_handler(model_object.events.an_event)
            self.add_child(ButtonInput(self, model_object.events.an_event))
            input = self.add_child(
                SelectInput(self,
                            model_object.fields.no_validation_exception_field))
            if input.validation_error:
                self.add_child(self.create_error_label(input))
            input = self.add_child(
                SelectInput(self,
                            model_object.fields.validation_exception_field))
            if input.validation_error:
                self.add_child(self.create_error_label(input))

    wsgi_app = web_fixture.new_wsgi_app(child_factory=MyForm.factory())
    browser = Browser(wsgi_app)

    browser.open('/')

    no_validation_exception_input = '//select[@name="my_form-no_validation_exception_field[]"]'
    validation_exception_input = '//select[@name="my_form-validation_exception_field[]"]'

    browser.select_many(no_validation_exception_input, ['One', 'Two'])
    browser.select_none(validation_exception_input
                        )  # select none to trigger the RequiredConstraint
    browser.click(XPath.button_labelled('click me'))

    assert browser.get_value(no_validation_exception_input) == ['1', '2']
    assert not browser.get_value(validation_exception_input)

    label = browser.get_html_for('//label')
    input_id = browser.get_id_of(validation_exception_input)
    assert label == '<label for="%s" class="error">Make your choice is required</label>' % input_id

    #2. Submit again ths time not expecting validation exceptions, also expecting the validation error to be cleared and the domain should have all input
    browser.select_many(validation_exception_input, ['Two', 'Three'])
    browser.click(XPath.button_labelled('click me'))

    assert not browser.is_element_present('//label[@class="error"]')
    assert browser.get_value(no_validation_exception_input) == ['1', '2']
    assert browser.get_value(validation_exception_input) == ['2', '3']
Ejemplo n.º 4
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 == '/'