class TasksItemModel(contentviews.ListViewRowModel): """ An item (row) in a Tasks list. """ def _instance_identifier(self): """ instance identifier: line number - 1 """ return self._name - 1 # Design: https://redhat.invisionapp.com/share/8N93NO7Q4 status_icon = StatusIcon( by=By.XPATH, locator="./div/i") name_label = PageElement( by=By.XPATH, locator="./div[2]/a") name = name_label task_id = PageElement( by=By.XPATH, locator="./div[2]/p") submitted = PageElement( by=By.XPATH, locator="./div[3]/p[2]") status = PageElement( by=By.XPATH, locator="./div[4]/p")
class ClustersRowModel(contentviews.ListViewRowModel): """ Row in Cluster table model. """ # https://github.com/Tendrl/specifications/pull/82 # # TODO # https://redhat.invisionapp.com/share/BR8JDCGSQ#/screens/185937524 # No status icon yet # status_icon = StatusIcon(By.XPATH, '') # name_text = PageElement(by=By.XPATH, locator='.//div[contains(@class, "cluster-name")]') name = name_text cluster_version = PageElement( by=By.XPATH, locator='.//div[contains(text(),"Cluster Version")]' '/following-sibling::*') managed = PageElement( by=By.XPATH, locator='.//div[contains(text(),"Managed")]/following-sibling::*') volume_profile = PageElement( by=By.XPATH, locator='.//div[contains(text(),"Volume Profile")]' '/following-sibling::*') import_btn = form.Button( By.XPATH, '//button[@ng-click="clusterCntrl.goToImportFlow(cluster)"]')
class NavMenuBarsModel(UpperMenuModel): """ Common page model for the main page - navigation. """ # left navbar nodes_link = PageElement(by=By.LINK_TEXT, locator="Hosts") volumes_link = PageElement(by=By.LINK_TEXT, locator="Volumes") tasks_link = PageElement(by=By.LINK_TEXT, locator='Tasks') events_link = PageElement(by=By.LINK_TEXT, locator='Events')
class UserMenuModel(WebstrModel): """ Common page model for main page - user actions drop down menu """ _base_locator = '//*[contains(@class, "dropdown user")]'\ '/*[contains(@class, "dropdown-menu")]/..' _root = RootPageElement(by=By.XPATH, locator=_base_locator + '/ul[./li]') my_settings = PageElement(by=By.LINK_TEXT, locator="My Settings") logout = PageElement(by=By.LINK_TEXT, locator="Logout")
class TaskEventModel(DynamicWebstrModel): """ An item (row) in a Tasks list. """ _root = NameRootPageElement(by=By.ID, locator='log-list-group-item-%d') # Design: https://redhat.invisionapp.com/share/8N93NO7Q4 # missing status icon # status_icon = StatusIcon( # by=By.XPATH, # locator="./div/i") status_text = PageElement(by=By.XPATH, locator="./div[2]") message = PageElement(by=By.XPATH, locator="./div[3]") time = PageElement(by=By.XPATH, locator="./div[4]")
class TaskDetailsModel(WebstrModel): """ task details page model """ tasks_link = PageElement(By.LINK_TEXT, locator="Tasks") name_id = PageElement( by=By.XPATH, locator="//li[./a[text()='Tasks']]/following-sibling::li/span") submitted = PageElement( by=By.XPATH, locator="//label[text()='Time Submitted:']/following-sibling::label") status = PageElement( by=By.XPATH, locator="//label[text()='Status:']/following-sibling::label") status_icon = StatusIcon( by=By.XPATH, locator="//label[text()='Status:']/following-sibling::label/i")
class ClustersMenuModel(ListMenuModel): """ Clusters page top menu """ header = PageElement( by=By.XPATH, locator="//h1[contains(text(),'Clusters')]")
class GenericStatPanelModel(WebstrModel): """ Generic model for displaying some data NOTE: _title (string): title of the panel it has to be properly set before use e.g. "Volume Utilization" """ _title = None _root = NameRootPageElement( By.XPATH, '//grafana-panel[.//span[contains(@class, "panel-title-text") and ' 'text()="%s"]]') header = PageElement(By.XPATH, './/span[contains(class, "panel-title-text")]') def __init__(self, driver): """ Save the webdriver instance to attribute. Parameters: driver: webdriver instance """ self._name = self._title super().__init__(driver)
class HostsItemModel(contentviews.ListViewRowModel): """ An item (row) in a Hosts list. """ def _instance_identifier(self): """ instance identifier: line number - 1 """ return self._name - 1 # Design: https://redhat.invisionapp.com/share/BR8JDCGSQ status_icon = StatusIcon( by=By.XPATH, locator=".//i[contains(@ng-class,'host.status')]") name_label = PageElement( by=By.XPATH, locator=".//div[contains(@class,'host-name')]") name = name_label gluster_label = PageElement( by=By.XPATH, locator=".//div[contains(text(),'Gluster Version')]") gluster_value = PageElement( by=By.XPATH, locator=".//div[contains(text(),'Gluster Version')]" "/following-sibling::*") roles_label = PageElement( by=By.XPATH, locator=".//div[contains(text(),'Role')]") roles_value = PageElement( by=By.XPATH, locator=".//div[contains(text(),'Role')]/following-sibling::*") bricks_label = PageElement( by=By.XPATH, locator=".//div[contains(text(),'Bricks')]") bricks_value = PageElement( by=By.XPATH, locator=".//div[contains(text(),'Bricks')]/following-sibling::*") alerts_label = PageElement( by=By.XPATH, locator=".//div[contains(text(),'Alerts')]") alerts_value = PageElement( by=By.XPATH, locator=".//div[contains(text(),'Alerts')]/following-sibling::*") dashboard_btn = form.Button( by=By.XPATH, locator=".//button[contains(@class,'dashboard-btn')]")
class AlertModel(WebstrModel): """ model for any alert/notice message """ _root = RootPageElement(By.XPATH, '//div[contains(@class, "alert")]') priority = StatusIcon(By.XPATH, './span') message = PageElement(By.XPATH, './strong') close_btn = form.Button(By.XPATH, './button')
class ImportClusterModel(ListMenuModel): """ model for Import Cluster - Configure Cluster page """ label = PageElement(By.XPATH, '//h1') profile_check = form.Checkbox(By.NAME, "volumeProfile") import_btn = form.Button(By.XPATH, '//button[contains(text(), "Import")]') cancel_btn = form.Button(By.XPATH, '//button[contains(text(), "Cancel")]')
class UserManagementModel(WebstrModel): """ Common page model for main page - user management drop down menu """ _base_locator = '//*[contains(@class, "dropdown admin")]'\ '/*[contains(@class, "dropdown-menu")]/..' _root = RootPageElement(by=By.XPATH, locator=_base_locator + '/ul[./li]') users = PageElement(by=By.LINK_TEXT, locator="Users")
class ModalWindowModel(WebstrModel): """ Base page model class for any modal window. """ _root = RootPageElement(by=By.XPATH, locator="//div[contains(@class, 'modal-dialog')]") header = PageElement(by=By.XPATH, locator=".//div[contains(@class, 'modal-header')]") body = PageElement(by=By.XPATH, locator=".//div[contains(@class, 'modal-body')]") footer = PageElement(by=By.XPATH, locator=".//div[contains(@class, 'modal-footer')]") # we expect that the title is always there title = PageElement(by=By.XPATH, locator=".//*[contains(@class, 'modal-title')]") # there is always a close button (in the right side of the header) close_btn = PageElement(by=By.XPATH, locator=".//button[@class='close']")
class TabsModel(WebstrModel): """ Tabs allow to display more pages at one place by changing tab. See: https://www.patternfly.org/widgets/#tabs """ TABS_XPATH = '//ul[contains(@class,"nav nav-tabs")]' _root = RootPageElement(By.XPATH, TABS_XPATH) tabs = PageElement(by=By.XPATH, locator=TABS_XPATH + "/li/a", as_list=True)
class HostsItemModel(contentviews.ListViewRowModel): """ An item (row) in a Hosts list. """ name_label = PageElement( by=By.XPATH, locator=".//div[contains(@class, 'host-name')]") release = PageElement( by=By.XPATH, locator=".//div[contains(@class, 'host-release')]") name = name_label role = PageElement( By.XPATH, ".//div[contains(@class, 'list-view-pf-additional-info')]/div[2]") _root = NameRootPageElement( by=By.XPATH, locator='({}//*[contains(concat(" ", @class, " "),' ' " list-group-item ")][@ng-repeat])[%d]'.format( contentviews.ListViewModel.LIST_XPATH))
class HostsListModel(contentviews.ListViewModel): """ Page model for list of nodes/hosts. """ rows = PageElement( by=By.XPATH, locator="{}//*[contains(concat(' ', @class, ' ')," " ' list-group-item ')][@ng-repeat]".format( contentviews.ListViewModel.LIST_XPATH), as_list=True)
class LoginPageModel(WebstrModel): """ Common page model for the login page. """ username = form.TextInput(by=By.ID, locator='username') password = form.PasswordInput(by=By.ID, locator='password') login_btn = form.Button(by=By.XPATH, locator='//*[contains(@class,"btn-lg")]') error_label = PageElement(by=By.XPATH, locator='//*[@ng-bind="loginCntrl.errorMsg"]/..')
class TasksMenuModel(FilterListMenuModel): """ Tasks page top menu """ header = PageElement(by=By.XPATH, locator="//h1[contains(text(),'Tasks')]") from_input = form.TextInput( By.XPATH, '//div[@ng-model="taskCntrl.date.fromDate"]/input') to_input = form.TextInput( By.XPATH, '//div[@ng-model="taskCntrl.date.toDate"]/input')
class UpperMenuModel(WebstrModel): """ Common model for upper menu """ # right part of upper navbar # TODO add context switcher drop-down list element # left part of upper navbar # TODO: waiting for fix of https://github.com/Tendrl/ui/issues/839 # users_link = PageElement(By.ID, locator="usermanagement") # alerts_link = PageElement(By.ID, locator="notifications") user_link = PageElement(By.ID, locator="usermenu")
class UpperMenuModel(WebstrModel): """ Common model for upper menu """ # left part of upper navbar # events_link # node_discovery_link # tasks_link # about_link # notifications_link user_link = PageElement(By.ID, locator="usermenu")
class TasksMenuModel(WebstrModel): """ Tasks page top menu """ header = PageElement(by=By.XPATH, locator="//h1[contains(text(),'Tasks')]") filter_by = form.Select(By.XPATH, '//select[contains(@ng-model, "filterBy")]') filter_input = form.TextInput(By.ID, 'filter') from_input = form.TextInput( By.XPATH, '//div[@ng-model="taskCntrl.date.fromDate"]/input') to_input = form.TextInput( By.XPATH, '//div[@ng-model="taskCntrl.date.toDate"]/input')
class TableViewModel(WebstrModel): """ The table view organizes data into rows (of items) and columns (of item attributes). See: https://www.patternfly.org/patterns/table-view/ """ TABLE_XPATH = '//table[@role = "grid"]' _root = RootPageElement(By.XPATH, TABLE_XPATH) rows = PageElement(by=By.XPATH, locator=TABLE_XPATH + '/tbody//tr[@role="row"]', as_list=True)
class TaskEventsModel(WebstrModel): """ Page model for list of tasks events. """ LIST_XPATH = '//*[contains(concat(" ", @class, " "), '\ '" div-with-scroll-logs ")]' _root = RootPageElement(By.XPATH, LIST_XPATH) # header is a row too rows = PageElement( by=By.XPATH, locator=LIST_XPATH + "//*[contains(concat(' ', @class, ' ')," " ' list-group-item ')]", as_list=True)
class ListViewModel(WebstrModel): """ A List View displays data in rows. Each row displays the same set of attributes, although not necessarily displayed in columns, and the attributes may wrap. See: https://www.patternfly.org/list-view/ Note: we are interested only for the list view presented in the correct container hence //*[contains(@class, "col-md-12")] """ LIST_XPATH = '//*[contains(concat(" ", @class, " "), " list-view-pf ")]' _root = RootPageElement(By.XPATH, LIST_XPATH) rows = PageElement( by=By.XPATH, locator=LIST_XPATH + "//*[contains(concat(' ', @class, ' '), ' list-group-item ')]", as_list=True)
class GenericDropDownListModel(WebstrModel): """ Grafana DropDown list """ _title = None _root = NameRootPageElement( By.XPATH, '//label[text()="%s"]/following::value-select-dropdown') rows = PageElement(By.XPATH, './/a[contains(@class, "variable-option")]', as_list=True) def __init__(self, driver): """ Save the webdriver instance to attribute. Parameters: driver: webdriver instance """ self._name = self._title super().__init__(driver)
class NavMenuBarsModel(UpperMenuModel): """ Common page model for the main page - navigation. """ # TODO # Coming soon... # # right part of upper navbar # left navbar # dashboard_link = PageElement(by=By.LINK_TEXT, locator="Dashboard") clusters_link = PageElement(by=By.LINK_TEXT, locator="Clusters") nodes_link = PageElement(by=By.LINK_TEXT, locator="Hosts") alerts_link = PageElement(by=By.LINK_TEXT, locator="Alerts") admin_link = PageElement(by=By.LINK_TEXT, locator="Admin") # Admin sub-menu links tasks_link = PageElement(by=By.LINK_TEXT, locator='Tasks') tasks_link = PageElement(by=By.LINK_TEXT, locator='Users')
class FilterListMenuModel(BaseListMenuModel): """ auxiliary model for list menu (filter and order fields) NOTE: Click on filter_by and order_by opens a menu with some links such links has will be instanced from Page object a _link_text parameter will be used e.g. name = PageElement(by=By.LINK_TEXT, locator="Name") """ filter_by = form.Button( By.XPATH, '//button[contains(translate(@uib-tooltip, "F", "f"), "filter by")]') filter_by_value = DynamicPageElement(by=By.LINK_TEXT, locator="%s") # TODO In some cases the following is Button # in other case it's real TextInput # if not be aware with value property usage filter_input = form.TextInput(By.XPATH, '//div[contains(@ng-if, "filterType")]') filter_input_value = filter_by_value order_by = form.Button(By.XPATH, '(//*[@id="hostSort"]//button)[1]') # note the element is present only if some filter is active clear_all_filters = PageElement(by=By.LINK_TEXT, locator="Clear All Filters")
class ModalDlgModel(WebstrModel): """ Base page model for modal dialogs. """ background_veil = PageElement(By.CSS_SELECTOR, 'div.gwt-PopupPanelGlass')
class ErrorDialogModel(CloseDlgModel): """ dialog with error message model """ _root = RootPageElement(by=By.XPATH, locator='//div[@class="gwt-DialogBox dialogBoxStyle"]') close_btn = models.Button(By.XPATH, '//div[@role="button"][contains(., "Close")]') error = PageElement(By.XPATH, '//div[@class="gwt-HTML"]')
class UserMenuModel(dropdown.DropDownMenuModel): """ Common page model for main page - user page """ logout = PageElement(by=By.LINK_TEXT, locator="Logout")