Compare commits

...

2 Commits

Author SHA1 Message Date
Radislav 85491b7cb9 feat: добавление проверки существования элемента навигации
- Добавлен метод check_navigation_item_exists с возвратом boolean
- Реализована мягкая проверка элементов навигационной панели
2025-11-25 14:57:08 +03:00
Radislav e00edb65ef refactor(users): исправление опечатки и форматирования кода
- Исправлена опечатка в названии метода check_navigation_panel_verticall_scrolling на check_navigation_panel_vertical_scrolling
- Улучшено форматирование кода для лучшей читаемости
- Удалены лишние пробелы и приведено к единому стилю оформления
2025-11-25 14:33:24 +03:00
2 changed files with 253 additions and 229 deletions

View File

@ -8,8 +8,8 @@ from playwright.sync_api import Page
from locators.navigation_panel_locators import NavigationPanelLocators from locators.navigation_panel_locators import NavigationPanelLocators
from components_derived.container_system_log_events import SystemLogEventsContainer from components_derived.container_system_log_events import SystemLogEventsContainer
from components_derived.user_card import UserCard from components_derived.user_card import UserCard
from components.navbar_component import NavigationPanelComponent
from components.eventbar_component import EventPanelComponent from components.eventbar_component import EventPanelComponent
from components.navbar_component import NavigationPanelComponent
from pages.base_page import BasePage from pages.base_page import BasePage
class MainPage(BasePage): class MainPage(BasePage):
@ -35,24 +35,6 @@ class MainPage(BasePage):
self.event_panel = EventPanelComponent(page) self.event_panel = EventPanelComponent(page)
# Действия: # Действия:
def click_main_navigation_panel_item(self, item_name: str) -> None:
"""Кликает по элементу основной панели навигации.
Args:
item_name: Название элемента для клика.
"""
self.navigation_panel.click_item(NavigationPanelLocators.PANEL_MAIN, item_name)
def click_subpanel_item(self, item_name: str, parent=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 заданного элемента и клик по нему
self.navigation_panel.click_sub_item(node_locator, item_name, parent)
def click_events_panel_expand_less_button(self) -> None: def click_events_panel_expand_less_button(self) -> None:
"""Выполняет нажатие кнопки галочка вверх.""" """Выполняет нажатие кнопки галочка вверх."""
@ -68,6 +50,35 @@ class MainPage(BasePage):
return self.event_panel.click_system_log_tab() return self.event_panel.click_system_log_tab()
def click_main_navigation_panel_item(self, item_name: str) -> None:
"""Кликает по элементу основной панели навигации.
Args:
item_name: Название элемента для клика.
"""
self.navigation_panel.click_item(
NavigationPanelLocators.PANEL_MAIN,
item_name
)
def click_subpanel_item(self, item_name: str, parent=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 заданного элемента
# и клик по нему
self.navigation_panel.click_sub_item(
node_locator, item_name, parent
)
def click_user_button(self) -> UserCard: def click_user_button(self) -> UserCard:
"""Выполняет нажатие кнопки пользователя.""" """Выполняет нажатие кнопки пользователя."""
@ -78,17 +89,31 @@ class MainPage(BasePage):
self.event_panel.do_logout() self.event_panel.do_logout()
def expand_navigation_subpanel(self): def expand_navigation_subpanel(self) -> None:
"""Выполняет полное открытие активной главной навигационной подпанели.""" """Выполняет полное открытие активной главной
навигационной подпанели."""
active_item_locator = self.page.locator(NavigationPanelLocators.PANEL_MAIN).locator(NavigationPanelLocators.ACTIVE_CONTAINER) active_item_locator = self.page.locator(
node_locator = active_item_locator.locator(NavigationPanelLocators.SUB_PANEL_MAIN).locator(NavigationPanelLocators.TREEVIEW).first 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) # Рекурсивный обход дерева v-treeview выбранной подпанели
self.navigation_panel.traverse_panel_tree(node_locator, debug=False) # и вывод информации об элементах в режиме отладки (debug=True)
self.navigation_panel.traverse_panel_tree(
node_locator, debug=False
)
def get_event_counters_by_tooltips(self) -> {}: def get_event_counters_by_buttons(self) -> dict:
"""Возвращает набор текстов всплывающих подсказок кнопок счетчиков событий.""" """Возвращает набор значений кнопок счетчиков событий."""
return self.event_panel.get_event_button_values()
def get_event_counters_by_tooltips(self) -> dict:
"""Возвращает набор текстов всплывающих подсказок
кнопок счетчиков событий."""
events = self.event_panel.get_event_tooltip_texts() events = self.event_panel.get_event_tooltip_texts()
@ -100,59 +125,27 @@ class MainPage(BasePage):
event_counters[event_name] = count event_counters[event_name] = count
return event_counters return event_counters
def get_event_counters_by_buttons(self) -> {}:
"""Возвращает набор значений кнопок счетчиков событий."""
return self.event_panel.get_event_button_values()
def get_events_panel_position(self) -> str: def get_events_panel_position(self) -> str:
"""Возвращает текущее положение панели событий относительно страницы: "top", "center","bottom".""" """Возвращает текущее положение панели событий
относительно страницы: "top", "center","bottom"."""
return self.event_panel.get_panel_position() return self.event_panel.get_panel_position()
def scroll_navigation_panel_up(self) -> None:
"""Прокручивает панель навигации вверх."""
self.navigation_panel.scroll_up(NavigationPanelLocators.PANEL_SCROLL_CONTAINER)
def scroll_navigation_panel_down(self) -> None: def scroll_navigation_panel_down(self) -> None:
"""Прокручивает панель навигации вниз.""" """Прокручивает панель навигации вниз."""
self.navigation_panel.scroll_down(NavigationPanelLocators.PANEL_SCROLL_CONTAINER) self.navigation_panel.scroll_down(
NavigationPanelLocators.PANEL_SCROLL_CONTAINER
)
def scroll_navigation_panel_up(self) -> None:
"""Прокручивает панель навигации вверх."""
self.navigation_panel.scroll_up(
NavigationPanelLocators.PANEL_SCROLL_CONTAINER
)
# Проверки: # Проверки:
def should_be_navigation_panel(self) -> None:
"""Проверяет наличие панели навигации."""
self.navigation_panel.check_visibility(
NavigationPanelLocators.PANEL_MAIN,
"Navigation panel is missing"
)
def should_be_event_panel(self) -> None:
"""Проверяет наличие элементов панели событий."""
## to-do: кнопки галочки???
self.event_panel.should_be_tab_buttons()
self.event_panel.should_be_event_buttons()
self.event_panel.should_be_search_button()
self.event_panel.should_be_user_button()
def check_navigation_item_exists(self, item_name: str) -> bool:
"""
Проверяет существование элемента в навигационной панели.
Args:
item_name: Название элемента для проверки
Returns:
bool: True если элемент существует, False если нет
"""
return self.navigation_panel.is_item_visible(
NavigationPanelLocators.PANEL_MAIN,
item_name
)
def check_expand_less_button(self) -> bool: def check_expand_less_button(self) -> bool:
"""Проверяет наличие кнопки галочка вверх.""" """Проверяет наличие кнопки галочка вверх."""
@ -163,15 +156,18 @@ class MainPage(BasePage):
return self.event_panel.check_expand_more_button() return self.event_panel.check_expand_more_button()
def check_navigation_panel_verticall_scrolling(self) -> bool: def check_navigation_item_exists(self, item_name: str) -> bool:
"""Проверяет возможность вертикальной прокрутки панели. """Проверяет существование элемента в навигационной панели.
Args:
item_name: Название элемента для проверки
Returns: Returns:
bool: True если прокрутка возможна, иначе False. bool: True если элемент существует, False если нет
""" """
return self.navigation_panel.is_item_visible(
return self.navigation_panel.is_scrollable_vertically( NavigationPanelLocators.PANEL_MAIN,
NavigationPanelLocators.PANEL_SCROLL_CONTAINER item_name
) )
def check_navigation_panel_item_visibility(self, item_name: str) -> None: def check_navigation_panel_item_visibility(self, item_name: str) -> None:
@ -185,3 +181,31 @@ class MainPage(BasePage):
NavigationPanelLocators.PANEL_MAIN, NavigationPanelLocators.PANEL_MAIN,
item_name item_name
) )
def check_navigation_panel_verticall_scrolling(self) -> bool:
"""Проверяет возможность вертикальной прокрутки панели.
Returns:
bool: True если прокрутка возможна, иначе False.
"""
return self.navigation_panel.is_scrollable_vertically(
NavigationPanelLocators.PANEL_SCROLL_CONTAINER
)
def should_be_event_panel(self) -> None:
"""Проверяет наличие элементов панели событий."""
## to-do: кнопки галочки???
self.event_panel.should_be_tab_buttons()
self.event_panel.should_be_event_buttons()
self.event_panel.should_be_search_button()
self.event_panel.should_be_user_button()
def should_be_navigation_panel(self) -> None:
"""Проверяет наличие панели навигации."""
self.navigation_panel.check_visibility(
NavigationPanelLocators.PANEL_MAIN,
"Navigation panel is missing"
)

View File

@ -50,6 +50,7 @@ class UsersTab(BasePage):
self.alert = AlertComponent(page) self.alert = AlertComponent(page)
# Действия: # Действия:
def add_modal_window(self, window_type: str, title: str) -> None: def add_modal_window(self, window_type: str, title: str) -> None:
"""Добавляет модальное окно в коллекцию. """Добавляет модальное окно в коллекцию.
@ -70,98 +71,6 @@ class UsersTab(BasePage):
else: else:
assert False, "Unsupported modal window type" assert False, "Unsupported modal window type"
def get_modal_window(self, title: str) -> ModalWindowComponent:
"""Возвращает модальное окно по заголовку.
Args:
title: Заголовок окна.
Returns:
ModalWindowComponent: Экземпляр модального окна.
Raises:
AssertionError: Если окно не найдено.
"""
modal_window = self.modal_windows.get(title)
if modal_window is None:
assert False, f"Modal window with title '{title}' not found"
return modal_window
def delete_modal_window(self, title: str) -> None:
"""Удаляет модальное окно из коллекции.
Args:
title: Заголовок окна.
Raises:
AssertionError: Если окно не найдено.
"""
if self.modal_windows.get(title) is None:
assert False, f"Modal window with title '{title}' not found"
self.modal_windows[title] = None
def close_modal_window_by_toolbar_button(self, title: str) -> None:
"""Закрывает модальное окно через кнопку в тулбаре.
Args:
title: Заголовок окна.
"""
modal_window = self.get_modal_window(title)
modal_window.close_window_by_toolbar_button()
self.delete_modal_window(title)
def close_modal_window(self, title: str) -> None:
"""Закрывает модальное окно через кнопку закрытия.
Args:
title: Заголовок окна.
"""
modal_window = self.get_modal_window(title)
modal_window.close_window()
self.delete_modal_window(title)
def close_add_AD_user_window_by_toolbar_button(self) -> None:
"""Закрывает окно добавления пользователя через тулбар."""
self.close_modal_window_by_toolbar_button("add_AD_user")
def close_add_AD_user_window(self) -> None:
"""Закрывает окно добавления пользователя."""
self.close_modal_window("add_AD_user")
def close_add_user_window_by_toolbar_button(self) -> None:
"""Закрывает окно добавления пользователя через тулбар."""
self.close_modal_window_by_toolbar_button("add_local_user")
def close_add_user_window(self) -> None:
"""Закрывает окно добавления пользователя."""
self.close_modal_window("add_local_user")
def close_edit_user_window_by_toolbar_button(self, title: str) -> None:
"""Закрывает окно редактирования через кнопку в тулбаре.
Args:
title: Имя пользователя (заголовок окна).
"""
self.close_modal_window_by_toolbar_button(title)
def close_edit_user_window(self, title: str) -> None:
"""Закрывает окно редактирования пользователя.
Args:
title: Имя пользователя (заголовок окна).
"""
self.close_modal_window(title)
def add_new_user(self, user_data: dict) -> bool: def add_new_user(self, user_data: dict) -> bool:
"""Добавляет нового пользователя или обрабатывает ошибку при дубликате. """Добавляет нового пользователя или обрабатывает ошибку при дубликате.
@ -193,7 +102,6 @@ class UsersTab(BasePage):
self.alert.check_alert_absence(' Новый пользователь \n успешно добавлен! ') self.alert.check_alert_absence(' Новый пользователь \n успешно добавлен! ')
is_added = True is_added = True
elif alert_type == "error": elif alert_type == "error":
print(f' Имя {user_data["name"]} уже используется ')
self.alert.check_alert_presence(f' Имя {user_data["name"]} уже \n используется ') self.alert.check_alert_presence(f' Имя {user_data["name"]} уже \n используется ')
self.alert.check_alert_absence(f' Имя {user_data["name"]} уже \n используется ') self.alert.check_alert_absence(f' Имя {user_data["name"]} уже \n используется ')
else: else:
@ -201,6 +109,80 @@ class UsersTab(BasePage):
return is_added return is_added
def close_add_AD_user_window(self) -> None:
"""Закрывает окно добавления пользователя."""
self.close_modal_window("add_AD_user")
def close_add_AD_user_window_by_toolbar_button(self) -> None:
"""Закрывает окно добавления пользователя через тулбар."""
self.close_modal_window_by_toolbar_button("add_AD_user")
def close_add_user_window(self) -> None:
"""Закрывает окно добавления пользователя."""
self.close_modal_window("add_local_user")
def close_add_user_window_by_toolbar_button(self) -> None:
"""Закрывает окно добавления пользователя через тулбар."""
self.close_modal_window_by_toolbar_button("add_local_user")
def close_edit_user_window(self, title: str) -> None:
"""Закрывает окно редактирования пользователя.
Args:
title: Имя пользователя (заголовок окна).
"""
self.close_modal_window(title)
def close_edit_user_window_by_toolbar_button(self, title: str) -> None:
"""Закрывает окно редактирования через кнопку в тулбаре.
Args:
title: Имя пользователя (заголовок окна).
"""
self.close_modal_window_by_toolbar_button(title)
def close_modal_window(self, title: str) -> None:
"""Закрывает модальное окно через кнопку закрытия.
Args:
title: Заголовок окна.
"""
modal_window = self.get_modal_window(title)
modal_window.close_window()
self.delete_modal_window(title)
def close_modal_window_by_toolbar_button(self, title: str) -> None:
"""Закрывает модальное окно через кнопку в тулбаре.
Args:
title: Заголовок окна.
"""
modal_window = self.get_modal_window(title)
modal_window.close_window_by_toolbar_button()
self.delete_modal_window(title)
def delete_modal_window(self, title: str) -> None:
"""Удаляет модальное окно из коллекции.
Args:
title: Заголовок окна.
Raises:
AssertionError: Если окно не найдено.
"""
if self.modal_windows.get(title) is None:
assert False, f"Modal window with title '{title}' not found"
self.modal_windows[title] = None
def delete_user(self, user_name: str) -> None: def delete_user(self, user_name: str) -> None:
"""Удаляет пользователя. """Удаляет пользователя.
@ -238,26 +220,6 @@ class UsersTab(BasePage):
self.alert.check_alert_presence('\nОбновление успешно\n') self.alert.check_alert_presence('\nОбновление успешно\n')
self.alert.check_alert_absence('\nОбновление успешно\n') self.alert.check_alert_absence('\nОбновление успешно\n')
def reset_password(self, user_name: str) -> str:
"""Сбрасывает пароль пользователя.
Args:
user_name: Имя пользователя.
Returns:
str: Новый пароль (если получен).
"""
new_password = ""
self.get_modal_window(user_name).reset_password()
self.alert.check_alert_presence("")
alert_message = self.alert.get_text()
if len(alert_message) > 0:
new_password = re.findall(r'[\d]+', alert_message)[0]
return new_password
def find_user_in_table(self, name: str, role: str) -> int: def find_user_in_table(self, name: str, role: str) -> int:
"""Ищет пользователя в таблице. """Ищет пользователя в таблице.
@ -278,13 +240,32 @@ class UsersTab(BasePage):
if len(table_content) == 0: if len(table_content) == 0:
assert False, "The contents of the table are missing" assert False, "The contents of the table are missing"
del table_content[0] # Удаляем заголовок # Удаляем заголовок
del table_content[0]
for row_index, user_info in enumerate(table_content): for row_index, user_info in enumerate(table_content):
if name in user_info and role in user_info: if name in user_info and role in user_info:
return row_index return row_index
return -1 return -1
def get_modal_window(self, title: str) -> ModalWindowComponent:
"""Возвращает модальное окно по заголовку.
Args:
title: Заголовок окна.
Returns:
ModalWindowComponent: Экземпляр модального окна.
Raises:
AssertionError: Если окно не найдено.
"""
modal_window = self.modal_windows.get(title)
if modal_window is None:
assert False, f"Modal window with title '{title}' not found"
return modal_window
def open_add_user_window(self) -> None: def open_add_user_window(self) -> None:
"""Открывает окно добавления пользователя. """Открывает окно добавления пользователя.
@ -325,7 +306,8 @@ class UsersTab(BasePage):
if len(table_content) == 0: if len(table_content) == 0:
assert False, "The contents of the table are missing" assert False, "The contents of the table are missing"
del table_content[0] # Удаляем заголовок # Удаляем заголовок
del table_content[0]
if row_index >= len(table_content): if row_index >= len(table_content):
assert False, "Row_index is out of range" assert False, "Row_index is out of range"
@ -359,11 +341,30 @@ class UsersTab(BasePage):
if row_index == -1: if row_index == -1:
assert False, f"User with name {user_name} and role {role} has not been found" assert False, f"User with name {user_name} and role {role} has not been found"
self.page.locator(TableLocators.TABLE_WORK_AREA).locator( self.page.locator(TableLocators.TABLE_WORK_AREA).locator("//tbody/tr").nth(row_index).click()
"//tbody/tr").nth(row_index).click()
self.add_modal_window("edit_user", user_name) self.add_modal_window("edit_user", user_name)
self.get_modal_window(user_name).check_by_window_title() self.get_modal_window(user_name).check_by_window_title()
def reset_password(self, user_name: str) -> str:
"""Сбрасывает пароль пользователя.
Args:
user_name: Имя пользователя.
Returns:
str: Новый пароль (если получен).
"""
new_password = ""
self.get_modal_window(user_name).reset_password()
self.alert.check_alert_presence("")
alert_message = self.alert.get_text()
if len(alert_message) > 0:
new_password = re.findall(r'[\d]+', alert_message)[0]
return new_password
def transform_to_add_AD_user_window(self): def transform_to_add_AD_user_window(self):
"""Трансформирует модальное окно добавления локального пользователя """Трансформирует модальное окно добавления локального пользователя
в окно добавления пользователя Active Directory с помощью нажатия в окно добавления пользователя Active Directory с помощью нажатия
@ -387,6 +388,27 @@ class UsersTab(BasePage):
self.add_modal_window("add_local_user", "") self.add_modal_window("add_local_user", "")
# Проверки: # Проверки:
def check_add_AD_user_window_content(self) -> None:
"""Проверяет содержимое окна добавления пользователя через Active Directory."""
self.get_modal_window("add_AD_user").check_content()
def check_add_user_window_content(self) -> None:
"""Проверяет содержимое окна добавления локального пользователя."""
self.get_modal_window("add_local_user").check_content()
def check_edit_user_window_content(self, user_name: str, role: str) -> None:
"""Проверяет содержимое окна редактирования.
Args:
user_name: Имя пользователя.
role: Роль пользователя.
"""
edit_user_window = self.get_modal_window(user_name)
edit_user_window.check_content(user_name, role)
def check_users_table_content(self, verify: bool = False) -> None: def check_users_table_content(self, verify: bool = False) -> None:
"""Проверяет содержимое таблицы пользователей. """Проверяет содержимое таблицы пользователей.
@ -418,27 +440,6 @@ class UsersTab(BasePage):
if verify: if verify:
self.verify_users_table_content(table_content) self.verify_users_table_content(table_content)
def check_add_user_window_content(self) -> None:
"""Проверяет содержимое окна добавления локального пользователя."""
self.get_modal_window("add_local_user").check_content()
def check_add_AD_user_window_content(self) -> None:
"""Проверяет содержимое окна добавления пользователя через Active Directory."""
self.get_modal_window("add_AD_user").check_content()
def check_edit_user_window_content(self, user_name: str, role: str) -> None:
"""Проверяет содержимое окна редактирования.
Args:
user_name: Имя пользователя.
role: Роль пользователя.
"""
edit_user_window = self.get_modal_window(user_name)
edit_user_window.check_content(user_name, role)
def should_be_toolbar(self) -> None: def should_be_toolbar(self) -> None:
"""Проверяет наличие тулбара. """Проверяет наличие тулбара.
@ -468,18 +469,6 @@ class UsersTab(BasePage):
self.toolbar.get_button_by_name("close").click() self.toolbar.get_button_by_name("close").click()
self.toolbar.check_button_visibility("edit") self.toolbar.check_button_visibility("edit")
def should_be_users_table(self) -> None:
"""Проверяет наличие таблицы пользователей.
Raises:
AssertionError: Если таблица отсутствует.
"""
self.users_table.check_visibility(
TableLocators.TABLE_WORK_AREA,
"Users table is missing"
)
def should_be_user_in_table(self, name: str, role: str) -> None: def should_be_user_in_table(self, name: str, role: str) -> None:
"""Проверяет наличие пользователя в таблице. """Проверяет наличие пользователя в таблице.
@ -495,6 +484,15 @@ class UsersTab(BasePage):
if found == -1: if found == -1:
assert False, f"User with name {name} and role {role} has not been found" assert False, f"User with name {name} and role {role} has not been found"
def should_be_users_table(self) -> None:
"""Проверяет наличие таблицы пользователей.
Raises:
AssertionError: Если таблица отсутствует.
"""
self.users_table.check_visibility(TableLocators.TABLE_WORK_AREA,"Users table is missing")
def should_not_be_user_in_table(self, name: str, role: str) -> None: def should_not_be_user_in_table(self, name: str, role: str) -> None:
"""Проверяет отсутствие пользователя в таблице. """Проверяет отсутствие пользователя в таблице.
@ -547,7 +545,8 @@ class UsersTab(BasePage):
if item["role"] is not None: if item["role"] is not None:
role = item["role"] role = item["role"]
if role in roles_dict: # Убрали вызов .keys() # Убрали вызов .keys()
if role in roles_dict:
item["role"] = roles_dict[role] item["role"] = roles_dict[role]
user_info.append(item["role"]) user_info.append(item["role"])
else: else:
@ -565,7 +564,8 @@ class UsersTab(BasePage):
expected_users_list.append(user_info) expected_users_list.append(user_info)
del users_table[0] # Удаляем заголовок # Удаляем заголовок
del users_table[0]
self.check_lists_equals( self.check_lists_equals(
users_table, users_table,