Exemplo n.º 1
0
    def non_writable_events_are_dealt_with_like_invalid_input(self, fixture):
        """If a form submits an Event with access rights that prohibit writing, a ValidationException is raised."""
        class ModelObject(object):
            @exposed
            def events(self, events):
                events.an_event = Event(
                    label='click me',
                    writable=Allowed(False),
                    disallowed_message='you cannot do this')

        model_object = ModelObject()

        class TestPanel(Div):
            def __init__(self, view):
                super(TestPanel, self).__init__(view)
                form = self.add_child(Form(view, 'some_form'))
                form.define_event_handler(model_object.events.an_event)
                button = form.add_child(
                    ButtonInput(form, model_object.events.an_event))
                if button.validation_error:
                    form.add_child(form.create_error_label(button))
                fixture.form = form

        wsgi_app = fixture.new_wsgi_app(child_factory=TestPanel.factory())
        browser = Browser(wsgi_app)
        browser.open('/')

        browser.post(fixture.form.event_channel.get_url().path,
                     {'event.an_event?': ''})
        browser.follow_response()
        input_id = browser.get_id_of('//input[@name="event.an_event?"]')
        error_label = browser.get_html_for('//label')
        vassert(error_label ==
                '<label for="%s" class="error">you cannot do this</label>' %
                input_id)
Exemplo n.º 2
0
def test_library_files(web_fixture, library_fixture):
    """The files part of configured frontend libraries are (a) added to /static and also (b) included on any page."""

    config = web_fixture.config
    config.web.frontend_libraries.clear()
    config.web.frontend_libraries.add(library_fixture.MyLibrary())

    browser = Browser(ReahlWSGIApplication(config))

    browser.open('/static/somefile.js')
    assert browser.raw_html == 'contents - js'

    browser.open('/static/somefile.css')
    assert browser.raw_html == 'contents - css'

    browser.open('/')
    script_added = browser.get_html_for('//script[@src]')
    assert script_added == '<script type="text/javascript" src="/static/somefile.js"></script>'

    link_added = browser.get_html_for('//link')
    assert link_added == '<link rel="stylesheet" href="/static/somefile.css" type="text/css">'
Exemplo n.º 3
0
    def widgets_for_tasks(self, fixture):
        """The widget to use for displaying a particular type of task can be set via an entry point."""
        pkg_resources.working_set.add(easter_egg)
        line = 'MyTaskWidget = reahl.domainui_dev.bootstrap.test_workflow:MyTaskWidget'
        easter_egg.add_entry_point_from_line('reahl.workflowui.task_widgets',
                                             line)

        with fixture.persistent_test_classes(MyTask):
            task = MyTask(queue=fixture.queue, title='a task')

            browser = Browser(fixture.wsgi_app)
            fixture.log_in(browser=browser)
            browser.open('/inbox/task/%s' % task.id)
            html = browser.get_html_for('//div/p')
            vassert(html == '<p>my task widget</p>')
Exemplo n.º 4
0
def test_form_input_validation(web_fixture):
    """Validation of input happens in JS on the client, but also on the server if JS is bypassed."""

    error_xpath = '//form[contains(@class, "reahl-form")]/label[contains(@class, "error")]'

    fixture = web_fixture

    class ModelObject(object):
        def handle_event(self):
            pass

        @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 = EmailField()

    model_object = ModelObject()

    class MyForm(Form):
        def __init__(self, view, name, other_view):
            super(MyForm, self).__init__(view, name)
            if self.exception:
                self.add_child(
                    P(view, ','.join(self.exception.detail_messages)))
            self.define_event_handler(model_object.events.an_event,
                                      target=other_view)
            self.add_child(ButtonInput(self, model_object.events.an_event))
            text_input = self.add_child(
                TextInput(self, model_object.fields.field_name))
            if text_input.validation_error:
                self.add_child(self.create_error_label(text_input))

    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, enable_js=True)

    # Case: form validation fails in JS on the client
    #  - Form submission is blocked
    #  - Error message is displayed
    fixture.reahl_server.set_app(wsgi_app)
    fixture.driver_browser.open('/')
    fixture.driver_browser.wait_for_element_not_visible(error_xpath)
    fixture.driver_browser.type('//input[@type="text"]',
                                'not@notvalid',
                                trigger_blur=False,
                                wait_for_ajax=False)
    fixture.driver_browser.press_tab()
    fixture.driver_browser.wait_for_element_visible(error_xpath)

    with fixture.driver_browser.no_page_load_expected():
        fixture.driver_browser.click("//input[@value='click me']")

    error_text = fixture.driver_browser.get_text(error_xpath)
    assert error_text == 'field_name should be a valid email address'

    # .. but the error is removed again upon valid input
    fixture.driver_browser.type('//input[@type="text"]', '*****@*****.**')
    fixture.driver_browser.wait_for_element_not_visible(error_xpath)

    # Case: form validation fails on the server (assuming no JS on the client to block submission)
    #  - ValidationException is raised (which is dealt with as any DomainException)
    browser = Browser(wsgi_app)
    browser.open('/')
    browser.type('//input[@type="text"]', 'not@notvalid')

    browser.click('//input[@type="submit"]')
    assert not hasattr(model_object, 'field_name')
    label = browser.get_html_for('//label')
    input_id = browser.get_id_of('//input[@type="text"]')
    assert label == '<label for="%s" class="error">field_name should be a valid email address</label>' % input_id

    assert Session.query(UserInput).filter_by(key='myform-field_name').count(
    ) == 1  # The invalid input was persisted
    exception = Session.query(PersistedException).one().exception
    assert isinstance(exception, ValidationException)  # Is was persisted
    assert not exception.commit

    # Case: form validation passes (no-js)
    #  - no ValidationException
    #  - all input is translated to python and set as values on the model objects
    #  - any saved input on the form is cleared
    browser.type('//input[@type="text"]', '*****@*****.**')
    browser.click("//input[@value='click me']")
    assert model_object.field_name == '*****@*****.**'

    assert Session.query(UserInput).filter_by(
        key='myform-field_name').count() == 0  # The invalid input was removed
    assert Session.query(
        PersistedException).count() == 0  # The exception was removed

    assert browser.current_url.path == '/page2'

    # Case: form validation passes (js)
    #  - no ValidationException
    #  - all input is translated to python and set as values on the model objects
    fixture.driver_browser.open('/')
    fixture.driver_browser.type('//input[@type="text"]', '*****@*****.**')
    fixture.driver_browser.wait_for_element_not_visible(error_xpath)
    fixture.driver_browser.click("//input[@value='click me']")
    assert model_object.field_name == '*****@*****.**'

    assert fixture.driver_browser.current_url.path == '/page2'
Exemplo n.º 5
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']