Изменено: в методе click_sub_item, убрана проверка 'Если не нашли среди непосредственных детей, ищем рекурсивно

Radislav 2025-10-22 19:58:40 +03:00
parent ccbd7a6727
commit 8a9228e75e
1 changed files with 105 additions and 60 deletions

View File

@ -47,79 +47,124 @@ class NavigationPanelComponent(BaseComponent):
loc.get_by_text(item_name).click()
def click_sub_item(self, node_root_locator: str | Locator, item_name: str, parent: None|str) -> None:
"""Кликает по вложенному элементу с указанным текстом.
Args:
node_root_locator: Локатор для поиска корневых элементов дерева (Локатор элемента или строка с CSS/XPath).
item_name: Текст элемента для клика.
"""
"""Кликает по вложенному элементу с указанным текстом."""
def find_and_click_item(page, root_locator, item_name: str, parent: None|str) -> bool:
# Находим все локаторы корневых узлов на текущем уровне
root_node = root_locator.locator('>div.v-treeview-node')
# Получаем список текстов
root_node_texts = root_node.all_inner_texts()
"""Рекурсивно ищет элемент в дереве и кликает по нему."""
# Если искомый элемент находится на данном уровне, вычисляем локатор и делаем клик
if parent is None:
for index, node_text in enumerate(root_node_texts):
node_text = node_text.replace("expand_more\n", "")
if item_name == node_text:
root_node.nth(index).click()
return True
# Если элемента нет, рекурсивно ищем дальше
# Если указан родитель, сначала находим его
if parent:
# Ищем родительский элемент
parent_found = 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_class_attr = node.get_attribute('class')
# Получаем текст контента для точного сравнения
content_locator = node.locator('div.v-treeview-node__content')
if content_locator.count() > 0:
content_text = content_locator.first.inner_text().strip()
is_expanded = False
has_children = False
# Ищем родителя в тексте контента
if parent == content_text:
parent_found = True
# Проверяем лист это или начало поддерева
if "v-treeview-node--leaf" not in node_class_attr:
# Проверяем, является ли узел раскрытым
class_attr = node.locator(NavigationPanelLocators.TOGGLE_BUTTON).get_attribute('class')
if "v-treeview-node__toggle--open" in class_attr:
is_expanded = True
# Раскрываем родительский элемент если нужно
toggle_buttons = node.locator(NavigationPanelLocators.TOGGLE_BUTTON)
if toggle_buttons.count() > 0:
class_attr = toggle_buttons.first.get_attribute('class')
is_expanded = class_attr and "v-treeview-node__toggle--open" in class_attr
# Если узел закрыт можем его раскрыть
if is_expanded is False:
toggle_button = node.locator(NavigationPanelLocators.TOGGLE_BUTTON)
toggle_button.click()
# Ждем, пока дочерние элементы прогрузятся/появятся
page.wait_for_timeout(300)
is_expanded = True
if not is_expanded:
toggle_buttons.first.click()
page.wait_for_timeout(1000)
# После раскрытия ждем появления дочерних элементов
page.wait_for_timeout(500)
# Ищем целевой элемент как непосредственного ребенка родителя
children_locator = node.locator('>div.v-treeview-node__children')
if children_locator.count() > 0:
# Ищем среди непосредственных детей
direct_children = children_locator.locator('>div.v-treeview-node')
direct_children_count = direct_children.count()
for child_index in range(direct_children_count):
child_node = direct_children.nth(child_index)
child_content = child_node.locator('div.v-treeview-node__content')
if child_content.count() > 0:
child_text = child_content.first.inner_text().strip()
if child_text == item_name:
child_content.first.click()
return True
# Если не нашли среди непосредственных детей, ищем рекурсивно
for child_index in range(direct_children_count):
child_node = direct_children.nth(child_index)
found = find_and_click_item(page, children_locator, item_name, parent=None)
if found:
return True
break
if not parent_found:
# Рекурсивный поиск родителя в дочерних элементах
for index in range(nodes_count):
node = root_locator.locator(f">div:nth-child({index + 1})").first
# Проверяем, имеет ли узел дочерние элементы
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
toggle_buttons = node.locator(NavigationPanelLocators.TOGGLE_BUTTON)
if toggle_buttons.count() > 0:
class_attr = toggle_buttons.first.get_attribute('class')
is_expanded = class_attr and "v-treeview-node__toggle--open" in class_attr
# Рекурсивный вызов для дочерних элементов
# Ищем дочерние элементы *внутри* текущего узла
if has_children and is_expanded:
child_nodes_locator = root_locator.locator(f">div:nth-child({index + 1})").locator('>div.v-treeview-node__children')
is_found = find_and_click_item(page, child_nodes_locator, item_name, parent=None)
if is_found:
if parent is None:
if not is_expanded:
toggle_buttons.first.click()
page.wait_for_timeout(500)
children_locator = node.locator('>div.v-treeview-node__children')
if children_locator.count() > 0:
found = find_and_click_item(page, children_locator, item_name, parent)
if found:
return True
return False
else:
root_texts = root_locator.locator(f">div:nth-child({index + 1})").inner_text().splitlines()
if parent in root_texts:
# Поиск без указания родителя
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
# Получаем только текст контента
content_locator = node.locator('div.v-treeview-node__content')
if content_locator.count() > 0:
content_text = content_locator.first.inner_text().strip()
if content_text == item_name:
content_locator.first.click()
return True
# закрываем узел, если в нем ничего не нашли
if is_expanded:
toggle_button = node.locator(NavigationPanelLocators.TOGGLE_BUTTON)
toggle_button.click()
# Рекурсивный поиск в дочерних элементах
node_class_attr = node.get_attribute('class')
if "v-treeview-node--leaf" not in node_class_attr:
toggle_buttons = node.locator(NavigationPanelLocators.TOGGLE_BUTTON)
if toggle_buttons.count() > 0:
class_attr = toggle_buttons.first.get_attribute('class')
is_expanded = class_attr and "v-treeview-node__toggle--open" in class_attr
if not is_expanded:
toggle_buttons.first.click()
page.wait_for_timeout(500)
children_locator = node.locator('>div.v-treeview-node__children')
if children_locator.count() > 0:
found = find_and_click_item(page, children_locator, item_name, parent=None)
if found:
return True
# элемент с заданным именем не найден
return False
root_locator = self.get_locator(node_root_locator)