def test_out_of_bound_widgets(web_fixture): """When you need to add a widget to the page, but not as a child/descendant.""" class MyPanel(Div): def __init__(self, view): super().__init__(view, css_id='main_panel') child_widget = self.add_child(P(view, text='Child Widget')) out_of_bound_widget = view.add_out_of_bound_widget( P(view, text='Out Of Bound Widget')) class MainUI(UserInterface): def assemble(self): self.define_page(HTML5Page).use_layout(BasicPageLayout()) home = self.define_view('/', title='Hello') home.set_slot('main', MyPanel.factory()) fixture = web_fixture wsgi_app = fixture.new_wsgi_app(site_root=MainUI) browser = Browser(wsgi_app) browser.open('/') main_panel = XPath.div().with_id('main_panel') assert browser.is_element_present( XPath.paragraph().with_text('Out Of Bound Widget')) assert not browser.is_element_present(XPath.paragraph().with_text( 'Out Of Bound Widget').inside_of(main_panel)) assert browser.is_element_present( XPath.paragraph().with_text('Child Widget').inside_of(main_panel))
def test_edit_and_add_own(web_fixture, access_domain_fixture, access_ui_fixture): """The owner of an AddressBook can add and edit Addresses to the owned AddressBook.""" browser = access_ui_fixture.browser fixture = access_domain_fixture account = fixture.account address_book = fixture.address_book web_fixture.log_in(browser=browser, system_account=account) browser.open('/') browser.click(XPath.link().with_text('Address book of [email protected]')) # add browser.click(XPath.link().with_text('Add address')) browser.type(XPath.input_labelled('Name'), 'Someone') browser.type(XPath.input_labelled('Email'), '*****@*****.**') browser.click(XPath.button_labelled('Save')) assert browser.is_element_present( XPath.paragraph().including_text('Someone: [email protected]')) # edit browser.click(XPath.button_labelled('Edit')) browser.type(XPath.input_labelled('Name'), 'Else') browser.type(XPath.input_labelled('Email'), '*****@*****.**') browser.click(XPath.button_labelled('Update')) assert browser.is_element_present( XPath.paragraph().including_text('Else: [email protected]'))
def test_refresh_widget_with_expired_csrf_token(web_fixture, csrf_fixture): """An Ajax request done with a valid expired token, shows a validation exception. After refresh, a new token is received and submit works.""" fixture = csrf_fixture wsgi_app = web_fixture.new_wsgi_app(child_factory=fixture.MyForm.factory(), enable_js=True) web_fixture.reahl_server.set_app(wsgi_app) browser = web_fixture.driver_browser wsgi_app.config.reahlsystem.debug = False #causes redirect to the error page and not stacktrace browser.open('/') select_widget_path = XPath.select_labelled('choice') assert browser.get_value(select_widget_path) == '1' wsgi_app.config.web.csrf_timeout_seconds = 0.5 time.sleep(wsgi_app.config.web.csrf_timeout_seconds + 0.1) browser.select(select_widget_path, '2', wait_for_ajax=False) wsgi_app.config.web.csrf_timeout_seconds = 300 with browser.alert_expected() as js_alert: assert js_alert.text == 'This page has expired. For security reasons, please review your input and retry.' js_alert.accept() #case: new csrftoken received in GET assert browser.get_value(select_widget_path) == '1' assert browser.wait_for_element_not_present( XPath.paragraph().with_text('Chosen: 2')) browser.select(select_widget_path, '2') assert browser.wait_for_element_present( XPath.paragraph().with_text('Chosen: 2')) assert browser.wait_for_not(browser.is_alert_present)
def test_see_other(web_fixture, access_domain_fixture, access_ui_fixture): """If allowed, an account may see another account's AddressBook, and could edit or add Addresses, depending on the allowed rights.""" browser = access_ui_fixture.browser account = access_domain_fixture.account address_book = access_domain_fixture.address_book other_address_book = access_domain_fixture.other_address_book other_address_book.allow(account) Address(address_book=other_address_book, email_address='*****@*****.**', name='Friend').save() web_fixture.log_in(browser=browser, system_account=account) browser.open('/') browser.click(XPath.link().with_text('Address book of [email protected]')) assert browser.is_element_present( XPath.paragraph().including_text('Friend: [email protected]')) # Case: can only see assert not browser.is_element_enabled( XPath.link().with_text('Add address')) assert not browser.is_element_enabled(XPath.button_labelled('Edit')) # Case: can edit only other_address_book.allow(account, can_edit_addresses=True, can_add_addresses=False) browser.refresh() assert not browser.is_element_enabled( XPath.link().with_text('Add address')) assert browser.is_element_enabled(XPath.button_labelled('Edit')) # Case: can add, and therefor also edit other_address_book.allow(account, can_add_addresses=True) browser.refresh() assert browser.is_element_enabled(XPath.link().with_text('Add address')) assert browser.is_element_enabled(XPath.button_labelled('Edit')) browser.click(XPath.button_labelled('Edit')) browser.type(XPath.input_labelled('Name'), 'Else') browser.type(XPath.input_labelled('Email'), '*****@*****.**') browser.click(XPath.button_labelled('Update')) assert browser.is_element_present( XPath.paragraph().including_text('Else: [email protected]'))
def test_views_with_parameters(web_fixture, parameterised_scenarios): """Views can have arguments that originate from code, or are parsed from the URL.""" class UIWithParameterisedViews(UserInterface): def assemble(self): self.define_view('/aview', view_class=fixture.ParameterisedView, some_arg=fixture.argument) class MainUI(UserInterface): def assemble(self): self.define_page(HTML5Page).use_layout(BasicPageLayout()) self.define_user_interface('/a_ui', UIWithParameterisedViews, {'main': 'main'}, name='myui') fixture = parameterised_scenarios wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI) browser = Browser(wsgi_app) if fixture.should_exist: browser.open(fixture.url) assert browser.title == 'View for: %s' % fixture.expected_value assert browser.is_element_present(XPath.paragraph().including_text( 'content for %s' % fixture.expected_value)) else: browser.open(fixture.url, status=404)
def test_submit_form_with_expired_csrf_token(web_fixture, csrf_fixture): """A form submitted with a valid expired token, shows a validation exception. After refresh, a new token is received and submit works.""" fixture = csrf_fixture wsgi_app = web_fixture.new_wsgi_app(child_factory=fixture.MyForm.factory(), enable_js=True) web_fixture.reahl_server.set_app(wsgi_app) browser = web_fixture.driver_browser browser.open('/') select_widget_path = XPath.select_labelled('choice') assert browser.get_value(select_widget_path) == '1' browser.select(select_widget_path, '2') wsgi_app.config.web.csrf_timeout_seconds = 0.5 time.sleep(wsgi_app.config.web.csrf_timeout_seconds + 0.1) browser.click(XPath.button_labelled('Submit')) wsgi_app.config.web.csrf_timeout_seconds = 300 error_message = XPath.paragraph().including_text( 'This page has expired. For security reasons, please review your input and retry.' ) assert browser.is_element_present(error_message) #case: submit again should work now - new csrftoken received in GET browser.click(XPath.button_labelled('Submit')) assert not browser.is_element_present(error_message)
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]'))
def test_addressbook2(web_fixture, addressbook2_scenario): browser = Browser(addressbook2_scenario.wsgi_app) browser.open('/') browser.type(XPath.input_labelled('Name'), 'John') browser.type(XPath.input_labelled('Email'), '*****@*****.**') browser.click(XPath.button_labelled('Save')) assert browser.is_element_present(XPath.paragraph().including_text('John: [email protected]'))
def test_language_menu(web_fixture): """A Nav can also be constructed to let a user choose to view the same page in another of the supported languages.""" class PanelWithMenu(Div): def __init__(self, view): super().__init__(view) self.add_child(Menu(view).with_languages()) self.add_child(P(view, text=_('This is an English sentence.'))) wsgi_app = web_fixture.new_wsgi_app(child_factory=PanelWithMenu.factory()) browser = Browser(wsgi_app) browser.open('/') assert browser.is_element_present(XPath.paragraph().including_text('This is an English sentence.')) browser.click(XPath.link().with_text('Afrikaans')) assert browser.is_element_present(XPath.paragraph().including_text('Hierdie is \'n sin in Afrikaans.')) browser.click(XPath.link().with_text('English (United Kingdom)')) assert browser.is_element_present(XPath.paragraph().including_text('This is an English sentence.'))
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]'))
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_logging_in(web_fixture, login_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 = login_fixture.browser login_fixture.new_account() 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 [email protected]'))
def test_optimistic_concurrency_forms(web_fixture, sql_alchemy_fixture, concurrency_fixture): """When a form cannot be found anymore while submitting, we also assume it is because of changing data, this time sending the user to an error page after resetting view data. """ fixture = concurrency_fixture fixture.show_form = True class FormContainer(Widget): def __init__(self, view): super().__init__(view) if fixture.show_form: self.add_child(fixture.MyForm(view)) with sql_alchemy_fixture.persistent_test_classes(fixture.ModelObject): model_object = fixture.model_object Session.add(model_object) model_object.some_field = 'some value' wsgi_app = web_fixture.new_wsgi_app( child_factory=FormContainer.factory()) web_fixture.reahl_server.set_app(wsgi_app) browser = web_fixture.driver_browser browser.open('/') # When submitting a form that is not present on the page anymore, user is ferried to an error page browser.type(XPath.input_labelled('Some field'), 'something else') fixture.show_form = False browser.click(XPath.button_labelled('Submit')) error_text = XPath.paragraph().with_text( 'Something changed on the server while you were busy. You cannot perform this action anymore.' ) assert browser.current_url.path == '/error' assert browser.is_element_present(error_text) # When presented with such an error, the user can click on a button to reset all inputs to the now-current values fixture.show_form = True # So we can check that form data was nuked browser.click(XPath.link().with_text('Ok')) assert browser.current_url.path == '/' # Went back assert browser.get_value( XPath.input_labelled('Some field') ) == 'some value' # Form fields were cleared should the form now appear again
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'))
def test_parameterised1(web_fixture, parameterised1_scenario): browser = Browser(parameterised1_scenario.wsgi_app) browser.open('/') browser.click(XPath.link().with_text('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 == '/' browser.click(XPath.link().with_text('edit')) john = Session.query(parameterised1.Address).one() assert browser.current_url.path == '/edit/%s' % john.id browser.type(XPath.input_labelled('Name'), 'Johnny') browser.type(XPath.input_labelled('Email'), '*****@*****.**') browser.click(XPath.button_labelled('Update')) assert browser.current_url.path == '/' assert browser.is_element_present(XPath.paragraph().including_text('Johnny: [email protected]'))
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 test_edit_other(web_fixture, access_domain_fixture, access_ui_fixture): """If you may only edit (not add) an address, then you may only edit the email address, not the name.""" browser = access_ui_fixture.browser address_book = access_domain_fixture.address_book account = access_domain_fixture.account other_address_book = access_domain_fixture.other_address_book other_address_book.allow(account, can_edit_addresses=True, can_add_addresses=True) Address(address_book=other_address_book, email_address='*****@*****.**', name='Friend').save() web_fixture.log_in(browser=browser, system_account=account) browser.open('/') browser.click(XPath.link().with_text('Address book of [email protected]')) browser.click(XPath.button_labelled('Edit')) # Case: may edit name assert browser.is_element_enabled(XPath.input_labelled('Name')) assert browser.is_element_enabled(XPath.input_labelled('Email')) # Case: may not edit name other_address_book.allow(account, can_edit_addresses=True, can_add_addresses=False) browser.refresh() assert not browser.is_element_enabled(XPath.input_labelled('Name')) assert browser.is_element_enabled(XPath.input_labelled('Email')) browser.type(XPath.input_labelled('Email'), '*****@*****.**') browser.click(XPath.button_labelled('Update')) assert browser.is_element_present( XPath.paragraph().including_text('Friend: [email protected]'))
def test_adding_an_address(web_fixture): """To add a new address, a user clicks on "Add Address" link on the menu, then supplies the information for the new address and clicks the Save button. Upon successful addition of the address, the user is returned to the home page where the new address is now listed.""" browser = Browser(web_fixture.new_wsgi_app(site_root=AddressBookUI)) browser.open('/') browser.click(XPath.link().with_text('Add')) actual_title = browser.title assert actual_title == 'Add', 'Expected to be on the Add an address page' browser.type(XPath.input_labelled('Name'), 'John Doe') browser.type(XPath.input_labelled('Email'), '*****@*****.**') browser.click(XPath.button_labelled('Save')) actual_title = browser.title assert actual_title == 'Show', 'Expected to be back on the home page after editing' assert browser.is_element_present(XPath.paragraph().including_text('John Doe: [email protected]')), \ 'Expected the newly added address to be listed on the home page'
def is_refreshing_element_displayed(self): return self.web_fixture.driver_browser.is_element_present( XPath.paragraph().including_text('Hello'))
def panel_is_expanded(self): return self.is_expanded(XPath.paragraph().including_text('Peek-A-Boo'))
def panel_is_visible(self): return self.web_fixture.driver_browser.is_visible( XPath.paragraph().including_text('Peek-A-Boo'))
def check_counter_value_is(self, counter_value): assert self.browser.is_element_present(XPath.paragraph().with_text( 'Counter: %s' % counter_value))
def text_shows_selected(self, expected_selected): return self.browser.is_element_present( XPath.paragraph().including_text('You selected link number %s' % expected_selected))
def address_is_listed_as(self, name, email_address): return self.browser.is_element_present( XPath.paragraph().including_text('%s: %s' % (name, email_address)))
def is_email_listed(self, email): return self.browser.is_element_present(XPath.paragraph().including_text(email))
def coactive_widget_text_is(expected_text): return web_fixture.driver_browser.is_element_present( XPath.paragraph().including_text(expected_text))
def address_is_listed_as(self, name, email_address, is_new): new = ' (new)' if is_new else '' return self.browser.is_element_present( XPath.paragraph().including_text('%s: %s%s' % (name, email_address, new)))
def is_state_labelled_now(self, label, state): return self.web_fixture.driver_browser.is_element_present( XPath.paragraph().including_text('%s is now %s' % (label, state)))