Добавлена проверка индикатора статуса в панели навигации
parent
b8c3b55ebd
commit
4ad79b108b
|
|
@ -49,110 +49,112 @@ class NavigationPanelComponent(BaseComponent):
|
||||||
item_name: Текст элемента для клика.
|
item_name: Текст элемента для клика.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def find_and_click_item(page, root_locator, item_name: str, parent: None|str) -> Locator|None:
|
|
||||||
# Находим все локаторы корневых узлов на текущем уровне
|
|
||||||
nodes_count = root_locator.locator('>div.v-treeview-node').count()
|
|
||||||
|
|
||||||
# Если искомый элемент находится на данном уровне, вычисляем локатор и делаем клик
|
|
||||||
if parent is None:
|
|
||||||
for index in range(nodes_count):
|
|
||||||
node = root_locator.locator(f">div:nth-child({index + 1})").first
|
|
||||||
node_content = node.locator('div.v-treeview-node__content')
|
|
||||||
if node_content.count() > 0:
|
|
||||||
node_text = node_content.first.inner_text().strip()
|
|
||||||
node_texts = node_text.splitlines()
|
|
||||||
if len(node_texts) > 1:
|
|
||||||
node_text = node_texts[1]
|
|
||||||
if item_name == node_text:
|
|
||||||
node_attr = node.get_attribute('class')
|
|
||||||
if "v-treeview-node--leaf" not in node_attr:
|
|
||||||
toggle_button = node.locator(
|
|
||||||
NavigationPanelLocators.NODE_ROOT
|
|
||||||
).locator(NavigationPanelLocators.TOGGLE_BUTTON).first
|
|
||||||
toogle_class_attr = toggle_button.get_attribute('class')
|
|
||||||
if "v-treeview-node__toggle--open" not in toogle_class_attr:
|
|
||||||
toggle_button.click()
|
|
||||||
else:
|
|
||||||
node.locator(NavigationPanelLocators.NODE_ROOT).click()
|
|
||||||
page.wait_for_timeout(1000)
|
|
||||||
return node
|
|
||||||
|
|
||||||
# Если элемента нет, рекурсивно ищем дальше
|
|
||||||
for index in range(nodes_count):
|
|
||||||
node = root_locator.locator(f">div:nth-child({index + 1})").first
|
|
||||||
|
|
||||||
# Извлекаем аттрибуты из корневого узла
|
|
||||||
node_class_attr = node.get_attribute('class')
|
|
||||||
|
|
||||||
is_expanded = False
|
|
||||||
has_children = False
|
|
||||||
|
|
||||||
# Проверяем лист это или начало поддерева
|
|
||||||
if "v-treeview-node--leaf" not in node_class_attr:
|
|
||||||
# Проверяем, является ли узел раскрытым
|
|
||||||
class_attr = node.locator(
|
|
||||||
NavigationPanelLocators.NODE_ROOT
|
|
||||||
).locator(NavigationPanelLocators.TOGGLE_BUTTON).first.get_attribute('class')
|
|
||||||
if "v-treeview-node__toggle--open" in class_attr:
|
|
||||||
is_expanded = True
|
|
||||||
|
|
||||||
# Если узел закрыт можем его раскрыть
|
|
||||||
if is_expanded is False:
|
|
||||||
toggle_button = node.locator(
|
|
||||||
NavigationPanelLocators.NODE_ROOT
|
|
||||||
).locator(NavigationPanelLocators.TOGGLE_BUTTON).first
|
|
||||||
toggle_button.click()
|
|
||||||
# Ждем, пока дочерние элементы прогрузятся/появятся
|
|
||||||
page.wait_for_timeout(1000)
|
|
||||||
is_expanded = True
|
|
||||||
|
|
||||||
# Проверяем, имеет ли узел дочерние элементы
|
|
||||||
children_count = node.locator('>div.v-treeview-node__children').count()
|
|
||||||
content = node.locator('>div.v-treeview-node__children').inner_html()
|
|
||||||
if children_count > 0 and len(content) != 0:
|
|
||||||
has_children = True
|
|
||||||
|
|
||||||
# Рекурсивный вызов для дочерних элементов
|
|
||||||
# Ищем дочерние элементы *внутри* текущего узла
|
|
||||||
if has_children and is_expanded:
|
|
||||||
child_nodes_locator = root_locator.locator(
|
|
||||||
f">div:nth-child({index + 1})"
|
|
||||||
).locator('>div.v-treeview-node__children')
|
|
||||||
found_loc = find_and_click_item(
|
|
||||||
page, child_nodes_locator, item_name, parent=None
|
|
||||||
)
|
|
||||||
if found_loc:
|
|
||||||
if parent is None:
|
|
||||||
return found_loc
|
|
||||||
|
|
||||||
root_texts = root_locator.locator(
|
|
||||||
f">div:nth-child({index + 1})"
|
|
||||||
).inner_text().splitlines()
|
|
||||||
if parent in root_texts:
|
|
||||||
return found_loc
|
|
||||||
|
|
||||||
# закрываем узел, если в нем ничего не нашли
|
|
||||||
if is_expanded:
|
|
||||||
toggle_button = node.locator(
|
|
||||||
NavigationPanelLocators.NODE_ROOT
|
|
||||||
).locator(NavigationPanelLocators.TOGGLE_BUTTON).first
|
|
||||||
toggle_button.click()
|
|
||||||
page.wait_for_timeout(1000)
|
|
||||||
|
|
||||||
# элемент с заданным именем не найден
|
|
||||||
return None
|
|
||||||
|
|
||||||
root_locator = self.get_locator(node_root_locator)
|
root_locator = self.get_locator(node_root_locator)
|
||||||
if parent:
|
if parent:
|
||||||
parent_loc = find_and_click_item(self.page, root_locator, parent, parent=None)
|
parent_loc = self._find_and_click_item(self.page, root_locator, parent, parent=None)
|
||||||
found = find_and_click_item(
|
found = self._find_and_click_item(
|
||||||
self.page, parent_loc.locator('>div.v-treeview-node__children'),
|
self.page, parent_loc.locator('>div.v-treeview-node__children'),
|
||||||
item_name, parent=None
|
item_name, parent=None
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
found = find_and_click_item(self.page, root_locator, item_name, parent=None)
|
found = self._find_and_click_item(self.page, root_locator, item_name, parent=None)
|
||||||
assert found, f"Navigation panel item {item_name} is missing"
|
assert found, f"Navigation panel item {item_name} is missing"
|
||||||
|
|
||||||
|
def _find_and_click_item(self, page, root_locator, item_name: str, parent: None|str) -> Locator|None:
|
||||||
|
"""Поиск вложенного элемента с указанным текстом и локатором корневого элемента"""
|
||||||
|
|
||||||
|
# Находим все локаторы корневых узлов на текущем уровне
|
||||||
|
nodes_count = root_locator.locator('>div.v-treeview-node').count()
|
||||||
|
|
||||||
|
# Если искомый элемент находится на данном уровне, вычисляем локатор и делаем клик
|
||||||
|
if parent is None:
|
||||||
|
for index in range(nodes_count):
|
||||||
|
node = root_locator.locator(f">div:nth-child({index + 1})").first
|
||||||
|
node_content = node.locator('div.v-treeview-node__content')
|
||||||
|
if node_content.count() > 0:
|
||||||
|
node_text = node_content.first.inner_text().strip()
|
||||||
|
node_texts = node_text.splitlines()
|
||||||
|
if len(node_texts) > 1:
|
||||||
|
node_text = node_texts[1]
|
||||||
|
if item_name == node_text:
|
||||||
|
node_attr = node.get_attribute('class')
|
||||||
|
if "v-treeview-node--leaf" not in node_attr:
|
||||||
|
toggle_button = node.locator(
|
||||||
|
NavigationPanelLocators.NODE_ROOT
|
||||||
|
).locator(NavigationPanelLocators.TOGGLE_BUTTON).first
|
||||||
|
toogle_class_attr = toggle_button.get_attribute('class')
|
||||||
|
if "v-treeview-node__toggle--open" not in toogle_class_attr:
|
||||||
|
toggle_button.click()
|
||||||
|
else:
|
||||||
|
node.locator(NavigationPanelLocators.NODE_ROOT).click()
|
||||||
|
page.wait_for_timeout(1000)
|
||||||
|
return node
|
||||||
|
|
||||||
|
# Если элемента нет, рекурсивно ищем дальше
|
||||||
|
for index in range(nodes_count):
|
||||||
|
node = root_locator.locator(f">div:nth-child({index + 1})").first
|
||||||
|
|
||||||
|
# Извлекаем аттрибуты из корневого узла
|
||||||
|
node_class_attr = node.get_attribute('class')
|
||||||
|
|
||||||
|
is_expanded = False
|
||||||
|
has_children = False
|
||||||
|
|
||||||
|
# Проверяем лист это или начало поддерева
|
||||||
|
if "v-treeview-node--leaf" not in node_class_attr:
|
||||||
|
# Проверяем, является ли узел раскрытым
|
||||||
|
class_attr = node.locator(
|
||||||
|
NavigationPanelLocators.NODE_ROOT
|
||||||
|
).locator(NavigationPanelLocators.TOGGLE_BUTTON).first.get_attribute('class')
|
||||||
|
if "v-treeview-node__toggle--open" in class_attr:
|
||||||
|
is_expanded = True
|
||||||
|
|
||||||
|
# Если узел закрыт можем его раскрыть
|
||||||
|
if is_expanded is False:
|
||||||
|
toggle_button = node.locator(
|
||||||
|
NavigationPanelLocators.NODE_ROOT
|
||||||
|
).locator(NavigationPanelLocators.TOGGLE_BUTTON).first
|
||||||
|
toggle_button.click()
|
||||||
|
# Ждем, пока дочерние элементы прогрузятся/появятся
|
||||||
|
page.wait_for_timeout(1000)
|
||||||
|
is_expanded = True
|
||||||
|
|
||||||
|
# Проверяем, имеет ли узел дочерние элементы
|
||||||
|
children_count = node.locator('>div.v-treeview-node__children').count()
|
||||||
|
content = node.locator('>div.v-treeview-node__children').inner_html()
|
||||||
|
if children_count > 0 and len(content) != 0:
|
||||||
|
has_children = True
|
||||||
|
|
||||||
|
# Рекурсивный вызов для дочерних элементов
|
||||||
|
# Ищем дочерние элементы *внутри* текущего узла
|
||||||
|
if has_children and is_expanded:
|
||||||
|
child_nodes_locator = root_locator.locator(
|
||||||
|
f">div:nth-child({index + 1})"
|
||||||
|
).locator('>div.v-treeview-node__children')
|
||||||
|
found_loc = self._find_and_click_item(
|
||||||
|
page, child_nodes_locator, item_name, parent=None
|
||||||
|
)
|
||||||
|
if found_loc:
|
||||||
|
if parent is None:
|
||||||
|
return found_loc
|
||||||
|
|
||||||
|
root_texts = root_locator.locator(
|
||||||
|
f">div:nth-child({index + 1})"
|
||||||
|
).inner_text().splitlines()
|
||||||
|
if parent in root_texts:
|
||||||
|
return found_loc
|
||||||
|
|
||||||
|
# закрываем узел, если в нем ничего не нашли
|
||||||
|
if is_expanded:
|
||||||
|
toggle_button = node.locator(
|
||||||
|
NavigationPanelLocators.NODE_ROOT
|
||||||
|
).locator(NavigationPanelLocators.TOGGLE_BUTTON).first
|
||||||
|
toggle_button.click()
|
||||||
|
page.wait_for_timeout(1000)
|
||||||
|
|
||||||
|
# элемент с заданным именем не найден
|
||||||
|
return None
|
||||||
|
|
||||||
def get_item_names(self, locator: str | Locator) -> list[str]:
|
def get_item_names(self, locator: str | Locator) -> list[str]:
|
||||||
"""Возвращает тексты всех элементов по указанному локатору.
|
"""Возвращает тексты всех элементов по указанному локатору.
|
||||||
|
|
||||||
|
|
@ -294,6 +296,32 @@ class NavigationPanelComponent(BaseComponent):
|
||||||
|
|
||||||
return element_locator.is_visible()
|
return element_locator.is_visible()
|
||||||
|
|
||||||
|
def check_sub_item_state(self, node_root_locator: str | Locator, item_name: str, parent: None|str) -> str|None:
|
||||||
|
"""Выполняет рекурсивный поиск по панели навигации
|
||||||
|
заданного элемента, делает клик по нему, проверяет наличие индикатора состояния.
|
||||||
|
Если индикатор состояния присутствует, возвращается его цвет. Иначе None"""
|
||||||
|
|
||||||
|
root_locator = self.get_locator(node_root_locator)
|
||||||
|
if parent:
|
||||||
|
parent_loc = self._find_and_click_item(self.page, root_locator, parent, parent=None)
|
||||||
|
found_node_loc = self._find_and_click_item(
|
||||||
|
self.page, parent_loc.locator('>div.v-treeview-node__children'),
|
||||||
|
item_name, parent=None
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
found_node_loc = self._find_and_click_item(self.page, root_locator, item_name, parent=None)
|
||||||
|
|
||||||
|
assert found_node_loc, f"Navigation panel item {item_name} is missing"
|
||||||
|
|
||||||
|
color = None
|
||||||
|
sub_item_state_loc_str = f"//span[text()='{item_name}']/preceding-sibling::*[name()='svg'][2]"
|
||||||
|
sub_item_state_locator = found_node_loc.locator("div.v-treeview-node__label").locator(sub_item_state_loc_str)
|
||||||
|
|
||||||
|
if sub_item_state_locator.count() > 0:
|
||||||
|
color = sub_item_state_locator.get_attribute("fill")
|
||||||
|
if color: color = color.lstrip('#')
|
||||||
|
return color
|
||||||
|
|
||||||
def should_be_expand_workarea_button(self) -> None:
|
def should_be_expand_workarea_button(self) -> None:
|
||||||
"""Проверяет наличие кнопки расширения рабочей области страницы.
|
"""Проверяет наличие кнопки расширения рабочей области страницы.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,25 @@ class MainPage(BasePage):
|
||||||
item_name
|
item_name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def check_subpanel_item_state(self, item_name: str, parent=None) -> str|None:
|
||||||
|
"""Выполняет рекурсивный поиск по панели навигации
|
||||||
|
заданного элемента, делает клик по нему, проверяет наличие индикатора состояния.
|
||||||
|
Если индикатор состояния присутствует, возвращается его цвет. Иначе None"""
|
||||||
|
|
||||||
|
active_item_locator = self.page.locator(
|
||||||
|
NavigationPanelLocators.PANEL_MAIN
|
||||||
|
).locator(NavigationPanelLocators.ACTIVE_CONTAINER)
|
||||||
|
node_locator = active_item_locator.locator(
|
||||||
|
NavigationPanelLocators.SUB_PANEL_MAIN
|
||||||
|
).locator(NavigationPanelLocators.TREEVIEW).first
|
||||||
|
|
||||||
|
# Рекурсивный поиск в дереве v-treeview заданного элемента
|
||||||
|
# и клик по нему
|
||||||
|
return self.navigation_panel.check_sub_item_state(
|
||||||
|
node_locator, item_name, parent
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def check_navigation_panel_verticall_scrolling(self) -> bool:
|
def check_navigation_panel_verticall_scrolling(self) -> bool:
|
||||||
"""Проверяет возможность вертикальной прокрутки панели.
|
"""Проверяет возможность вертикальной прокрутки панели.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ class TestNavigationPanel:
|
||||||
mp.wait_for_timeout(5000)
|
mp.wait_for_timeout(5000)
|
||||||
|
|
||||||
|
|
||||||
mp.click_subpanel_item("test-zone-01")
|
mp.click_subpanel_item("test-zone")
|
||||||
mp.wait_for_timeout(3000)
|
mp.wait_for_timeout(3000)
|
||||||
|
|
||||||
# Переходим к Стойке
|
# Переходим к Стойке
|
||||||
|
|
@ -128,3 +128,41 @@ class TestNavigationPanel:
|
||||||
# # Переходим к Стойка систем питания с указанием родителя
|
# # Переходим к Стойка систем питания с указанием родителя
|
||||||
# mp.click_subpanel_item("Стойка систем питания", parent="Виртуальные устройства")
|
# mp.click_subpanel_item("Стойка систем питания", parent="Виртуальные устройства")
|
||||||
# mp.wait_for_timeout(5000)
|
# mp.wait_for_timeout(5000)
|
||||||
|
|
||||||
|
@pytest.mark.develop
|
||||||
|
def test_check_sub_panel_item_state(self, browser: Page):
|
||||||
|
"""Проверяет наличие индикатора состояния заданного элемента в подпанели навигации.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
browser: Фикстура для работы с браузером.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Действия:
|
||||||
|
lp = LoginPage(browser)
|
||||||
|
lp.do_login()
|
||||||
|
|
||||||
|
# Мы на главной странице
|
||||||
|
mp = MainPage(browser)
|
||||||
|
|
||||||
|
# Проверки:
|
||||||
|
# Проверяем наличие панели навигации
|
||||||
|
mp.should_be_navigation_panel()
|
||||||
|
|
||||||
|
# Открываем разные пункты панели
|
||||||
|
mp.click_main_navigation_panel_item("Настройки")
|
||||||
|
|
||||||
|
mp.click_subpanel_item("Обслуживание и диагностика")
|
||||||
|
state_color = mp.check_subpanel_item_state("Сеансы")
|
||||||
|
assert not state_color, "Got state color but subpanel item 'Сеансы' has no state indicator"
|
||||||
|
mp.wait_for_timeout(2000)
|
||||||
|
|
||||||
|
# Переходим к Объектам
|
||||||
|
mp.click_main_navigation_panel_item("Объекты")
|
||||||
|
mp.wait_for_timeout(5000)
|
||||||
|
|
||||||
|
state_color = mp.check_subpanel_item_state("test-zone")
|
||||||
|
assert state_color, "State indicator has not found for subpanel item 'test-zone'"
|
||||||
|
|
||||||
|
state_color = mp.check_subpanel_item_state("Test-Rack-01")
|
||||||
|
assert state_color, "State indicator has not found for subpanel item 'Test-Rack-01'"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue