def fields(self, fields): fields.name = Field(label='Name', required=self.can_be_added(), writable=Action(self.can_be_added)) fields.email_address = EmailField(label='Email', required=True, writable=Action(self.can_be_edited))
def events(self, events): events.upload_file = Event(label=_('Upload'), action=Action(self.upload_file)) events.remove_file = Event(label=_('Remove'), action=Action(self.remove_file, ['filename']), filename=Field(required=True))
def assemble(self): contents_layout = ColumnLayout( ('main', ResponsiveSize(lg=6))).with_slots() page_layout = PageLayout(contents_layout=contents_layout, document_layout=Container()) self.define_page(HTML5Page).use_layout(page_layout) comment = Comment() home = self.define_view('/', title='Page flow demo') home.set_slot('main', CommentForm.factory(comment)) thanks = self.define_view('/thanks', title='Thank you!') thanks_text = 'Thanks for submitting your comment' thanks.set_slot('main', P.factory(text=thanks_text)) none_submitted = self.define_view('/none', title='Nothing to say?') none_text = 'Mmm, you submitted an empty comment??' none_submitted.set_slot('main', P.factory(text=none_text)) self.define_transition(comment.events.submit, home, thanks, guard=Action(comment.contains_text)) self.define_transition(comment.events.submit, home, none_submitted, guard=Not(Action(comment.contains_text)))
def assemble_register_help(self, verify_bookmark): register_help = self.define_view('/registerHelp', title=_('Problems registering?')) register_help.set_slot('main_slot', RegisterHelpWidget.factory(self.account_management_interface)) help_duplicate = self.define_view('/registerHelp/duplicate', title=_('Address already registered')) help_duplicate.set_slot('main_slot', RegistrationDuplicatedWidget.factory(self.account_management_interface)) help_pending = self.define_view('/registerHelp/pending', title=_('Registration still pending')) help_pending.set_slot('main_slot', RegistrationPendingWidget.factory(self.account_management_interface, verify_bookmark)) help_reregister = self.define_view('/registerHelp/reregister', title=_('Registration not found')) help_reregister.set_slot('main_slot', RegistrationNotFoundWidget.factory(self.account_management_interface)) help_sent = self.define_view('/registerHelp/pending/sent', title=_('Registration email sent')) help_sent.set_slot('main_slot', RegistrationEmailSentWidget.factory(self.account_management_interface)) investigate_event = self.account_management_interface.events.investigate_event self.define_transition(investigate_event, register_help, help_duplicate, guard=Action(self.account_management_interface.is_login_active)) self.define_transition(investigate_event, register_help, help_pending, guard=Action(self.account_management_interface.is_login_pending)) self.define_transition(self.account_management_interface.events.resend_event, help_pending, help_sent) self.define_transition(investigate_event, register_help, help_reregister, guard=Action(self.account_management_interface.is_login_available)) return register_help.as_bookmark(self)
def fields(self, fields): fields.greyed_out_field = Field( label='Some data', default= 'a value you\'re allowed to see, but not edit, so it is greyed out', readable=Action(self.allowed_to_see), writable=Action(self.allowed_to_write))
def test_event_security_action_and_rw(): """Supply either an action or a readable/writable to an Event, but not both.""" def do_nothing(): pass with expected(ProgrammerError): Event(action=Action(do_nothing), readable=Action(do_nothing)) with expected(ProgrammerError): Event(action=Action(do_nothing), writable=Action(do_nothing))
def events(self, events): events.take_task = Event(label=_('Take'), action=Action(Task.reserve_for, ['task', 'party']), task=PersistedField(Task, required=True), party=CurrentUser()) events.defer_task = Event(label=_('Defer')) events.go_to_task = Event(label=_('Go to'), task=PersistedField(Task, required=True), party=CurrentUser(), readable=Action(Task.is_reserved_for, ['task', 'party'])) events.release_task = Event(label=_('Release'), action=Action(Task.release, ['task']), task=PersistedField(Task, required=True), party=CurrentUser())
def events(self, events): events.an_event = Event( label='click me', action=Action(self.handle_event, ['one_argument', 'another_argument']), one_argument=IntegerField(), another_argument=Field())
def new_form(self): form = Form(self.web_fixture.view, 'some_form') event = Event(label='click me', action=Action(self.action)) event.bind('an_event', None) form.define_event_handler(event, target=self.target) form.add_child(ButtonInput(form, event)) return form
def events(self, events): events.an_event = Event(one_argument=IntegerField(required=True), another_argument=IntegerField(), unused_argument=IntegerField(), action=Action( self.do_something, ['one_argument'], dict(a_kwarg='another_argument')))
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"]')
def assemble(self): event = Event(label='Click me', action=Action(do_something)) event.bind('anevent', None) viewa = self.define_view('/viewa', title='View a') viewa.set_slot('main', FormWithButton.factory(event)) viewb = self.define_view('/viewb', title='View b') viewb.set_slot('main', FormWithButton.factory(event)) self.define_transition(event, viewa, viewb)
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)
def events(self, events): events.verify_event = Event(label=_('Verify'), action=Action(self.verify_email)) events.register_event = Event(label=_('Register'), action=Action(self.register)) events.change_email_event = Event(label=_('Change email address'), action=Action(self.request_email_change)) events.investigate_event = Event(label=_('Investigate')) events.choose_password_event = Event(label=_('Set new password'), action=Action(self.choose_new_password)) events.reset_password_event = Event(label=_('Reset password'), action=Action(self.request_password_reset)) events.login_event = Event(label=_('Log in'), action=Action(self.log_in)) events.resend_event = Event(label=_('Send'), action=Action(self.send_activation_notification)) events.log_out_event = Event(label=_('Log out'), action=Action(self.log_out))
def assemble(self): comment = Comment() home = self.define_view('/', title='Page flow demo') home.set_slot('main', CommentForm.factory(comment)) thanks = self.define_view('/thanks', title='Thank you!') thanks_text = 'Thanks for submitting your comment' thanks.set_slot('main', P.factory(text=thanks_text)) none_submitted = self.define_view('/none', title='Nothing to say?') none_text = 'Mmm, you submitted an empty comment??' none_submitted.set_slot('main', P.factory(text=none_text)) self.define_transition(comment.events.submit, home, thanks, guard=Action(comment.contains_text)) self.define_transition(comment.events.submit, home, none_submitted, guard=Not(Action(comment.contains_text)))
def test_fields_have_access_rights(web_fixture): """Fields have access rights for reading and for writing. By default both reading and writing are allowed. This default can be changed by passing an Action (which returns a boolean) for each kind of access which will be called to determine whether that kind of access is allowed. """ fixture = web_fixture def not_allowed(): return False # Case: the default field = Field() assert field.can_read() assert field.can_write() # Case: tailored rights field = Field(readable=Action(not_allowed), writable=Action(not_allowed)) field.bind('field_name', fixture) assert not field.can_read() assert not field.can_write()
def test_checkbox_basics_with_multichoice_field(web_fixture, checkbox_fixture): """CheckboxInput can also be used to choose many things from a list, in which case it renders many checkboxes.""" choices = [ Choice(1, IntegerField(label='One')), Choice(2, IntegerField(label='Two', writable=Action(lambda: False))), Choice(3, IntegerField(label='Three')), Choice(4, IntegerField(label='Four')), ] checkbox_fixture.field = MultiChoiceField(choices, label='Make your choice', default=[1]) web_fixture.reahl_server.set_app( web_fixture.new_wsgi_app( child_factory=checkbox_fixture.Form.factory())) browser = web_fixture.driver_browser browser.open('/') assert browser.is_element_present( XPath.label().with_text('Make your choice')) assert browser.get_xpath_count( '//div[@class="reahl-checkbox-input reahl-primitiveinput"]/div/input[@class="custom-control-input"]/following-sibling::label[@class="custom-control-label"]' ) == 4 checkbox_one = XPath.input_labelled('One') checkbox_two = XPath.input_labelled('Two') checkbox_three = XPath.input_labelled('Three') checkbox_four = XPath.input_labelled('Four') assert browser.is_selected(checkbox_one) assert not browser.is_selected(checkbox_two) assert not browser.is_element_enabled(checkbox_two) # assert browser.is_visible(checkbox_two) #cannot do this as the way bootsrap renders, the actual html input has opacity=0 assert not browser.is_selected(checkbox_three) assert not browser.is_selected(checkbox_four) browser.set_deselected(checkbox_one) browser.set_selected(checkbox_three) browser.set_selected(checkbox_four) browser.click(XPath.button_labelled('Submit')) assert not browser.is_selected(checkbox_one) assert browser.is_selected(checkbox_three) assert browser.is_selected(checkbox_four)
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"]')
def test_local_transition(web_fixture): """A local Transition has its source as its target.""" fixture = web_fixture 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) viewa = self.define_view('/viewa', title='View a') viewa.set_slot('main', FormWithButton.factory(event)) self.define_local_transition(event, viewa, guard=guard) class MainUI(UserInterface): def assemble(self): self.define_page(HTML5Page).use_layout(BasicPageLayout()) self.define_user_interface('/a_ui', UIWithAView, IdentityDictionary(), name='test_ui') wsgi_app = web_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"]') assert browser.current_url.path == '/a_ui/viewa' assert 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"]')
def events(self, events): events.submit = Event(label='Submit', action=Action(self.submit))
def events(self, events): events.an_event = Event(label='click me', action=Action(self.handle_event))
def events(self, events): events.an_event = Event( label='click me', action=Action(self.handle_event, ['some_argument']), some_argument=Field(default='default value'))
def events(self, events): events.outer_event = Event(label='click outer', action=Action(self.handle_event))
def events(self, events): events.nested_event = Event(label='click nested', action=Action(self.handle_event))
def events(self, events): events.an_event = Event(label='click me', action=Action(self.clicked))
def events(self, events): events.submit = Event(label='Submit', action=Action(self.submit)) events.allocation_changed = Event(action=Action(self.recalculate))
def events(self, events): events.save = Event(label=_('Save'), action=Action(self.save))
def events(self, events): events.save = Event(label='Save', action=Action(self.save)) events.update = Event(label='Update')
def events(self, events): events.submit = Event(label='Submit') events.submit_break = Event(label='Submit break', action=Action(self.always_break))
def events(self, events): events.an_event = Event(readable=Action(self.allow_read), writable=Action(self.allow_write))