def __init__(self, view): super().__init__(view, 'simple_form') self.use_layout(FormLayout()) if self.exception: self.layout.add_alert_for_domain_exception(self.exception) domain_object = self.get_or_create_domain_object() link = self.add_child( A(view, Url('/'), description='Open another tab...')) link.set_attribute('target', '_blank') self.add_child( P(view, text= '...and increment the value there. Come back here and submit the value. A Concurrency error will be shown' )) #Your own widget that tracks changes self.add_child(MyConcurrencyWidget(view, domain_object)) self.layout.add_input( TextInput(self, domain_object.fields.some_field_value)) self.define_event_handler(domain_object.events.submit) self.add_child(Button(self, domain_object.events.submit)) self.define_event_handler(domain_object.events.increment) self.add_child(Button(self, domain_object.events.increment))
def failing_field(self): # - a field that fails one or more? constraints self.url = Url('/__some_form_validate_method?some_form-field_name=invalidaddress') self.expected_body = '"field_name should be a valid email address"' self.expected_status = '200 OK' self.expected_content_type = 'application/json' self.expected_charset = 'utf-8'
def non_existent_field(self): # - a field that does not exist self.url = Url('/__some_form_validate_method?nonexistantfield=value') self.expected_body = 'false' self.expected_status = '200 OK' self.expected_content_type = 'application/json' self.expected_charset = 'utf-8'
def files_of_type(self, extension): if extension == '.css': from reahl.web.fw import Url hostname = self.force_theme or Url.get_current_url().hostname return ['%s.css' % hostname] else: return super().files_of_type(extension)
def test_button_layouts_on_anchors(web_fixture): """A ButtonLayout can also be used to make an A (anchor) look like a button.""" anchor = A(web_fixture.view, href=Url('/an/href'), description='link text').use_layout(ButtonLayout()) tester = WidgetTester(anchor) [rendered_anchor] = tester.xpath(XPath.link().with_text('link text')) assert rendered_anchor.attrib['class'] == 'btn btn-secondary' assert 'aria-disabled' not in rendered_anchor.attrib assert 'tabindex' not in rendered_anchor.attrib anchor = A(web_fixture.view, href=Url('/an/href'), description='link text', write_check=lambda: False).use_layout(ButtonLayout()) tester = WidgetTester(anchor) [rendered_anchor] = tester.xpath(XPath.link().with_text('link text')) assert rendered_anchor.attrib['class'] == 'btn btn-secondary disabled' assert rendered_anchor.attrib['aria-disabled'] == 'true' assert rendered_anchor.attrib['tabindex'] == '-1'
def empty_querystring(self): # - an empty querystring self.url = Url('/__some_form_validate_method') self.expected_body = 'false' self.expected_status = '200 OK' self.expected_content_type = 'application/json' self.expected_charset = 'utf-8'
def test_dropdown_menus(web_fixture): """You can add a DropdownMenu as a dropdown inside a Nav.""" menu = Nav(web_fixture.view) sub_menu = DropdownMenu(web_fixture.view) sub_menu.add_a( A(web_fixture.view, Url('/an/url'), description='sub menu item')) menu.add_dropdown('Dropdown title', sub_menu) [item] = menu.html_representation.children assert item.tag_name == 'li' assert 'dropdown' in item.get_attribute('class') [toggle, added_sub_menu] = item.children assert 'dropdown-toggle' in toggle.get_attribute('class') assert 'button' in toggle.get_attribute('role') assert 'true' in toggle.get_attribute('aria-haspopup') assert 'dropdown' in toggle.get_attribute('data-toggle') title_text = toggle.children[0].value assert title_text == 'Dropdown title' assert added_sub_menu is sub_menu assert 'dropdown-menu' in added_sub_menu.html_representation.get_attribute( 'class').split() assert isinstance(added_sub_menu.html_representation, Div) [dropdown_item] = added_sub_menu.html_representation.children assert isinstance(dropdown_item, A) assert 'dropdown-item' in dropdown_item.get_attribute('class').split()
def overridden_on_unrelated_url(self): # On an unrelated url, active is forced url_on_which_item_is_usually_inactive = Url('/another_href') self.go_to_href = url_on_which_item_is_usually_inactive self.expects_active = True self.overriding_callable = lambda: True
class MenuItemScenarios(Fixture): description = 'The link' href = Url('/link') @scenario def not_active(self): self.active_regex = None self.web_fixture.request.environ['PATH_INFO'] = '/something/else' self.active = False @scenario def active_exact_path(self): self.active_regex = None self.web_fixture.request.environ['PATH_INFO'] = '/link' self.active = True @scenario def active_partial_path(self): self.active_regex = None self.web_fixture.request.environ['PATH_INFO'] = '/link/something/more' self.active = True @scenario def inactive_partial_path(self): self.active_regex = '^/link$' self.web_fixture.request.environ['PATH_INFO'] = '/link/something/more' self.active = False
def valid_field(self): # - a field that passes validation self.url = Url('/[email protected]') self.expected_body = 'true' self.expected_status = '200 OK' self.expected_content_type = 'application/json' self.expected_charset = 'utf-8'
def new_menu_item_a(self): description = 'The link' href = Url('/link') menu_item_a = A(self.web_fixture.view, self.href, description=description) return menu_item_a
def button_layouts_on_anchors(fixture): """A ButtonLayout can also be used to make an A (anchor) look like a button.""" anchor = A(fixture.view, href=Url('/an/href'), description='link text').use_layout(ButtonLayout()) tester = WidgetTester(anchor) [rendered_anchor] = tester.xpath(XPath.link_with_text('link text')) vassert(rendered_anchor.attrib['class'] == 'btn')
def __init__(self, view): super().__init__(view) error_widget = self.body.insert_child(0, ErrorWidget(view)) error_widget.add_child(H(view, 1, text='Oops, something broke')) error_widget.add_child(P(view, text=error_widget.error_message)) error_widget.add_child( A(view, Url(error_widget.error_source_href), description='Click here to try again'))
def disabled(self): """The mouse cursor is shown as no-access on disabled items.""" def not_allowed(): return False self.menu_item_with_state = A(self.view, Url('/another_url'), write_check=not_allowed) self.state_indicator_class = 'disabled'
def __init__(self, view): super(I18nExample, self).__init__(view) menu = Nav(self.view).use_layout(PillLayout()).with_languages() self.add_child(menu) current_url = Url.get_current_url() message = _('This is a translated message. The current URL is "%s".' ) % current_url.path self.add_child(P(view, text=message))
def __init__(self, view): super(CustomErrorPage, self).__init__(view) error_widget = self.body.insert_child(0, ErrorWidget(view)) error_widget.add_child(H(view, 1, text='My custom error page')) error_widget.add_child(P(view, text=error_widget.error_message)) error_widget.add_child( A(view, Url(error_widget.error_source_href), description='Ok'))
def test_button_layouts_on_disabled_anchors(web_fixture): """Disabled A's are marked with a class so Bootstrap can style them appropriately.""" def can_write(): return False anchor = A(web_fixture.view, href=Url('/an/href'), description='link text', write_check=can_write) anchor.use_layout(ButtonLayout()) tester = WidgetTester(anchor) [rendered_anchor] = tester.xpath(XPath.link().with_text('link text')) assert rendered_anchor.attrib['class'] == 'btn btn-secondary disabled'
def __init__(self, view): super(HomePage, self).__init__(view) menu = Nav(self.view).use_layout( PillLayout(stacked=True)).with_languages() self.body.add_child(menu) current_url = Url.get_current_url() message = _('This is a translated string. The current URL is "%s".') \ % current_url.path self.body.add_child(P(view, text=message))
def __init__(self, view): super().__init__(view) self.add_child( Alert(view, 'This is an alert in danger color', severity='danger')) self.add_child( Alert(view, 'This is an alert in primary color', severity='primary')) self.add_child(A(view, Url('#'), description='Link styled as button')).use_layout( ButtonLayout(style='primary'))
def test_default_active_multi_tab(web_fixture, tabbed_panel_ajax_fixture, default_multi_tab_scenarios): """The first item of the first tab is active by default (if the active tab is not indicated in the query_string).""" fixture = default_multi_tab_scenarios web_fixture.reahl_server.set_app(tabbed_panel_ajax_fixture.wsgi_app) url = Url('/') url.set_query_from(fixture.query_args) web_fixture.driver_browser.open(str(url)) assert tabbed_panel_ajax_fixture.tab_contents_equals( fixture.expected_contents) assert (not fixture.multi_tab_active ) or tabbed_panel_ajax_fixture.tab_is_active('multitab name') assert (not fixture.tab1_active ) or tabbed_panel_ajax_fixture.tab_is_active('tab 1 name') assert (not fixture.tab2_active ) or tabbed_panel_ajax_fixture.tab_is_active('tab 2 name') assert (not fixture.tab3_active ) or tabbed_panel_ajax_fixture.tab_is_active('tab 3 name')
def get_interface_locale(self): context = ExecutionContext.get_context() if not hasattr(context, 'request'): return 'en_gb' url = Url.get_current_url() possible_locale, path = url.get_locale_split_path() supported_locales = ReahlEgg.get_languages_supported_by_all(context.config.reahlsystem.root_egg) if possible_locale: if possible_locale in supported_locales: return possible_locale return context.config.web.default_url_locale
def test_visual_feedback_on_items(web_fixture, visual_feedback_scenarios): """The state of a MenuItem is visually indicated to a user.""" menu = Nav(web_fixture.view) menu.add_a(A(web_fixture.view, Url('/an_url'))) menu.add_a(visual_feedback_scenarios.menu_item_with_state) [defaulted_item, item_with_state] = menu.html_representation.children [defaulted_a] = defaulted_item.children [a_with_state] = item_with_state.children assert visual_feedback_scenarios.state_indicator_class not in defaulted_a.get_attribute('class') assert visual_feedback_scenarios.state_indicator_class in a_with_state.get_attribute('class')
def test_rendering_active_menu_items(web_fixture, menu_item_scenarios): """A MenuItem is marked as active based on its active_regex or the A it represents.""" description = 'The link' href = Url('/link') menu = Nav(web_fixture.view) menu_item_a = A(web_fixture.view, href, description=description) menu.add_a(menu_item_a, active_regex=menu_item_scenarios.active_regex) tester = WidgetTester(menu) actual = tester.get_html_for('//li') active_str = '' if not menu_item_scenarios.active else 'active ' expected_menu_item_html = '<li class="nav-item"><a href="/link" class="%snav-link">The link</a></li>' % (active_str) assert actual == expected_menu_item_html
def test_error_page_degrades_gracefully(web_fixture, error_fixture): """The error page can be customised, and depending on what was specified for the app, degrades gracefully.""" wsgi_app = web_fixture.new_wsgi_app(site_root=error_fixture.MainUI) web_fixture.reahl_server.set_app(wsgi_app) # browser = Browser(wsgi_app) browser = web_fixture.driver_browser browser.open( '/error?error_message=something+went+wrong&error_source_href=/a_page') assert browser.current_url.path == '/error' error_fixture.check_error_page_contents(browser) assert browser.is_element_present( XPath.paragraph().including_text('something went wrong')) assert Url(browser.get_attribute(XPath.link().with_text('Ok'), 'href')).path == '/a_page'
def test_bootstrap_default_error_page(web_fixture, fixture): """Bootstrap HTML5Page has a styled error page by default, placed depending on the layout""" wsgi_app = web_fixture.new_wsgi_app(site_root=fixture.MainUI) web_fixture.reahl_server.set_app(wsgi_app) browser = web_fixture.driver_browser browser.open('/error?error_message=something+went+wrong&error_source_href=/a_page') assert browser.is_element_present(fixture.expected_alert) error_message = XPath.paragraph().including_text('something went wrong').inside_of(fixture.expected_alert) assert browser.is_element_present(error_message) ok_button = XPath.link().including_text('Ok').inside_of(fixture.expected_alert) assert browser.is_element_present(ok_button) assert Url(browser.find_element(ok_button).get_attribute('href')).path == '/a_page'
def __init__(self, view, bookmarks): super(FundingRequestPage, self).__init__(view) self.head.add_css(Url('/css/pyconza2019.css')) self.use_layout(PageLayout(document_layout=Container())) contents_layout = ColumnLayout( ColumnOptions('main', size=ResponsiveSize())).with_slots() self.layout.contents.use_layout(contents_layout) layout = ResponsiveLayout('md', colour_theme='dark', bg_scheme='primary') navbar = Navbar(view, css_id='my_nav').use_layout(layout) navbar.layout.set_brand_text('PyConZA 2019 Financial Aid') navbar.layout.add(Nav(view).with_bookmarks(bookmarks)) if LoginSession.for_current_session().is_logged_in(): navbar.layout.add(LogoutForm(view)) self.layout.header.add_child(navbar)
def with_languages(self): """Populates this Menu with a MenuItem for each available language. Answers the same Menu. .. versionadded: 3.2 """ current_url = Url.get_current_url() context = WebExecutionContext.get_context() supported_locales = ReahlEgg.get_languages_supported_by_all( context.config.reahlsystem.root_egg) for locale in supported_locales: try: language_name = Locale.parse(locale).display_name except UnknownLocaleError: language_name = locale bookmark = self.view.as_bookmark(description=language_name, locale=locale) bookmark.exact = True self.add_bookmark(bookmark) return self
def query_string_on_form_submit(self): form_action = self.web_fixture.driver_browser.get_attribute( '//form', 'action') return Url(form_action).query
class Bookmarks(object): terms_bookmark = BookmarkStub(Url('/#terms'), 'Terms') privacy_bookmark = BookmarkStub(Url('/#privacy'), 'Privacy Policy') disclaimer_bookmark = BookmarkStub(Url('/#disclaimer'), 'Disclaimer')
def new_view(self): """An :class:`UrlBoundView` to use when constructing :class:`Widget`\s for testing.""" current_path = Url(ExecutionContext.get_context().request.url).path view = UrlBoundView(self.user_interface, current_path, 'A view') return view