def _get_state(): navigate_to(cls, 'Saved') row = records_table.find_row("queued_at", queued_at) status = sel.text(row.status).strip().lower() assert status != "error", sel.text(row) return status == version.pick({"5.6": "finished", "5.7": "complete"})
def on_details(self, force=False): """A function to determine if the browser is already on the proper image details page. """ locator = ( "//div[@class='dhtmlxInfoBarLabel' and contains(. , 'Image \"{}\"')]" .format(self.name)) # If the locator isn't on the page, or if it _is_ on the page and contains # 'Timelines' we are on the wrong page and take the appropriate action if not sel.is_displayed(locator): wrong_page = True else: wrong_page = 'Timelines' in sel.text(locator) if wrong_page: if not force: return False else: self.load_details() return True text = sel.text(locator).encode("utf-8") pattern = r'("[A-Za-z0-9_\./\\-]*")' import re m = re.search(pattern, text) if not force: return self.name == m.group().replace('"', '') else: if self.name != m.group().replace('"', ''): self.load_details() return True else: return True
def queue_canned_report(*path): """Queue report from selection of pre-prepared reports. Args: *path: Path in tree after All Reports Returns: Value of Run At in the table so the run can be then checked. """ sel.force_navigate("report_canned_info", context={"path": path}) toolbar.select("Queue") flash.assert_no_errors() tabstrip.select_tab("Saved Reports") queued_at = sel.text(list(records_table.rows())[0].queued_at) def _get_state(): row = records_table.find_row("queued_at", queued_at) status = sel.text(row.status).strip().lower() assert status != "error", sel.text(row) return status == "finished" wait_for( _get_state, delay=1, message="wait for report generation finished", fail_func=reload_view ) return sel.text(list(records_table.rows())[0].run_at).encode("utf-8")
def queue_canned_report(cls, path): """Queue report from selection of pre-prepared reports. Args: *path: Path in tree after All Reports Returns: Value of Run At in the table so the run can be then checked. """ cls.path = path navigate_to(cls, "Info") toolbar.select("Queue") flash.assert_no_errors() tabstrip.select_tab("Saved Reports") queued_at = sel.text(list(records_table.rows())[0].queued_at) def _get_state(): navigate_to(cls, 'Saved') row = records_table.find_row("queued_at", queued_at) status = sel.text(row.status).strip().lower() assert status != "error", sel.text(row) return status == version.pick({"5.6": "finished", "5.7": "complete"}) wait_for( _get_state, delay=3, message="wait for report generation finished", fail_func=toolbar.refresh() ) return sel.text(list(records_table.rows())[0].run_at).encode("utf-8")
def data(self): """Retrieves data from the saved report. Returns: :py:class:`SavedReportData` if it is not a candu report. If it is, then it returns a list of groups in the table. """ navigate_to(self, "Details") if isinstance(self._table, CAndUGroupTable): return list(self._table.groups()) try: headers = tuple( [sel.text(hdr).encode("utf-8") for hdr in self._table.headers]) body = [] for page in paginator.pages(): for row in self._table.rows(): row_data = tuple([ sel.text(row[header]).encode("utf-8") for header in headers ]) body.append(row_data) except sel.NoSuchElementException: # No data found return SavedReportData([], []) else: return SavedReportData(headers, body)
def get_current_menu_state(self): """Returns the current menu state This function returns what each level of the menu is pointing to, or None, if that level of menu is unused. Future work could possibly see this method using recursion to allow unlimited levels of menu to be used, however it is unlikely that more than 3 will ever be used. """ lev = [None, None, None] lev[0] = (sel.text(self.CURRENT_TOP_MENU).encode("utf-8").strip()) if version.current_version() < "5.6.0.1": try: lev[1] = sel.text("//nav[contains(@class, 'navbar')]//ul/li[@class='active']/a") \ .encode("utf-8").strip() except NoSuchElementException: pass else: lev[1] = sel.text("{}{}".format( self.CURRENT_TOP_MENU, self.ACTIVE_LEV)).encode("utf-8").strip() try: lev[2] = sel.text("{}{}{}".format( self.CURRENT_TOP_MENU, self.ACTIVE_LEV, self.ACTIVE_LEV)).encode( "utf-8").strip() except NoSuchElementException: pass return lev
def get_current_menu_state(self): """Returns the current menu state This function returns what each level of the menu is pointing to, or None, if that level of menu is unused. Future work could possibly see this method using recursion to allow unlimited levels of menu to be used, however it is unlikely that more than 3 will ever be used. """ lev = [None, None, None] lev[0] = (sel.text(self.CURRENT_TOP_MENU).encode("utf-8").strip()) if version.current_version() < "5.6.0.1": try: lev[1] = sel.text("//nav[contains(@class, 'navbar')]//ul/li[@class='active']/a") \ .encode("utf-8").strip() except NoSuchElementException: pass else: lev[1] = sel.text( "{}{}".format(self.CURRENT_TOP_MENU, self.ACTIVE_LEV)).encode("utf-8").strip() try: lev[2] = sel.text( "{}{}{}".format(self.CURRENT_TOP_MENU, self.ACTIVE_LEV, self.ACTIVE_LEV)).encode("utf-8").strip() except NoSuchElementException: pass return lev
def on_details(self, force=False): """A function to determine if the browser is already on the proper instance details page. """ locator = ("//div[@class='dhtmlxInfoBarLabel' and contains(. , 'Instance \"%s\"')]" % self.name) # If the locator isn't on the page, or if it _is_ on the page and contains # 'Timelines' we are on the wrong page and take the appropriate action if not sel.is_displayed(locator): wrong_page = True else: wrong_page = 'Timelines' in sel.text(locator) if wrong_page: if not force: return False else: self.load_details() return True text = sel.text(locator).encode("utf-8") pattern = r'("[A-Za-z0-9_\./\\-]*")' import re m = re.search(pattern, text) if not force: return self.name == m.group().replace('"', '') else: if self.name != m.group().replace('"', ''): self.load_details() return True else: return True
def queue(self, wait_for_finish=False): navigate_to(self, 'Details') toolbar.select("Queue") flash.assert_no_errors() tabstrip.select_tab("Saved Reports") if wait_for_finish: # Get the queued_at value to always target the correct row queued_at = sel.text(list(records_table.rows())[0].queued_at) def _get_state(): navigate_to(self, 'Saved') row = records_table.find_row("queued_at", queued_at) status = sel.text(row.status).strip().lower() assert status != "error", sel.text(row) return status == version.pick({ "5.6": "finished", "5.7": "complete" }) wait_for( _get_state, delay=1, message="wait for report generation finished", fail_func=toolbar.refresh(), num_sec=300, )
def get_relevant_rows(table): result = [] for row in table.rows(): text = sel.text(row.label).encode("utf-8").strip() if text.startswith("test_paginator_"): result.append(text) return result
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 test_modify_host_condition(random_host_condition): with update(random_host_condition): random_host_condition.notes = "Modified!" flash.assert_no_errors() sel.force_navigate("host_condition", context={"condition_name": random_host_condition.description}) assert sel.text(random_host_condition.form.notes).strip() == "Modified!"
def test_modify_host_control_policy(random_host_control_policy): with update(random_host_control_policy): random_host_control_policy.notes = "Modified!" flash.assert_no_errors() sel.force_navigate("host_control_policy", context={"policy_name": random_host_control_policy.description}) assert sel.text(random_host_control_policy.form.notes).strip() == "Modified!"
def test_modify_policy_profile(): global profile with update(profile): profile.notes = "Modified!" flash.assert_no_errors() sel.force_navigate("policy_profile", context={"policy_profile_name": profile.description}) assert sel.text(profile.form.notes).strip() == "Modified!"
def go_to_default_func(_): """This can change, because the title of the default dashboard is mutable. However, we can xpath there quite reliable, so we use it that way we extract the name from the tree directly. """ t = "//li[@id='db_xx-1' or @id='dashboards_xx-1']/span/a" accordion.click("Dashboards") accordion.tree("Dashboards", "All Dashboards", sel.text(t).encode("utf-8"))
def test_verify_rss_links(appliance): navigate_to(appliance.server, 'RSS') for row in rss_table.rows(): url = sel.text(row["feed_url"]).strip() req = requests.get(url, verify=False) assert 200 <= req.status_code < 400, "The url {} seems malformed".format( repr(url))
def headers(cls): navigate_to(MiddlewareDomain, 'All') headers = [ sel.text(hdr).encode("utf-8") for hdr in sel.elements("//thead/tr/th") if hdr.text ] return headers
def visible_toplevel_tabs(): menu_names = [] ele = 'li/a[2]' for menu_elem in sel.elements(ele, root=toplevel_tabs_loc): menu_names.append(sel.text(menu_elem)) return menu_names
def headers(cls): sel.force_navigate('middleware_servers') headers = [ sel.text(hdr).encode("utf-8") for hdr in sel.elements("//thead/tr/th") if hdr.text ] return headers
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 current_snapshot_name(self): """Returns the current snapshot name.""" self.load_details(refresh=True) sel.click(InfoBlock("Properties", "Snapshots")) text = sel.text( "//a[contains(normalize-space(.), '(Active)')]").strip() return re.sub(r"\s*\(Active\)$", "", text)
def current_snapshot_name(self): """Returns the current snapshot name.""" self.load_details(refresh=True) sel.click(InfoBlock("Properties", "Snapshots")) text = sel.text("//a[contains(normalize-space(.), '(Active)')]|" "//li[contains(normalize-space(.), '(Active)')]").strip() return re.sub(r"\s*\(Active\)$", "", text)
def mapping(self): """Determine mapping Menu item => menu item id. Needed because the boxes with shortcuts are accessible only via ids. Need to close boxes because boxes displayed are not in the Select. """ # Save opened boxes closed_boxes = [] for box_id in self.opened_boxes_ids: closed_boxes.append((self.get_text_of(box_id), box_id)) self.close_box(box_id) # Check the select result = {} for option in self.select.options: try: result[sel.text(option)] = int( sel.get_attribute(option, "value")) except (ValueError, TypeError): pass # Restore box layout for name, id in closed_boxes: sel.select(self.select, sel.ByValue(str(id))) self.set_text_of(id, name) return result
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 selected_field(self): """Return selected field's text. Returns: :py:class:`str` if field is selected, else `None` """ sf = self.selected_field_element return None if sf is None else sel.text(sf).encode("utf-8").strip()
def on_details(self, force=False): """A function to determine if the browser is already on the proper vm details page. Args: vm_name: VM name that you are looking for. force: If its not on the right page, load it. provider_name: name of provider the vm resides on. datacenter_name: When passed with provider_name, allows navigation through tree when navigating to the vm """ locator = ( "//div[@class='dhtmlxInfoBarLabel' and contains(. , 'VM and Instance \"%s\"')]" % self.name) if not sel.is_displayed(locator): if not force: return False else: self.load_details() return True text = sel.text(locator).encode("utf-8") pattern = r'("[A-Za-z0-9_\./\\-]*")' import re m = re.search(pattern, text) if not force: return self.name == m.group().replace('"', '') else: if self.name != m.group().replace('"', ''): self.load_vm_details() else: return False
def headers(cls, domain): _get_server_groups_page(domain=domain) headers = [ sel.text(hdr).encode("utf-8") for hdr in sel.elements("//thead/tr/th") if hdr.text ] return headers
def on_details(self, force=False): """A function to determine if the browser is already on the proper vm details page. Args: vm_name: VM name that you are looking for. force: If its not on the right page, load it. provider_name: name of provider the vm resides on. datacenter_name: When passed with provider_name, allows navigation through tree when navigating to the vm """ locator = ("//div[@class='dhtmlxInfoBarLabel' and contains(. , 'VM and Instance \"%s\"')]" % self.name) if not sel.is_displayed(locator): if not force: return False else: self.load_details() return True text = sel.text(locator).encode("utf-8") pattern = r'("[A-Za-z0-9_\./\\-]*")' import re m = re.search(pattern, text) if not force: return self.name == m.group().replace('"', '') else: if self.name != m.group().replace('"', ''): self.load_vm_details() else: return False
def _old_visible_toplevel_tabs(self): """Method returning the visible toplevel_tabs in 5.4""" menu_names = [] ele = 'li/a[2]' for menu_elem in sel.elements(ele, root=self.toplevel_tabs_loc): menu_names.append(sel.text(menu_elem)) return menu_names
def get_tags(tag="My Company Tags"): tags = [] tagpath = "//*[(self::th or self::td) and normalize-space(.)={}]/../.."\ "//td[img[contains(@src, 'smarttag')]]" if current_version() < '5.8'\ else "//td[i[contains(@class, 'fa-tag')]]" for row in sel.elements(tagpath.format(quoteattr(tag))): tags.append(sel.text(row).strip()) return tags
def get_tags(self): sel.force_navigate('clouds_stack', context={'stack': self}) row = sel.elements( "//*[(self::th or self::td) and normalize-space(.)={}]/../.." "//td[img[contains(@src, 'smarttag')]]".format( quoteattr("My Company Tags"))) company_tag = sel.text(row).strip() return company_tag
def create_service_dialog(self, dialog_name): sel.force_navigate('orch_template_type', context={'template_type': self.template_type}) if(self.template_type == "CloudFormation Templates"): template_name = sel.text("//li[@id='ot_xx-otcfn']/ul" "//a[contains(@class, 'dynatree-title')]").encode("utf-8") else: template_name = sel.text("//li[@id='ot_xx-othot']/ul" "//a[contains(@class, 'dynatree-title')]").encode("utf-8") sel.force_navigate('create_service_dialog', context={'template_type': self.template_type, 'template_name': template_name}) fill(dialog_form, {'dialog_name': dialog_name}, action=dialog_form.save_button) flash.assert_success_message('Service Dialog "{}" was successfully created'.format( dialog_name)) return template_name
def visible_toplevel_tabs(): menu_names = [] ele = version.pick({ "5.4": 'li/a[2]', version.LOWEST: 'li/a'}) for menu_elem in sel.elements(ele, root=Loc.toplevel_tabs_loc): menu_names.append(sel.text(menu_elem)) return menu_names
def current_snapshot_name(self): """Returns the current snapshot name.""" self.load_details(refresh=True) sel.click(InfoBlock("Properties", "Snapshots")) text = sel.text("//a[contains(normalize-space(.), '(Active)')]|" "//li[contains(normalize-space(.), '(Active)')]").strip() # In 5.6 the locator returns the entire tree string, snapshot name is after a newline return re.sub(r"\s*\(Active\)$", "", text.split('\n')[-1:][0])
def create_service_dialog(self, dialog_name): sel.force_navigate('orch_template_type', context={'template_type': self.template_type}) if(self.template_type == "CloudFormation Templates"): template_name = sel.text("//li[@id='ot_xx-otcfn']/ul" "//a[contains(@class, 'dynatree-title')]").encode("utf-8") else: template_name = sel.text("//li[@id='ot_xx-othot']/ul" "//a[contains(@class, 'dynatree-title')]").encode("utf-8") sel.force_navigate('create_service_dialog', context={'template_type': self.template_type, 'template_name': template_name}) fill(dialog_form, {'dialog_name': dialog_name}, action=dialog_form.save_button) flash.assert_success_message('Service Dialog "%s" was successfully created' % dialog_name) return template_name
def simulate(**data): """Runs the simulation of specified Automate object. If `attribute` is not specified, will be chosen randomly. Args: **data: See :py:data:`sim_form` for keyword reference """ sel.force_navigate("automate_simulation") if data.get("attribute", None) is None: t = sel.text(sim_form.attribute[0].options[1]).encode("utf-8") sel.select(sim_form.attribute[0], t) selection = sel.text(sim_form.attribute[1].options[1]).encode("utf-8") data["attribute"] = [t, selection] fill(sim_form, data, action=sim_btn) flash.assert_message_match("Automation Simulation has been run") flash.assert_no_errors()
def get_tags(self): navigate_to(self, 'Details') row = sel.elements( "//*[(self::th or self::td) and normalize-space(.)={}]/../.." "//td[img[contains(@src, 'smarttag')]]".format( quoteattr("My Company Tags"))) company_tag = sel.text(row).strip() return company_tag
def step(self): """This can change, because the title of the default dashboard is mutable. However, we can xpath there quite reliable, so we use it that way we extract the name from the tree directly """'' t = version.pick({ "5.6": "//li[@id='db_xx-1' or @id='dashboards_xx-1']/span/a", "5.7": "//li[@data-nodeid='0.0.0' and @class = 'list-group-item node-db_treebox']"}) accordion.tree("Dashboards", "All Dashboards", sel.text(t).encode("utf-8"))
def get_tags(tag="My Company Tags"): tags = [] for row in sel.elements( "//*[(self::th or self::td) and normalize-space(.)={}]/../.." "//td[img[contains(@src, 'smarttag')]]".format( quoteattr(tag))): tags.append(sel.text(row).strip()) return tags
def data(self): """Retrieves data from the saved report. Returns: :py:class:`SavedReportData` """ self.navigate() try: headers = tuple([sel.text(hdr).encode("utf-8") for hdr in self._table.headers]) body = [] for page in paginator.pages(): for row in self._table.rows(): row_data = tuple([sel.text(row[header]).encode("utf-8") for header in headers]) body.append(row_data) except sel.NoSuchElementException: # No data found return SavedReportData([], []) else: return SavedReportData(headers, body)
def data(self): result = [] for row in sel.elements("./div/table/tbody/tr/td", root=self.root): # Regular expressions? Boring. desc, date = sel.text(row).encode("utf-8").strip().rsplit("\n", 1) date = date.split(":", 1)[-1].strip() date = parsetime.from_iso_with_utc(date) result.append((desc, date)) return result
def get_saved_reports_for(name): sel.force_navigate("saved_reports_for", context={"report_name": name}) dates = [] try: for row in reports_table.rows(): dates.append(sel.text(row.queued_at).encode("utf-8").strip()) except sel.NoSuchElementException: pass return dates
def get_current_toplevel_name(): """Returns text of the currently selected top level menu item.""" get_rid_of_the_menu_box() return sel.text( version.pick({ "5.4": "//ul[@id='maintab']/li[not(contains(@class, 'drop'))]/a[2]", "5.3": "//ul[@id='maintab']/li[not(contains(@class, 'in'))]/a", version.LOWEST: "//ul[@id='maintab']/li/ul[not(contains(@style, 'none'))]/../a" })).encode("utf-8").strip()
def test_group_edit_tag(): group = new_group() group.create() group.edit_tags("Cost Center *", "Cost Center 001") row = sel.elements("//*[(self::th or self::td) and normalize-space(.)={}]/../.." "//td[img[contains(@src, 'smarttag')]]".format(quoteattr("My Company Tags"))) tag = sel.text(row).strip() assert tag == "Cost Center: Cost Center 001", "Group edit tag failed" group.delete()
def current_username(): """ Returns the current username. Returns: the current username. """ if logged_in(): return sel.text(page.user_dropdown).split('|')[0].strip() else: return None
def message(el): """ Turns an element into a :py:class:`Message` object. Args: el: The element containing the flass message. Returns: A :py:class:`Message` object. """ return Message(message=sel.text(el), level=sel.get_attribute(el, 'class'))