c6d4bc459a
Add model of project-dropdown menu Partially implements blueprint: selenium-integration-testing Change-Id: I71756f263c8e2d9dcdfb20138f1379daadb22f95
214 lines
7.6 KiB
Python
214 lines
7.6 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.common import exceptions
|
|
from selenium.webdriver.common import by
|
|
|
|
from openstack_dashboard.test.integration_tests.regions import baseregion
|
|
|
|
|
|
class CannotClickMenuItemException(Exception):
|
|
pass
|
|
|
|
|
|
class NavigationAccordionRegion(baseregion.BaseRegion):
|
|
"""Navigation menu located in the left."""
|
|
_project_access_security_locator = (
|
|
by.By.CSS_SELECTOR, 'a[href*="/project/access_and_security/"]')
|
|
_settings_change_password_locator = (
|
|
by.By.CSS_SELECTOR, 'a[href*="/settings/password//"]')
|
|
_project_bar_locator = (by.By.XPATH,
|
|
".//*[@id='main_content']//div[contains(text(),"
|
|
"'Project')]")
|
|
|
|
MAX_MENU_ITEM_CLICK_TRIES = 100
|
|
|
|
@property
|
|
def project_bar(self):
|
|
return self._get_element(*self._project_bar_locator)
|
|
|
|
_first_level_item_selected_locator = (by.By.CSS_SELECTOR, 'dt.active')
|
|
_second_level_item_selected_locator = (by.By.CSS_SELECTOR, 'h4.active')
|
|
|
|
_first_level_item_xpath_template = '//dt[contains(text(),\'%s\')]'
|
|
_second_level_item_xpath_template = '//h4[contains(text(),\'%s\')]'
|
|
_third_level_item_xpath_template = '//li/a[text()=\'%s\']'
|
|
|
|
def _get_first_level_item_locator(self, text):
|
|
return (by.By.XPATH,
|
|
self._first_level_item_xpath_template % text)
|
|
|
|
def _get_second_level_item_locator(self, text):
|
|
return (by.By.XPATH,
|
|
self._second_level_item_xpath_template % text)
|
|
|
|
def _get_third_level_item_locator(self, text):
|
|
return (by.By.XPATH,
|
|
self._third_level_item_xpath_template % text)
|
|
|
|
def get_first_level_selected_item(self):
|
|
if self._is_element_present(*self._first_level_item_selected_locator):
|
|
return self._get_element(*self._first_level_item_selected_locator)
|
|
else:
|
|
return None
|
|
|
|
def get_second_level_selected_item(self):
|
|
if self._is_element_present(*self._second_level_item_selected_locator):
|
|
return self._get_element(*self._second_level_item_selected_locator)
|
|
else:
|
|
return None
|
|
|
|
@property
|
|
def access_security(self):
|
|
return self._get_element(*self._project_access_security_locator)
|
|
|
|
@property
|
|
def change_password(self):
|
|
return self._get_element(*self._settings_change_password_locator)
|
|
|
|
def _click_menu_item(self, text, loc_craft_func, get_selected_func=None):
|
|
"""Click on menu item if not selected.
|
|
|
|
Menu animation that visualize transition from one selection to
|
|
another take some time - if clicked on item during this animation
|
|
nothing happens, therefore it is necessary to do this in a loop.
|
|
"""
|
|
|
|
if not get_selected_func:
|
|
self._click_item(text, loc_craft_func)
|
|
else:
|
|
for _ in xrange(self.MAX_MENU_ITEM_CLICK_TRIES):
|
|
selected_item = get_selected_func()
|
|
if selected_item and text == selected_item.text:
|
|
break
|
|
|
|
# In case different item was chosen previously scroll it,
|
|
# because otherwise selenium will complain with
|
|
# MoveTargetOutOfBoundsException
|
|
if selected_item:
|
|
selected_item.click()
|
|
self._click_item(text, loc_craft_func)
|
|
else:
|
|
|
|
# One should never get in here,
|
|
# this suggest that something is wrong
|
|
raise CannotClickMenuItemException()
|
|
|
|
def _click_item(self, text, loc_craft_func):
|
|
"""Click on item."""
|
|
item_locator = loc_craft_func(text)
|
|
item = self._get_element(*item_locator)
|
|
item.click()
|
|
|
|
def click_on_menu_items(self, first_level=None,
|
|
second_level=None,
|
|
third_level=None):
|
|
if first_level:
|
|
self._click_menu_item(first_level,
|
|
self._get_first_level_item_locator,
|
|
self.get_first_level_selected_item)
|
|
if second_level:
|
|
self._click_menu_item(second_level,
|
|
self._get_second_level_item_locator,
|
|
self.get_second_level_selected_item)
|
|
|
|
# it is not checked that third level item is clicked because behaviour
|
|
# of the third menu layer is buggy => always click
|
|
if third_level:
|
|
self._click_menu_item(third_level,
|
|
self._get_third_level_item_locator)
|
|
|
|
|
|
class DropDownMenuRegion(baseregion.BaseRegion):
|
|
"""Drop down menu region."""
|
|
|
|
_menu_items_locator = (by.By.CSS_SELECTOR,
|
|
'ul.dropdown-menu > li > *')
|
|
_menu_first_child_locator = (by.By.CSS_SELECTOR,
|
|
'a[data-toggle="dropdown"]')
|
|
|
|
@property
|
|
def menu_items(self):
|
|
self.open()
|
|
menu_items = self._get_elements(*self._menu_items_locator)
|
|
return menu_items
|
|
|
|
def is_open(self):
|
|
"""Returns True if drop down menu is open, otherwise False."""
|
|
return "open" in self.src_elem.get_attribute('class')
|
|
|
|
def open(self):
|
|
"""Opens menu by clicking on the first child of the source element."""
|
|
if self.is_open() is False:
|
|
self._get_element(*self._menu_first_child_locator).click()
|
|
|
|
|
|
class UserDropDownMenuRegion(DropDownMenuRegion):
|
|
"""Drop down menu located in the right side of the topbar,
|
|
contains links to settings and help.
|
|
"""
|
|
_menu_first_child_locator = (by.By.CSS_SELECTOR, '*')
|
|
_settings_link_locator = (by.By.CSS_SELECTOR,
|
|
'a[href*="/settings/"]')
|
|
_help_link_locator = (by.By.CSS_SELECTOR,
|
|
'ul#editor_list li:nth-of-type(2) > a')
|
|
_logout_link_locator = (by.By.CSS_SELECTOR,
|
|
'a[href*="/auth/logout/"]')
|
|
|
|
@property
|
|
def settings_link(self):
|
|
return self._get_element(*self._settings_link_locator)
|
|
|
|
@property
|
|
def help_link(self):
|
|
return self._get_element(*self._help_link_locator)
|
|
|
|
@property
|
|
def logout_link(self):
|
|
return self._get_element(*self._logout_link_locator)
|
|
|
|
def click_on_settings(self):
|
|
self.open()
|
|
self.settings_link.click()
|
|
|
|
def click_on_help(self):
|
|
self.open()
|
|
self.help_link.click()
|
|
|
|
def click_on_logout(self):
|
|
self.open()
|
|
self.logout_link.click()
|
|
|
|
|
|
class TabbedMenuRegion(baseregion.BaseRegion):
|
|
|
|
_tab_locator = (by.By.CSS_SELECTOR, 'a')
|
|
_default_src_locator = (by.By.CSS_SELECTOR, 'ul.nav.nav-tabs')
|
|
|
|
def switch_to(self, index=0):
|
|
self._get_elements(*self._tab_locator)[index].click()
|
|
|
|
|
|
class ProjectDropDownRegion(DropDownMenuRegion):
|
|
|
|
_menu_first_child_locator = (by.By.CSS_SELECTOR, '*')
|
|
_menu_items_locator = (by.By.CSS_SELECTOR,
|
|
'div.context-lists a')
|
|
|
|
def click_on_project(self, name):
|
|
for item in self.menu_items:
|
|
if item.text == name:
|
|
item.click()
|
|
break
|
|
else:
|
|
raise exceptions.NoSuchElementException(
|
|
"Not found element with text: %s" % name)
|