Skip to content

# DropdownList

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

Класс DropdownList наследует базовый функционал BaseComponent и добавляет методы для взаимодействия с выпадающими списками на странице.

## `DropdownList`

Bases: `BaseComponent`

Класс для работы с выпадающими списками.

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

Source code in `components\dropdown_list_component.py`

     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    class DropdownList(BaseComponent):
        """Класс для работы с выпадающими списками.

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

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

            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_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 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

### `__init__(page)`

Инициализирует компонент выпадающего списка.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`page` | `Page` | Экземпляр страницы Playwright. | required

Source code in `components\dropdown_list_component.py`

    20
    21
    22
    23
    24
    25
    26
    27
    def __init__(self, page: Page):
        """Инициализирует компонент выпадающего списка.

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

        super().__init__(page)

### `check_item_with_text(text)`

Проверяет наличие и доступность элемента списка.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`text` | `str` | Текст элемента для проверки. | required

Raises:

Type | Description
--- | ---
`AssertionError` | Если элемент отсутствует или недоступен.

Source code in `components\dropdown_list_component.py`

     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    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"

### `check_vertical_scrolling(locator)`

Проверяет функцию вертикального скроллинга списка.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`locator` | `str | Locator` | Локатор элементов или строка с CSS/XPath. | required

Returns:

Type | Description
--- | ---
`bool` | True или False значение в зависимости от скроллируемый список или нет.

Source code in `components\dropdown_list_component.py`

    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    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

### `click_item_with_text(text)`

Выбирает элемент списка по указанному тексту.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`text` | `str` | Текст элемента для выбора. | required

Source code in `components\dropdown_list_component.py`

    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    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()

### `get_item_names(locator)`

Возвращает тексты всех элементов по указанному локатору.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`locator` | `str | Locator` | Локатор элементов или строка с CSS/XPath. | required

Returns:

Type | Description
--- | ---
`list[str]` | Список текстов элементов.

Source code in `components\dropdown_list_component.py`

    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    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()

### `scroll_until_end(locator)`

Скроллит список до тех пор, пока не перестанут подгружаться новые элементы.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`locator` | `str | Locator` | Локатор элементов или строка с CSS/XPath. | required

Source code in `components\dropdown_list_component.py`

    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    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)