Merge "In integration tests reference table columns by name"

This commit is contained in:
Jenkins 2016-01-21 06:54:54 +00:00 committed by Gerrit Code Review
commit 87304d8423
10 changed files with 64 additions and 41 deletions

View File

@ -434,6 +434,11 @@ class Column(html.HTMLElement):
except urlresolvers.NoReverseMatch:
return self.link
def get_default_attrs(self):
attrs = super(Column, self).get_default_attrs()
attrs.update({'data-selenium': self.name})
return attrs
def get_summation(self):
"""Returns the summary value for the data in this column if a
valid summation method is specified for it. Otherwise returns ``None``.

View File

@ -17,7 +17,7 @@ from openstack_dashboard.test.integration_tests.regions import tables
class FlavorsPage(basepage.BaseNavigationPage):
DEFAULT_ID = "auto"
FLAVORS_TABLE_NAME_COLUMN_INDEX = 0
FLAVORS_TABLE_NAME_COLUMN = 'name'
FLAVORS_TABLE_NAME = "flavors"
FLAVORS_TABLE_ACTIONS = ("create", "delete")
@ -36,8 +36,7 @@ class FlavorsPage(basepage.BaseNavigationPage):
self._page_title = "Flavors"
def _get_row_with_flavor_name(self, name):
return self.flavors_table.get_row(
self.FLAVORS_TABLE_NAME_COLUMN_INDEX, name)
return self.flavors_table.get_row(self.FLAVORS_TABLE_NAME_COLUMN, name)
@property
def flavors_table(self):

View File

@ -32,7 +32,7 @@ class ProjectsPage(basepage.BaseNavigationPage):
'div.modal-backdrop')
DEFAULT_ENABLED = True
PROJECTS_TABLE_NAME_COLUMN_INDEX = 0
PROJECTS_TABLE_NAME_COLUMN = 'name'
PROJECTS_TABLE_NAME = "tenants"
PROJECTS_TABLE_ACTIONS = ("create", "delete")
PROJECTS_TABLE_ROW_ACTIONS = {
@ -75,8 +75,8 @@ class ProjectsPage(basepage.BaseNavigationPage):
*self._delete_project_submit_button_locator)
def _get_row_with_project_name(self, name):
return self.projects_table.get_row(
self.PROJECTS_TABLE_NAME_COLUMN_INDEX, name)
return self.projects_table.get_row(self.PROJECTS_TABLE_NAME_COLUMN,
name)
def _cancel_popup(self):
self.create_project_cancel_button.click()

View File

@ -17,7 +17,7 @@ from openstack_dashboard.test.integration_tests.regions import tables
class UsersPage(basepage.BaseNavigationPage):
USERS_TABLE_NAME_COLUMN_INDEX = 0
USERS_TABLE_NAME_COLUMN = 'name'
USERS_TABLE_NAME = "users"
USERS_TABLE_ACTIONS = ("create", "delete")
@ -36,8 +36,7 @@ class UsersPage(basepage.BaseNavigationPage):
self._page_title = "Users"
def _get_row_with_user_name(self, name):
return self.users_table.get_row(
self.USERS_TABLE_NAME_COLUMN_INDEX, name)
return self.users_table.get_row(self.USERS_TABLE_NAME_COLUMN, name)
@property
def users_table(self):

View File

@ -23,7 +23,7 @@ from openstack_dashboard.test.integration_tests.regions import tables
class FloatingipsPage(basepage.BaseNavigationPage):
FLOATING_IPS_TABLE_NAME_COLUMN_INDEX = 0
FLOATING_IPS_TABLE_IP_COLUMN = 'ip'
_floatingips_fadein_popup_locator = (
by.By.CSS_SELECTOR, '.alert.alert-success.alert-dismissable.fade.in>p')
@ -42,7 +42,7 @@ class FloatingipsPage(basepage.BaseNavigationPage):
def _get_row_with_floatingip(self, floatingip):
return self.floatingips_table.get_row(
self.FLOATING_IPS_TABLE_NAME_COLUMN_INDEX, floatingip)
self.FLOATING_IPS_TABLE_IP_COLUMN, floatingip)
@property
def floatingips_table(self):

View File

@ -23,7 +23,7 @@ class KeypairsPage(basepage.BaseNavigationPage):
KEY_PAIRS_TABLE_NAME = "keypairs"
KEY_PAIRS_TABLE_ACTIONS = ("create", "import", "delete")
KEY_PAIRS_TABLE_ROW_ACTION = "delete"
KEY_PAIRS_TABLE_NAME_COLUMN_INDEX = 0
KEY_PAIRS_TABLE_NAME_COLUMN = 'name'
CREATE_KEY_PAIR_FORM_FIELDS = ('name',)
@ -32,8 +32,8 @@ class KeypairsPage(basepage.BaseNavigationPage):
self._page_title = "Access & Security"
def _get_row_with_keypair_name(self, name):
return self.keypairs_table.get_row(
self.KEY_PAIRS_TABLE_NAME_COLUMN_INDEX, name)
return self.keypairs_table.get_row(self.KEY_PAIRS_TABLE_NAME_COLUMN,
name)
@property
def keypairs_table(self):

View File

@ -17,7 +17,7 @@ from openstack_dashboard.test.integration_tests.regions import tables
class SecuritygroupsPage(basepage.BaseNavigationPage):
SECURITYGROUPS_TABLE_NAME_COLUMN_INDEX = 0
SECURITYGROUPS_TABLE_NAME_COLUMN = 'name'
SECURITYGROUPS_TABLE_NAME = "security_groups"
SECURITYGROUPS_TABLE_ACTIONS = ("create", "delete")
@ -35,7 +35,7 @@ class SecuritygroupsPage(basepage.BaseNavigationPage):
def _get_row_with_securitygroup_name(self, name):
return self.securitygroups_table.get_row(
self.SECURITYGROUPS_TABLE_NAME_COLUMN_INDEX, name)
self.SECURITYGROUPS_TABLE_NAME_COLUMN, name)
@property
def securitygroups_table(self):

View File

@ -23,8 +23,8 @@ class ImagesPage(basepage.BaseNavigationPage):
DEFAULT_IMAGE_FORMAT = 'qcow2'
DEFAULT_ACCESSIBILITY = False
DEFAULT_PROTECTION = False
IMAGES_TABLE_NAME_COLUMN_INDEX = 0
IMAGES_TABLE_STATUS_COLUMN_INDEX = 2
IMAGES_TABLE_NAME_COLUMN = 'name'
IMAGES_TABLE_STATUS_COLUMN = 'status'
IMAGES_TABLE_NAME = "images"
IMAGES_TABLE_ACTIONS = ("create", "delete")
@ -45,8 +45,7 @@ class ImagesPage(basepage.BaseNavigationPage):
self._page_title = "Images"
def _get_row_with_image_name(self, name):
return self.images_table.get_row(
self.IMAGES_TABLE_NAME_COLUMN_INDEX, name)
return self.images_table.get_row(self.IMAGES_TABLE_NAME_COLUMN, name)
@property
def images_table(self):
@ -108,7 +107,7 @@ class ImagesPage(basepage.BaseNavigationPage):
# to avoid problems with cell being replaced with totally different
# element by Javascript
def cell_getter():
return row.cells[self.IMAGES_TABLE_STATUS_COLUMN_INDEX]
return row.cells[self.IMAGES_TABLE_STATUS_COLUMN]
try:
self._wait_till_text_present_in_element(cell_getter, 'Active')
except exceptions.TimeoutException:

View File

@ -30,8 +30,8 @@ class InstancesPage(basepage.BaseNavigationPage):
INSTANCES_TABLE_NAME = "instances"
INSTANCES_TABLE_ACTIONS = ("launch_ng", "launch", "delete",
('start', 'stop', "reboot"))
INSTANCES_TABLE_NAME_COLUMN_INDEX = 0
INSTANCES_TABLE_STATUS_COLUMN_INDEX = 5
INSTANCES_TABLE_NAME_COLUMN = 'name'
INSTANCES_TABLE_STATUS_COLUMN = 'status'
INSTANCES_TABLE_ROW_ACTIONS = {
tables.ComplexActionRowRegion.PRIMARY_ACTION: "create_snapshot",
tables.ComplexActionRowRegion.SECONDARY_ACTIONS: (
@ -56,8 +56,8 @@ class InstancesPage(basepage.BaseNavigationPage):
self._page_title = "Instances"
def _get_row_with_instance_name(self, name):
return self.instances_table.get_row(
self.INSTANCES_TABLE_NAME_COLUMN_INDEX, name)
return self.instances_table.get_row(self.INSTANCES_TABLE_NAME_COLUMN,
name)
@property
def instances_table(self):
@ -133,7 +133,7 @@ class InstancesPage(basepage.BaseNavigationPage):
row = self._get_row_with_instance_name(name)
def cell_getter():
return row.cells[self.INSTANCES_TABLE_STATUS_COLUMN_INDEX]
return row.cells[self.INSTANCES_TABLE_STATUS_COLUMN]
try:
self._wait_till_text_present_in_element(cell_getter, 'Active')
except exceptions.TimeoutException:

View File

@ -11,20 +11,29 @@
# under the License.
from selenium.common import exceptions
from selenium.webdriver.common import by
from openstack_dashboard.test.integration_tests.regions import baseregion
from openstack_dashboard.test.integration_tests.regions import menus
NORMAL_COLUMN_CLASS = 'normal_column'
class RowRegion(baseregion.BaseRegion):
"""Classic table row."""
_cell_locator = (by.By.CSS_SELECTOR, 'td.normal_column')
_cell_locator = (by.By.CSS_SELECTOR, 'td.%s' % NORMAL_COLUMN_CLASS)
def __init__(self, driver, conf, src_elem, column_names):
self.column_names = column_names
super(RowRegion, self).__init__(driver, conf, src_elem)
@property
def cells(self):
return self._get_elements(*self._cell_locator)
elements = self._get_elements(*self._cell_locator)
return {column_name: elements[i]
for i, column_name in enumerate(self.column_names)}
class BaseActionRowRegion(RowRegion):
@ -42,8 +51,9 @@ class BtnActionRowRegion(BaseActionRowRegion):
_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)
def __init__(self, driver, conf, src_elem, column_names, action_name):
super(BtnActionRowRegion, self).__init__(driver, conf, src_elem,
column_names)
self.action_name = action_name
self._action_id_pattern = ("%s__action_%%s" %
src_elem.get_attribute('id'))
@ -76,8 +86,9 @@ class ComplexActionRowRegion(BaseActionRowRegion):
" {%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)
def __init__(self, driver, conf, src_elem, column_names, action_names):
super(ComplexActionRowRegion, self).__init__(driver, conf, src_elem,
column_names)
try:
self.primary_action_name = action_names[self.PRIMARY_ACTION]
self.secondary_action_names = action_names[self.SECONDARY_ACTIONS]
@ -145,7 +156,12 @@ class BasicTableRegion(baseregion.BaseRegion):
@property
def column_names(self):
return self._get_elements(*self._columns_names_locator)
names = []
for element in self._get_elements(*self._columns_names_locator):
classes = element.get_attribute('class').split()
if NORMAL_COLUMN_CLASS in classes:
names.append(element.get_attribute('data-selenium'))
return names
@property
def footer(self):
@ -155,7 +171,7 @@ class BasicTableRegion(baseregion.BaseRegion):
self._set_search_field(value)
self._click_search_btn()
def get_row(self, column_index, text, exact_match=True):
def get_row(self, column_name, 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
@ -167,10 +183,15 @@ class BasicTableRegion(baseregion.BaseRegion):
return text or element.text
for row in self.rows:
if exact_match and text == get_text(row.cells[column_index]):
return row
if not exact_match and text in get_text(row.cells[column_index]):
return row
try:
cell = row.cells[column_name]
if exact_match and text == get_text(cell):
return row
if not exact_match and text in get_text(cell):
return row
# NOTE(tsufiev): if a row was deleted during iteration
except exceptions.StaleElementReferenceException:
pass
return None
def _set_search_field(self, value):
@ -182,7 +203,7 @@ class BasicTableRegion(baseregion.BaseRegion):
btn.click()
def _make_row(self, elem):
return RowRegion(self.driver, self.conf, elem)
return RowRegion(self.driver, self.conf, elem, self.column_names)
def _get_rows(self, *args):
elements = self._get_elements(*self._rows_locator)
@ -232,7 +253,7 @@ class SimpleActionsTableRegion(ActionsTableRegion):
def _make_row(self, elem):
return BtnActionRowRegion(self.driver, self.conf, elem,
self.row_action_name)
self.column_names, self.row_action_name)
class ComplexActionTableRegion(ActionsTableRegion):
@ -246,4 +267,4 @@ class ComplexActionTableRegion(ActionsTableRegion):
def _make_row(self, elem):
return ComplexActionRowRegion(self.driver, self.conf, elem,
self.row_action_names)
self.column_names, self.row_action_names)