# Исходный код components.dropdown_list_component

    """Модуль dropdown_list_component содержит класс для работы с выпадающими списками.

    Класс DropdownList наследует базовый функционал BaseComponent и добавляет
    методы для взаимодействия с выпадающими списками на странице.
    """
    import re
    from playwright.sync_api import Page, Locator
    from tools.logger import get_logger
    from components.base_component import BaseComponent

    logger = get_logger("DROPDOWN_LIST")

    class DropdownList(BaseComponent):
        """Класс для работы с выпадающими списками.

        Наследует функциональность BaseElement и добавляет специфичные
        методы для выбора и проверки элементов списка.
        """

        def __init__(self, page: Page) -> None:
            """Инициализирует компонент выпадающего списка.

            Args:
               page: Экземпляр страницы Playwright.
            """

            super().__init__(page)

        # Действия:

        def click_item_with_text(self, text: str) -> None:
            """Выбирает элемент списка по указанному тексту.

            Args:
                text (str): Текст элемента для выбора.
            """

            element = self.page.get_by_role("listitem").filter(has_text=text)
            if element.count() > 1:
                rtext = f"^{text}$"
                element = self.page.get_by_role("listitem").filter(
                    has_text=re.compile(rtext)
                )
            element.click()

        def get_combobox_options(self, combobox_locator: str | Locator,
                                listbox_locator: str | Locator,
                                icon_locator: str | Locator = None) -> list[str]:
            """
            Получает список доступных опций из combobox.

            Args:
                combobox_locator: Локатор combobox
                listbox_locator: Локатор выпадающего списка
                icon_locator: Локатор иконки для клика (опционально)

            Returns:
                list[str]: Список доступных опций
            """
            logger.info("Getting combobox options list...")

            # Открываем combobox (если еще не открыт)
            self.open_combobox(combobox_locator, listbox_locator, icon_locator)

            options_list = self.get_item_names(listbox_locator)

            # Закрываем combobox (кликаем вне его)
            self.page.mouse.click(10, 10)
            self.page.wait_for_timeout(500)

            logger.info(f"Found options: {len(options_list)} - {options_list}")
            return options_list

        def get_item_names(self, locator: str | Locator) -> list[str]:
            """Возвращает тексты всех элементов по указанному локатору.

            Args:
                locator: Локатор элементов или строка с CSS/XPath.

            Returns:
                Список текстов элементов.
            """

            loc = self.get_locator(locator)
            texts = loc.all_inner_texts()
            return texts[0].splitlines()

        def get_selected_combobox_value(self, combobox_locator: str | Locator,
                                       value_locator: str | Locator = None) -> str:
            """
            Получает выбранное значение из combobox.

            Args:
                combobox_locator: Локатор combobox
                value_locator: Локатор элемента с выбранным значением (опционально)

            Returns:
                str: Выбранное значение или пустая строка если ничего не выбрано
            """
            combobox = self.get_locator(combobox_locator)

            selected_value = ""

            if value_locator:
                # Используем переданный локатор для значения
                value_element = combobox.locator(value_locator)
                if value_element.count() > 0:
                    selected_value = value_element.first.text_content().strip()
            else:
                # Ищем в span элементах по умолчанию
                span_locator = combobox.locator("span")
                if span_locator.count() > 0:
                    for i in range(span_locator.count()):
                        span_text = span_locator.nth(i).text_content().strip()
                        if span_text and span_text not in ["Класс объекта учета"]:
                            selected_value = span_text
                            break

            logger.info(f"Selected combobox value: '{selected_value}'")
            return selected_value

        def open_combobox(self, combobox_locator: str | Locator,
                         listbox_locator: str | Locator,
                         icon_locator: str | Locator = None) -> None:
            """
            Открывает выпадающий список combobox.

            Args:
                combobox_locator: Локатор combobox
                listbox_locator: Локатор выпадающего списка
                icon_locator: Локатор иконки для клика (опционально)
            """
            logger.info("Opening combobox...")

            combobox = self.get_locator(combobox_locator)
            listbox = self.get_locator(listbox_locator)

            # Прокручиваем до combobox
            combobox.scroll_into_view_if_needed()
            self.page.wait_for_timeout(1000)

            # Проверяем, не открыт ли уже список
            listbox_already_open = False
            listbox_count = listbox.count()

            if listbox_count > 0:
                listbox_already_open = listbox.first.is_visible()

            if not listbox_already_open:
                # Если указан локатор иконки, кликаем на него, иначе на сам combobox
                if icon_locator:
                    icon = combobox.locator(icon_locator)
                    icon.scroll_into_view_if_needed()
                    icon.click(timeout=10000)
                else:
                    combobox.click(timeout=10000)
                logger.info("Combobox click completed")
                self.page.wait_for_timeout(1000)

            # Проверяем что список открылся
            listbox_count_after = listbox.count()
            listbox_visible = False

            if listbox_count_after > 0:
                listbox_visible = listbox.first.is_visible()

            if listbox_visible:
                logger.info("Dropdown list found and opened")
            else:
                logger.warning("Failed to open dropdown list")

        def scroll_until_end(self, locator: str | Locator) -> None:
            """
            Скроллит список до тех пор, пока не перестанут подгружаться новые элементы.

            Args:
                locator: Локатор элементов или строка с CSS/XPath.
            """

            loc = self.get_locator(locator)

            items_count = 0
            attempts = 0
            max_attempts = 3
            last_item_name = ""

            while attempts < max_attempts:
                self.page.wait_for_timeout(300)

                item_names = self.get_item_names(loc)
                current_count = len(item_names)

                if current_count == items_count:
                    attempts += 1
                else:
                    items_count = current_count
                    attempts = 0

                last_item_name = item_names[current_count-1]
                element = self.page.get_by_role("listitem").filter(
                    has_text=last_item_name
                )
                element.scroll_into_view_if_needed()

            self.page.wait_for_timeout(300)
            self.check_item_with_text(last_item_name)

        # Проверки:

        def check_item_with_text(self, text: str) -> None:
            """Проверяет наличие и доступность элемента списка.

            Args:
                text (str): Текст элемента для проверки.

            Raises:
                AssertionError: Если элемент отсутствует или недоступен.
            """

            element = self.page.get_by_role("listitem").filter(has_text=text)
            if element.count() > 1:
                rtext = f"^{text}$"
                element = self.page.get_by_role("listitem").filter(
                    has_text=re.compile(rtext)
                )
            enabled = element.is_enabled()
            if not enabled:
                assert False, f"Dropdown list item '{text}' is missing or disabled"

        def check_vertical_scrolling(self, locator: str | Locator) -> bool:
            """
            Проверяет функцию вертикального скроллинга списка.

            Args:
                locator: Локатор элементов или строка с CSS/XPath.

            Returns:
                True или False значение в зависимости от скроллируемый список или нет.
            """

            loc = self.get_locator(locator)

            is_scrollable_vertically = self.is_scrollable_vertically(loc)
            if  is_scrollable_vertically:
                self.scroll_until_end(loc)

                item_names = self.get_item_names(loc)
                first_item_name = item_names[0]

                self.scroll_up(loc)
                self.page.wait_for_timeout(300)
                self.check_item_with_text(first_item_name)

            return is_scrollable_vertically