Exemple #1
0
def test_transitions_to_parameterised_views_error(web_fixture):
    """If an Event triggers a Transition to a parameterised View, and it was not bound to the arguments
       expected by the target View, an error is raised."""
    class ModelObject:
        @exposed
        def events(self, events):
            events.an_event = Event(label='Click me')

    model_object = ModelObject()

    class FormWithIncorrectButtonToParameterisedView(Form):
        def __init__(self, view):
            super().__init__(view, 'test_events')
            self.add_child(
                ButtonInput(
                    self,
                    model_object.events.an_event.with_arguments(arg1='1',
                                                                arg2='2')))

    class ParameterisedView(UrlBoundView):
        def assemble(self, object_key=None):
            self.title = 'View for: %s' % object_key

    class UIWithParameterisedViews(UserInterface):
        def assemble(self):
            normal_view = self.define_view('/static', title='Static')
            normal_view.set_slot(
                'main', FormWithIncorrectButtonToParameterisedView.factory())
            parameterised_view = self.define_view(
                '/dynamic',
                view_class=ParameterisedView,
                object_key=Field(required=True))
            self.define_transition(model_object.events.an_event, normal_view,
                                   parameterised_view)

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

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

    browser.open('/a_ui/static')
    with expected(ProgrammerError):
        browser.click(XPath.button_labelled('Click me'))
Exemple #2
0
    def parameterised_uis(self, fixture):
        """Sub UserInterfaces can also be parameterised by defining arguments in .define_user_interface, and receiving them in .assemble()."""
        class ParameterisedUserInterface(UserInterface):
            def assemble(self, ui_arg=None):
                if ui_arg == 'doesnotexist':
                    raise CannotCreate()

                self.name = 'user_interface-%s' % ui_arg
                root = self.define_view('/aview',
                                        title='Simple user_interface %s' %
                                        self.name)
                root.set_slot('user_interface-slot',
                              P.factory(text='in user_interface slot'))

        class UIWithParameterisedUserInterfaces(UserInterface):
            def assemble(self):
                self.define_user_interface('/parameterisedui',
                                           ParameterisedUserInterface,
                                           {'user_interface-slot': 'main'},
                                           ui_arg=fixture.argument,
                                           name='paramui')

        class MainUI(UserInterface):
            def assemble(self):
                self.define_page(HTML5Page).use_layout(
                    PageLayout(
                        contents_layout=ColumnLayout('main').with_slots()))
                self.define_user_interface('/a_ui',
                                           UIWithParameterisedUserInterfaces,
                                           IdentityDictionary(),
                                           name='myui')

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

        if fixture.should_exist:
            browser.open(fixture.url)

            # The correct argument was passed
            vassert(
                browser.title == 'Simple user_interface user_interface-%s' %
                fixture.expected_value)

            # The slots of the sub-user_interface is correctly plugged into the page
            [p] = browser.lxml_html.xpath('//p')
            vassert(p.text == 'in user_interface slot')
        else:
            # When the URL cannot be mapped
            browser.open(fixture.url, status=404)
def test_handling_uncaught_exceptions(web_fixture):
    """If an uncaught exception is raised, the session is closed properly."""
    @stubclass(ReahlWSGIApplication)
    class ReahlWSGIApplicationStub2(ReahlWSGIApplicationStub):
        def resource_for(self, request):
            raise AssertionError('this an unknown breakage')

    app = ReahlWSGIApplicationStub2(web_fixture.config)
    browser = Browser(app)

    with CallMonitor(app.system_control.finalise_session) as monitor:
        assert monitor.times_called == 0
        with expected(AssertionError):
            browser.open('/')
        assert monitor.times_called == 1
Exemple #4
0
def test_domain_exception(web_fixture, session_scope_fixture):
    """Typing the wrong password results in an error message being shown to the user."""

    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'), 'wrong password')
    browser.click(XPath.button_labelled('Log in'))

    assert browser.is_element_present(
        XPath.div().including_text('The email/password given do not match'))
Exemple #5
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>')
Exemple #6
0
def test_wrong_arguments_to_define_event_handler(web_fixture):
    """Passing anything other than an Event to define_event_handler is an error."""

    fixture = web_fixture

    class MyForm(Form):
        def __init__(self, view, name):
            super(MyForm, self).__init__(view, name)
            self.define_event_handler(EmptyStub())

    wsgi_app = fixture.new_wsgi_app(child_factory=MyForm.factory('form'))
    browser = Browser(wsgi_app)

    with expected(IsInstance):
        browser.open('/')
Exemple #7
0
def test_basic_error2(web_fixture):
    """Sending the the wrong arguments for the specified class to define_page is reported to the programmer."""

    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page, 1, 2)
            self.define_view('/', title='Hello')

    fixture = web_fixture

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

    with expected(IncorrectArgumentError, test='define_page was called with arguments that do not match those expected by.*'):
        browser.open('/')
Exemple #8
0
def test_getting_view(web_fixture):
    """ONLY If a View is readable, it can be GET"""
    fixture = web_fixture

    def disallowed():
        return False

    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page)
            self.define_view('/view', 'Title', read_check=disallowed)

    wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI)
    browser = Browser(wsgi_app)
    browser.open('/view', status=403)
Exemple #9
0
def basic_error3(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')

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

    def check_exc(ex):
        msg = six.text_type(ex)
        vassert(msg == 'there is no page defined for /')

    with expected(ProgrammerError, test=check_exc):
        browser.open('/')
def test_logging_in(web_fixture, session_scope_fixture):
    """A user can log in by going to the Log in page.
       The name of the currently logged in user is displayed on the home 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'))

    browser.click(XPath.link().with_text('Home'))
    assert browser.is_element_present(XPath.paragraph().including_text('Welcome John Doe'))
Exemple #11
0
def test_slot_error(web_fixture):
    """Supplying contents for a slot that does not exist results in s sensible error."""
    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page).use_layout(BasicPageLayout())
            home = self.define_view('/', title='Hello')
            home.set_slot('main', P.factory(text='Hello world'))
            home.set_slot('nonexistantslotname', P.factory(text='I am breaking'))

    fixture = web_fixture

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

    with expected(ProgrammerError, test='An attempt was made to plug Widgets into the following slots that do not exist.*'):
        browser.open('/')
Exemple #12
0
    def guards(self, fixture):
        """Guards can be set on Transitions. A Transition is only elegible for firing if its guard is True."""
        fixture.guard_value = None
        adjustable_guard = Action(lambda: fixture.guard_value)

        false_guard = Action(lambda: False)

        class UIWithGuardedTransitions(UserInterface):
            def assemble(self):
                event = Event(label='Click me')
                event.bind('anevent', None)
                slot_definitions = {'main': FormWithButton.factory(event)}
                viewa = self.define_view('/viewa',
                                         title='View a',
                                         slot_definitions=slot_definitions)
                viewb = self.define_view('/viewb', title='View b')
                viewc = self.define_view('/viewc', title='View c')
                self.define_transition(event, viewa, viewb, guard=false_guard)
                self.define_transition(event,
                                       viewa,
                                       viewc,
                                       guard=adjustable_guard)

        class MainUI(UserInterface):
            def assemble(self):
                self.define_page(HTML5Page).use_layout(
                    PageLayout(
                        contents_layout=ColumnLayout('main').with_slots()))
                self.define_user_interface('/a_ui',
                                           UIWithGuardedTransitions,
                                           IdentityDictionary(),
                                           name='test_ui')

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

        # The transition with True guard is the one followed
        fixture.guard_value = True
        browser.open('/a_ui/viewa')
        browser.click('//input[@value="Click me"]')
        vassert(browser.location_path == '/a_ui/viewc')

        # If there is no Transition with a True guard, fail
        fixture.guard_value = False
        browser.open('/a_ui/viewa')
        with expected(ProgrammerError):
            browser.click('//input[@value="Click me"]')
Exemple #13
0
    def redirect_used_to_return(self, fixture):
        """A Return is an exception used with Preconditoins to return automatically to another View (as set by detour),
           instead of using a return_transition (the latter can only be triggered by a user)."""
        class UIWithDetour(UserInterface):
            def assemble(self):
                viewa = self.define_view('/viewa', title='View a')
                explicit_return_view = self.define_view(
                    '/explicitReturnView', title='Explicit Return View')
                default = self.define_view('/defaultReturnView',
                                           title='Default view to return to')
                detour = self.define_view('/detour', title='Detour')

                viewa.add_precondition(
                    ViewPreCondition(
                        lambda: False,
                        exception=Detour(
                            detour.as_bookmark(self),
                            return_to=explicit_return_view.as_bookmark(self))))
                detour.add_precondition(
                    ViewPreCondition(lambda: False,
                                     exception=Return(
                                         default.as_bookmark(self))))

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

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

        # Normal operation - when a caller can be determined
        browser.open('/a_ui/viewa')
        vassert(browser.location_path == '/a_ui/explicitReturnView')

        #  - the query string is cleared after such a return (it is used to remember where to return to)
        vassert(browser.location_query_string == '')

        # When a caller cannot be determined, the default is used
        browser.open('/a_ui/detour')
        vassert(browser.location_path == '/a_ui/defaultReturnView')

        #  - the query string is cleared after such a return (it is used to remember where to return to)
        vassert(browser.location_query_string == '')
def test_ui_slots_map_error(web_fixture, user_interface_error_scenarios):

    class SimpleUserInterface(UserInterface):
        def assemble(self):
            root = self.define_view('/', title='View')
            root.set_slot('name', P.factory())

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

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

    with expected(ProgrammerError):
        browser.open('/a_ui/')
Exemple #15
0
def omitting_label(fixture):
    """The label will be rendered hidden (but available to screen readers) if this is explicity requested."""
    class FormWithInputNoLabel(Form):
        def __init__(self, view):
            super(FormWithInputNoLabel, self).__init__(view, 'aform')
            self.use_layout(FormLayout())
            self.layout.add_input(TextInput(
                self, fixture.domain_object.fields.an_attribute),
                                  hide_label=True)

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

    [label, help_text] = fixture.get_form_group_children(browser)
    vassert(label.tag == 'label')
    vassert(label.attrib['class'] == 'sr-only')
Exemple #16
0
def test_pageflow1(web_fixture, pageflow1_scenario):

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

    assert browser.is_element_present('//ul[contains(@class,"nav")]')

    browser.click(XPath.link().with_text('Add'))
    assert browser.current_url.path == '/add'

    browser.type(XPath.input_labelled('Name'), 'John')
    browser.type(XPath.input_labelled('Email'), '*****@*****.**')
    browser.click(XPath.button_labelled('Save'))

    assert browser.current_url.path == '/'
    assert browser.is_element_present(
        XPath.paragraph().including_text('John: [email protected]'))
Exemple #17
0
    def bookmarks_support_such_fragments(self, fixture):
        """Page-internal bookmarks support such bookmarkable widgets.

           These Bookmarks usually do not affect an URL - they just set widget states in different ways,
           depending on whether the client has javascript support or not.
           However, if a page was opened using the widget arguments on the querystring, a bookmark that would
           normally only have changed that argument on the hash will point to a new
           url on which the argument has been removed from the querystring and changed on the hash.
        """

        internal_bookmark = Bookmark.for_widget(
            'an ajax bookmark', query_arguments={'fancy_state': 2})
        normal_bookmark = Bookmark('/', '', 'a normal bookmark')

        # You can query whether a bookmark is page_internal or not
        vassert(internal_bookmark.is_page_internal)
        vassert(not normal_bookmark.is_page_internal)

        # page-internal bookmarks must be added to normal ones to be useful
        usable_bookmark = normal_bookmark + internal_bookmark

        wsgi_app = fixture.new_wsgi_app(
            widget_factory=A.factory_from_bookmark(usable_bookmark))

        # Case: when rendered without javascript
        browser = Browser(wsgi_app)
        browser.open('/')

        a = browser.lxml_html.xpath('//a')[0]
        vassert(a.attrib['href'] == '/?fancy_state=2')
        vassert(a.text == 'an ajax bookmark')

        # Case: when rendered in a browser with javascript support
        fixture.reahl_server.set_app(wsgi_app)
        fixture.driver_browser.open('/')
        vassert(
            fixture.driver_browser.is_element_present(
                "//a[@href='/#fancy_state=2']"))
        vassert(not fixture.driver_browser.is_element_present(
            "//a[@href='/?fancy_state=2']"))

        # Case: when the argument was given on the query string of the current page
        fixture.driver_browser.open('/?fancy_state=4')
        vassert(
            fixture.driver_browser.is_element_present(
                "//a[@href='/#fancy_state=2']"))
Exemple #18
0
def test_pageflow2(fixture):
    browser = Browser(fixture.wsgi_app)
    browser.open('/')

    vassert(browser.is_element_present('//ul[contains(@class,"nav")]'))

    browser.click(XPath.link_with_text('Add an address'))
    vassert(browser.location_path == '/add')

    browser.type(XPath.input_labelled('Name'), 'John')
    browser.type(XPath.input_labelled('Email'), '*****@*****.**')
    browser.click(XPath.button_labelled('Save'))

    vassert(browser.location_path == '/')
    vassert(
        browser.is_element_present(
            XPath.paragraph_containing('John: [email protected]')))
Exemple #19
0
    def dynamic_sub_resources_factory_args(self, fixture):
        """Such dynamic SubResources can also be created with arguments specified to its Factory (instead of 
           only from the path)."""
        @stubclass(SubResource)
        class ParameterisedSubResource(SubResource):
            sub_regex = 'dynamic_(?P<path_param>[^/]+)'
            sub_path_template = 'dynamic_%(path_param)s'

            def __init__(self, unique_name, factory_arg, factory_kwarg,
                         path_param):
                super(ParameterisedSubResource, self).__init__(unique_name)
                self.path_param = path_param
                self.factory_arg = factory_arg
                self.factory_kwarg = factory_kwarg

            @exempt
            def handle_get(self, request):
                args = '%s|%s|%s' % (self.factory_arg, self.factory_kwarg,
                                     self.path_param)
                return Response(unicode_body=six.text_type(args))

            @exempt
            @classmethod
            def create_resource(cls,
                                unique_name,
                                factory_arg,
                                factory_kwarg=None,
                                path_param=None):
                return cls(unique_name, factory_arg, factory_kwarg, path_param)

        @stubclass(Widget)
        class WidgetWithSubResource(Widget):
            def __init__(self, view):
                super(WidgetWithSubResource, self).__init__(view)
                factory = ParameterisedSubResource.factory(
                    'uniquename', {'path_param': Field(required=True)},
                    'arg to factory',
                    factory_kwarg='kwarg to factory')
                view.add_resource_factory(factory)

        wsgi_app = fixture.new_wsgi_app(
            view_slots={'main': WidgetWithSubResource.factory()})
        browser = Browser(wsgi_app)
        browser.open('/__uniquename_dynamic_one')
        vassert(browser.raw_html == 'arg to factory|kwarg to factory|one')
Exemple #20
0
    def detours_and_explicit_return_view(self, fixture):
        """A Detour can also explicitly set the View to return to."""
        class UIWithDetour(UserInterface):
            def assemble(self):
                event = Event(label='Click me')
                event.bind('anevent', None)
                viewa = self.define_view('/viewa', title='View a')
                explicit_return_view = self.define_view(
                    '/explicitReturnView', title='Explicit Return View')

                slot_with_button = {'main': FormWithButton.factory(event)}
                detour = self.define_view('/detour',
                                          title='Detour',
                                          slot_definitions=slot_with_button)

                viewa.add_precondition(
                    ViewPreCondition(
                        lambda: False,
                        exception=Detour(
                            detour.as_bookmark(self),
                            return_to=explicit_return_view.as_bookmark(self))))
                self.define_return_transition(event, detour)

        class MainUI(UserInterface):
            def assemble(self):
                self.define_page(HTML5Page).use_layout(
                    PageLayout(
                        contents_layout=ColumnLayout('main').with_slots()))
                self.define_user_interface('/a_ui',
                                           UIWithDetour,
                                           IdentityDictionary(),
                                           name='test_ui')

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

        browser.open('/a_ui/viewa')
        vassert(browser.location_path == '/a_ui/detour')

        browser.click('//input[@type="submit"]')
        vassert(browser.location_path == '/a_ui/explicitReturnView')

        # The query string is cleared after such a return (it is used to remember where to return to)
        vassert(browser.location_query_string == '')
Exemple #21
0
    def basic_transition(self, fixture):
        """Transitions express how the browser is ferried between Views in reaction to user-initiated Events."""
        def do_something():
            fixture.did_something = True

        class UIWithTwoViews(UserInterface):
            def assemble(self):
                event = Event(label='Click me', action=Action(do_something))
                event.bind('anevent', None)
                slot_definitions = {'main': FormWithButton.factory(event)}
                viewa = self.define_view('/viewa',
                                         title='View a',
                                         slot_definitions=slot_definitions)
                viewb = self.define_view('/viewb',
                                         title='View b',
                                         slot_definitions=slot_definitions)
                self.define_transition(event, viewa, viewb)

        class MainUI(UserInterface):
            def assemble(self):
                self.define_page(HTML5Page).use_layout(
                    PageLayout(
                        contents_layout=ColumnLayout('main').with_slots()))
                self.define_user_interface('/a_ui',
                                           UIWithTwoViews,
                                           IdentityDictionary(),
                                           name='test_ui')

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

        # The transition works from viewa
        fixture.did_something = False
        browser.open('/a_ui/viewa')
        browser.click('//input[@value="Click me"]')
        vassert(browser.location_path == '/a_ui/viewb')
        vassert(fixture.did_something)

        # The transition does not work from viewb
        fixture.did_something = False
        browser.open('/a_ui/viewb')
        with expected(ProgrammerError):
            browser.click('//input[@value="Click me"]')
        vassert(not fixture.did_something)
Exemple #22
0
def test_specifying_help_text(web_fixture, form_layout_fixture):
    """You can optionally specify help_text when adding an input."""
    fixture = form_layout_fixture

    class FormWithInputAndHelp(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), help_text='some help')

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

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

    # form-group has help-text
    assert help_text.tag == 'p'
    assert 'text-muted' in help_text.attrib['class']
    assert help_text.text == 'some help'
Exemple #23
0
def basic_error2(fixture):
    """Sending the the wrong arguments for the specified class to define_page is reported to the programmer."""
    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page, 1, 2)
            self.define_view('/', title='Hello')

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

    def check_exc(ex):
        msg = six.text_type(ex)
        vassert(
            msg.startswith(
                'define_page was called with arguments that do not match those expected by'
            ))

    with expected(IncorrectArgumentError, test=check_exc):
        browser.open('/')
Exemple #24
0
    def immutable_remote_methods(self, fixture):
        """A RemoteMethod that is immutable is accessible via GET (instead of POST)."""
        def callable_object():
            return 'value returned from method'

        remote_method = RemoteMethod('amethod',
                                     callable_object,
                                     MethodResult(),
                                     immutable=True)

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

        # GET, since the method is immutable
        browser.open('/_amethod_method')
        vassert(browser.raw_html == 'value returned from method')

        # POSTing to the URL, is not supported
        browser.post('/_amethod_method', {}, status=405)
Exemple #25
0
def test_query_string_widget_arguments(web_fixture, value_scenarios):
    """Widgets can have arguments that are read from a query string"""

    fixture = value_scenarios

    class WidgetWithQueryArguments(Widget):
        def __init__(self, view):
            super().__init__(view)
            self.add_child(P(view, text=str(self.arg_directly_on_widget)))

        @exposed
        def query_fields(self, fields):
            fields.arg_directly_on_widget = fixture.field.unbound_copy() # We use a copy, because the Field on the fixture is only constructed once, but we get here more than once during a GET

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

    browser.open('/?%s' % fixture.field_on_query_string.format(field_name='arg_directly_on_widget'))
    assert browser.lxml_html.xpath('//p')[0].text == str(fixture.field_value_marshalled)
Exemple #26
0
    def local_transition(self, fixture):
        """A local Transition has its source as its target."""
        def do_something():
            fixture.did_something = True

        fixture.guard_passes = True
        guard = Action(lambda: fixture.guard_passes)

        class UIWithAView(UserInterface):
            def assemble(self):
                event = Event(label='Click me', action=Action(do_something))
                event.bind('anevent', None)
                slot_definitions = {'main': FormWithButton.factory(event)}
                viewa = self.define_view('/viewa',
                                         title='View a',
                                         slot_definitions=slot_definitions)
                self.define_local_transition(event, viewa, guard=guard)

        class MainUI(UserInterface):
            def assemble(self):
                self.define_page(HTML5Page).use_layout(
                    PageLayout(
                        contents_layout=ColumnLayout('main').with_slots()))
                self.define_user_interface('/a_ui',
                                           UIWithAView,
                                           IdentityDictionary(),
                                           name='test_ui')

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

        # The transition works from viewa
        fixture.did_something = False
        browser.open('/a_ui/viewa')
        browser.click('//input[@value="Click me"]')
        vassert(browser.location_path == '/a_ui/viewa')
        vassert(fixture.did_something)

        # But it is also guarded
        fixture.guard_passes = False
        browser.open('/a_ui/viewa')
        with expected(ProgrammerError):
            browser.click('//input[@value="Click me"]')
Exemple #27
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(object):
        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(TestPanel, self).__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('/')

    browser.post(
        fixture.form.event_channel.get_url().path, {
            'event.some_form-an_event?': '',
            'field_name': 'illigitimate value',
            'some_form-_reahl_client_concurrency_digest': '',
            'some_form-_reahl_database_concurrency_digest': ''
        })
    browser.follow_response()
    assert model_object.field_name == 'Original value'
Exemple #28
0
    def defaults_for_slots(self, fixture):
        """A Widget can have defaults for its slots."""
        class MyPage(Widget):
            def __init__(self, view):
                super(MyPage, self).__init__(view)
                self.add_child(Slot(view, 'slot3'))
                self.add_default_slot('slot3', P.factory(text='default'))

        class MainUI(UserInterface):
            def assemble(self):
                self.define_page(MyPage)
                self.define_view('/', title='Home')

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

        browser.open('/')
        [slot3_p] = browser.lxml_html.xpath('//p')
        vassert(slot3_p.text == 'default')
Exemple #29
0
def test_inverse_view_preconditions(web_fixture):
    """A ViewPreCondition can give you another ViewPreCondition which it itself negated, optionally with its own exception."""
    class SomeException(Exception):
        pass

    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page)
            view = self.define_view('/', title='Hello')
            passing_precondition = ViewPreCondition(lambda: True)
            failing_precondition = passing_precondition.negated(
                exception=SomeException)
            view.add_precondition(failing_precondition)

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

    with expected(SomeException):
        browser.open('/')
Exemple #30
0
def test_duplicate_forms(web_fixture):
    """It is an error to add more than one form with the same unique_name to a page."""

    fixture = web_fixture

    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page).use_layout(
                BasicPageLayout(slots=['main', 'secondary']))
            home = self.define_view('/', title='Home page')
            home.set_slot('main', Form.factory('myform'))
            home.set_slot('secondary', Form.factory('myform'))

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

    with expected(
            ProgrammerError,
            test='More than one form was added using the same unique_name.*'):
        browser.open('/')