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