7b16bbf920
Add simple test for page under /Project/Data Processing/Image Registry, that registers and unregisters an image in the Sahara registry. Infrastructure changes needed by the test: - new page object with basic handling of the Image Registry page; - new ssh_user config option with the cloud-init username for the image (named after the corresponding tempest option); - new parameter in get_row() table method for exact match; - add "wait-until-active" method for the Image page; - enable sahara service by default in horizon.conf. Partially implements blueprint: selenium-integration-testing Co-Authored-By: Luigi Toscano <ltoscano@redhat.com> Change-Id: I1e389f0baff655f8f06a0a6cbb4a10b9a68dd444
232 lines
8.1 KiB
Python
232 lines
8.1 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
|
|
from selenium.webdriver.common import by
|
|
|
|
from openstack_dashboard.test.integration_tests.regions import baseregion
|
|
from openstack_dashboard.test.integration_tests.regions import menus
|
|
|
|
|
|
class RowRegion(baseregion.BaseRegion):
|
|
"""Classic table row."""
|
|
|
|
_cell_locator = (by.By.CSS_SELECTOR, 'td.normal_column')
|
|
|
|
@property
|
|
def cells(self):
|
|
return self._get_elements(*self._cell_locator)
|
|
|
|
|
|
class BaseActionRowRegion(RowRegion):
|
|
"""Base class for creating ActionRow class derivative."""
|
|
|
|
_row_checkbox_locator = (by.By.CSS_SELECTOR, 'td > input')
|
|
|
|
def mark(self):
|
|
chck_box = self._get_element(*self._row_checkbox_locator)
|
|
chck_box.click()
|
|
|
|
|
|
class BtnActionRowRegion(BaseActionRowRegion):
|
|
"""Row with buttons in action column."""
|
|
|
|
_action_locator = (by.By.CSS_SELECTOR, 'td.actions_column > button')
|
|
|
|
def __init__(self, driver, conf, src_elem, action_name):
|
|
super(BtnActionRowRegion, self).__init__(driver, conf, src_elem)
|
|
self.action_name = action_name
|
|
self._init_action()
|
|
|
|
def _init_action(self):
|
|
self._init_dynamic_property(self.action_name, self._get_action)
|
|
|
|
def _get_action(self):
|
|
return self._get_element(*self._action_locator)
|
|
|
|
@property
|
|
def action(self):
|
|
return self._get_action()
|
|
|
|
|
|
class ComplexActionRowRegion(BaseActionRowRegion):
|
|
"""Row with button and select box in action column."""
|
|
|
|
_primary_action_locator = (by.By.CSS_SELECTOR,
|
|
'td.actions_column > div.btn-group > *.btn')
|
|
_secondary_actions_dropdown_locator = (by.By.CSS_SELECTOR,
|
|
'div.btn-group')
|
|
|
|
PRIMARY_ACTION = "primary_action"
|
|
SECONDARY_ACTIONS = "secondary_actions"
|
|
|
|
ACTIONS_ERROR_MSG = ("Actions must be supplied in dictionary:"
|
|
" {%s: 'action_name', '%s': ('action_name',...)}"
|
|
% (PRIMARY_ACTION, SECONDARY_ACTIONS))
|
|
|
|
def __init__(self, driver, conf, src_elem, action_names):
|
|
super(ComplexActionRowRegion, self).__init__(driver, conf, src_elem)
|
|
try:
|
|
self.primary_action_name = action_names[self.PRIMARY_ACTION]
|
|
self.secondary_action_names = action_names[self.SECONDARY_ACTIONS]
|
|
self._init_actions()
|
|
except (TypeError, KeyError):
|
|
raise AttributeError(self.ACTIONS_ERROR_MSG)
|
|
|
|
def _init_actions(self):
|
|
self._init_dynamic_property(self.primary_action_name,
|
|
self._get_primary_action)
|
|
self._init_dynamic_properties(self.secondary_action_names,
|
|
self._get_secondary_actions)
|
|
|
|
def _get_primary_action(self):
|
|
return self._get_element(*self._primary_action_locator)
|
|
|
|
def _get_secondary_actions(self):
|
|
src_elem = self._get_element(*self._secondary_actions_dropdown_locator)
|
|
dropdown = menus.DropDownMenuRegion(self.driver, self.conf, src_elem)
|
|
return dropdown.menu_items
|
|
|
|
@property
|
|
def primary_action(self):
|
|
return self._get_primary_action()
|
|
|
|
@property
|
|
def secondary_actions(self):
|
|
return self._get_secondary_actions()
|
|
|
|
|
|
class BasicTableRegion(baseregion.BaseRegion):
|
|
"""Basic class representing table object."""
|
|
|
|
_heading_locator = (by.By.CSS_SELECTOR, 'h3.table_title')
|
|
_columns_names_locator = (by.By.CSS_SELECTOR, 'thead > tr > th')
|
|
_footer_locator = (by.By.CSS_SELECTOR, 'tfoot > tr > td > span')
|
|
_rows_locator = (by.By.CSS_SELECTOR, 'tbody > tr')
|
|
_empty_table_locator = (by.By.CSS_SELECTOR, 'tbody > tr.empty')
|
|
_search_field_locator = (by.By.CSS_SELECTOR,
|
|
'div.table_search.client > input')
|
|
_search_button_locator = (by.By.CSS_SELECTOR,
|
|
'div.table_search.client > button')
|
|
|
|
@property
|
|
def heading(self):
|
|
return self._get_element(*self._heading_locator)
|
|
|
|
@property
|
|
def rows(self):
|
|
if self._is_element_present(*self._empty_table_locator):
|
|
return []
|
|
else:
|
|
return self._get_rows()
|
|
|
|
@property
|
|
def column_names(self):
|
|
return self._get_elements(*self._columns_names_locator)
|
|
|
|
@property
|
|
def footer(self):
|
|
return self._get_element(*self._footer_locator)
|
|
|
|
def filter(self, value):
|
|
self._set_search_field(value)
|
|
self._click_search_btn()
|
|
|
|
def get_row(self, column_index, text, exact_match=True):
|
|
"""Get row that contains specified text in specified column.
|
|
|
|
In case exact_match is set to True, text contained in row must equal
|
|
searched text, otherwise occurrence of searched text in the column
|
|
text will result in row match.
|
|
"""
|
|
for row in self.rows:
|
|
if exact_match and text == row.cells[column_index].text:
|
|
return row
|
|
if not exact_match and text in row.cells[column_index].text:
|
|
return row
|
|
return None
|
|
|
|
def _set_search_field(self, value):
|
|
srch_field = self._get_element(*self._search_field_locator)
|
|
srch_field.send_keys(value)
|
|
|
|
def _click_search_btn(self):
|
|
btn = self._get_element(*self._search_button_locator)
|
|
btn.click()
|
|
|
|
def _get_rows(self):
|
|
rows = []
|
|
for elem in self._get_elements(*self._rows_locator):
|
|
rows.append(RowRegion(self.driver, self.conf, elem))
|
|
|
|
|
|
class ActionsTableRegion(BasicTableRegion):
|
|
"""Base class for creating derivative of BasicTableRegion that
|
|
has some actions.
|
|
"""
|
|
|
|
_actions_locator = (by.By.CSS_SELECTOR, 'div.table_actions > button,'
|
|
' div.table_actions > a')
|
|
|
|
# private methods
|
|
def __init__(self, driver, conf, src_elm, action_names):
|
|
super(ActionsTableRegion, self).__init__(driver, conf, src_elm)
|
|
self.action_names = action_names
|
|
self._init_actions()
|
|
|
|
# protected methods
|
|
def _init_actions(self):
|
|
"""Create new methods that corresponds to picking table's
|
|
action buttons.
|
|
"""
|
|
self._init_dynamic_properties(self.action_names, self._get_actions)
|
|
|
|
def _get_actions(self):
|
|
return self._get_elements(*self._actions_locator)
|
|
|
|
# properties
|
|
@property
|
|
def actions(self):
|
|
return self._get_actions()
|
|
|
|
|
|
class SimpleActionsTableRegion(ActionsTableRegion):
|
|
"""Table which rows has buttons in action column."""
|
|
|
|
def __init__(self, driver, conf, src_elm, action_names, row_action_name):
|
|
super(SimpleActionsTableRegion, self).__init__(driver, conf, src_elm,
|
|
action_names)
|
|
self.row_action_name = row_action_name
|
|
|
|
def _get_rows(self):
|
|
rows = []
|
|
for elem in self._get_elements(*self._rows_locator):
|
|
rows.append(BtnActionRowRegion(self.driver, self.conf, elem,
|
|
self.row_action_name))
|
|
return rows
|
|
|
|
|
|
class ComplexActionTableRegion(ActionsTableRegion):
|
|
"""Table which has button and selectbox in the action column."""
|
|
|
|
def __init__(self, driver, conf, src_elm, action_names, row_action_names):
|
|
super(ComplexActionTableRegion, self).__init__(driver, conf, src_elm,
|
|
action_names)
|
|
self.row_action_names = row_action_names
|
|
|
|
def _get_rows(self):
|
|
rows = []
|
|
for elem in self._get_elements(*self._rows_locator):
|
|
rows.append(ComplexActionRowRegion(self.driver, self.conf, elem,
|
|
self.row_action_names))
|
|
return rows
|