refactor: переименовать InteractiveDropdownList в CheckboxGroupComponent

- Переименование и перенос компонента в папку components
- Обновление импортов
- Расширение функционала компонента
ra6/create_rack
Radislav 2026-03-12 15:45:17 +03:00
parent 0295852986
commit b024fac0d8
3 changed files with 165 additions and 94 deletions

View File

@ -0,0 +1,155 @@
"""Модуль компонента группы чек-боксов.
Содержит класс CheckboxGroupComponent для работы с группами чек-боксов,
в том числе в выпадающих списках с множественным выбором.
"""
import re
from playwright.sync_api import Page, Locator, expect
from tools.logger import get_logger
from components.base_component import BaseComponent
logger = get_logger("CHECKBOX_GROUP_COMPONENT")
class CheckboxGroupComponent(BaseComponent):
"""Компонент для работы с группами чек-боксов.
Позволяет выбирать/снимать выбор с чек-боксов в группе,
получать список выбранных элементов и проверять их состояние.
Может использоваться как для выпадающих списков с множественным выбором,
так и для любых других групп чек-боксов на странице.
"""
def __init__(self, page: Page) -> None:
"""Инициализирует компонент группы чек-боксов.
Args:
page: Экземпляр страницы Playwright.
"""
super().__init__(page)
def get_checkbox_locator(self, text: str, container_locator: Locator | None = None) -> Locator:
"""Возвращает локатор чек-бокса с указанным текстом.
Args:
text (str): Текст элемента для выбора.
container_locator (Locator | None): Локатор контейнера с чек-боксами.
Если не указан, поиск по всей странице.
Returns:
Locator: Локатор чек-бокса.
"""
if container_locator:
checkbox_locator = container_locator.get_by_role("listitem").filter(has_text=text).get_by_role("checkbox")
else:
checkbox_locator = self.page.get_by_role("listitem").filter(has_text=text).get_by_role("checkbox")
if checkbox_locator.count() > 1:
rtext = f"^{text}$"
if container_locator:
checkbox_locator = container_locator.get_by_role("listitem").filter(
has_text=re.compile(rtext)
).get_by_role("checkbox")
else:
checkbox_locator = self.page.get_by_role("listitem").filter(
has_text=re.compile(rtext)
).get_by_role("checkbox")
expect(checkbox_locator).to_be_visible(), \
f"Checkbox with text '{text}' is missing or not visible"
return checkbox_locator
def uncheck_by_text(self, text: str, container_locator: Locator | None = None) -> None:
"""Снимает выбор с чек-бокса по указанному тексту.
Args:
text (str): Текст чек-бокса для снятия выбора.
container_locator (Locator | None): Локатор контейнера с чек-боксами.
"""
logger.info(f"Unchecking checkbox with text: {text}")
self.get_checkbox_locator(text, container_locator).uncheck(force=True)
def check_by_text(self, text: str, container_locator: Locator | None = None) -> None:
"""Выбирает чек-бокс по указанному тексту.
Args:
text (str): Текст чек-бокса для выбора.
container_locator (Locator | None): Локатор контейнера с чек-боксами.
"""
logger.info(f"Checking checkbox with text: {text}")
self.get_checkbox_locator(text, container_locator).check(force=True)
def get_checked_items(self, container_locator: str | Locator) -> list[str]:
"""Возвращает список текстов отмеченных чек-боксов.
Args:
container_locator (str | Locator): Локатор контейнера с группой чек-боксов.
Returns:
list[str]: Список текстов выбранных чек-боксов.
"""
checked_items = []
list_container = self.get_locator(container_locator)
items = list_container.get_by_role("listitem").all()
for item in items:
if item.get_by_role("checkbox").is_checked():
item_text = item.text_content().strip()
if item_text:
checked_items.append(item_text)
logger.info(f"Checked items: {checked_items}")
return checked_items
def are_items_checked(self, container_locator: str | Locator, expected_items: list[str]) -> bool:
"""Проверяет, что указанные чек-боксы выбраны.
Args:
container_locator (str | Locator): Локатор контейнера с группой чек-боксов.
expected_items (list[str]): Список ожидаемых выбранных элементов.
Returns:
bool: True если все указанные чек-боксы выбраны.
"""
checked_items = self.get_checked_items(container_locator)
return all(item in checked_items for item in expected_items)
def check_all(self, container_locator: str | Locator) -> None:
"""Выбирает все чек-боксы в группе.
Args:
container_locator (str | Locator): Локатор контейнера с группой чек-боксов.
"""
logger.info("Checking all checkboxes in group")
list_container = self.get_locator(container_locator)
checkboxes = list_container.get_by_role("checkbox").all()
for checkbox in checkboxes:
if not checkbox.is_checked():
checkbox.check(force=True)
def uncheck_all(self, container_locator: str | Locator) -> None:
"""Снимает выбор со всех чек-боксов в группе.
Args:
container_locator (str | Locator): Локатор контейнера с группой чек-боксов.
"""
logger.info("Unchecking all checkboxes in group")
list_container = self.get_locator(container_locator)
checkboxes = list_container.get_by_role("checkbox").all()
for checkbox in checkboxes:
if checkbox.is_checked():
checkbox.uncheck(force=True)
def get_items_count(self, container_locator: str | Locator) -> int:
"""Возвращает количество чек-боксов в группе.
Args:
container_locator (str | Locator): Локатор контейнера с группой чек-боксов.
Returns:
int: Количество чек-боксов.
"""
list_container = self.get_locator(container_locator)
return list_container.get_by_role("checkbox").count()

View File

@ -1,84 +0,0 @@
"""Модуль interactive_dropdown_list_component содержит класс для работы с интерактивными выпадающими списками,
позволяющими сделать выбор нескольких элементов.
Класс InteractiveDropdownList наследует базовый функционал BaseComponent и добавляет
методы для взаимодействия с интерактивными выпадающими списками на странице.
"""
import re
from playwright.sync_api import Page, Locator, expect
from tools.logger import get_logger
from components.base_component import BaseComponent
logger = get_logger("INTERACTIVE_DROPDOWN_LIST")
class InteractiveDropdownList(BaseComponent):
"""Класс для работы с выпадающими списками.
Наследует функциональность BaseElement и добавляет специфичные
методы для выбора и проверки элементов списка.
"""
def __init__(self, page: Page) -> None:
"""Инициализирует компонент интерактивного выпадающего списка.
Args:
page: Экземпляр страницы Playwright.
"""
super().__init__(page)
# Действия:
def get_checkbox_locator(self, text: str) -> Locator:
"""Возвращает локатор чек-бокса для элемента списка с указанным текстом.
Args:
text (str): Текст элемента для выбора.
"""
checkbox_locator = self.page.get_by_role("listitem").filter(has_text=text).get_by_role("checkbox")
if checkbox_locator.count() > 1:
rtext = f"^{text}$"
checkbox_locator = self.page.get_by_role("listitem").filter(
has_text=re.compile(rtext)
).get_by_role("checkbox")
expect(checkbox_locator).to_be_visible(), \
f"Checkbox for dropdown list item with text {text} is missing"
return checkbox_locator
def deselect_item_with_text(self, text: str) -> None:
"""Выбирает элемент списка по указанному тексту.
Args:
text (str): Текст элемента для выбора.
"""
self.get_checkbox_locator(text).uncheck(force=True)
def select_item_with_text(self, text: str) -> None:
"""Выбирает элемент списка по указанному тексту.
Args:
text (str): Текст элемента для выбора.
"""
self.get_checkbox_locator(text).check(force=True)
def get_selected_items(self, locator: str|Locator) -> list[str]:
"""Возвращает список отмеченных элементов."""
selected_items = []
list_locator = self.get_locator(locator)
items = list_locator.get_by_role("listitem").all()
for item in items:
if item.get_by_role("checkbox").is_checked():
item_text = item.text_content().strip()
if item_text:
selected_items.append(item_text)
return selected_items
# Проверки:

View File

@ -9,7 +9,7 @@ from locators.settings_form_locators import SettingsFormLocators
from elements.text_input_element import TextInput from elements.text_input_element import TextInput
from components.alert_component import AlertComponent from components.alert_component import AlertComponent
from components_derived.settings_form_component import SettingsFormComponent from components_derived.settings_form_component import SettingsFormComponent
from components_derived.interactive_dropdown_list import InteractiveDropdownList from components.checkbox_group_component import CheckboxGroupComponent # Изменен импорт
from pages.base_page import BasePage from pages.base_page import BasePage
@ -40,13 +40,13 @@ class PushNotificationsSettingsTab(BasePage):
message_setting_input = TextInput(page, loc_message_input, "message_setting_input") message_setting_input = TextInput(page, loc_message_input, "message_setting_input")
self.settings_form.add_content_item("message_setting_input", message_setting_input) self.settings_form.add_content_item("message_setting_input", message_setting_input)
loc = self.input_fields_locators.get("Пользователи") loc = self.input_fields_locators.get("Пользователи")
users_setting_input = TextInput(page, users_setting_input = TextInput(page,
loc.get_by_role("combobox"), loc.get_by_role("combobox"),
"users_setting_input") "users_setting_input")
self.settings_form.add_content_item("users_setting_input", users_setting_input) self.settings_form.add_content_item("users_setting_input", users_setting_input)
self.settings_form.add_content_item("users_list", InteractiveDropdownList(page)) # Используем новый компонент CheckboxGroupComponent
self.settings_form.add_content_item("users_checkbox_group", CheckboxGroupComponent(page))
self.settings_form.add_tooltip_button(page.locator(SettingsFormLocators.PUSH_NOTIFICATIONS_BUTTON_SUBMIT), self.settings_form.add_tooltip_button(page.locator(SettingsFormLocators.PUSH_NOTIFICATIONS_BUTTON_SUBMIT),
"submit_button") "submit_button")
@ -104,10 +104,10 @@ class PushNotificationsSettingsTab(BasePage):
assert len(users) != 0, "Users list should not be empty" assert len(users) != 0, "Users list should not be empty"
self.settings_form.get_content_item("users_setting_input").click() self.settings_form.get_content_item("users_setting_input").click()
users_list = self.settings_form.get_content_item("users_list") users_checkbox_group = self.settings_form.get_content_item("users_checkbox_group")
for user in users: for user in users:
users_list.deselect_item_with_text(user) users_checkbox_group.uncheck_by_text(user)
# Закрываем выпадающий список (кликаем вне его) # Закрываем выпадающий список (кликаем вне его)
self.page.mouse.click(10, 10) self.page.mouse.click(10, 10)
@ -118,10 +118,10 @@ class PushNotificationsSettingsTab(BasePage):
assert len(users) != 0, "Users list should not be empty" assert len(users) != 0, "Users list should not be empty"
self.settings_form.get_content_item("users_setting_input").click() self.settings_form.get_content_item("users_setting_input").click()
users_list = self.settings_form.get_content_item("users_list") users_checkbox_group = self.settings_form.get_content_item("users_checkbox_group")
for user in users: for user in users:
users_list.select_item_with_text(user) users_checkbox_group.check_by_text(user)
# Закрываем выпадающий список (кликаем вне его) # Закрываем выпадающий список (кликаем вне его)
self.page.mouse.click(10, 10) self.page.mouse.click(10, 10)
@ -142,10 +142,10 @@ class PushNotificationsSettingsTab(BasePage):
f"Misscomparison input field names: Expected {expected_input_field_names}, Actual {actual_input_field_names}" f"Misscomparison input field names: Expected {expected_input_field_names}, Actual {actual_input_field_names}"
for name in self.settings_form.content_items.keys(): for name in self.settings_form.content_items.keys():
if name == "users_list": if name == "users_checkbox_group":
self.settings_form.get_content_item("users_setting_input").click() self.settings_form.get_content_item("users_setting_input").click()
users_list = self.settings_form.get_content_item(name) users_checkbox_group = self.settings_form.get_content_item(name)
selected_users = users_list.get_selected_items(SettingsFormLocators.DROPDOWN_LIST) selected_users = users_checkbox_group.get_checked_items(SettingsFormLocators.DROPDOWN_LIST)
assert len(selected_users) == 0, "There should be no selected users" assert len(selected_users) == 0, "There should be no selected users"
else: else:
item = self.settings_form.get_content_item(name) item = self.settings_form.get_content_item(name)