def f(_): toplevel_elem = sel.element(toplevel_loc % toplevel) if secondlevel is None: sel.click(toplevel_elem) else: sel.move_to_element(toplevel_elem) sel.click(sel.element(secondlevel_loc % (toplevel, secondlevel)))
def is_selected(self): """Looks whether this option is selected""" self._check_exists() e = sel.element(self.locate(), root=self.root) parent_li = sel.element('..', root=e) return 'active' in (sel.get_attribute(parent_li, 'class') or '') # Ensure it is a str
def deselect(self, *items): self._close_combo() for item in items: sel.click( sel.element( self._remove_button.format(item), root=sel.element(self._root_loc)))
def tree(name, *path): """Get underlying Tree() object. And eventually click path. If the accordion is not active, will be clicked. Attention! The object is 'live' so when it's obscured, it won't work! Usage: accordion.tree("Something").click_path("level 1", "level 2") accordion.tree("Something", "level 1", "level 2") # is the same Args: *path: If specified, it will directly pass these parameters into click_path of Tree. Otherwise it returns the Tree object. """ try: if not is_active(name): click(name) except AccordionItemNotFound: click(name) root_element = sel.element(locate(name)) if sel.is_displayed(DYNATREE, root=root_element): # Dynatree detected tree = Tree(sel.element(DYNATREE, root=root_element)) elif sel.is_displayed(TREEVIEW, root=root_element): # treeview detected el = sel.element(TREEVIEW, root=root_element) tree_id = sel.get_attribute(el, 'id') tree = BootstrapTreeview(tree_id) if path: return tree.click_path(*path) else: return tree
def is_editing(): try: sel.element("//a[contains(@id,'exp_')][contains(text(),'???')]", root=_expressions_root()) return True except NoSuchElementException: return False
def tree(name, *path): """Get underlying Tree() object. And eventually click path. If the accordion is not active, will be clicked. Attention! The object is 'live' so when it's obscured, it won't work! Usage: accordion.tree("Something").click_path("level 1", "level 2") accordion.tree("Something", "level 1", "level 2") # is the same Args: *path: If specified, it will directly pass these parameters into click_path of Tree. Otherwise it returns the Tree object. """ try: if not is_active(name): click(name) except AccordionItemNotFound: click(name) el = sel.element( # | for only single query "|".join([ # Current tree for 5.4 (still with dhx) "../../div[contains(@class, 'dhxcont_global_content_area')]//" "ul[@class='dynatree-container']", # Newer accordion tree "../../..//div[@class='panel-body']//ul[@class='dynatree-container']"]), root=sel.element(locate(name))) tree = Tree(el) if path: return tree.click_path(*path) else: return tree
def is_page_active(toplevel, secondlevel=None): try: if get_current_toplevel_name() != toplevel: return False except NoSuchElementException: return False if secondlevel: try: sel.element( version.pick( { "5.4": ( "//nav[contains(@class, 'navbar')]//ul/li[@class='active']" "/a[normalize-space(.)='{}']/..".format(secondlevel) ), version.LOWEST: ( "//div[@class='navbar']//ul/li[@class='active']" "/a[normalize-space(.)='{}']/..".format(secondlevel) ), } ) ) except NoSuchElementException: return False return True
def dismiss(): """Dismiss the current flash message""" element = sel.element(area.message) if version.current_version() < '5.7': sel.click(element) else: close_button = sel.element('.//button[@class="close"]', root=element) sel.click(close_button)
def text(self, submit=True, text=None): if text is not None: self.clear() sel.element(self.SEARCH_BOX).send_keys(text) if submit: self.submit() else: return sel.element(self.SEARCH_BOX).text
def _content_element(name): """ Element with content of section specified by name Args: name: The name of the accordion. """ root = sel.element(locate(name)) el = sel.element('./../following-sibling::div[1]', root=root) return el
def is_editing(): try: sel.element( "//a[contains(@id,'exp_')][contains(normalize-space(text()),'???')]", root=_expressions_root() ) return True except NoSuchElementException: return False
def _fill_recordgrouper(rg, d): logger.info(" Filling {} with data {}".format(str(rg), str(d))) for row_column_name, content in d.iteritems(): row = rg.table.find_row("column_name", row_column_name) if version.current_version() < "5.7": select = sel.element("./select", root=row.calculations) else: select = sel.element("./div/select", root=row.calculations) select_id = sel.get_attribute(select, "id") fill(AngularSelect(select_id, multi=True), content)
def _content_element(name): """ Element with content of section specified by name Args: name: The name of the accordion. """ root = sel.element(locate(name)) # Older or newer locator el = sel.element('./../following-sibling::div[1]|' './../../following-sibling::div//ul[contains(@class, "nav-stack")]', root=root) return el
def is_internal(self): """ Checks if the link leads internally or not Returns: ``True`` if the element is an internal link, ``False`` if not. """ self._check_exists() el = sel.element(self.locate(), root=self.root) img = sel.element('./img', root=el) if 'internal' in sel.get_attribute(img, 'src'): return True else: return False
def _content_element(name): """ Element with content of section specified by name Args: name: The name of the accordion. """ root = sel.element(locate(name)) # Older or newer locator el = sel.element( './../following-sibling::div[1]|' './../../following-sibling::div//ul[contains(@class, "nav-stack")]', root=root) return el
def is_internal(title): """ Checks if the link leads internally or not Args: title: The title of the button to check. Returns: ``True`` if the element is an internal link, ``False`` if not. """ loc = sel.element(locate(title)) href = sel.get_attribute(loc, 'href').replace(sel.base_url(), '') img = sel.element('//div[@class="panecontent"]//a[@href="%s"]/img' % href) if 'internal' in sel.get_attribute(img, 'src'): return True else: return False
def is_page_active(toplevel, secondlevel=None): try: if get_current_toplevel_name() != toplevel: return False except NoSuchElementException: return False if secondlevel: try: sel.element( ("//nav[contains(@class, 'navbar')]//ul/li[@class='active']" "/a[normalize-space(.)='{}']/..".format(secondlevel))) except NoSuchElementException: return False return True
def is_tab_element_selected(element): """ Determine whether the passed element is selected. This function takes the element, climbs to its parent and looks whether the aria-selected attribute contains true. If yes, element is selected. Args: element: WebElement with the link (a) Returns: :py:class:`bool` """ aria = sel.element("..", root=element).get_attribute("aria-selected") if aria is not None: return "true" in aria.lower() else: return sel.element("..", root=element).get_attribute("class").lower() == "active"
def test_server_name(): """Tests that changing the server name updates the about page""" flash_msg = 'Configuration settings saved for CFME Server "{}' navigate_to(current_appliance.server, 'Server') old_server_name = sel.value(BasicInformation.basic_information.appliance_name) new_server_name = old_server_name + "-CFME" settings_pg = BasicInformation(appliance_name=new_server_name) settings_pg.update() flash.assert_message_contain(flash_msg.format(new_server_name)) # CFME updates about box only after any navigation BZ(1408681) navigate_to(current_appliance.server, 'Dashboard') # if version.current_version() < '5.7': # current_server_name = InfoBlock('Session Information', 'Server Name').text # navigate_to(current_appliance.server, 'About') # else: current_server_name = get_detail('Server Name') close_button = sel.element('//div[contains(@class, "about-modal-pf")]//button[@class="close"]') close_button.click() assert new_server_name == current_server_name, \ "Server name in About section does not match the new name" clear_property_cache(store.current_appliance, 'configuration_details') settings_pg = BasicInformation(appliance_name=old_server_name) settings_pg.update() flash.assert_message_contain(flash_msg.format(old_server_name)) clear_property_cache(store.current_appliance, 'configuration_details')
def select_expression_by_text(text): sel.click( sel.element( "//a[contains(@id,'exp_')][contains(text(),'%s')]" % text, root=_expressions_root() ) )
def _process_user_filling(fill_callback, cancel_on_user_filling=False): """This function handles answering CFME's requests on user input. A `fill_callback` function is passed. If the box with user input appears, all requested inputs are gathered and iterated over. On each element the `fill_callback` function is called with 2 parameters: text which precedes the element itself to do matching, and the element. This function does not check return status after `fill_callback` call. Args: fill_callback: The function to be called on each user input. """ if sel.is_displayed(search_box.quick_search_box): # That is the one with user inputs if fill_callback is None: raise Exception("User should have provided a callback function!") if isinstance(fill_callback, dict): fill_callback = partial(_answering_function, fill_callback) for input in sel.elements( "//fieldset/*[contains(@id, 'value_')]", root=sel.element(search_box.quick_search_box)): fill_callback( # Let the func fill it sel.text(input.find_element_by_xpath("..")), # Parent element's text input # The form element ) if cancel_on_user_filling: sel.click(search_box.userinput_cancel_button) else: sel.click(search_box.userinput_apply_filter_button)
def _move_to_selected(self): """ Clicks the button for moving items from unselected to selected. Returns: :py:class:`bool` with success. """ sel.click(sel.element(self._to_selected)) return not any(map(flash.is_error, flash.get_all_messages()))
def refresh(name): """ Closes and opens accordion Args: name: The name of the accordion. Returns: A web element of the clicked accordion. """ try: el = sel.element(locate(name)) if is_active(name): sel.click(el) for _ in range(3): if sel.is_alert_present(): alert = sel.get_alert() alert.accept() if not is_active(name): sel.click(el, wait_ajax=False) continue else: return el except sel.NoSuchElementException: raise AccordionItemNotFound( "Accordion item '{}' not found!".format(name))
def is_task_finished(tab, page, task_name, expected_status, clear_tasks_after_success=True): el = None try: if not sel.is_displayed(tasks_table) or not tabs.is_tab_selected(tab): sel.force_navigate(page) el = tasks_table.find_row_by_cells({ 'task_name': task_name, 'state': expected_status }) if el is None: return False except Exception: return False # throw exception if status is error if 'Error' in sel.get_attribute(sel.element('.//td/img', root=el), 'title'): raise Exception("Task {} errored".format(task_name)) if clear_tasks_after_success: # Remove all finished tasks so they wouldn't poison other tests toolbar.select('Delete Tasks', 'Delete All', invokes_alert=True) sel.handle_alert(cancel=False) return True
def refresh(name): """ Closes and opens accordion Args: name: The name of the accordion. Returns: A web element of the clicked accordion. """ try: el = sel.element(locate(name)) if is_active(name): sel.click(el) for _ in range(3): if sel.is_alert_present(): alert = sel.get_alert() alert.accept() if not is_active(name): sel.click(el, wait_ajax=False) continue else: return el except sel.NoSuchElementException: raise AccordionItemNotFound("Accordion item '{}' not found!".format(name))
def _get_tooltip(cls, lines, circle_index): for line in lines: cir = line.find_elements_by_tag_name("circle")[circle_index] if 'opacity: 1' in cir.get_attribute('style'): sel.move_to_element(cir) return sel.element('//*[contains(@class, "c3-tooltip-container")]') return None
def select_expression_by_text(text): sel.click( sel.element( "//a[contains(@id,'exp_')][contains(normalize-space(text()),'%s')]" % text, root=_expressions_root() ) )
def row_by_name(self, name): for row in self.rows: row_name = sel.text_sane(sel.element("./td[1]", root=row)) if row_name == name: return row else: raise NameError("Did not find row named {}!".format(name))
def delete(self): sel.force_navigate("my_settings_time_profiles") row = timeprofile_table.find_row_by_cells({"description": self.description}) sel.check(sel.element(".//input[@type='checkbox']", root=row[0])) cfg_btn("Delete selected Time Profiles", invokes_alert=True) sel.handle_alert() flash.assert_success_message('Time Profile "{}": Delete successful'.format(self.description))
def select_expression_by_text(text): sel.click( sel.element( "//a[contains(@id,'exp_')][contains(normalize-space(text()),'{}')]".format(text), root=_expressions_root() ) )
def click(title): """ Clicks an element by title. Args: title: The title of the button to check. """ sel.click(sel.element(locate(title)))
def is_vm_analysis_finished(vm_name): """ Check if analysis is finished - if not, reload page """ el = None try: if not pytest.sel.is_displayed(tasks.tasks_table) or \ not tabs.is_tab_selected('All VM Analysis Tasks'): pytest.sel.force_navigate('tasks_all_vm') el = tasks.tasks_table.find_row_by_cells({ 'task_name': "Scan from Vm {}".format(vm_name), 'state': 'finished' }) if el is None: return False except: return False # throw exception if status is error if 'Error' in sel.get_attribute(sel.element('.//td/img', root=el), 'title'): raise Exception("Smart State Analysis errored") # Remove all finished tasks so they wouldn't poison other tests tb.select('Delete Tasks', 'Delete All', invokes_alert=True) sel.handle_alert(cancel=False) return True
def _process_user_filling(fill_callback, cancel_on_user_filling=False): """This function handles answering CFME's requests on user input. A `fill_callback` function is passed. If the box with user input appears, all requested inputs are gathered and iterated over. On each element the `fill_callback` function is called with 2 parameters: text which precedes the element itself to do matching, and the element. This function does not check return status after `fill_callback` call. Args: fill_callback: The function to be called on each user input. """ if sel.is_displayed( search_box.quick_search_box): # That is the one with user inputs if fill_callback is None: raise Exception("User should have provided a callback function!") if isinstance(fill_callback, dict): fill_callback = partial(_answering_function, fill_callback) for input in sel.elements("//fieldset/*[contains(@id, 'value_')]", root=sel.element( search_box.quick_search_box)): fill_callback( # Let the func fill it sel.text(input.find_element_by_xpath( "..")), # Parent element's text input # The form element ) if cancel_on_user_filling: sel.click(search_box.userinput_cancel_button) else: sel.click(search_box.userinput_apply_filter_button)
def get_clickable_tab(ident_string): """ Returns the relevant tab element that can be clicked on. Args: ident_string: The text diplayed on the tab. """ return sel.element(".//li/a[contains(text(), '%s')]" % ident_string, root=_root())
def selected_items(self): self._close_combo() return [ sel.text(item).encode("utf-8") for item in sel.elements(self._selected, root=sel.element(self._root_loc)) ]
def tree(name, *path): """Get underlying Tree() object. And eventually click path. If the accordion is not active, will be clicked. Attention! The object is 'live' so when it's obscured, it won't work! Usage: accordion.tree("Something").click_path("level 1", "level 2") accordion.tree("Something", "level 1", "level 2") # is the same Args: *path: If specified, it will directly pass these parameters into click_path of Tree. Otherwise it returns the Tree object. """ click(name) tree = Tree( sel.first_from( # Current tree "../../div[contains(@class, 'dhxcont_global_content_area')]//" "ul[@class='dynatree-container']", # Legacy tree "../../div[contains(@class, 'dhxcont_global_content_area')]//" "div[@class='containerTableStyle']//table[not(ancestor::tr[contains(@style,'none')])]", root=sel.element(locate(name)) ) ) if path: return tree.click_path(*path) else: return tree
def tree(name, *path): """Get underlying Tree() object. And eventually click path. If the accordion is not active, will be clicked. Attention! The object is 'live' so when it's obscured, it won't work! Usage: accordion.tree("Something").click_path("level 1", "level 2") accordion.tree("Something", "level 1", "level 2") # is the same Args: *path: If specified, it will directly pass these parameters into click_path of Tree. Otherwise it returns the Tree object. """ try: if not is_active(name): logger.debug( 'Clicking accordion item %s because it is not active.', name) click(name) except AccordionItemNotFound: logger.debug( 'Clicking accordion item %s because AccordionItemNotFound raised.', name) click(name) locator = locate(name) # Wait a bit for any of the trees to appear wait_for(lambda: sel.is_displayed(ANY_TREE, root=locator), quiet=True, silent_failure=True, delay=0.2, timeout=5) if sel.is_displayed(DYNATREE, root=locator): # Dynatree detected tree = Tree(sel.element(DYNATREE, root=locator)) elif sel.is_displayed(TREEVIEW, root=locator): # treeview detected el = sel.element(TREEVIEW, root=locator) tree_id = sel.get_attribute(el, 'id') tree = BootstrapTreeview(tree_id) else: raise TypeError('None of the supported trees was detected.') if path: return tree.click_path(*path) else: return tree
def is_tab_element_selected(element): """ Determine whether the passed element is selected. This function takes the element, climbs to its parent and looks whether the aria-selected attribute contains true. If yes, element is selected. Args: element: WebElement with the link (a) Returns: :py:class:`bool` """ aria = sel.element("..", root=element).get_attribute("aria-selected") if aria is not None: return "true" in aria.lower() else: return sel.element("..", root=element)\ .get_attribute("class")\ .lower() in {"active", "active-single"}
def sort_by(sort): """ Changes the sort by field. Args: sort: Value to sort by (visible text in select box) """ select = sel.element(_locator + _sort_by) sel.select(Select(select), sel.ByText(sort))
def results_per_page(num): """ Changes the number of results on a page. Args: num: Number of results per page """ select = sel.element(_locator + _num_results) sel.select(Select(select), sel.ByText(str(num)))
def _check_repo(name, callback=None): if current_version() >= '5.4': quadicon = Quadicon(name, "repository") sel.check(quadicon.checkbox()) else: sel.check(sel.element('.//img', root=_repo_row(name)[0])) if callback: return callback()
def select_field(self, field): """Select field by text. Args: field: Field text. """ sel.click(sel.element(self._field.format(field), root=self.root)) wait_for(lambda: self.selected_field is not None, num_sec=5, delay=0.1)
def select(self, *items): for item in items: if item not in self.selected_items: with self.combo as combo: sel.click( sel.element( "./div/div[contains(., '{}')]".format(item), root=combo))
def __init__(self, widget_box_id): self.root = lambda: sel.element( version.pick({ version.LOWEST: "//div[@id='{}']//div[contains(@class, 'modbox')]", '5.5': "//div[@id='{}']//div[contains(@class, 'panel-body')]" }).format(widget_box_id))
def test_edit_default_group(): flash_msg = 'Read Only EVM Group "{}" can not be edited' group = ac.Group(description='EvmGroup-approver') sel.force_navigate("cfg_accesscontrol_groups") row = group_table.find_row_by_cells({'Name': group.description}) sel.check(sel.element(".//input[@type='checkbox']", root=row[0])) tb.select('Configuration', 'Edit the selected Group') flash.assert_message_match(flash_msg.format(group.description))
def get_clickable_tab(ident_string): """ Returns the relevant tab element that can be clicked on. Args: ident_string: The text diplayed on the tab. """ return sel.element( ".//li/a[contains(normalize-space(text()), '{}')]".format(ident_string), root=_root())