class summary(WaitTab): # noqa TAB_NAME = 'Summary' options = View.nested(SummaryOptionView) chart = GroupedBarChart(id='miq_chart_parent_utilts_0') cpu_table = Table(".//tr/th[contains(text(), 'CPU')]/ancestor::table") memory_table = Table( ".//tr/th[contains(text(), 'Memory')]/ancestor::table")
class TestForm(View): table = Table('#with-thead') table1 = Table('#rowcolspan_table', column_widgets={'First Name': TextInput(locator='./input'), 'Last Name': TextInput(locator='./input'), 'Widget': TextInput(locator='./input'), })
class MethodDetailsView(AutomateExplorerView): title = Text('#explorer_title_text') fqdn = SummaryFormItem( 'Main Info', 'Fully Qualified Name', text_filter=lambda text: [item.strip() for item in text.strip().lstrip('/').split('/')]) name = SummaryFormItem('Main Info', 'Name') display_name = SummaryFormItem('Main Info', 'Display Name') location = SummaryFormItem('Main Info', 'Location') created_on = SummaryFormItem('Main Info', 'Created On', text_filter=parsetime.from_iso_with_utc) inputs = Table(locator='#params_grid', assoc_column='Input Name') script = ScriptBox() embedded_method_table = Table( "//*[@id='embedded_methods_div']/table[contains(@class, 'table')]" ) @property def is_displayed(self): return ( self.in_explorer and self.title.text.startswith('Automate Method [{}'.format( self.context['object'].display_name or self.context['object'].name)) and self.fqdn.is_displayed and # We check namespace separately as in tree there is status included self.fqdn.text[0] in self.context['object'].tree_path_name_only[1] and # We need to chop off the leading Domain name and namespace(cheecked in previous line) self.fqdn.text[1:] == self.context['object'].tree_path_name_only[2:])
class report(WaitTab): # noqa TAB_NAME = 'Report' options = View.nested(ReportOptionView) cpu_table = Table(".//tr/th[contains(text(), 'CPU')]/ancestor::table") memory_table = Table( ".//tr/th[contains(text(), 'Memory')]/ancestor::table") disk_table = Table( ".//tr/th[contains(text(), 'Disk')]/ancestor::table")
class TestForm(View): table = Table("#with-thead") table1 = Table( "#rowcolspan_table", column_widgets={ "First Name": TextInput(locator="./input"), "Last Name": TextInput(locator="./input"), "Widget": TextInput(locator="./input"), }, )
class EventDetailsView(ControlExplorerView): title = Text("#explorer_title_text") toolbar = View.nested(EventDetailsToolbar) true_actions = Table( ".//h3[text()='Order of Actions if ALL Conditions are True']/" "following-sibling::table[1]") false_actions = Table( ".//h3[text()='Order of Actions if ANY Conditions are False']/" "following-sibling::table[1]") @property def is_displayed(self): return (self.in_control_explorer and self.title.text == 'Event "{}"'.format(self.context["object"].context_event))
class ButtonGroupDetailView(AutomateCustomizationView): title = Text("#explorer_title_text") text = SummaryFormItem( "Basic Information", "Text", text_filter=lambda text: re.sub(r"\s+Display on Button\s*$", "", text), ) hover = SummaryFormItem("Basic Information", "Hover Text") assigned_buttons = Table( '//h3[contains(text(), "Basic Information")]/following-sibling::table') @property def is_displayed(self): # Unassigned Buttons is default group for each custom button object obj = self.context["object"] if obj.text == "[Unassigned Buttons]": expected_title = '{} Button Group "{}"'.format( obj.type, "Unassigned Buttons") else: expected_title = (f'Button Group "{obj.text}"' if self.browser.product_version < "5.11" else f'{obj.type} Button Group "{obj.text}"') return (self.in_customization and self.title.text == expected_title and self.buttons.is_opened and not self.buttons.is_dimmed and self.buttons.tree.currently_selected == ["Object Types", obj.type, obj.text])
class ContentViewVersionRemoveView(BaseLoggedInView): breadcrumb = BreadCrumb() table = Table( locator='.//table', column_widgets={ 0: Checkbox(locator="./input[@type='checkbox']"), } ) completely = Checkbox( locator=".//input[@ng-model='deleteOptions.deleteArchive']") next = Text(".//button[@ng-click='processSelection()']") cancel = Text(".//button[normalize-space(.)='Cancel']") @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element( self.breadcrumb, exception=False) return ( breadcrumb_loaded and self.breadcrumb.locations[0] == 'Content Views' and len(self.breadcrumb.locations) == 3 and self.breadcrumb.read() == 'Deletion' and self.next.is_displayed )
class versions(SatTab): searchbox = Search() table = Table( locator='//table', column_widgets={ 'Version': Text('.//a'), 'Status': PublishPromoteProgressBar(), 'Actions': ActionsDropdown( './div[contains(@class, "btn-group")]') }, ) def search(self, version_name): """Searches for content view version. Searchbox can't search by version name, only by id, that's why in case version name was passed, it's transformed into recognizable value before filling, for example:: 'Version 1.0' -> 'version = 1' """ search_phrase = version_name if version_name.startswith('V') and '.' in version_name: search_phrase = 'version = {}'.format( version_name.split()[1].split('.')[0]) self.searchbox.search(search_phrase) return self.table.read()
class FiltersView(BaseLoggedInView): breadcrumb = BreadCrumb() searchbox = Search() new = Text("//a[contains(@href, '/filters/new')]") table = Table( ".//table", column_widgets={ 'Actions': ActionsDropdown("./div[contains(@class, 'btn-group')]"), }, ) pagination = Pagination() @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element(self.breadcrumb, exception=False) return (breadcrumb_loaded and self.breadcrumb.locations[0] == 'Roles' and self.breadcrumb.read().endswith(' filters')) def search(self, query): value = self.searchbox.read() role_id = [int(s) for s in value.split() if s.isdigit()] if len(role_id) > 0: query = f'role_id = {role_id[0]} and resource = "{query}"' self.searchbox.search(query) return self.table.read()
class ListRemoveTab(SatSecondaryTab): TAB_NAME = 'List/Remove' searchbox = Search() remove_button = Text('.//button[@ng-click="removeSelected()"]') table = Table(locator=".//table") no_rows = Text(".//table//span[@data-block='no-rows-message' or " "@data-block='no-search-results-message']") def search(self, value): self.searchbox.search(value) return self.browser.element(self.parent_view.checkbox_locator % value) def remove(self, value): checkbox = self.search(value) checkbox.click() self.remove_button.click() def fill(self, values): if not isinstance(values, list): values = list((values, )) for value in values: self.remove(value) def read(self): if self.no_rows.is_displayed: return [] return [row.name.text for row in self.table.rows()]
class repositories(SatTab): table = Table( locator=".//table", column_widgets={ 'Name': Text("./a"), }, )
class RedHatUpdatesView(RegionView): title = Text('//div[@id="main-content"]//h3[1]') edit_registration = Button('Edit Registration') updates_table = Table("//div[@id='form_div']/table") flash = FlashMessages( './/div[@id="flash_msg_div"]/div[@id="flash_text_div" or ' 'contains(@class, "flash_text_div")]')
class SettingsView(BaseLoggedInView, SearchableViewMixin): title = Text("//h1[text()='Settings']") table = Table( './/table', column_widgets={ 'Value': PopOverWidget() }, ) @SatTab.nested class Email(SatTab): test_email_button = Button(id="test_mail_button") @property def is_displayed(self): return self.browser.wait_for_element( self.title, exception=False) is not None def wait_for_update(self): """Wait for value to update""" wait_for( lambda: not self.table.row()['Value'].widget.header.is_displayed, timeout=30, delay=1, logger=self.logger, )
class TemplatesCompareView(InfraProvidersView): """Compare Templates page.""" title = Text('.//div[@id="center_div" or @id="main-content"]//h1') comparison_table = Table(locator='//div[@id="compare-grid"]/table') @property def is_displayed(self): title = "Compare VM Template and Image" return (self.navigation.currently_selected == ['Compute', 'Infrastructure', 'Providers'] and self.title.text == title) def verify_checked_items_compared(self, checkedList, view): # The first and last header items do not contain template names, so are not iterated upon. for header_with_template in view.comparison_table.headers[1:-1]: try: # Split and slice are used to remove extra characters in the header item checkedList.remove(header_with_template.split(' ')[0]) except ValueError: pytest.fail( f"Entity {header_with_template.split(' ')[0]} is in compare view, " f"but was not checked.") except TypeError: pytest.fail('No entities found in compare view.') if len(checkedList) > 0: pytest.fail( f'Some checked items did not appear in the compare view: {checkedList}.' ) return True
class TestForm(View): table = Table('#withwidgets', column_widgets={ 'Column 2': TextInput(locator='./input'), 'Column 3': TextInput(locator='./input') }, assoc_column=0)
class StoppedChart(View): ROOT = ".//div[@id='stopped-tasks-card']" name = Text("./h2") table = Table(locator='.//table', column_widgets={ 'Total': Text('./button'), })
class images(SatTab, SearchableViewMixin): table = Table( './/table', column_widgets={ 'Actions': ActionsDropdown("./div[contains(@class, 'btn-group')]"), })
class retirement(View): # noqa results = SummaryTable(title='Results') plays = Table('.//table[./thead/tr/th[contains(@align, "left") and ' 'normalize-space(.)="Plays"]]') details = SummaryTable(title='Details') credentials = SummaryTable(title='Credentials') standart_output = Text('.//div[@id="retirement"]//pre')
class AddTab(SatSecondaryTab): TAB_NAME = 'Add' searchbox = Search() add_button = Text('.//div[@data-block="list-actions"]' '//button[contains(@ng-click, "add")]') table = Table(locator=".//table") columns_exists = Text( ".//table//*[contains(name(), 'body')]/tr[1]/td[2]") def search(self, value): self.searchbox.search(value) return self.browser.element(self.parent_view.checkbox_locator % value) def add(self, value): checkbox = self.search(value) checkbox.click() self.add_button.click() def fill(self, values): if not isinstance(values, list): values = list((values, )) for value in values: self.add(value) def read(self): if self.columns_exists.is_displayed: return self.parent_view.table_labels(self.table) return []
class TestForm(View): table = Table( '#withwidgets', column_widgets={ 'Column 2': TextInput(locator='./input'), 'Column 3': TextInput(locator='./input')}, rows_ignore_top=1)
class volume_parts(ParametrizedView): """ Nested view for each volume part. """ PARAMETERS = ("part_id", ) ROOT = ParametrizedLocator( "(.//div[@class='list-group list-view-pf list-view-pf-view" " ng-scope'])[position() = {part_id|quote}]") bricks = Table(".//table", column_widgets={5: Button("Dashboard")}) part_name = Text(".//div[@class='list-group-item-heading " "bold-text sub-volume ng-binding']") brick_count = Text( ".//div[@class='list-view-pf-additional-info-item ng-binding']") utilization = Text(".//utilisation-chart") @classmethod def all(cls, browser): return [ browser.text(e) for e in browser.elements(cls.ALL_VOLUMES) if browser.text(e) is not None and browser.text(e) != '' ] @property def is_expanded(self): return self.browser.elements("div")[0].get_attribute("class").find( "expand" "-active") > 0
class form(View): # noqa tags = Table("//div[@id='assignments_div']//table") tag_category = BootstrapSelect(id='tag_cat') tag_name = BootstrapSelect(id='tag_add') entities = View.nested(BaseNonInteractiveEntitiesView) save = Button('Save') reset = Button('Reset') cancel = Button('Cancel')
class SyncPlansView(BaseLoggedInView, SearchableViewMixin): title = Text("//h2[contains(., 'Sync Plans')]") new = Text("//button[contains(@href, '/sync_plans/new')]") table = Table('.//table', column_widgets={'Name': Text('./a')}) @property def is_displayed(self): return self.browser.wait_for_element(self.title, exception=False) is not None
class containers(SatTab, SearchableViewMixin): table = Table( './/table', column_widgets={ 'Name': Text('./a'), 'Action': ActionsDropdown("./div[contains(@class, 'btn-group')]"), })
class AnsibleExtraVariables(View): """Represents extra variables part of ansible service catalog edit form. Args: tab (str): tab name where this view is located. Can be "provisioning" or "retirement". """ variable = Input(name=ParametrizedString("{@tab}_key")) default_value = Input(name=ParametrizedString("{@tab}_value")) add = Button( **{"ng-click": ParametrizedString("vm.addKeyValue('{@tab}')")}) variables_table = Table( ".//div[@id='variables_div']//table", column_widgets={"Actions": ActionsCell(tab=Parameter("@tab"))}) def __init__(self, parent, tab, logger=None): View.__init__(self, parent, logger=logger) self.tab = tab def _values_to_remove(self, values): return list(map(tuple, set(self.all_vars) - set(values))) def _values_to_add(self, values): return list(map(tuple, set(values) - set(self.all_vars))) def fill(self, values): """ Args: values (list): [] to remove all vars or [("var", "value"), ...] to fill the view. """ if set(values) == set(self.all_vars): return False else: for value in self._values_to_remove(values): rows = list(self.variables_table) for row in rows: if row[0].text == value[0]: row["Actions"].widget.delete.click() break for value in self._values_to_add(values): self.variable.fill(value[0]) self.default_value.fill(value[1]) self.add.click() return True @property def all_vars(self): if self.variables_table.is_displayed: return [(row["Variable"].text, row["Default value"].text) for row in self.variables_table] else: return [] def read(self): return self.all_vars
class retirement(WaitTab): # noqa TAB_NAME = 'Retirement' results = SummaryTable(title='Results') plays = Table('.//table[./thead/tr/th[contains(@align, "left") and ' 'normalize-space(.)="Plays"]]') details = SummaryTable(title='Details') credentials = SummaryTable(title='Credentials') standard_output = Text('.//div[h3[normalize-space(.)="Standard Output"]]' '//div[contains(@class, "term-container")]')
class TestForm(View): table = Table( "#withwidgets", column_widgets={ "Column 2": TextInput(locator="./input"), "Column 3": TextInput(locator="./input"), }, rows_ignore_top=1, )
class TestForm(View): table = Table( "#withwidgets", column_widgets={ "Column 2": TextInput(locator="./input"), "Column 3": TextInput(locator="./input"), }, assoc_column=0, )
class virtual_machines(SatTab, SearchableViewMixin): TAB_NAME = 'Virtual Machines' actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") table = Table('.//table', column_widgets={ 'Name': Text('./a'), 'Actions': Text('.//a[@data-method="put"]'), 'Power': Text('.//span[contains(@class,"label")]'), })
def __init__(self, parent, *args, **kwargs): kwargs['column_widgets'] = self.column_widgets VanillaTable.__init__(self, parent, self.BASELOC.format(quote('Disks')), *args, **kwargs)