Integration tests no longer use form's fields ordering for matching
Relying on suggestion that some predefined list of field names in test will always be the same in actual forms rendered by Horizon is perilous. It leads to a test failure every time the order of fields in some form being tested changes or a new field appears at the beginning of the form. Tests which are using 'name' attribute for matching predefined fields to the actual form fields are much more durable since field names change less frequently. Closes-Bug: #1467950 Related-Bug: #1456294 Related-Bug: #1447432 Implements blueprint: integration-tests-hardening Change-Id: Ia39c003a628f5abbb73ff824329b2a31a0b6e179
This commit is contained in:
parent
ce53171d18
commit
59717143bc
|
@ -30,9 +30,8 @@ class FlavorsPage(basepage.BaseNavigationPage):
|
|||
"modify_access", "update_metadata", "delete_flavor")
|
||||
}
|
||||
|
||||
CREATE_FLAVOR_FORM_FIELDS = (("name", "id_", "vcpus", "ram",
|
||||
"root_disk", "ephemeral_disk",
|
||||
"swap_disk"),
|
||||
CREATE_FLAVOR_FORM_FIELDS = (("name", "flavor_id", "vcpus", "memory_mb",
|
||||
"disk_gb", "eph_gb", "swap_mb"),
|
||||
("all_projects", "selected_projects"))
|
||||
|
||||
def __init__(self, driver, conf):
|
||||
|
@ -65,12 +64,12 @@ class FlavorsPage(basepage.BaseNavigationPage):
|
|||
self.flavors_table.create_flavor.click()
|
||||
self.create_flavor_form.name.text = name
|
||||
if id_ is not None:
|
||||
self.create_flavor_form.id_.text = id_
|
||||
self.create_flavor_form.flavor_id.text = id_
|
||||
self.create_flavor_form.vcpus.value = vcpus
|
||||
self.create_flavor_form.ram.value = ram
|
||||
self.create_flavor_form.root_disk.value = root_disk
|
||||
self.create_flavor_form.ephemeral_disk.value = ephemeral_disk
|
||||
self.create_flavor_form.swap_disk.value = swap_disk
|
||||
self.create_flavor_form.memory_mb.value = ram
|
||||
self.create_flavor_form.disk_gb.value = root_disk
|
||||
self.create_flavor_form.eph_gb.value = ephemeral_disk
|
||||
self.create_flavor_form.swap_mb.value = swap_disk
|
||||
self.create_flavor_form.submit.click()
|
||||
self._wait_till_spinner_disappears()
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class UsersPage(basepage.BaseNavigationPage):
|
|||
}
|
||||
|
||||
CREATE_USER_FORM_FIELDS = ("name", "email", "password",
|
||||
"confirm_password", "project", "role")
|
||||
"confirm_password", "project", "role_id")
|
||||
|
||||
def __init__(self, driver, conf):
|
||||
super(UsersPage, self).__init__(driver, conf)
|
||||
|
@ -69,7 +69,7 @@ class UsersPage(basepage.BaseNavigationPage):
|
|||
self.create_user_form.password.text = password
|
||||
self.create_user_form.confirm_password.text = password
|
||||
self.create_user_form.project.text = project
|
||||
self.create_user_form.role.text = role
|
||||
self.create_user_form.role_id.text = role
|
||||
self.create_user_form.submit.click()
|
||||
self._wait_till_spinner_disappears()
|
||||
|
||||
|
|
|
@ -36,10 +36,10 @@ class ImagesPage(basepage.BaseNavigationPage):
|
|||
}
|
||||
|
||||
CREATE_IMAGE_FORM_FIELDS = (
|
||||
"name", "description", "image_source", "image_location",
|
||||
"name", "description", "source_type", "image_url",
|
||||
"image_file", "kernel", "ramdisk",
|
||||
"format", "architecture", "minimum_disk",
|
||||
"minimum_ram", "public", "protected"
|
||||
"disk_format", "architecture", "minimum_disk",
|
||||
"minimum_ram", "is_public", "protected"
|
||||
)
|
||||
|
||||
def __init__(self, driver, conf):
|
||||
|
@ -69,7 +69,7 @@ class ImagesPage(basepage.BaseNavigationPage):
|
|||
return forms.BaseFormRegion(self.driver, self.conf, None)
|
||||
|
||||
def create_image(self, name, description=None,
|
||||
image_source=DEFAULT_IMAGE_SOURCE,
|
||||
image_source_type=DEFAULT_IMAGE_SOURCE,
|
||||
location=None, image_file=None,
|
||||
image_format=DEFAULT_IMAGE_FORMAT,
|
||||
is_public=DEFAULT_ACCESSIBILITY,
|
||||
|
@ -78,18 +78,18 @@ class ImagesPage(basepage.BaseNavigationPage):
|
|||
self.create_image_form.name.text = name
|
||||
if description is not None:
|
||||
self.create_image_form.description.text = description
|
||||
self.create_image_form.image_source.value = image_source
|
||||
if image_source == 'url':
|
||||
self.create_image_form.source_type.value = image_source_type
|
||||
if image_source_type == 'url':
|
||||
if location is None:
|
||||
self.create_image_form.image_location.text = \
|
||||
self.create_image_form.image_url.text = \
|
||||
self.conf.image.http_image
|
||||
else:
|
||||
self.create_image_form.location.text = location
|
||||
self.create_image_form.image_url.text = location
|
||||
else:
|
||||
self.create_image_form.image_file.choose(image_file)
|
||||
self.create_image_form.format.value = image_format
|
||||
self.create_image_form.disk_format.value = image_format
|
||||
if is_public:
|
||||
self.create_image_form.public.mark()
|
||||
self.create_image_form.is_public.mark()
|
||||
if is_protected:
|
||||
self.create_image_form.protected.mark()
|
||||
self.create_image_form.submit.click()
|
||||
|
|
|
@ -21,7 +21,7 @@ class ChangepasswordPage(basepage.BaseNavigationPage):
|
|||
_password_form_locator = (by.By.ID, 'change_password_modal')
|
||||
|
||||
CHANGE_PASSWORD_FORM_FIELDS = ("current_password", "new_password",
|
||||
"confirm_new_password")
|
||||
"confirm_password")
|
||||
|
||||
@property
|
||||
def password_form(self):
|
||||
|
@ -32,7 +32,7 @@ class ChangepasswordPage(basepage.BaseNavigationPage):
|
|||
def change_password(self, current, new):
|
||||
self.password_form.current_password.text = current
|
||||
self.password_form.new_password.text = new
|
||||
self.password_form.confirm_new_password.text = new
|
||||
self.password_form.confirm_password.text = new
|
||||
self.password_form.submit.click()
|
||||
|
||||
def reset_to_default_password(self, current):
|
||||
|
|
|
@ -30,7 +30,8 @@ class UsersettingsPage(basepage.BaseNavigationPage):
|
|||
"loglines": DEFAULT_LOGLINES
|
||||
}
|
||||
|
||||
SETTINGS_FORM_FIELDS = ("language", "timezone", "pagesize", "loglines")
|
||||
SETTINGS_FORM_FIELDS = (
|
||||
"language", "timezone", "pagesize", "instance_log_length")
|
||||
|
||||
_settings_form_locator = (by.By.ID, 'user_settings_modal')
|
||||
_change_password_tab_locator = (by.By.CSS_SELECTOR,
|
||||
|
@ -67,7 +68,7 @@ class UsersettingsPage(basepage.BaseNavigationPage):
|
|||
self.settings_form.submit.click()
|
||||
|
||||
def change_loglines(self, lines=DEFAULT_LOGLINES):
|
||||
self.settings_form.loglines.value = lines
|
||||
self.settings_form.instance_log_length.value = lines
|
||||
self.settings_form.submit.click()
|
||||
|
||||
def return_to_default_settings(self):
|
||||
|
|
|
@ -65,17 +65,21 @@ class BaseRegion(basewebobject.BaseWebObject):
|
|||
class _DynamicProperty(object):
|
||||
"""Serves as new property holder."""
|
||||
|
||||
def __init__(self, method, index=None):
|
||||
def __init__(self, method, index=None, name=None):
|
||||
"""In case object was created with index != None,
|
||||
it is assumed that the result of self.method should be tuple()
|
||||
and just certain index should be returned
|
||||
"""
|
||||
self.method = method
|
||||
self.index = index
|
||||
self.name = name
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
result = self.method()
|
||||
return result if self.index is None else result[self.index]
|
||||
if isinstance(result, dict):
|
||||
return result if self.name is None else result[self.name]
|
||||
else:
|
||||
return result if self.index is None else result[self.index]
|
||||
|
||||
def _init_dynamic_properties(self, new_attr_names, method):
|
||||
"""Create new object's 'properties' at runtime."""
|
||||
|
@ -93,7 +97,8 @@ class BaseRegion(basewebobject.BaseWebObject):
|
|||
"The new property could not be "
|
||||
"created." % (self.__class__.__name__,
|
||||
new_attr_name))
|
||||
new_method = self.__class__._DynamicProperty(method, index)
|
||||
new_method = self.__class__._DynamicProperty(method, index,
|
||||
new_attr_name)
|
||||
inst_method = types.MethodType(new_method, self)
|
||||
self._dynamic_properties[new_attr_name] = inst_method
|
||||
|
||||
|
|
|
@ -64,6 +64,10 @@ class BaseFormFieldRegion(baseregion.BaseRegion):
|
|||
def element(self):
|
||||
return self._get_element(*self._element_locator)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.element.get_attribute('name')
|
||||
|
||||
def is_required(self):
|
||||
classes = self.driver.get_attribute('class')
|
||||
return 'required' in classes
|
||||
|
@ -205,6 +209,10 @@ class SelectFormFieldRegion(BaseFormFieldRegion):
|
|||
results.append(option.get_attribute('value'))
|
||||
return results
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.element._el.get_attribute('name')
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
return self.element.first_selected_option.text
|
||||
|
@ -254,6 +262,7 @@ class FormRegion(BaseFormRegion):
|
|||
_header_locator = (by.By.CSS_SELECTOR, 'div.modal-header > h3')
|
||||
_side_info_locator = (by.By.CSS_SELECTOR, 'div.right')
|
||||
_fields_locator = (by.By.CSS_SELECTOR, 'fieldset > div.form-group')
|
||||
_input_locator = (by.By.CSS_SELECTOR, 'input,select,textarea')
|
||||
|
||||
# private methods
|
||||
def __init__(self, driver, conf, src_elem, form_field_names):
|
||||
|
@ -268,12 +277,13 @@ class FormRegion(BaseFormRegion):
|
|||
|
||||
def _get_form_fields(self):
|
||||
fields_els = self._get_elements(*self._fields_locator)
|
||||
form_fields = []
|
||||
form_fields = {}
|
||||
try:
|
||||
self._turn_off_implicit_wait()
|
||||
for elem in fields_els:
|
||||
field_factory = FieldFactory(self.driver, self.conf, elem)
|
||||
form_fields.append(field_factory.make_form_field())
|
||||
field = field_factory.make_form_field()
|
||||
form_fields[field.name] = field
|
||||
finally:
|
||||
self._turn_on_implicit_wait()
|
||||
return form_fields
|
||||
|
@ -350,8 +360,12 @@ class TabbedFormRegion(FormRegion):
|
|||
|
||||
def __call__(self, *args, **kwargs):
|
||||
self.switch_to_tab(self.tab_index)
|
||||
return [field for field in self.get_fields()
|
||||
if field.is_displayed()]
|
||||
fields = self.get_fields()
|
||||
if isinstance(fields, dict):
|
||||
return dict([(key, field) for (key, field)
|
||||
in fields.iteritems() if field.is_displayed()])
|
||||
else:
|
||||
return [field for field in fields if field.is_displayed()]
|
||||
|
||||
@property
|
||||
def tabs(self):
|
||||
|
|
|
@ -19,7 +19,7 @@ class TestUserSettings(helpers.TestCase):
|
|||
language = self.settings_page.settings_form.language.value
|
||||
timezone = self.settings_page.settings_form.timezone.value
|
||||
pagesize = self.settings_page.settings_form.pagesize.value
|
||||
loglines = self.settings_page.settings_form.loglines.value
|
||||
loglines = self.settings_page.settings_form.instance_log_length.value
|
||||
|
||||
user_settings = (("Language", changed_settings["language"], language),
|
||||
("Timezone", changed_settings["timezone"], timezone),
|
||||
|
|
Loading…
Reference in New Issue