diff options
Diffstat (limited to 'openstack_dashboard/test/integration_tests/regions/tables.py')
-rw-r--r-- | openstack_dashboard/test/integration_tests/regions/tables.py | 157 |
1 files changed, 155 insertions, 2 deletions
diff --git a/openstack_dashboard/test/integration_tests/regions/tables.py b/openstack_dashboard/test/integration_tests/regions/tables.py index 9778950b3..6d9334edd 100644 --- a/openstack_dashboard/test/integration_tests/regions/tables.py +++ b/openstack_dashboard/test/integration_tests/regions/tables.py @@ -45,6 +45,12 @@ class RowRegion(baseregion.BaseRegion): chck_box.click() +class RowRegionNG(RowRegion): + """Angular-based table row.""" + + _cell_locator = (by.By.CSS_SELECTOR, 'td > hz-cell') + + class TableRegion(baseregion.BaseRegion): """Basic class representing table object.""" @@ -253,6 +259,38 @@ class TableRegion(baseregion.BaseRegion): self.assertDictEqual(actual_table, expected_table_definition) +class TableRegionNG(TableRegion): + """Basic class representing angular-based table object.""" + + _heading_locator = (by.By.CSS_SELECTOR, + 'hz-resource-panel hz-page-header h1') + _empty_table_locator = (by.By.CSS_SELECTOR, 'tbody > tr > td.no-rows-help') + + def _table_locator(self, table_name): + return by.By.CSS_SELECTOR, 'hz-dynamic-table' + + @property + def _next_locator(self): + return by.By.CSS_SELECTOR, 'a[ng-click^="selectPage(currentPage + 1)"]' + + @property + def _prev_locator(self): + return by.By.CSS_SELECTOR, 'a[ng-click^="selectPage(currentPage - 1)"]' + + @property + def column_names(self): + names = [] + for element in self._get_elements(*self._columns_names_locator): + if element.text: + names.append(element.text) + return names + + def _get_rows(self, *args): + return [RowRegionNG(self.driver, self.conf, elem, self.column_names) + for elem in self._get_elements(*self._rows_locator) + if elem.text and elem.text != ''] + + def bind_table_action(action_name): """Decorator to bind table region method to an actual table action button. @@ -290,6 +328,44 @@ def bind_table_action(action_name): return decorator +def bind_table_action_ng(action_name): + """Decorator to bind table region method to an actual table action button. + + This decorator works with angular-based tables. + Many table actions when started (by clicking a corresponding button + in UI) lead to some form showing up. To further interact with this form, + a Python/ Selenium wrapper needs to be created for it. It is very + convenient to return this newly created wrapper in the same method that + initiates clicking an actual table action button. Binding the method to a + button is performed behind the scenes in this decorator. + + .. param:: action_name + + Part of the action button id which is specific to action itself. It + is safe to use action `name` attribute from the dashboard tables.py + code. + """ + _actions_locator = (by.By.CSS_SELECTOR, + 'actions.hz-dynamic-table-actions > action-list') + + def decorator(method): + @functools.wraps(method) + def wrapper(table): + actions = table._get_elements(*_actions_locator) + action_element = None + for action in actions: + if action.text == action_name: + action_element = action + break + if action_element is None: + msg = "Could not bind method '%s' to action control '%s'" % ( + method.__name__, action_name) + raise ValueError(msg) + return method(table, action_element) + return wrapper + return decorator + + def bind_row_action(action_name): """A decorator to bind table region method to an actual row action button. @@ -347,11 +423,67 @@ def bind_row_action(action_name): return decorator +def bind_row_action_ng(action_name): + """A decorator to bind table region method to an actual row action button. + + This decorator works with angular-based tables. + Many table actions when started (by clicking a corresponding button + in UI) lead to some form showing up. To further interact with this form, + a Python/ Selenium wrapper needs to be created for it. It is very + convenient to return this newly created wrapper in the same method that + initiates clicking an actual action button. Row action could be + either primary (if its name is written right away on row action + button) or secondary (if its name is inside of a button drop-down). Binding + the method to a button and toggling the button drop-down open (in case + a row action is secondary) is performed behind the scenes in this + decorator. + + .. param:: action_name + + Part of the action button id which is specific to action itself. It + is safe to use action `name` attribute from the dashboard tables.py + code. + """ + primary_action_locator = ( + by.By.CSS_SELECTOR, + 'td.actions_column > actions > action-list > button.split-button') + secondary_actions_opener_locator = ( + by.By.CSS_SELECTOR, + 'td.actions_column > actions > action-list > button.split-caret') + secondary_actions_locator = ( + by.By.CSS_SELECTOR, + 'td.actions_column > actions > action-list > ul > li > a') + + def decorator(method): + @functools.wraps(method) + def wrapper(table, row): + def find_action(element): + pattern = action_name + return element.text.endswith(pattern) + + action_element = row._get_element(*primary_action_locator) + if not find_action(action_element): + action_element = None + row._get_element(*secondary_actions_opener_locator).click() + for element in row._get_elements(*secondary_actions_locator): + if find_action(element): + action_element = element + break + + if action_element is None: + msg = "Could not bind method '%s' to action control '%s'" % ( + method.__name__, action_name) + raise ValueError(msg) + return method(table, action_element, row) + return wrapper + return decorator + + def bind_row_anchor_column(column_name): """A decorator to bind table region method to a anchor in a column. - Typical examples of such tables are Project -> Compute -> Images, Admin - -> System -> Flavors, Project -> Compute -> Instancies. + Typical examples of such tables are Project -> Compute -> Instances, Admin + -> System -> Flavors. The method can be used to follow the link in the anchor by the click. """ @@ -365,3 +497,24 @@ def bind_row_anchor_column(column_name): return wrapper return decorator + + +def bind_row_anchor_column_ng(column_name): + """A decorator to bind table region method to a anchor in a column. + + This decorator works with angular-based tables. + Typical examples of such tables are Project -> Compute -> Images, + Admin -> Compute -> Images. + The method can be used to follow the link in the anchor by the click. + """ + + def decorator(method): + @functools.wraps(method) + def wrapper(table, row): + cell = row.cells[column_name] + action_element = cell.find_element( + by.By.CSS_SELECTOR, 'td > hz-cell > a') + return method(table, action_element, row) + + return wrapper + return decorator |