e-nms_qa_automation/components_derived/selection_bar_component.py

230 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""Модуль компонента панели выбора значения.
Содержит класс для работы с компонентом панели выбора значения через Playwright.
"""
from playwright.sync_api import Page, Locator, expect
from tools.logger import get_logger
from locators.selection_bar_locators import SelectionBarLocators
from locators.combobox_locators import ComboboxLocators
from components.dropdown_list_component import DropdownList
from components.base_component import BaseComponent
logger = get_logger("SELECTION_BAR")
class SelectionBarComponent(BaseComponent):
"""Компонент панели выбора значения.
Предоставляет методы для взаимодействия с элементами компонента панели выбора значения.
"""
def __init__(self, page: Page, locator_or_text: str | Locator) -> None:
"""Инициализирует компонент панели выбора значения.
Args:
page: Экземпляр страницы Playwright.
locator_or_text: Локатор панели выбора значения (строка или объект Locator)
или текст для поиска
"""
super().__init__(page)
# Определяем локатор в зависимости от типа параметра
if isinstance(locator_or_text, Locator):
# Если передан готовый Locator
self.selection_bar_locator = locator_or_text
elif locator_or_text.startswith(('//', '.', '#', 'xpath=', 'css=')):
# Если передан строковый локатор
self.selection_bar_locator = self.get_locator(locator_or_text)
else:
# Если передан текст - ищем по тексту label
xpath = SelectionBarLocators.COMBOBOX_BY_LABEL_XPATH.format(locator_or_text)
self.selection_bar_locator = self.page.locator(xpath)
# При нажатии на панель появляется выпадающий список с параметрами фильтрации для выбора
self.selected_values_list = DropdownList(self.page)
# Действия:
def clear_selections(self) -> None:
"""Удаление ранее выбранных значений"""
selected_values = self.get_selected_values()
if len(selected_values) > 0:
clear_button_locator = self.selection_bar_locator.locator(
SelectionBarLocators.CLEAR_SELECTION_BUTTON
)
clear_button_locator.click()
def get_available_options(self) -> list[str]:
"""Возвращает список всех доступных опций из выпадающего списка.
Returns:
list[str]: Список доступных опций
"""
logger.info("Getting available options from dropdown list...")
# Открываем выпадающий список
self.open_values_list()
# Ждем появления списка
self.wait_for_timeout(1000)
# Получаем все элементы списка
options = self.selected_values_list.get_item_names(
SelectionBarLocators.LIST_ITEMS
)
# Закрываем список (кликаем вне его)
self.page.mouse.click(10, 10)
self.wait_for_timeout(500)
logger.info(f"Found available options: {len(options)} - {options}")
return options
def get_selection_bar_title(self) -> str:
"""Возвращает название панели выбора значения"""
title_locator = self.selection_bar_locator.locator(SelectionBarLocators.TITLE_LOCATOR)
return title_locator.text_content()
def get_selected_values(self) -> list[str]:
"""Возвращает список выбранных значений"""
selected_values_locator = self.selection_bar_locator.locator(
SelectionBarLocators.PARAMETERS_SELECTED
)
selected_values = selected_values_locator.all_inner_texts()
return selected_values[0].splitlines()
def clear_combobox_field(self, field_name: str, field_locator: str) -> None:
"""Очищает значение в combobox поле с помощью кнопки закрытия (крестика).
Args:
field_name: Название поля для очистки
field_locator: Локатор поля combobox
"""
logger.info(f"Clearing combobox field '{field_name}' using close button...")
# Находим поле по локатору
field_container = self.page.locator(field_locator).first
# Проверяем что поле видимо
if not field_container.is_visible():
logger.info(f"Field '{field_name}' is not visible, trying to make it visible...")
# Прокручиваем до поля
field_container.scroll_into_view_if_needed()
self.wait_for_timeout(500)
# Если все еще не видимо, пробуем кликнуть
if not field_container.is_visible():
logger.info(f"Field '{field_name}' still not visible after scrolling, skipping")
return
# **ИСПРАВЛЕНИЕ: Используем правильный локатор для кнопки закрытия из combobox_locators**
# Ищем кнопку закрытия (крестик) внутри контейнера поля
close_button = field_container.locator("i.mdi-close").first
# Проверяем наличие и видимость кнопки закрытия
if close_button.count() > 0:
logger.info(f"Found {close_button.count()} close button(s) for field '{field_name}'")
# Прокручиваем до кнопки
close_button.scroll_into_view_if_needed()
self.wait_for_timeout(500)
# Если кнопка закрытия видима - кликаем на нее
close_button.click(force=True)
self.wait_for_timeout(500)
logger.info(f"Combobox field '{field_name}' cleared using close button")
else:
# Если кнопки закрытия нет, просто логируем этот факт
msg = f"Close button (i.mdi-close) not found for field '{field_name}', clearing not performed"
logger.info(msg)
def open_values_list(self) -> None:
"""Открытие выпадающего списка путем нажатия на панель выбора значения"""
expect(self.selection_bar_locator).to_be_visible()
# Проверяем, не открыт ли уже список
parent_class = self.selection_bar_locator.get_attribute("class")
if parent_class and SelectionBarLocators.MENU_ACTIVE_CLASS in parent_class:
logger.info("Values list is already open")
return
# Используем force click для обхода перекрывающих элементов
logger.info("Using force click to open the list")
self.selection_bar_locator.click(force=True)
# Ждем появления выпадающего списка
self.wait_for_timeout(1500)
def select_value(self, name: str) -> None:
"""Выбор значения из списка"""
self.selected_values_list.check_item_with_text(name)
self.selected_values_list.click_item_with_text(name)
# Проверки:
def check_field_error_highlighted(self, field_name: str, field_locator: str) -> None:
"""Проверяет, что поле подсвечено цветом ошибки (валидация не пройдена).
Args:
field_name: Название поля для проверки
field_locator: Локатор поля для проверки
"""
logger.info(f"Checking field '{field_name}' for error highlighting...")
# Получаем контейнер поля
field_container = self.page.locator(field_locator).first
# Проверяем что контейнер поля видимо
self.check_visibility(field_container, f"Field container '{field_name}' not found")
# Ищем элементы с классами ошибки внутри контейнера поля
error_elements = field_container.locator(SelectionBarLocators.ERROR_CSS_SELECTORS)
# Проверяем, что есть хотя бы один элемент с классом ошибки
has_error = error_elements.count() > 0
assert has_error, (
f"Field '{field_name}' has no elements with error classes. "
f"Expected to find elements matching: {SelectionBarLocators.ERROR_CSS_SELECTORS}"
)
logger.info(f"Field '{field_name}' is correctly highlighted with error color")
def check_field_error_not_highlighted(self, field_name: str, field_locator: str) -> None:
"""Проверяет, что поле НЕ подсвечено цветом ошибки (валидация успешна).
Args:
field_name: Название поля для проверки
field_locator: Локатор поля для проверки
"""
logger.info(f"Checking field '{field_name}' for absence of error highlighting...")
# Получаем контейнер поля
field_container = self.page.locator(field_locator).first
# Проверяем что контейнер поля видимо
self.check_visibility(field_container, f"Field container '{field_name}' not found")
# Ищем элементы с классами ошибки внутри контейнера поля
error_elements = field_container.locator(SelectionBarLocators.ERROR_CSS_SELECTORS)
# Проверяем, что нет элементов с классами ошибки
has_error = error_elements.count() > 0
assert not has_error, (
f"Field '{field_name}' has {error_elements.count()} elements with error classes. "
f"Expected no elements matching: {SelectionBarLocators.ERROR_CSS_SELECTORS}"
)
logger.info(f"Field '{field_name}' correctly has no error highlighting")