Добавлена возможность полного открытия панели навигации на основе рекурсивного обхода дерева элементов
parent
eb0246e84a
commit
351b11573a
|
|
@ -34,6 +34,7 @@ class NavigationPanelComponent(BaseComponent):
|
||||||
loc = self.get_locator(locator)
|
loc = self.get_locator(locator)
|
||||||
return loc.all_inner_texts()
|
return loc.all_inner_texts()
|
||||||
|
|
||||||
|
|
||||||
def click_item(self, locator: str | Locator, item_name: str) -> None:
|
def click_item(self, locator: str | Locator, item_name: str) -> None:
|
||||||
"""Кликает по элементу с указанным текстом.
|
"""Кликает по элементу с указанным текстом.
|
||||||
|
|
||||||
|
|
@ -69,6 +70,69 @@ class NavigationPanelComponent(BaseComponent):
|
||||||
else:
|
else:
|
||||||
raise ValueError("the navigation panel has two levels of nesting only")
|
raise ValueError("the navigation panel has two levels of nesting only")
|
||||||
|
|
||||||
|
def traverse_panel_tree(self, node_root_locator, level=0, debug=False):
|
||||||
|
"""
|
||||||
|
Рекурсивно обходит дерево v-treeview и выводит информацию об элементах в режиме отладки (debug=True).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node_root_locator: Локатор для поиска корневых элементов дерева (Локатор элемента или строка с CSS/XPath).
|
||||||
|
"""
|
||||||
|
def traverse_tree(page, root_locator, level=0, debug=False):
|
||||||
|
# Находим все локаторы корневых узлов на текущем уровне
|
||||||
|
nodes_count = root_locator.locator('>div.v-treeview-node').count()
|
||||||
|
|
||||||
|
for index in range(nodes_count):
|
||||||
|
node = root_locator.locator(f">div:nth-child({index + 1})").first
|
||||||
|
|
||||||
|
# Извлекаем текст и аттрибуты из корневого узла
|
||||||
|
node_text = node.inner_text()
|
||||||
|
node_class_attr = node.get_attribute('class')
|
||||||
|
|
||||||
|
is_expanded = False
|
||||||
|
has_children = False
|
||||||
|
|
||||||
|
# Проверяем лист это или начало поддерева
|
||||||
|
if "v-treeview-node--leaf" in node_class_attr:
|
||||||
|
if debug:
|
||||||
|
print(f'[{level}][{index}] {node_text} (LEAF, Expanded: {is_expanded}, Has Children: {has_children})')
|
||||||
|
print("-----------------------------------------")
|
||||||
|
else:
|
||||||
|
# Проверяем, является ли узел раскрытым
|
||||||
|
class_attr = node.locator(NavigationPanelLocators.TOGGLE_BUTTON).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.TOGGLE_BUTTON)
|
||||||
|
toggle_button.click()
|
||||||
|
# Ждем, пока дочерние элементы прогрузятся/появятся
|
||||||
|
page.wait_for_timeout(300)
|
||||||
|
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
|
||||||
|
|
||||||
|
edited_node_text = node_text.replace("expand_more\n", "")
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
# Выводим информацию об узле
|
||||||
|
print(f'[{level}][{index}] {edited_node_text} (NODE, Expanded: {is_expanded}, Has Children: {has_children})')
|
||||||
|
print("-----------------------------------------")
|
||||||
|
|
||||||
|
# Рекурсивный вызов для дочерних элементов
|
||||||
|
# Ищем дочерние элементы *внутри* текущего узла
|
||||||
|
if has_children and is_expanded:
|
||||||
|
child_nodes_locator = root_locator.locator(f">div:nth-child({index + 1})").locator('>div.v-treeview-node__children')
|
||||||
|
traverse_tree(page, child_nodes_locator, level+1, debug)
|
||||||
|
|
||||||
|
root_locator = self.get_locator(node_root_locator)
|
||||||
|
traverse_tree(self.page, root_locator, level=level, debug=debug)
|
||||||
|
|
||||||
# Проверки:
|
# Проверки:
|
||||||
def check_item_visibility(self, locator: str | Locator, item_name: str) -> None:
|
def check_item_visibility(self, locator: str | Locator, item_name: str) -> None:
|
||||||
"""Проверяет видимость элемента с указанным текстом.
|
"""Проверяет видимость элемента с указанным текстом.
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,22 @@ class NavigationPanelLocators:
|
||||||
Содержит XPath локаторы для:
|
Содержит XPath локаторы для:
|
||||||
PANEL_MAIN (str): основной панели навигации
|
PANEL_MAIN (str): основной панели навигации
|
||||||
PANEL_SCROLL_CONTAINER (str): контейнера с прокруткой
|
PANEL_SCROLL_CONTAINER (str): контейнера с прокруткой
|
||||||
|
ACTIVE_CONTAINER(str): активного контейнера, содержащего открываемые элементы панели навигации
|
||||||
|
TREEVIEW(str): корня объекта v-treeview
|
||||||
|
NODE(str): узла дерева
|
||||||
NODE_ROOT (str): корневого узла дерева
|
NODE_ROOT (str): корневого узла дерева
|
||||||
NODE_CHILDREN (str): дочерних элементов узла
|
NODE_CHILDREN (str): дочерних элементов узла
|
||||||
|
TOGGLE_BUTTON(str): кнопки раскрытия элементов панели навигации
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PANEL_MAIN = "//ul[contains(@class, 'v-expansion-panel')]"
|
PANEL_MAIN = "//ul[contains(@class, 'v-expansion-panel')]"
|
||||||
PANEL_SCROLL_CONTAINER = "//div[contains(@class, 'scrollarea__body') and .//ul[contains(@class, 'v-expansion-panel')]]"
|
PANEL_SCROLL_CONTAINER = "//div[contains(@class, 'scrollarea__body') and .//ul[contains(@class, 'v-expansion-panel')]]"
|
||||||
|
|
||||||
|
ACTIVE_CONTAINER = "//li[contains(@class, 'v-expansion-panel__container--active')]"
|
||||||
|
SUB_PANEL_MAIN = "//div[contains(@class,'v-expansion-panel__body')]"
|
||||||
|
|
||||||
|
TREEVIEW = "//div[contains(@class,'v-treeview')]"
|
||||||
|
NODE = "//div[contains(@class,'v-treeview-node')]"
|
||||||
NODE_ROOT = "//div[contains(@class,'v-treeview-node__root')]"
|
NODE_ROOT = "//div[contains(@class,'v-treeview-node__root')]"
|
||||||
NODE_CHILDREN = "//div[contains(@class,'v-treeview-node__children')]"
|
NODE_CHILDREN = "//div[contains(@class,'v-treeview-node__children')]"
|
||||||
|
TOGGLE_BUTTON = "//i[contains(@class,'v-treeview-node__toggle')]"
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,15 @@ class MainPage(BasePage):
|
||||||
self.click_user_button()
|
self.click_user_button()
|
||||||
self.user_card.click_logout_button()
|
self.user_card.click_logout_button()
|
||||||
|
|
||||||
|
def expand_navigation_subpanel(self):
|
||||||
|
"""Выполняет полное открытие активной главной навигационной подпанели."""
|
||||||
|
|
||||||
|
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 выбранной подпанели и вывод информации об элементах в режиме отладки (debug=True)
|
||||||
|
self.navigation_panel.traverse_panel_tree(node_locator, debug=False)
|
||||||
|
|
||||||
def scroll_navigation_panel_up(self) -> None:
|
def scroll_navigation_panel_up(self) -> None:
|
||||||
"""Прокручивает панель навигации вверх."""
|
"""Прокручивает панель навигации вверх."""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,11 @@ class TestNavigationPanel:
|
||||||
|
|
||||||
# Открываем все пункты панели
|
# Открываем все пункты панели
|
||||||
mp.click_main_navigation_panel_item("Настройки")
|
mp.click_main_navigation_panel_item("Настройки")
|
||||||
mp.click_configuration_navigation_panel_item("Аутентификация")
|
mp.expand_navigation_subpanel()
|
||||||
mp.click_configuration_navigation_panel_item("Уведомления")
|
|
||||||
mp.click_configuration_navigation_panel_item("Обслуживание и диагностика")
|
mp.click_main_navigation_panel_item("Объекты")
|
||||||
mp.click_configuration_navigation_panel_item("Zero Touch Provisioning")
|
mp.wait_for_timeout(300)
|
||||||
|
mp.expand_navigation_subpanel()
|
||||||
|
|
||||||
# Проверяем возможность вертикальной прокрутки
|
# Проверяем возможность вертикальной прокрутки
|
||||||
is_scrollable = mp.check_navigation_panel_verticall_scrolling()
|
is_scrollable = mp.check_navigation_panel_verticall_scrolling()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
"""Модуль тестов панели навигации.
|
||||||
|
|
||||||
|
Содержит тесты для проверки функциональности
|
||||||
|
панели навигации в приложении.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from playwright.sync_api import Page
|
||||||
|
from pages.main_page import MainPage
|
||||||
|
from pages.login_page import LoginPage
|
||||||
|
|
||||||
|
|
||||||
|
# @pytest.mark.smoke
|
||||||
|
class TestNavigationPanel:
|
||||||
|
"""Класс тестов для проверки панели навигации.
|
||||||
|
|
||||||
|
Атрибуты:
|
||||||
|
browser: Фикстура для работы с браузером.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_expand_panel(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.expand_navigation_subpanel()
|
||||||
|
|
||||||
|
mp.click_main_navigation_panel_item("Объекты")
|
||||||
|
mp.wait_for_timeout(300)
|
||||||
|
|
||||||
|
mp.expand_navigation_subpanel()
|
||||||
Loading…
Reference in New Issue