# UsersTab - Документация тестов eNODE-Мониторинг

Skip to content

# UsersTab

Модуль вкладки 'Пользователи'.

Содержит класс UsersTab для работы с таблицей пользователей. Позволяет управлять пользователями через модальные окна и проверять их состояние.

## `UsersTab`

Bases: `BasePage`

Класс для работы с вкладкой 'Пользователи'.

Предоставляет методы для взаимодействия с таблицей пользователей, модальными окнами и проверки состояния элементов.

Parameters:

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

Source code in `pages\users_tab.py`

     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
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574

    class UsersTab(BasePage):
        """Класс для работы с вкладкой 'Пользователи'.

        Предоставляет методы для взаимодействия с таблицей пользователей,
        модальными окнами и проверки состояния элементов.

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

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

            super().__init__(page)

            locator_button_1 = self.page.get_by_role("navigation").filter(
                has_text=re.compile("Пользователи")
            ).get_by_role("button").nth(0)
            locator_button_2 = self.page.get_by_role("navigation").filter(
                has_text=re.compile("Пользователи")
            ).get_by_role("button").nth(1)

            self.toolbar = ToolbarComponent(page, "Пользователи")
            self.toolbar.add_tooltip_button(locator_button_1, "edit")
            self.toolbar.add_tooltip_button(locator_button_1, "add_user")
            self.toolbar.add_tooltip_button(locator_button_2, "close")

            self.users_table = TableComponent(page)
            self.modal_windows = {}
            self.alert = AlertComponent(page)

        # Действия:
        def add_modal_window(self, window_type: str, title: str) -> None:
            """Добавляет модальное окно в коллекцию.

            Args:
                window_type: Тип окна ('add_user' или 'edit_user').
                title: Заголовок окна.

            Raises:
                AssertionError: Если тип окна не поддерживается.
            """

            if window_type == "add_local_user":
                self.modal_windows["add_local_user"] = AddLocalUserModalWindow(self.page)
            elif window_type == "add_AD_user":
                self.modal_windows["add_AD_user"] = AddADUserModalWindow(self.page)
            elif window_type == "edit_user":
                self.modal_windows[title] = EditUserModalWindow(self.page, title)
            else:
                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:
            """Добавляет нового пользователя или обрабатывает ошибку при дубликате.

            Args:
                user_data: Данные пользователя (name, role, password).

            Returns:
                bool: True если пользователь успешно добавлен, False если пользователь уже существует.

            Raises:
                AssertionError: Если открылось alert окно отличное от success или error,
                            или если текст alert не соответствует ожидаемому.
            """

            add_user_window = self.get_modal_window("add_local_user")

            auth_type = user_data.get("auth_type")
            if auth_type == "active_directory":
                add_user_window.check_active_directory_checkbox()
                self.add_modal_window("add_AD_user", "")
                add_user_window = self.get_modal_window("add_AD_user")

            add_user_window.new_user(user_data)

            is_added = False
            alert_type = self.alert.get_alert_type()
            if alert_type == "success":
                self.alert.check_alert_presence(' Новый пользователь \n успешно добавлен! ')
                self.alert.check_alert_absence(' Новый пользователь \n успешно добавлен! ')
                is_added = True
            elif alert_type == "error":
                print(f' Имя {user_data["name"]} уже используется ')
                self.alert.check_alert_presence(f' Имя {user_data["name"]} уже \n используется ')
                self.alert.check_alert_absence(f' Имя {user_data["name"]} уже \n используется ')
            else:
                assert False, f"Got unexpected alert type {alert_type}"

            return is_added

        def delete_user(self, user_name: str) -> None:
            """Удаляет пользователя.

            Args:
                user_name: Имя пользователя.

            Raises:
                AssertionError: Если нет сообщения об успешном удалении.
            """

            self.get_modal_window(user_name).delete_user()

            alert_type = self.alert.get_alert_type()
            assert alert_type == "success", f"Expected success alert, but got {alert_type} alert"

            self.alert.check_alert_presence('\nПользователь удалён\n')
            self.alert.check_alert_absence('\nПользователь удалён\n')

        def edit_user(self, user_name: str, user_data: dict) -> None:
            """Редактирует данные пользователя.

            Args:
                user_name: Имя пользователя.
                user_data: Новые данные пользователя.

            Raises:
                AssertionError: Если нет сообщения об успешном обновлении.
            """

            self.get_modal_window(user_name).edit_user(user_data)

            alert_type = self.alert.get_alert_type()
            assert alert_type == "success", f"Expected success alert, but got {alert_type} alert"

            self.alert.check_alert_presence('\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:
            """Ищет пользователя в таблице.

            Args:
                name: Имя пользователя.
                role: Роль пользователя.

            Returns:
                int: Индекс строки или -1 если не найден.

            Raises:
                AssertionError: Если таблица пуста.
            """

            self.page.wait_for_timeout(1000)

            table_content = self.users_table.read(TableLocators.TABLE_WORK_AREA)
            if len(table_content) == 0:
                assert False, "The contents of the table are missing"

            del table_content[0]  # Удаляем заголовок

            for row_index, user_info in enumerate(table_content):
                if name in user_info and role in user_info:
                    return row_index
            return -1

        def open_add_user_window(self) -> None:
            """Открывает окно добавления пользователя.

            Raises:
                AssertionError: Если кнопки недоступны или окно не открылось.
            """

            if self.toolbar.is_button_not_present("close"):
                self.toolbar.check_button_visibility("edit")
                self.toolbar.click_button("edit")

            self.toolbar.check_button_visibility("add_user")
            self.toolbar.click_button("add_user")
            self.page.wait_for_timeout(700)

            self.add_modal_window("add_local_user", "")
            self.get_modal_window("add_local_user").check_by_window_title()

        def open_edit_user_page_by_index(self, row_index: int) -> tuple:
            """Открывает окно редактирования по индексу строки.

            Args:
                row_index: Индекс строки в таблице.

            Returns:
                tuple: (имя пользователя, роль).

            Raises:
                AssertionError: Если таблица пуста или индекс вне диапазона.
            """

            self.page.wait_for_timeout(2000)

            tmp_dict = {"admin": "Администратор", "manager": "Контактное лицо",
                       "operator": "Оператор"}
            table_content = self.users_table.read(TableLocators.TABLE_WORK_AREA)

            if len(table_content) == 0:
                assert False, "The contents of the table are missing"

            del table_content[0]  # Удаляем заголовок

            if row_index >= len(table_content):
                assert False, "Row_index is out of range"

            user_name = table_content[row_index][0]
            for key, val in tmp_dict.items():
                if user_name == val:
                    user_name = key

            role = table_content[row_index][2]

            self.page.locator(TableLocators.TABLE_WORK_AREA).locator(
                "//tbody/tr").nth(row_index).click()
            self.add_modal_window("edit_user", user_name)
            self.get_modal_window(user_name).check_by_window_title()

            return user_name, role

        def open_edit_user_page_by_user(self, user_name: str, role: str) -> None:
            """Открывает окно редактирования по имени и роли.

            Args:
                user_name: Имя пользователя.
                role: Роль пользователя.

            Raises:
                AssertionError: Если пользователь не найден.
            """

            row_index = self.find_user_in_table(user_name, role)
            if row_index == -1:
                assert False, f"User with name {user_name} and role {role} has not been found"

            self.page.locator(TableLocators.TABLE_WORK_AREA).locator(
                "//tbody/tr").nth(row_index).click()
            self.add_modal_window("edit_user", user_name)
            self.get_modal_window(user_name).check_by_window_title()

        def transform_to_add_AD_user_window(self):
            """Трансформирует модальное окно добавления локального пользователя
               в окно добавления пользователя Active Directory с помощью нажатия
               чек-бокса Active Directory.
            """

            self.get_modal_window("add_local_user").check_active_directory_checkbox()
            modal_window = self.modal_windows.get("add_AD_user")
            if modal_window is None:
                self.add_modal_window("add_AD_user", "")

        def transform_to_add_user_window(self):
            """Трансформирует модальное окно добавления пользователя Active Directory
               в окно добавления локального пользователя с помощью снятия отметки с
               чек-бокса Active Directory.
            """

            self.get_modal_window("add_AD_user").uncheck_active_directory_checkbox()
            modal_window = self.modal_windows.get("add_local_user")
            if modal_window is None:
                self.add_modal_window("add_local_user", "")

        # Проверки:
        def check_users_table_content(self, verify: bool = False) -> None:
            """Проверяет содержимое таблицы пользователей.

            Args:
                verify: Проверять соответствие данных из БД. По умолчанию False.

            Raises:
                AssertionError: Если таблица пуста или заголовки неверны.
            """
            self.page.wait_for_timeout(2000)

            expected_headers = ['Имя пользователя', 'Тип авторизации', 'Роль',
                               'E-mail', 'Номер для СМС']
            table_content = self.users_table.read(TableLocators.TABLE_WORK_AREA)

            if len(table_content) == 0:
                assert False, "The contents of the table are missing"

            actual_headers = table_content[0]
            self.check_equals(
                actual_headers,
                expected_headers,
                f"Expected table headers {expected_headers} are not equal {actual_headers}"
            )

            if len(table_content) == 1:
                assert False, "Table body is missing"

            if verify:
                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:
            """Проверяет наличие тулбара.

            Raises:
                AssertionError: Если тулбар или кнопка редактирования отсутствуют.
            """

            self.toolbar.check_toolbar_presence("Toolbar is missing")
            self.toolbar.check_button_visibility("edit")

        def should_be_toolbar_buttons(self) -> None:
            """Проверяет наличие и функциональность кнопок тулбара.

            Raises:
                AssertionError: Если кнопки недоступны или подсказки неверны.
            """

            self.toolbar.check_button_visibility("edit")
            self.toolbar.check_button_tooltip("edit", "Редактировать")

            self.toolbar.get_button_by_name("edit").click()
            self.toolbar.check_button_visibility("add_user")
            self.toolbar.check_button_visibility("close")
            self.toolbar.check_button_tooltip("add_user", "Добавить")
            self.toolbar.check_button_tooltip("close", "Закрыть")

            self.toolbar.get_button_by_name("close").click()
            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:
            """Проверяет наличие пользователя в таблице.

            Args:
                name: Имя пользователя.
                role: Роль пользователя.

            Raises:
                AssertionError: Если пользователь не найден.
            """

            found = self.find_user_in_table(name, role)
            if found == -1:
                assert False, f"User with name {name} and role {role} has not been found"

        def should_not_be_user_in_table(self, name: str, role: str) -> None:
            """Проверяет отсутствие пользователя в таблице.

            Args:
                name: Имя пользователя.
                role: Роль пользователя.

            Raises:
                AssertionError: Если пользователь найден.
            """

            found = self.find_user_in_table(name, role)
            if found != -1:
                assert False, f"User with name {name} and role {role} has been found"

        def verify_users_table_content(self, users_table: list) -> None:
            """Сверяет данные таблицы с данными из БД.

            Args:
                users_table: Данные из таблицы на странице.

            Raises:
                AssertionError: Если данные не соответствуют.
            """

            expected_users_list = []

            query = {
                "id": ["/catalogs/user"],
                "data": {
                    "namePath": True,
                    "children": {"flatten": True}
                }
            }

            response = self.send_post_api_request("e-cmdb/api/query", query)
            response_body = self.get_response_body(response)

            for item in response_body[0]["children"]:
                user_info = []
                user_name = item["name"]

                # НЕ преобразуем имя пользователя - оставляем как есть из БД
                user_info.append(user_name)

                if item["type_auth"] is not None:
                    user_info.append(item["type_auth"])
                else:
                    user_info.append("")

                if item["role"] is not None:
                    role = item["role"]
                    if role in roles_dict:  # Убрали вызов .keys()
                        item["role"] = roles_dict[role]
                    user_info.append(item["role"])
                else:
                    user_info.append("")

                if item["email"] is not None:
                    user_info.append(item["email"])
                else:
                    user_info.append("")

                if item["sms_phone"] is not None:
                    user_info.append(item["sms_phone"])
                else:
                    user_info.append("")

                expected_users_list.append(user_info)

            del users_table[0]  # Удаляем заголовок

            self.check_lists_equals(
                users_table,
                expected_users_list,
                "Actual users list is not equal expected users list on base db"
            )

### `__init__(page)`

Инициализирует компоненты вкладки 'Пользователи'.

Source code in `pages\users_tab.py`

    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50

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

        super().__init__(page)

        locator_button_1 = self.page.get_by_role("navigation").filter(
            has_text=re.compile("Пользователи")
        ).get_by_role("button").nth(0)
        locator_button_2 = self.page.get_by_role("navigation").filter(
            has_text=re.compile("Пользователи")
        ).get_by_role("button").nth(1)

        self.toolbar = ToolbarComponent(page, "Пользователи")
        self.toolbar.add_tooltip_button(locator_button_1, "edit")
        self.toolbar.add_tooltip_button(locator_button_1, "add_user")
        self.toolbar.add_tooltip_button(locator_button_2, "close")

        self.users_table = TableComponent(page)
        self.modal_windows = {}
        self.alert = AlertComponent(page)

### `add_modal_window(window_type, title)`

Добавляет модальное окно в коллекцию.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`window_type` | `str` | Тип окна ('add_user' или 'edit_user'). | required
`title` | `str` | Заголовок окна. | required

Raises:

Type | Description
--- | ---
`AssertionError` | Если тип окна не поддерживается.

Source code in `pages\users_tab.py`

    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71

    def add_modal_window(self, window_type: str, title: str) -> None:
        """Добавляет модальное окно в коллекцию.

        Args:
            window_type: Тип окна ('add_user' или 'edit_user').
            title: Заголовок окна.

        Raises:
            AssertionError: Если тип окна не поддерживается.
        """

        if window_type == "add_local_user":
            self.modal_windows["add_local_user"] = AddLocalUserModalWindow(self.page)
        elif window_type == "add_AD_user":
            self.modal_windows["add_AD_user"] = AddADUserModalWindow(self.page)
        elif window_type == "edit_user":
            self.modal_windows[title] = EditUserModalWindow(self.page, title)
        else:
            assert False, "Unsupported modal window type"

### `add_new_user(user_data)`

Добавляет нового пользователя или обрабатывает ошибку при дубликате.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`user_data` | `dict` | Данные пользователя (name, role, password). | required

Returns:

Name | Type | Description
--- | --- | ---
`bool` | `bool` | True если пользователь успешно добавлен, False если пользователь уже существует.

Raises:

Type | Description
--- | ---
`AssertionError` | Если открылось alert окно отличное от success или error, или если текст alert не соответствует ожидаемому.

Source code in `pages\users_tab.py`

    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202

    def add_new_user(self, user_data: dict) -> bool:
        """Добавляет нового пользователя или обрабатывает ошибку при дубликате.

        Args:
            user_data: Данные пользователя (name, role, password).

        Returns:
            bool: True если пользователь успешно добавлен, False если пользователь уже существует.

        Raises:
            AssertionError: Если открылось alert окно отличное от success или error,
                        или если текст alert не соответствует ожидаемому.
        """

        add_user_window = self.get_modal_window("add_local_user")

        auth_type = user_data.get("auth_type")
        if auth_type == "active_directory":
            add_user_window.check_active_directory_checkbox()
            self.add_modal_window("add_AD_user", "")
            add_user_window = self.get_modal_window("add_AD_user")

        add_user_window.new_user(user_data)

        is_added = False
        alert_type = self.alert.get_alert_type()
        if alert_type == "success":
            self.alert.check_alert_presence(' Новый пользователь \n успешно добавлен! ')
            self.alert.check_alert_absence(' Новый пользователь \n успешно добавлен! ')
            is_added = True
        elif alert_type == "error":
            print(f' Имя {user_data["name"]} уже используется ')
            self.alert.check_alert_presence(f' Имя {user_data["name"]} уже \n используется ')
            self.alert.check_alert_absence(f' Имя {user_data["name"]} уже \n используется ')
        else:
            assert False, f"Got unexpected alert type {alert_type}"

        return is_added

### `check_add_AD_user_window_content()`

Проверяет содержимое окна добавления пользователя через Active Directory.

Source code in `pages\users_tab.py`

    426
    427
    428
    429

    def check_add_AD_user_window_content(self) -> None:
        """Проверяет содержимое окна добавления пользователя через Active Directory."""

        self.get_modal_window("add_AD_user").check_content()

### `check_add_user_window_content()`

Проверяет содержимое окна добавления локального пользователя.

Source code in `pages\users_tab.py`

    421
    422
    423
    424

    def check_add_user_window_content(self) -> None:
        """Проверяет содержимое окна добавления локального пользователя."""

        self.get_modal_window("add_local_user").check_content()

### `check_edit_user_window_content(user_name, role)`

Проверяет содержимое окна редактирования.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`user_name` | `str` | Имя пользователя. | required
`role` | `str` | Роль пользователя. | required

Source code in `pages\users_tab.py`

    431
    432
    433
    434
    435
    436
    437
    438
    439
    440

    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)

### `check_users_table_content(verify=False)`

Проверяет содержимое таблицы пользователей.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`verify` | `bool` | Проверять соответствие данных из БД. По умолчанию False. | `False`

Raises:

Type | Description
--- | ---
`AssertionError` | Если таблица пуста или заголовки неверны.

Source code in `pages\users_tab.py`

    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419

    def check_users_table_content(self, verify: bool = False) -> None:
        """Проверяет содержимое таблицы пользователей.

        Args:
            verify: Проверять соответствие данных из БД. По умолчанию False.

        Raises:
            AssertionError: Если таблица пуста или заголовки неверны.
        """
        self.page.wait_for_timeout(2000)

        expected_headers = ['Имя пользователя', 'Тип авторизации', 'Роль',
                           'E-mail', 'Номер для СМС']
        table_content = self.users_table.read(TableLocators.TABLE_WORK_AREA)

        if len(table_content) == 0:
            assert False, "The contents of the table are missing"

        actual_headers = table_content[0]
        self.check_equals(
            actual_headers,
            expected_headers,
            f"Expected table headers {expected_headers} are not equal {actual_headers}"
        )

        if len(table_content) == 1:
            assert False, "Table body is missing"

        if verify:
            self.verify_users_table_content(table_content)

### `close_add_AD_user_window()`

Закрывает окно добавления пользователя.

Source code in `pages\users_tab.py`

    132
    133
    134
    135

    def close_add_AD_user_window(self) -> None:
        """Закрывает окно добавления пользователя."""

        self.close_modal_window("add_AD_user")

### `close_add_AD_user_window_by_toolbar_button()`

Закрывает окно добавления пользователя через тулбар.

Source code in `pages\users_tab.py`

    127
    128
    129
    130

    def close_add_AD_user_window_by_toolbar_button(self) -> None:
        """Закрывает окно добавления пользователя через тулбар."""

        self.close_modal_window_by_toolbar_button("add_AD_user")

### `close_add_user_window()`

Закрывает окно добавления пользователя.

Source code in `pages\users_tab.py`

    142
    143
    144
    145

    def close_add_user_window(self) -> None:
        """Закрывает окно добавления пользователя."""

        self.close_modal_window("add_local_user")

### `close_add_user_window_by_toolbar_button()`

Закрывает окно добавления пользователя через тулбар.

Source code in `pages\users_tab.py`

    137
    138
    139
    140

    def close_add_user_window_by_toolbar_button(self) -> None:
        """Закрывает окно добавления пользователя через тулбар."""

        self.close_modal_window_by_toolbar_button("add_local_user")

### `close_edit_user_window(title)`

Закрывает окно редактирования пользователя.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`title` | `str` | Имя пользователя (заголовок окна). | required

Source code in `pages\users_tab.py`

    156
    157
    158
    159
    160
    161
    162
    163

    def close_edit_user_window(self, title: str) -> None:
        """Закрывает окно редактирования пользователя.

        Args:
            title: Имя пользователя (заголовок окна).
        """

        self.close_modal_window(title)

### `close_edit_user_window_by_toolbar_button(title)`

Закрывает окно редактирования через кнопку в тулбаре.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`title` | `str` | Имя пользователя (заголовок окна). | required

Source code in `pages\users_tab.py`

    147
    148
    149
    150
    151
    152
    153
    154

    def close_edit_user_window_by_toolbar_button(self, title: str) -> None:
        """Закрывает окно редактирования через кнопку в тулбаре.

        Args:
            title: Имя пользователя (заголовок окна).
        """

        self.close_modal_window_by_toolbar_button(title)

### `close_modal_window(title)`

Закрывает модальное окно через кнопку закрытия.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`title` | `str` | Заголовок окна. | required

Source code in `pages\users_tab.py`

    116
    117
    118
    119
    120
    121
    122
    123
    124
    125

    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)

### `close_modal_window_by_toolbar_button(title)`

Закрывает модальное окно через кнопку в тулбаре.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`title` | `str` | Заголовок окна. | required

Source code in `pages\users_tab.py`

    105
    106
    107
    108
    109
    110
    111
    112
    113
    114

    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)

### `delete_modal_window(title)`

Удаляет модальное окно из коллекции.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`title` | `str` | Заголовок окна. | required

Raises:

Type | Description
--- | ---
`AssertionError` | Если окно не найдено.

Source code in `pages\users_tab.py`

     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103

    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

### `delete_user(user_name)`

Удаляет пользователя.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`user_name` | `str` | Имя пользователя. | required

Raises:

Type | Description
--- | ---
`AssertionError` | Если нет сообщения об успешном удалении.

Source code in `pages\users_tab.py`

    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220

    def delete_user(self, user_name: str) -> None:
        """Удаляет пользователя.

        Args:
            user_name: Имя пользователя.

        Raises:
            AssertionError: Если нет сообщения об успешном удалении.
        """

        self.get_modal_window(user_name).delete_user()

        alert_type = self.alert.get_alert_type()
        assert alert_type == "success", f"Expected success alert, but got {alert_type} alert"

        self.alert.check_alert_presence('\nПользователь удалён\n')
        self.alert.check_alert_absence('\nПользователь удалён\n')

### `edit_user(user_name, user_data)`

Редактирует данные пользователя.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`user_name` | `str` | Имя пользователя. | required
`user_data` | `dict` | Новые данные пользователя. | required

Raises:

Type | Description
--- | ---
`AssertionError` | Если нет сообщения об успешном обновлении.

Source code in `pages\users_tab.py`

    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239

    def edit_user(self, user_name: str, user_data: dict) -> None:
        """Редактирует данные пользователя.

        Args:
            user_name: Имя пользователя.
            user_data: Новые данные пользователя.

        Raises:
            AssertionError: Если нет сообщения об успешном обновлении.
        """

        self.get_modal_window(user_name).edit_user(user_data)

        alert_type = self.alert.get_alert_type()
        assert alert_type == "success", f"Expected success alert, but got {alert_type} alert"

        self.alert.check_alert_presence('\nОбновление успешно\n')
        self.alert.check_alert_absence('\nОбновление успешно\n')

### `find_user_in_table(name, role)`

Ищет пользователя в таблице.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`name` | `str` | Имя пользователя. | required
`role` | `str` | Роль пользователя. | required

Returns:

Name | Type | Description
--- | --- | ---
`int` | `int` | Индекс строки или -1 если не найден.

Raises:

Type | Description
--- | ---
`AssertionError` | Если таблица пуста.

Source code in `pages\users_tab.py`

    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286

    def find_user_in_table(self, name: str, role: str) -> int:
        """Ищет пользователя в таблице.

        Args:
            name: Имя пользователя.
            role: Роль пользователя.

        Returns:
            int: Индекс строки или -1 если не найден.

        Raises:
            AssertionError: Если таблица пуста.
        """

        self.page.wait_for_timeout(1000)

        table_content = self.users_table.read(TableLocators.TABLE_WORK_AREA)
        if len(table_content) == 0:
            assert False, "The contents of the table are missing"

        del table_content[0]  # Удаляем заголовок

        for row_index, user_info in enumerate(table_content):
            if name in user_info and role in user_info:
                return row_index
        return -1

### `get_modal_window(title)`

Возвращает модальное окно по заголовку.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`title` | `str` | Заголовок окна. | required

Returns:

Name | Type | Description
--- | --- | ---
`ModalWindowComponent` | `ModalWindowComponent` | Экземпляр модального окна.

Raises:

Type | Description
--- | ---
`AssertionError` | Если окно не найдено.

Source code in `pages\users_tab.py`

    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89

    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

### `open_add_user_window()`

Открывает окно добавления пользователя.

Raises:

Type | Description
--- | ---
`AssertionError` | Если кнопки недоступны или окно не открылось.

Source code in `pages\users_tab.py`

    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304

    def open_add_user_window(self) -> None:
        """Открывает окно добавления пользователя.

        Raises:
            AssertionError: Если кнопки недоступны или окно не открылось.
        """

        if self.toolbar.is_button_not_present("close"):
            self.toolbar.check_button_visibility("edit")
            self.toolbar.click_button("edit")

        self.toolbar.check_button_visibility("add_user")
        self.toolbar.click_button("add_user")
        self.page.wait_for_timeout(700)

        self.add_modal_window("add_local_user", "")
        self.get_modal_window("add_local_user").check_by_window_title()

### `open_edit_user_page_by_index(row_index)`

Открывает окно редактирования по индексу строки.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`row_index` | `int` | Индекс строки в таблице. | required

Returns:

Name | Type | Description
--- | --- | ---
`tuple` | `tuple` | (имя пользователя, роль).

Raises:

Type | Description
--- | ---
`AssertionError` | Если таблица пуста или индекс вне диапазона.

Source code in `pages\users_tab.py`

    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345

    def open_edit_user_page_by_index(self, row_index: int) -> tuple:
        """Открывает окно редактирования по индексу строки.

        Args:
            row_index: Индекс строки в таблице.

        Returns:
            tuple: (имя пользователя, роль).

        Raises:
            AssertionError: Если таблица пуста или индекс вне диапазона.
        """

        self.page.wait_for_timeout(2000)

        tmp_dict = {"admin": "Администратор", "manager": "Контактное лицо",
                   "operator": "Оператор"}
        table_content = self.users_table.read(TableLocators.TABLE_WORK_AREA)

        if len(table_content) == 0:
            assert False, "The contents of the table are missing"

        del table_content[0]  # Удаляем заголовок

        if row_index >= len(table_content):
            assert False, "Row_index is out of range"

        user_name = table_content[row_index][0]
        for key, val in tmp_dict.items():
            if user_name == val:
                user_name = key

        role = table_content[row_index][2]

        self.page.locator(TableLocators.TABLE_WORK_AREA).locator(
            "//tbody/tr").nth(row_index).click()
        self.add_modal_window("edit_user", user_name)
        self.get_modal_window(user_name).check_by_window_title()

        return user_name, role

### `open_edit_user_page_by_user(user_name, role)`

Открывает окно редактирования по имени и роли.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`user_name` | `str` | Имя пользователя. | required
`role` | `str` | Роль пользователя. | required

Raises:

Type | Description
--- | ---
`AssertionError` | Если пользователь не найден.

Source code in `pages\users_tab.py`

    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365

    def open_edit_user_page_by_user(self, user_name: str, role: str) -> None:
        """Открывает окно редактирования по имени и роли.

        Args:
            user_name: Имя пользователя.
            role: Роль пользователя.

        Raises:
            AssertionError: Если пользователь не найден.
        """

        row_index = self.find_user_in_table(user_name, role)
        if row_index == -1:
            assert False, f"User with name {user_name} and role {role} has not been found"

        self.page.locator(TableLocators.TABLE_WORK_AREA).locator(
            "//tbody/tr").nth(row_index).click()
        self.add_modal_window("edit_user", user_name)
        self.get_modal_window(user_name).check_by_window_title()

### `reset_password(user_name)`

Сбрасывает пароль пользователя.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`user_name` | `str` | Имя пользователя. | required

Returns:

Name | Type | Description
--- | --- | ---
`str` | `str` | Новый пароль (если получен).

Source code in `pages\users_tab.py`

    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259

    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

### `should_be_toolbar()`

Проверяет наличие тулбара.

Raises:

Type | Description
--- | ---
`AssertionError` | Если тулбар или кнопка редактирования отсутствуют.

Source code in `pages\users_tab.py`

    442
    443
    444
    445
    446
    447
    448
    449
    450

    def should_be_toolbar(self) -> None:
        """Проверяет наличие тулбара.

        Raises:
            AssertionError: Если тулбар или кнопка редактирования отсутствуют.
        """

        self.toolbar.check_toolbar_presence("Toolbar is missing")
        self.toolbar.check_button_visibility("edit")

### `should_be_toolbar_buttons()`

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

Raises:

Type | Description
--- | ---
`AssertionError` | Если кнопки недоступны или подсказки неверны.

Source code in `pages\users_tab.py`

    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469

    def should_be_toolbar_buttons(self) -> None:
        """Проверяет наличие и функциональность кнопок тулбара.

        Raises:
            AssertionError: Если кнопки недоступны или подсказки неверны.
        """

        self.toolbar.check_button_visibility("edit")
        self.toolbar.check_button_tooltip("edit", "Редактировать")

        self.toolbar.get_button_by_name("edit").click()
        self.toolbar.check_button_visibility("add_user")
        self.toolbar.check_button_visibility("close")
        self.toolbar.check_button_tooltip("add_user", "Добавить")
        self.toolbar.check_button_tooltip("close", "Закрыть")

        self.toolbar.get_button_by_name("close").click()
        self.toolbar.check_button_visibility("edit")

### `should_be_user_in_table(name, role)`

Проверяет наличие пользователя в таблице.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`name` | `str` | Имя пользователя. | required
`role` | `str` | Роль пользователя. | required

Raises:

Type | Description
--- | ---
`AssertionError` | Если пользователь не найден.

Source code in `pages\users_tab.py`

    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496

    def should_be_user_in_table(self, name: str, role: str) -> None:
        """Проверяет наличие пользователя в таблице.

        Args:
            name: Имя пользователя.
            role: Роль пользователя.

        Raises:
            AssertionError: Если пользователь не найден.
        """

        found = self.find_user_in_table(name, role)
        if found == -1:
            assert False, f"User with name {name} and role {role} has not been found"

### `should_be_users_table()`

Проверяет наличие таблицы пользователей.

Raises:

Type | Description
--- | ---
`AssertionError` | Если таблица отсутствует.

Source code in `pages\users_tab.py`

    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481

    def should_be_users_table(self) -> None:
        """Проверяет наличие таблицы пользователей.

        Raises:
            AssertionError: Если таблица отсутствует.
        """

        self.users_table.check_visibility(
            TableLocators.TABLE_WORK_AREA,
            "Users table is missing"
        )

### `should_not_be_user_in_table(name, role)`

Проверяет отсутствие пользователя в таблице.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`name` | `str` | Имя пользователя. | required
`role` | `str` | Роль пользователя. | required

Raises:

Type | Description
--- | ---
`AssertionError` | Если пользователь найден.

Source code in `pages\users_tab.py`

    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511

    def should_not_be_user_in_table(self, name: str, role: str) -> None:
        """Проверяет отсутствие пользователя в таблице.

        Args:
            name: Имя пользователя.
            role: Роль пользователя.

        Raises:
            AssertionError: Если пользователь найден.
        """

        found = self.find_user_in_table(name, role)
        if found != -1:
            assert False, f"User with name {name} and role {role} has been found"

### `transform_to_add_AD_user_window()`

Трансформирует модальное окно добавления локального пользователя в окно добавления пользователя Active Directory с помощью нажатия чек-бокса Active Directory.

Source code in `pages\users_tab.py`

    367
    368
    369
    370
    371
    372
    373
    374
    375
    376

    def transform_to_add_AD_user_window(self):
        """Трансформирует модальное окно добавления локального пользователя
           в окно добавления пользователя Active Directory с помощью нажатия
           чек-бокса Active Directory.
        """

        self.get_modal_window("add_local_user").check_active_directory_checkbox()
        modal_window = self.modal_windows.get("add_AD_user")
        if modal_window is None:
            self.add_modal_window("add_AD_user", "")

### `transform_to_add_user_window()`

Трансформирует модальное окно добавления пользователя Active Directory в окно добавления локального пользователя с помощью снятия отметки с чек-бокса Active Directory.

Source code in `pages\users_tab.py`

    378
    379
    380
    381
    382
    383
    384
    385
    386
    387

    def transform_to_add_user_window(self):
        """Трансформирует модальное окно добавления пользователя Active Directory
           в окно добавления локального пользователя с помощью снятия отметки с
           чек-бокса Active Directory.
        """

        self.get_modal_window("add_AD_user").uncheck_active_directory_checkbox()
        modal_window = self.modal_windows.get("add_local_user")
        if modal_window is None:
            self.add_modal_window("add_local_user", "")

### `verify_users_table_content(users_table)`

Сверяет данные таблицы с данными из БД.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`users_table` | `list` | Данные из таблицы на странице. | required

Raises:

Type | Description
--- | ---
`AssertionError` | Если данные не соответствуют.

Source code in `pages\users_tab.py`

    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574

    def verify_users_table_content(self, users_table: list) -> None:
        """Сверяет данные таблицы с данными из БД.

        Args:
            users_table: Данные из таблицы на странице.

        Raises:
            AssertionError: Если данные не соответствуют.
        """

        expected_users_list = []

        query = {
            "id": ["/catalogs/user"],
            "data": {
                "namePath": True,
                "children": {"flatten": True}
            }
        }

        response = self.send_post_api_request("e-cmdb/api/query", query)
        response_body = self.get_response_body(response)

        for item in response_body[0]["children"]:
            user_info = []
            user_name = item["name"]

            # НЕ преобразуем имя пользователя - оставляем как есть из БД
            user_info.append(user_name)

            if item["type_auth"] is not None:
                user_info.append(item["type_auth"])
            else:
                user_info.append("")

            if item["role"] is not None:
                role = item["role"]
                if role in roles_dict:  # Убрали вызов .keys()
                    item["role"] = roles_dict[role]
                user_info.append(item["role"])
            else:
                user_info.append("")

            if item["email"] is not None:
                user_info.append(item["email"])
            else:
                user_info.append("")

            if item["sms_phone"] is not None:
                user_info.append(item["sms_phone"])
            else:
                user_info.append("")

            expected_users_list.append(user_info)

        del users_table[0]  # Удаляем заголовок

        self.check_lists_equals(
            users_table,
            expected_users_list,
            "Actual users list is not equal expected users list on base db"
        )