def percentage_total_is(self, percentage): return self.browser.get_text(self.percentage_cell_for('Totals').inside_of(XPath.table_footer())) == percentage
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 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 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 heading_is_displayed(self): return self.browser.is_element_present( XPath.heading(1).with_text('Addresses'))
def change_value(browser): browser.select(XPath.select_labelled('Choice'), 'Three')
def is_email_listed(self, email): return self.browser.is_element_present( XPath.paragraph().including_text(email))
def is_marked_active(self, link_label, nth=1): [li] = self.driver_browser.xpath('%s/..' % (XPath.link_with_text(link_label, nth=nth))) return 'active' in li.attrib.get('class', '')
def table_summary_is(self, summary): return self.driver_browser.find_element( XPath.table_with_summary(summary))
def select_input(self): self.input_type = SelectInput self.xpath_function_to_choice = XPath.option().with_text
def active_state_of_next_prev_links(self, fixture): """Next and Last links are only active when not on the last range of pages, and Prev and First are similarly deactive when on the first range of pages.""" fixture.number_of_pages = 15 fixture.max_page_links = 5 fixture.reahl_server.set_app(fixture.wsgi_app) fixture.driver_browser.open('/') # Case: when you are on the left of the page range vassert( not fixture.driver_browser.is_active(XPath.link_starting_with_text('←')) ) vassert( not fixture.driver_browser.is_active(XPath.link_starting_with_text('«')) ) vassert( fixture.driver_browser.is_active(XPath.link_starting_with_text('»')) ) vassert( fixture.driver_browser.is_active(XPath.link_starting_with_text('→')) ) # Case: when you are in the middle of the page range fixture.driver_browser.click(XPath.link_starting_with_text('»')) fixture.driver_browser.wait_for_element_present(XPath.link_with_text('p6')) vassert( fixture.driver_browser.is_active(XPath.link_starting_with_text('←')) ) vassert( fixture.driver_browser.is_active(XPath.link_starting_with_text('«')) ) vassert( fixture.driver_browser.is_active(XPath.link_starting_with_text('»')) ) vassert( fixture.driver_browser.is_active(XPath.link_starting_with_text('→')) ) # Case: when you are at the end of the page range fixture.driver_browser.click(XPath.link_starting_with_text('»')) fixture.driver_browser.wait_for_element_present(XPath.link_with_text('p11')) vassert( fixture.driver_browser.is_active(XPath.link_starting_with_text('←')) ) vassert( fixture.driver_browser.is_active(XPath.link_starting_with_text('«')) ) vassert( not fixture.driver_browser.is_active(XPath.link_starting_with_text('»')) ) vassert( not fixture.driver_browser.is_active(XPath.link_starting_with_text('→')) )
def new_domain_exception_alert(self): return XPath.div().including_class('alert').with_text('Please ensure allocation percentages add up to 100')
def percentage_cell_for(self, fund_name): return XPath.table_cell_aligned_to('Percentage', 'Fund', fund_name)
def percentage_input_for(self, fund_name): return XPath.input().inside_of(self.percentage_cell_for(fund_name))
def check_widget_value(browser, value): browser.wait_for(browser.is_element_value, XPath.input_labelled('Calculated'), str(value)) status_text = browser.get_text(XPath.paragraph().including_text('Status: ')) assert 'invalidly_entered' not in status_text
def panel_is_visible(self): return self.web_fixture.driver_browser.is_visible( XPath.paragraph().including_text('Peek-A-Boo'))
def test_invalid_trigger_inputs(web_fixture, query_string_fixture, sql_alchemy_fixture): """Invalid values of trigger inputs are retained, while the calculated values are based on the last valid values in the domain.""" fixture = scenario class ModelObject(Base): __tablename__ = 'test_responsive_disclosure_recalculate_invalids' id = Column(Integer, primary_key=True) choice = Column(Integer, default=1) choice2 = Column(Integer, default=4) choice3 = Column(Integer, default=9) calculated_state = Column(Integer, default=0) def recalculate(self): self.calculated_state = self.choice + self.choice2 def submit(self): raise DomainException(message='An exception happened on submit') @exposed def events(self, events): events.choice_changed = Event(action=Action(self.recalculate)) events.submit = Event(action=Action(self.submit)) @exposed def fields(self, fields): fields.choice = ChoiceField([Choice(1, IntegerField(label='One')), Choice(2, IntegerField(label='Two')), Choice(3, IntegerField(label='Three'))], label='Choice') fields.choice2 = ChoiceField([Choice(4, IntegerField(label='Four')), Choice(5, IntegerField(label='Five')), Choice(6, IntegerField(label='Six'))], label='Choice2') fields.calculated_state = IntegerField(label='Calculated', writable=Allowed(False)) class MyForm(Form): def __init__(self, view, an_object): super(MyForm, self).__init__(view, 'myform') self.use_layout(FormLayout()) self.an_object = an_object self.enable_refresh(on_refresh=an_object.events.choice_changed) if self.exception: self.layout.add_alert_for_domain_exception(self.exception) self.change_trigger_input = TextInput(self, an_object.fields.choice, refresh_widget=self) self.layout.add_input(self.change_trigger_input) self.add_child(P(self.view, text='My choice state is now %s' % an_object.choice)) self.change2_trigger_input = TextInput(self, an_object.fields.choice2, refresh_widget=self) self.layout.add_input(self.change2_trigger_input) self.add_child(P(self.view, text='My choice2 state is now %s' % an_object.choice2)) self.add_child(P(self.view, text='My calculated state is now %s' % an_object.calculated_state)) self.define_event_handler(an_object.events.submit) self.add_child(ButtonInput(self, an_object.events.submit)) class MainWidgetWithPersistentModelObject(Widget): def __init__(self, view): super(MainWidgetWithPersistentModelObject, self).__init__(view) an_object = fixture.model_object self.add_child(MyForm(view, an_object)) with sql_alchemy_fixture.persistent_test_classes(ModelObject): fixture.model_object = ModelObject() Session.add(fixture.model_object) wsgi_app = web_fixture.new_wsgi_app(enable_js=True, child_factory=MainWidgetWithPersistentModelObject.factory()) web_fixture.reahl_server.set_app(wsgi_app) browser = web_fixture.driver_browser browser.open('/') assert browser.wait_for(query_string_fixture.is_state_labelled_now, 'My choice state', 1) assert browser.wait_for(query_string_fixture.is_state_labelled_now, 'My choice2 state', 4) assert browser.wait_for(query_string_fixture.is_state_labelled_now, 'My calculated state', '5') # Case: Entering an invalid value does not trigger a refresh of the input doing the triggering with web_fixture.driver_browser.no_load_expected_for('input[name="myform-choice"]'): browser.type(XPath.input_labelled('Choice'), 'invalid value') # Case: Entering an valid value in a different trigger, triggers a refresh, but last valid value of choice is used browser.type(XPath.input_labelled('Choice2'), '5') assert browser.wait_for(query_string_fixture.is_state_labelled_now, 'My calculated state', '6') # But, the invalid input is retained assert browser.is_element_value(XPath.input_labelled('Choice'), 'invalid value')
def panel_is_expanded(self): return self.is_expanded(XPath.paragraph().including_text('Peek-A-Boo'))
def test_invalid_non_trigger_input_corner_case(web_fixture, query_string_fixture, sql_alchemy_fixture): """If an invalid value was submitted via ajax for a non-trigger input, and a valid value is submitted for is with a form, and a DomainException happens... then the non-trigger input must retain its new, valid value.""" fixture = scenario class ModelObject(Base): __tablename__ = 'test_responsive_disclosure_recalculate_invalids' id = Column(Integer, primary_key=True) choice = Column(Integer, default=1) choice3 = Column(Integer, default=9) calculated_state = Column(Integer, default=0) def recalculate(self): self.calculated_state = self.choice * 10 def submit(self): raise DomainException(message='An exception happened on submit') @exposed def events(self, events): events.choice_changed = Event(action=Action(self.recalculate)) events.submit = Event(action=Action(self.submit)) @exposed def fields(self, fields): fields.choice = ChoiceField([Choice(1, IntegerField(label='One')), Choice(2, IntegerField(label='Two')), Choice(3, IntegerField(label='Three'))], label='Choice') fields.choice3 = ChoiceField([Choice(7, IntegerField(label='Seven')), Choice(8, IntegerField(label='Eight')), Choice(9, IntegerField(label='Nine'))], label='Choice3') fields.calculated_state = IntegerField(label='Calculated', writable=Allowed(False)) class MyForm(Form): def __init__(self, view, an_object): super(MyForm, self).__init__(view, 'myform') self.an_object = an_object self.enable_refresh(on_refresh=an_object.events.choice_changed) if self.exception: self.add_child(P(self.view, text=str(self.exception))) self.change_trigger_input = TextInput(self, an_object.fields.choice, refresh_widget=self) self.add_child(Label(view, for_input=self.change_trigger_input)) self.add_child(self.change_trigger_input) self.add_child(P(self.view, text='My choice state is now %s' % an_object.choice)) self.change3_non_trigger_input = TextInput(self, an_object.fields.choice3) self.add_child(Label(view, for_input=self.change3_non_trigger_input)) self.add_child(self.change3_non_trigger_input) self.add_child(P(self.view, text='My calculated state is now %s' % an_object.calculated_state)) self.define_event_handler(an_object.events.submit) self.add_child(ButtonInput(self, an_object.events.submit)) class MainWidgetWithPersistentModelObject(Widget): def __init__(self, view): super(MainWidgetWithPersistentModelObject, self).__init__(view) an_object = fixture.model_object self.add_child(MyForm(view, an_object)) with sql_alchemy_fixture.persistent_test_classes(ModelObject): fixture.model_object = ModelObject() Session.add(fixture.model_object) wsgi_app = web_fixture.new_wsgi_app(enable_js=True, child_factory=MainWidgetWithPersistentModelObject.factory()) web_fixture.reahl_server.set_app(wsgi_app) browser = web_fixture.driver_browser browser.open('/') assert browser.wait_for(query_string_fixture.is_state_labelled_now, 'My choice state', 1) assert browser.wait_for(query_string_fixture.is_state_labelled_now, 'My calculated state', '10') browser.type(XPath.input_labelled('Choice3'), 'other invalid input') browser.type(XPath.input_labelled('Choice'), '2') browser.press_tab() assert browser.wait_for(query_string_fixture.is_state_labelled_now, 'My calculated state', '20') assert browser.is_element_value(XPath.input_labelled('Choice3'), 'other invalid input') browser.type(XPath.input_labelled('Choice3'), '8') browser.click(XPath.button_labelled('submit')) assert browser.is_element_present(XPath.paragraph().including_text('An exception happened on submit')) assert browser.is_element_value(XPath.input_labelled('Choice3'), '8')
def xpath_to_locate_toggle(self): return XPath('//span[contains(@class,"navbar-toggler-icon")]')
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): return self.browser.is_element_present( XPath.table_cell_with_text(name))
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 change_value(browser): browser.click(XPath.input_labelled('One'))
def error_is_displayed(self, text): return self.web_fixture.driver_browser.is_element_present(XPath.span().including_text(text))
def is_form_blocked(self, browser): form_xpath = XPath('//form[@id="myform"]') form_blocked_xpath = XPath('%s/div[@class="blockUI"]' % form_xpath) return browser.is_element_present(form_blocked_xpath)
def is_email_listed(self, email): return self.browser.is_element_present(XPath.paragraph_containing(email))
def are_all_parts_enabled(self, browser): return browser.is_interactable(XPath.input_labelled('Trigger field')) and \ browser.is_interactable(XPath.input_labelled('Nested trigger field')) and \ browser.is_on_top(XPath.paragraph().including_text('showing nested responsive content'))
def table_caption_is(self, expected): return self.web_fixture.driver_browser.find_element( XPath.caption().with_text(expected))
def is_marked_active(self, link_label, nth=1): [li] = self.web_fixture.driver_browser.xpath('%s/..' % (XPath.link().with_text(link_label).inside_of(XPath.ul().including_class('reahl-menu')[nth]))) return 'active' in li.attrib.get('class', '')