Example #1
0
def test_concatenated_files(web_fixture, concatenate_scenarios):
    """Files can also be formed by concatenating other files.  Files ending in .css or .js are appropriately
       minified in the process."""

    fixture = concatenate_scenarios

    # Make an egg with a package called packaged_files, and two files in there.
    egg_dir = temp_dir()
    package_dir = egg_dir.sub_dir('packaged_files')
    init_file = package_dir.file_with('__init__.py', '')
    afile = package_dir.file_with('packaged_file', fixture.file1_contents)
    another_file = package_dir.file_with('packaged_file2', fixture.file2_contents)

    pkg_resources.working_set.add(easter_egg)
    easter_egg.location = egg_dir.name

    class MainUI(UserInterface):
        def assemble(self):
            to_concatenate = [PackagedFile('test==1.0', 'packaged_files', 'packaged_file'),
                              PackagedFile('test==1.0', 'packaged_files', 'packaged_file2')]
            list_of_files = [ConcatenatedFile(fixture.filename, to_concatenate)]
            self.define_static_files('/files', list_of_files)

    web_fixture.config.reahlsystem.debug = False  # To enable minification
    wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI)
    browser = Browser(wsgi_app)

    # How the first file would be accessed
    browser.open('/files/%s' % fixture.filename)
    assert browser.raw_html == fixture.expected_result
Example #2
0
def test_widget_factory_creates_widget_with_layout(web_fixture,
                                                   widget_creation_scenarios):
    """A Layout can be specified to any WidgetFactory or to UserInterface.define_page"""
    class MyLayout(Layout):
        def customise_widget(self):
            self.widget.add_child(
                P(self.view, text='This widget is using Mylayout'))

    layout_for_widget = MyLayout()

    class MainUI(UserInterface):
        def assemble(self):
            self.define_view(
                '/',
                title='Hello',
                page=HTML5Page.factory(use_layout=layout_for_widget))

    fixture = widget_creation_scenarios

    wsgi_app = web_fixture.new_wsgi_app(site_root=fixture.MainUI)
    browser = Browser(wsgi_app)

    browser.open('/')
    [p] = browser.lxml_html.xpath('//p')
    assert p.text == 'This widget is using Mylayout'
Example #3
0
def test_files_from_database(web_fixture):
    """Files can also be created on the fly such as from data in a database."""


    content_bytes = ('hôt stuff').encode('utf-8')

    class MainUI(UserInterface):
        def assemble(self):
            mime_type = 'text/html'
            encoding = 'utf-8'
            mtime = 123
            size = len(content_bytes)

            list_of_files = [FileFromBlob('database_file', content_bytes, mime_type, encoding, size, mtime)]
            self.define_static_files('/files', list_of_files)

    wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI)
    browser = Browser(wsgi_app)

    # How the file would be accessed
    browser.open('/files/database_file')
    assert browser.raw_html == 'hôt stuff'
    response = browser.last_response

    # The meta-info of the file
    assert response.content_type == 'text/html'
    assert not response.content_encoding
    assert response.content_length == len(content_bytes)
    assert response.last_modified.replace(tzinfo=None) == datetime.datetime.fromtimestamp(123)
    expected_etag = '123-%s-%s' % (len(content_bytes), abs(hash('database_file')))
    assert response.etag == expected_etag
def test_ui_arguments(web_fixture):
    """UserInterfaces can take exta args and kwargs."""
    class UIWithArguments(UserInterface):
        def assemble(self, kwarg=None):
            self.kwarg = kwarg
            text = self.kwarg
            root = self.define_view('/', title='A view')
            root.set_slot('text', P.factory(text=text))

    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page).use_layout(BasicPageLayout())
            self.define_user_interface('/a_ui',
                                       UIWithArguments, {'text': 'main'},
                                       name='myui',
                                       kwarg='the kwarg')

    fixture = web_fixture

    wsgi_app = fixture.new_wsgi_app(site_root=MainUI)
    browser = Browser(wsgi_app)

    browser.open('/a_ui/')
    [p] = browser.lxml_html.xpath('//p')
    assert p.text == 'the kwarg'
def test_ui_slots_map_to_window(web_fixture):
    """The UserInterface uses its own names for Slots. When attaching a UserInterface, you have to specify 
        which of the UserInterface's Slots plug into which of the page's Slots.
    """
    class UIWithSlots(UserInterface):
        def assemble(self):
            root = self.define_view('/', title='UserInterface root view')
            root.set_slot('text',
                          P.factory(text='in user_interface slot named text'))

    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page).use_layout(BasicPageLayout())
            self.define_user_interface('/a_ui',
                                       UIWithSlots, {'text': 'main'},
                                       name='myui')

    fixture = web_fixture

    wsgi_app = fixture.new_wsgi_app(site_root=MainUI)
    browser = Browser(wsgi_app)

    browser.open('/a_ui/')
    assert browser.title == 'UserInterface root view'

    # The widget in the UserInterface's slot named 'text' end up in the HTML5Page slot called main
    [p] = browser.lxml_html.xpath('//div[contains(@class,"column-main")]/p')
    assert p.text == 'in user_interface slot named text'
Example #6
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
Example #7
0
def test_adding_checkboxes(web_fixture, form_layout_fixture):
    """CheckboxInputs are added non-inlined, and by default without labels."""
    class DomainObjectWithBoolean:
        @exposed
        def fields(self, fields):
            fields.an_attribute = BooleanField(label='Some input',
                                               required=True)

    fixture = form_layout_fixture

    fixture.domain_object = DomainObjectWithBoolean()

    class FormWithInputWithCheckbox(Form):
        def __init__(self, view):
            super().__init__(view, 'aform')
            self.use_layout(FormLayout())
            self.layout.add_input(
                CheckboxInput(self, fixture.domain_object.fields.an_attribute))

    browser = Browser(
        web_fixture.new_wsgi_app(
            child_factory=FormWithInputWithCheckbox.factory()))
    browser.open('/')

    assert not any(child.tag == 'label'
                   for child in fixture.get_form_group_children(browser))
    [div] = fixture.get_form_group_children(browser)
    [checkbox] = div.getchildren()
    checkbox_classes = checkbox.attrib['class'].split(' ')
    assert 'custom-control' in checkbox_classes
    assert 'custom-checkbox' in checkbox_classes
Example #8
0
def test_missing_variable_in_ui_regex(web_fixture):
    class RegexUserInterface(UserInterface):
        def assemble(self, ui_key=None):
            self.name = 'user_interface-%s' % ui_key

    class UIWithParameterisedUserInterfaces(UserInterface):
        def assemble(self):
            self.define_regex_user_interface('/(?P<xxx>[^/]*)',
                                             'N/A',
                                             RegexUserInterface, {},
                                             ui_key=Field(required=True))

    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page)
            self.define_user_interface('/a_ui',
                                       UIWithParameterisedUserInterfaces, {},
                                       name='test_ui')

    wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI)

    browser = Browser(wsgi_app)

    with expected(RequiredConstraint):
        browser.open('/a_ui/test1/')
Example #9
0
def test_i18n_urls(web_fixture):
    """The current locale is determined by reading the first segment of the path. If the locale is not present in the
    path, web.default_url_locale is used."""
    _ = Catalogue('reahl-web')

    class I18nUI(UserInterface):
        def assemble(self):
            view = self.define_view('/aview', title=_('A View'))

    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page)
            self.define_user_interface('/a_ui',
                                       I18nUI,
                                       IdentityDictionary(),
                                       name='test_ui')

    wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI)
    browser = Browser(wsgi_app)

    browser.open('/a_ui/aview')
    assert browser.title == 'A View'

    browser.open('/af/a_ui/aview')
    assert browser.title == '\'n Oogpunt'

    web_fixture.config.web.default_url_locale = 'af'
    browser.open('/a_ui/aview')
    assert browser.title == '\'n Oogpunt'

    browser.open('/en_gb/a_ui/aview')
    assert browser.title == 'A View'
Example #10
0
def test_immutable_remote_methods(web_fixture, remote_method_fixture,
                                  sql_alchemy_fixture):
    """The database is always rolled back at the end of an immutable RemoteMethod."""
    class TestObject(Base):
        __tablename__ = 'test_remotemethods_test_object'
        id = Column(Integer, primary_key=True)
        name = Column(UnicodeText)

    with sql_alchemy_fixture.persistent_test_classes(TestObject):

        def callable_object():
            Session.add(TestObject(name='new object'))
            assert Session.query(TestObject).count() == 1
            return 'value returned from method'

        remote_method = RemoteMethod(web_fixture.view,
                                     'amethod',
                                     callable_object,
                                     MethodResult(),
                                     immutable=True,
                                     disable_csrf_check=True)

        assert remote_method.idempotent  # Immutable methods are idempotent

        wsgi_app = remote_method_fixture.new_wsgi_app(
            remote_method=remote_method)
        browser = Browser(wsgi_app)

        browser.open('/_amethod_method')
        assert browser.raw_html == 'value returned from method'

        # The database is rolled back to ensure immutability
        assert Session.query(TestObject).count() == 0
Example #11
0
def test_remote_methods_via_ajax(web_fixture, remote_method_fixture):
    """A RemoteMethod can be called via AJAX with CSRF protection built-in."""

    fixture = remote_method_fixture

    def callable_object():
        return 'value returned from method'

    remote_method = RemoteMethod(web_fixture.view,
                                 'amethod',
                                 callable_object,
                                 MethodResult(),
                                 disable_csrf_check=False)

    wsgi_app = fixture.new_wsgi_app(remote_method=remote_method,
                                    enable_js=True)
    web_fixture.reahl_server.set_app(wsgi_app)
    browser = web_fixture.driver_browser

    # Case: using jquery to POST to the method includes the necessary xsrf info automatically
    browser.open('/')
    browser.execute_script(
        '$.post("/_amethod_method", success=function(data){ $("body").attr("data-result", data) })'
    )
    results = browser.execute_script('return $("body").attr("data-result")')
    assert results == 'value returned from method'

    # Case: POSTing without a csrf token breaks
    browser = Browser(wsgi_app)
    browser.post('/_amethod_method', {}, status=403)
Example #12
0
def test_basic_workings(web_fixture, dhtml_fixture):
    """A DhtmlUI provides a UserInterface which maps to the filesystem where there may be
       a combination of .d.html and other files. When a d.html file is requested from
       it, the contents of the specified div from inside the d.html file is inserted
       into the specified Slot. When a normal file is requested, the file is sent verbatim."""
    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page).use_layout(BasicPageLayout())
            self.define_user_interface('/dhtml_ui',
                                       DhtmlUI, {'main_slot': 'main'},
                                       name='test_ui',
                                       static_div_name='astatic')

    fixture = dhtml_fixture

    # Dhtml files should be located in the web.static_root
    web_fixture.config.web.static_root = fixture.static_dir.name

    wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI, enable_js=True)
    browser = Browser(wsgi_app)

    # A dhtml file: HTML5Page's main_slot now contains the insides of the div in the dhtml file
    browser.open('/dhtml_ui/correctfile.d.html')
    html = fixture.get_inserted_html(browser)
    assert html == fixture.div_internals

    # A non-dhtml file is returned verbatim
    browser.open('/dhtml_ui/otherfile.txt')
    contents = browser.raw_html
    assert contents == 'other'

    # Files that do not exist are reported as such
    browser.open('/dhtml_ui/idonotexist.txt', status=404)
    browser.open('/dhtml_ui/idonotexist.d.html', status=404)
Example #13
0
def test_views_from_regex(web_fixture):
    """Parameterised Views can also be added based on a regex over the url."""
    class ParameterisedView(UrlBoundView):
        def assemble(self, some_key=None):
            self.title = 'View for: %s' % some_key

    class UIWithParameterisedViews(UserInterface):
        def assemble(self):
            self.define_regex_view('/someurl_(?P<some_key>.*)',
                                   '/someurl_${some_key}',
                                   view_class=ParameterisedView,
                                   some_key=Field(required=True))

    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page)
            self.define_user_interface('/a_ui',
                                       UIWithParameterisedViews, {},
                                       name='myui')

    wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI)
    browser = Browser(wsgi_app)

    # Parameterised constructing a View from an URL
    browser.open('/a_ui/someurl_test1')
    assert browser.title == 'View for: test1'
Example #14
0
def test_simple_sub_resources(web_fixture):
    """During their construction, Widgets can add SubResources to their View.  The SubResource
       will then be available via a special URL underneath the URL of the Widget's View."""

    fixture = web_fixture

    @stubclass(SubResource)
    class ASimpleSubResource(SubResource):
        sub_regex = 'simple_resource'
        sub_path_template = 'simple_resource'

        @exempt
        def handle_get(self, request):
            return Response()

    @stubclass(Widget)
    class WidgetWithSubResource(Widget):
        def __init__(self, view):
            super().__init__(view)
            view.add_resource(ASimpleSubResource(view, 'uniquename'))

    wsgi_app = fixture.new_wsgi_app(
        child_factory=WidgetWithSubResource.factory())
    browser = Browser(wsgi_app)
    browser.open('/_uniquename_simple_resource')
Example #15
0
def test_check_missing_form(web_fixture):
    """All forms referred to by inputs on a page have to be present on that page."""

    fixture = web_fixture

    class ModelObject:
        @exposed
        def fields(self, fields):
            fields.name = Field()

    class MyPanel(Div):
        def __init__(self, view):
            super().__init__(view)
            model_object = ModelObject()
            forgotten_form = Form(view, 'myform')
            self.add_child(TextInput(forgotten_form, model_object.fields.name))

    wsgi_app = fixture.new_wsgi_app(child_factory=MyPanel.factory())
    browser = Browser(wsgi_app)

    expected_message = 'Could not find form for <TextInput name=myform-name>. '\
                       'Its form, <Form form id="myform".*> is not present on the current page'

    with expected(ProgrammerError, test=expected_message):
        browser.open('/')
Example #16
0
def test_packaged_files(web_fixture):
    """Files can also be served straight from a python egg."""


    # Create an egg with package packaged_files, containing the file packaged_file
    egg_dir = temp_dir()
    package_dir = egg_dir.sub_dir('packaged_files')
    init_file = package_dir.file_with('__init__.py', '')
    afile = package_dir.file_with('packaged_file', 'contents')

    easter_egg.clear()
    pkg_resources.working_set.add(easter_egg)
    easter_egg.location = egg_dir.name

    class MainUI(UserInterface):
        def assemble(self):
            list_of_files = [PackagedFile(easter_egg.as_requirement_string(), 'packaged_files', 'packaged_file')]
            self.define_static_files('/files', list_of_files)

    wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI)
    browser = Browser(wsgi_app)

    # How the file would be accessed
    browser.open('/files/packaged_file')
    assert browser.raw_html == 'contents'
Example #17
0
def test_internal_redirects(web_fixture):
    """During request handling, an InternalRedirect exception can be thrown. This is handled by
       restarting the request loop from scratch to handle the same request again, using a freshly
       constructed resource just as though the request was submitted again by the browser
       save for the browser round trip."""

    fixture = web_fixture
    fixture.requests_handled = []
    fixture.handling_resources = []

    @stubclass(Resource)
    class ResourceStub:
        should_commit = True
        def cleanup_after_transaction(self): pass
        def handle_request(self, request):
            fixture.requests_handled.append(request)
            fixture.handling_resources.append(self)
            if hasattr(request, 'internal_redirect'):
                return Response(body='response given after internal redirect')
            raise InternalRedirect(None, None)

    @stubclass(ReahlWSGIApplication)
    class ReahlWSGIApplicationStub2(ReahlWSGIApplicationStub):
        def resource_for(self, request):
            return ResourceStub()

    browser = Browser(ReahlWSGIApplicationStub2(fixture.config))

    browser.open('/')

    assert browser.raw_html == 'response given after internal redirect'
    assert fixture.requests_handled[0] is fixture.requests_handled[1]
    assert fixture.handling_resources[0] is not fixture.handling_resources[1]
Example #18
0
def test_missing_variable_in_regex(web_fixture):
    """If a variable is missing from the regex, an appropriate error is raised."""
    class ParameterisedView(UrlBoundView):
        def assemble(self, some_key=None):
            self.title = 'View for: %s' % some_key

    class UIWithParameterisedViews(UserInterface):
        def assemble(self):
            self.define_regex_view('/(?P<incorrect_name_for_key>.*)',
                                   '/${key}',
                                   view_class=ParameterisedView,
                                   some_key=Field(required=True))

    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page)
            self.define_user_interface('/a_ui',
                                       UIWithParameterisedViews, {},
                                       name='test_ui')

    fixture = web_fixture

    wsgi_app = fixture.new_wsgi_app(site_root=MainUI)
    browser = Browser(wsgi_app)

    with expected(ProgrammerError, test='The arguments contained in URL.*'):
        browser.open('/a_ui/test1/')
Example #19
0
def test_i18n_dhtml(web_fixture, dhtml_fixture):
    """Dhtml files can have i18nsed versions, which would be served up if applicable."""
    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page).use_layout(BasicPageLayout())
            self.define_user_interface('/dhtml_ui',
                                       DhtmlUI, {'main_slot': 'main'},
                                       name='test_ui',
                                       static_div_name='astatic')

    fixture = dhtml_fixture

    # Dhtml files should be located in the web.static_root
    web_fixture.config.web.static_root = fixture.static_dir.name

    wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI)

    browser = Browser(wsgi_app)

    # request the file, but get the translated alternative for the locale
    def stubbed_create_context_for_request():
        return LocaleContextStub(locale='af')

    with replaced(wsgi_app.create_context_for_request,
                  stubbed_create_context_for_request):
        browser.open('/dhtml_ui/correctfile.d.html')

    assert browser.title == 'Afrikaans bo!'
Example #20
0
def test_inline_form_layouts(web_fixture, form_layout_fixture):
    """An InlineFormLayout adds the Label and Input of each added input next to each other, with some space between them."""
    fixture = form_layout_fixture

    class FormWithInlineFormLayout(Form):
        def __init__(self, view):
            super().__init__(view, 'aform')
            self.use_layout(InlineFormLayout())
            self.layout.add_input(TextInput(
                self, fixture.domain_object.fields.an_attribute),
                                  help_text='some help')

    browser = Browser(
        web_fixture.new_wsgi_app(
            child_factory=FormWithInlineFormLayout.factory()))
    browser.open('/')

    [label, input_, help_text] = fixture.get_form_group_children(browser)

    #check spacing specified between label, input and help_text
    assert label.tag == 'label'
    assert 'mr-2' == label.attrib['class']

    assert input_.tag == 'input'

    assert help_text.tag == 'span'
    assert 'ml-2' in help_text.attrib['class'].split(' ')
Example #21
0
def test_grid_form_layouts(web_fixture, form_layout_fixture):
    """A GridFormLayout adds the Label and Input of each added input in separate columns sized like you specify"""
    fixture = form_layout_fixture

    class FormWithGridFormLayout(Form):
        def __init__(self, view):
            super().__init__(view, 'aform')
            self.use_layout(
                GridFormLayout(ResponsiveSize(lg=4), ResponsiveSize(lg=8)))
            self.layout.add_input(TextInput(
                self, fixture.domain_object.fields.an_attribute),
                                  help_text='some help')

    browser = Browser(
        web_fixture.new_wsgi_app(
            child_factory=FormWithGridFormLayout.factory()))
    browser.open('/')

    [label_column, input_column] = fixture.get_form_group_children(browser)
    assert label_column.tag == 'div'
    assert 'col-lg-4' in label_column.attrib['class'].split(' ')
    assert 'column-label' in label_column.attrib['class'].split(' ')

    [label] = fixture.get_label_in_form_group(browser)
    assert 'col-form-label' in label.attrib['class'].split(' ')

    assert input_column.tag == 'div'
    assert 'col-lg-8' in input_column.attrib['class'].split(' ')
    assert 'column-input' in input_column.attrib['class'].split(' ')

    [input_, help_text] = input_column.getchildren()
    assert input_.tag == 'input'
    assert help_text.tag == 'p'
    assert 'form-text' in help_text.attrib['class'].split(' ')
Example #22
0
def test_adding_basic_input(web_fixture, form_layout_fixture):
    """Adding an input to a FormLayout, adds it in a bootstrap form-group with Some input."""
    fixture = form_layout_fixture

    class FormWithInputAddedUsingDefaults(Form):
        def __init__(self, view):
            super().__init__(view, 'aform')
            self.use_layout(FormLayout())
            self.layout.add_input(
                TextInput(self, fixture.domain_object.fields.an_attribute))

    browser = Browser(
        web_fixture.new_wsgi_app(
            child_factory=FormWithInputAddedUsingDefaults.factory()))
    browser.open('/')

    assert fixture.form_contains_form_group(browser)

    [label, input_widget] = fixture.get_form_group_children(browser)

    # form-group has a label, correctly set up for bootstrap
    assert label.tag == 'label'
    assert label.attrib['for'] == input_widget.attrib['id']
    assert label.text == 'Some input'

    # form-group has an input, correctly set up for bootstrap
    assert input_widget.tag == 'input'
    assert input_widget.attrib['name'] == 'aform-an_attribute'
Example #23
0
def test_addressbook1(web_fixture, addressbook1_scenario):

    john = addressbook1.Address(name='John', email_address='*****@*****.**')
    john.save()

    browser = Browser(addressbook1_scenario.wsgi_app)
    browser.open('/')

    assert browser.is_element_present(XPath.paragraph().including_text('John: [email protected]')) 
Example #24
0
def test_error_page_shown_on_error(web_fixture, error_fixture):
    """If not in debug mode and an uncaught Exception is raised, the user is redirected to an error page."""

    wsgi_app = web_fixture.new_wsgi_app(site_root=error_fixture.MainUI)
    browser = Browser(wsgi_app)

    wsgi_app.config.reahlsystem.debug = False

    browser.open('/a_page')
    assert browser.current_url.path == '/error'
Example #25
0
def test_handling_HTTPError_exceptions(web_fixture):
    """If an HTTPError exception is raised, it is used as response."""
    @stubclass(ReahlWSGIApplication)
    class ReahlWSGIApplicationStub2(ReahlWSGIApplicationStub):
        def resource_for(self, request):
            raise HTTPNotFound()

    browser = Browser(ReahlWSGIApplicationStub2(web_fixture.config))

    browser.open('/', status=404)
Example #26
0
def test_non_writable_input_is_dealt_with_like_invalid_input(web_fixture):
    """If a form submits a value for an Input that is linked to Field with access rights that prohibit writing,
       the input is silently ignored."""
    fixture = web_fixture

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

        @exposed
        def fields(self, fields):
            fields.field_name = Field(default='abc', writable=Allowed(False), disallowed_message='you are not allowed to write this')
    model_object = ModelObject()

    class TestPanel(Div):
        def __init__(self, view):
            super().__init__(view)
            form = self.add_child(Form(view, 'some_form'))
            form.define_event_handler(model_object.events.an_event)
            form.add_child(ButtonInput(form, model_object.events.an_event))
            form.add_child(TextInput(form, model_object.fields.field_name))

            fixture.form = form


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

    csrf_token = browser.get_value('//input[@name="some_form-_reahl_csrf_token"]')
    browser.post(fixture.form.event_channel.get_url().path, {'event.some_form-an_event?':'', 'some_form-field_name': 'illigitimate value', 'some_form-_reahl_database_concurrency_digest':'', 'some_form-_reahl_csrf_token': csrf_token})
    browser.follow_response()
    assert model_object.field_name == 'Original value'
Example #27
0
def test_slots(web_fixture, slot_scenarios):
    """A View modifies the page by populating named Slots in the page with Widgets."""
    fixture = slot_scenarios

    wsgi_app = web_fixture.new_wsgi_app(site_root=fixture.MainUI)
    browser = Browser(wsgi_app)

    browser.open('/')
    assert browser.title == 'Hello'
    [main_p, footer_p] = browser.xpath('//p')
    assert main_p.text == 'Hello world'
    assert footer_p.text == 'I am the footer'
Example #28
0
def test_alternative_event_trigerring(web_fixture):
    """Events can also be triggered by submitting a Form via Ajax. In such cases the normal redirect-after-submit
       behaviour of the underlying EventChannel is not desirable. This behaviour can be switched off by submitting
       an extra argument along with the Form in order to request the alternative behaviour.
    """

    fixture = web_fixture

    class ModelObject:
        def handle_event(self):
            self.handled_event = True

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

    model_object = ModelObject()

    class MyForm(Form):
        def __init__(self, view, name, other_view):
            super().__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))

    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)

    # when POSTing with _noredirect, the Action is executed, but the browser is not redirected to /page2 as usual
    browser.open('/')
    csrf_token = browser.get_value('//input[@name="myform-_reahl_csrf_token"]')
    browser.post(
        '/__myform_method', {
            'event.myform-an_event?': '',
            '_noredirect': '',
            'myform-_reahl_database_concurrency_digest': '',
            'myform-_reahl_csrf_token': csrf_token
        })
    browser.follow_response(
    )  # Needed to make the test break should a HTTPTemporaryRedirect response be sent
    assert model_object.handled_event
    assert browser.current_url.path != '/page2'
    assert browser.current_url.path == '/__myform_method'

    # the response is a json object reporting the success of the event and a new rendition of the form
    json_dict = json.loads(browser.raw_html)
    assert json_dict['success']
    expected_html = '<div id="myform_hashes">'
    assert json_dict['result']['myform'].startswith(expected_html)
Example #29
0
def test_basic_error3(web_fixture):
    """Forgetting to define either a page of a page for a View is reported to the programmer."""
    class MainUI(UserInterface):
        def assemble(self):
            self.define_view('/', title='Hello')

    fixture = web_fixture

    wsgi_app = fixture.new_wsgi_app(site_root=MainUI)
    browser = Browser(wsgi_app)

    with expected(ProgrammerError, test='there is no page defined for /'):
        browser.open('/')
Example #30
0
def test_detour_to_login(web_fixture, party_account_fixture,
                         workflow_web_fixture):
    fixture = workflow_web_fixture

    browser = Browser(fixture.wsgi_app)

    browser.open('/inbox/')
    assert browser.current_url.path == '/accounts/login'
    browser.type(XPath.input_labelled('Email'),
                 party_account_fixture.system_account.email)
    browser.type(XPath.input_labelled('Password'),
                 party_account_fixture.system_account.password)
    browser.click(XPath.button_labelled('Log in'))
    assert browser.current_url.path == '/inbox/'