From 0509d5bee3ac088ec620f0988c48ca7474b972c6 Mon Sep 17 00:00:00 2001 From: nsubbot Date: Fri, 6 Mar 2026 09:08:55 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B2=D0=BA?= =?UTF-8?q?=D0=BB=D0=B0=D0=B4=D0=BA=D0=B8=20'=D0=A0=D0=B5=D0=B7=D0=B5?= =?UTF-8?q?=D1=80=D0=B2=D0=BD=D0=BE=D0=B5=20=D0=BA=D0=BE=D0=BF=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locators/backup_tab_locators.py | 48 ++ pages/backup_settings_tab.py | 1017 +++++++++++++++++++++++++ tests/e2e/test_backup_settings_tab.py | 372 +++++++++ 3 files changed, 1437 insertions(+) create mode 100644 locators/backup_tab_locators.py create mode 100644 pages/backup_settings_tab.py create mode 100644 tests/e2e/test_backup_settings_tab.py diff --git a/locators/backup_tab_locators.py b/locators/backup_tab_locators.py new file mode 100644 index 0000000..d2cc7cc --- /dev/null +++ b/locators/backup_tab_locators.py @@ -0,0 +1,48 @@ +"""Модуль backup_tab_locators содержит локаторы элементов страницы 'Резервное копирование'. + +Класс RackLocators хранит XPath/CSS локаторы для взаимодействия +с элементами интерфейса вкладки в тестах. + +""" + +class BackupTabLocators: + """Класс для хранения локаторов элементов страницы 'Резервное копирование'. + + Содержит локаторы в формате XPath/CSS для поиска элементов + """ + + # Кнопки на тулбаре + BUTTON_EDIT_TOOLBAR = "//button[@data-testid='BACKUP_PANEL__btn__edit']" + BUTTON_SAVE_TOOLBAR = "//button[@data-testid='BACKUP_PANEL__btn__submit']" + BUTTON_CANCEL_TOOLBAR = "//button[@data-testid='BACKUP_PANEL__btn__cancel']" + + # Кнопки раздела 'Инвентаризация' + BUTTON_INVENTORY_CREATE_COPY = "//button[@data-testid='BACKUP_PANEL__btn__createCopy_cmdb']" + BUTTON_INVENTORY_UPLOAD_COPY = "//button[@data-testid='BACKUP_PANEL__btn__upload_cmdb']" + BUTTON_INVENTORY_RESTORE_COPY = "//button[@data-testid='BACKUP_PANEL__btn__restore_cmdb']" + BUTTON_INVENTORY_DOWNLOAD_COPY = "//button[@data-testid='BACKUP_PANEL__btn__download_cmdb']" + + # Набор полей 'Инвентаризация/Параметры планировщика' + INPUT_INVENTORY_BACKUP_CREATION_TIME = "//input[@data-testid='BACKUP_PANEL__text-field__auto_backup_cmdb']" + INPUT_INVENTORY_BACKUP_NUMBERS = "//input[@data-testid='BACKUP_PANEL__text-field__backup_limitation_cmdb']" + + # Кнопки раздела 'Потоковые данные' + BUTTON_STREAMING_DATA_CREATE_COPY = "//button[@data-testid='BACKUP_PANEL__btn__createCopy_streaming_data']" + BUTTON_STREAMING_DATA_UPLOAD_COPY = "//button[@data-testid='BACKUP_PANEL__btn__upload_streaming_data']" + BUTTON_STREAMING_DATA_RESTORE_COPY = "//button[@data-testid='BACKUP_PANEL__btn__restore_streaming_data']" + BUTTON_STREAMING_DATA_DOWNLOAD_COPY = "//button[@data-testid='BACKUP_PANEL__btn__download_streaming_data']" + + # Поля ввода данных для различных категорий раздела 'Потоковые данные' + INPUT_AUDIT_TIME_PERIOD = "//input[@data-testid='BACKUP_PANEL__text-field__data_limitation_default_audit']" + INPUT_AUDIT_TIME_PERIOD_INTERVAL = "//input[@data-testid='BACKUP_PANEL__select__interval_limitation_default_audit']" + INPUT_LOGS_TIME_PERIOD = "//input[@data-testid='BACKUP_PANEL__text-field__data_limitation_logs_logs']" + INPUT_LOGS_TIME_PERIOD_INTERVAL ="//input[@data-testid='BACKUP_PANEL__select__interval_limitation_logs_logs']" + INPUT_METRICS_TIME_PERIOD = "//input[@data-testid='BACKUP_PANEL__text-field__data_limitation_metrics_metrics']" + INPUT_METRICS_TIME_PERIOD_INTERVAL = "//input[@data-testid='BACKUP_PANEL__select__interval_limitation_metrics_metrics']" + INPUT_SYSLOG_TIME_PERIOD = "//input[@data-testid='BACKUP_PANEL__text-field__data_limitation_syslog_syslog']" + INPUT_SYSLOG_TIME_PERIOD_INTERVAL = "//input[@data-testid='BACKUP_PANEL__select__interval_limitation_syslog_syslog']" + INPUT_TASKS_TIME_PERIOD = "//input[@data-testid='BACKUP_PANEL__text-field__data_limitation_tasks_tasks']" + INPUT_TASKS_TIME_PERIOD_INTERVAL = "//input[@data-testid='BACKUP_PANEL__select__interval_limitation_tasks_tasks']" + + # Набор полей 'Потоковые данные/Параметры планировщика' + INPUT_STREAMING_DATA_BACKUP_CREATION_TIME = "//input[@data-testid='BACKUP_PANEL__text-field__auto_backup_streaming_data']" diff --git a/pages/backup_settings_tab.py b/pages/backup_settings_tab.py new file mode 100644 index 0000000..c5863c5 --- /dev/null +++ b/pages/backup_settings_tab.py @@ -0,0 +1,1017 @@ +"""Модуль вкладки настройки резервного копирования. + +Содержит класс BackupSettings для работы с вкладкой настройки резервного копирования. +Позволяет проверять состояние и взаимодействовать с элементами вкладки. +""" + +import re +from playwright.sync_api import Page +from locators.backup_tab_locators import BackupTabLocators +from elements.text_input_element import TextInput +from elements.text_element import Text +from elements.button_element import Button +from components.toolbar_component import ToolbarComponent +from components.alert_component import AlertComponent +from components_derived.settings_form_component import SettingsFormComponent +from components_derived.selection_bar_component import SelectionBarComponent +from pages.base_page import BasePage + + +class BackupSettingsTab(BasePage): + """Класс для работы с вкладкой настройки резервного копирования. + + Предоставляет методы для взаимодействия с вкладкой настройки резервного копирования. + + Args: + page: Экземпляр страницы Playwright. + """ + + def __init__(self, page: Page) -> None: + """Инициализирует компоненты вкладки настройки резервного копирования.""" + + super().__init__(page) + + # Тулбар + self.toolbar = ToolbarComponent(page, "Резервное копирование") + + toolbar_button_edit = self.page.get_by_role("navigation"). \ + filter(has_text=re.compile("Резервное копирование")). \ + locator(BackupTabLocators.BUTTON_EDIT_TOOLBAR) + self.toolbar.add_tooltip_button(toolbar_button_edit, "edit") + + toolbar_button_save = self.page.get_by_role("navigation"). \ + filter(has_text=re.compile("Резервное копирование")). \ + locator(BackupTabLocators.BUTTON_SAVE_TOOLBAR) + self.toolbar.add_tooltip_button(toolbar_button_save, "save") + + toolbar_button_cancel = self.page.get_by_role("navigation"). \ + filter(has_text=re.compile("Резервное копирование")). \ + locator(BackupTabLocators.BUTTON_CANCEL_TOOLBAR) + self.toolbar.add_tooltip_button(toolbar_button_cancel, "cancel") + + # Форма для отображения/редактирования полей настроек 'Инвентаризация' + self.inventory_settings = self._create_inventory_settings() + + # Форма для отображения/редактирования полей настроек 'Инвентаризация/Параметры планировщика' + self.inventory_scheduler_settings = self._create_inventory_scheduler_settings() + + # Форма для отображения/редактирования полей настроек 'Потоковые данные' + self.streaming_data_settings = self._create_streaming_data_settings() + + # Форма для отображения/редактирования полей настроек 'Потоковые данные/Параметры планировщика' + self.streaming_data_scheduler_settings = self._create_streaming_data_scheduler_settings() + + self.alert = AlertComponent(page) + + # Действия: + def click_cancel_button(self) -> None: + """Нажатие кнопки 'Отменить' на тулбаре.""" + + self.toolbar.check_button_visibility("cancel") + self.toolbar.get_button_by_name("cancel").click() + + def click_edit_button(self) -> None: + """Нажатие кнопки 'Редактировать' на тулбаре.""" + + self.toolbar.check_button_visibility("edit") + self.toolbar.get_button_by_name("edit").click() + + def click_save_button(self) -> None: + """Нажатие кнопки 'Сохранить' на тулбаре.""" + + self.toolbar.check_button_visibility("save") + self.toolbar.get_button_by_name("save").click() + + def clear_inventory_dump_selection(self) -> None: + """Удаление ранее выбранного имени дампа""" + + dump_selector = self.inventory_settings.get_content_item("inventory_dump_selector") + dump_selector.clear_selections() + + def clear_streaming_data_dump_selection(self) -> None: + """Удаление ранее выбранного имени дампа""" + + dump_selector = self.streaming_data_settings.get_content_item("streaming_data_dump_selector") + dump_selector.clear_selections() + + + def create_inventory_copy(self) -> None: + """Создать резервную копию Системы.""" + + button_create_copy = self.inventory_settings.get_content_item("inventory_button_create_copy") + button_create_copy.check_visibility("Inventory button to create copy is missing") + button_create_copy.click() + + self.page.wait_for_load_state() + + 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 create_streaming_data_copy(self) -> None: + """Создать резервную копию потоковых данных.""" + + button_create_copy = self.streaming_data_settings.get_content_item("streaming_data_button_create_copy") + button_create_copy.check_visibility("Streaming data button to create copy is missing") + button_create_copy.click() + + self.page.wait_for_load_state() + + 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 download_inventory_copy(self, dump: str, path_to_download: str) -> None: + """Скачать резервную копию Системы.""" + + assert path_to_download.exists(), f"{path_to_download} does not exist" + + dump_selector = self.inventory_settings.get_content_item("inventory_dump_selector") + if dump_selector: + dump_selector.open_values_list() + dump_selector.select_value(dump) + + button_download_copy = self.inventory_settings.get_content_item("inventory_button_download_copy") + button_download_copy.check_visibility("Inventory button to download copy is missing") + + with self.page.expect_download() as download_info: + button_download_copy.click() + download = download_info.value + + download_error = download.failure() + assert not download_error, f"Download error: {download_error}" + + download.save_as(str(path_to_download) + "/" + download.suggested_filename) + + def get_inventory_scheduler_settings_values(self) -> dict: + """Возвращает текущее значение полей настроек 'Инвентаризация/Параметры планировщика'. + + Returns: + dict : Текущее значение полей настроек 'Инвентаризация/Параметры планировщика'. + """ + + values = {} + field = self.inventory_scheduler_settings.get_content_item("backup_creation_time_input") + values.update({"auto_backup": field.get_input_value().strip()}) + + field = self.inventory_scheduler_settings.get_content_item("backups_number_input") + values.update({"backup_limitation": field.get_input_value().strip()}) + + return values + + def get_streaming_data_settings_values(self) -> dict: + """Возвращает текущее значение полей настроек 'Потоковые данные'. + + Returns: + dict : Текущее значение полей настроек 'Потоковые данные'. + """ + + values = {} + field = self.streaming_data_settings.get_content_item("audit_time_period_value") + values.update({"data_limitation_default": field.get_input_value().strip()}) + interval = self.streaming_data_settings.get_content_item("audit_time_period_value_interval_selector") + interval_values = interval.get_selected_values() + values.update({"interval_limitation_default": interval_values[0]}) + + field = self.streaming_data_settings.get_content_item("logs_time_period_value") + values.update({"data_limitation_logs": field.get_input_value().strip()}) + interval = self.streaming_data_settings.get_content_item("logs_time_period_value_interval_selector") + interval_values = interval.get_selected_values() + values.update({"interval_limitation_logs": interval_values[0]}) + + field = self.streaming_data_settings.get_content_item("metrics_time_period_value") + values.update({"data_limitation_metrics": field.get_input_value().strip()}) + interval = self.streaming_data_settings.get_content_item("metrics_time_period_value_interval_selector") + interval_values = interval.get_selected_values() + values.update({"interval_limitation_metrics": interval_values[0]}) + + field = self.streaming_data_settings.get_content_item("syslog_time_period_value") + values.update({"data_limitation_syslog": field.get_input_value().strip()}) + interval = self.streaming_data_settings.get_content_item("syslog_time_period_value_interval_selector") + interval_values = interval.get_selected_values() + values.update({"interval_limitation_syslog": interval_values[0]}) + + field = self.streaming_data_settings.get_content_item("tasks_time_period_value") + values.update({"data_limitation_tasks": field.get_input_value().strip()}) + interval = self.streaming_data_settings.get_content_item("tasks_time_period_value_interval_selector") + interval_values = interval.get_selected_values() + values.update({"interval_limitation_tasks": interval_values[0]}) + + return values + + def get_streaming_data_scheduler_settings_values(self) -> dict: + """Возвращает текущее значение полей настроек 'Потоковые данные/Параметры планировщика'. + + Returns: + dict : Текущее значение полей настроек 'Потоковые данные/Параметры планировщика'. + """ + + values = {} + field = self.streaming_data_scheduler_settings.get_content_item("backup_creation_time_input") + values.update({"auto_backup": field.get_input_value().strip()}) + + return values + + def get_inventory_dumps_list(self) -> list[str]: + """Возвращает текущий список дампов для настроек 'Инвентаризация'. + + Returns: + list[str] : Текущий список дампов для настроек 'Инвентаризация'. + """ + + dump_selector = self.inventory_settings.get_content_item("inventory_dump_selector") + return dump_selector.get_available_options() + + def get_streaming_data_dumps_list(self) -> list[str]: + """Возвращает текущий список дампов для настроек 'Потоковые данные'. + + Returns: + list[str] : Текущий список дампов для настроек 'Потоковые данные'. + """ + + dump_selector = self.streaming_data_settings.get_content_item("streaming_data_dump_selector") + return dump_selector.get_available_options() + + def input_inventory_backup_creation_time(self, value: str) -> None: + """Заполнение поля 'Время создания резервной копии' настроек 'Инвентаризация/Параметры планировщика'""" + + field = self.inventory_scheduler_settings.get_content_item("backup_creation_time_input") + field.clear() + field.input_value(value) + + def input_inventory_backups_number(self, value: str) -> None: + """Заполнение поля 'Количество резервных копий' настроек 'Инвентаризация/Параметры планировщика'""" + + field = self.inventory_scheduler_settings.get_content_item("backups_number_input") + field.clear() + field.input_value(value) + + def input_audit_time_period(self, time_period: str, time_interval: str) -> None: + """Заполнение поля 'Период хранения данных' для категории 'Аудит' настроек 'Потоковые данные'""" + + field = self.streaming_data_settings.get_content_item("audit_time_period_value") + field.clear() + field.input_value(time_period) + + interval = self.streaming_data_settings.get_content_item("audit_time_period_value_interval_selector") + interval.open_values_list() + interval.select_value(time_interval) + + def input_logs_time_period(self, time_period: str, time_interval: str) -> None: + """Заполнение поля 'Период хранения данных' для категории 'Логи' настроек 'Потоковые данные'""" + + field = self.streaming_data_settings.get_content_item("logs_time_period_value") + field.clear() + field.input_value(time_period) + + interval = self.streaming_data_settings.get_content_item("logs_time_period_value_interval_selector") + interval.open_values_list() + interval.select_value(time_interval) + + def input_metrics_time_period(self, time_period: str, time_interval: str) -> None: + """Заполнение поля 'Период хранения данных' для категории 'Метрики' настроек 'Потоковые данные'""" + + field = self.streaming_data_settings.get_content_item("metrics_time_period_value") + field.clear() + field.input_value(time_period) + + interval = self.streaming_data_settings.get_content_item("metrics_time_period_value_interval_selector") + interval.open_values_list() + interval.select_value(time_interval) + + def input_syslog_time_period(self, time_period: str, time_interval: str) -> None: + """Заполнение поля 'Период хранения данных' для категории 'Системный лог' настроек 'Потоковые данные'""" + + field = self.streaming_data_settings.get_content_item("syslog_time_period_value") + field.clear() + field.input_value(time_period) + + interval = self.streaming_data_settings.get_content_item("syslog_time_period_value_interval_selector") + interval.open_values_list() + interval.select_value(time_interval) + + def input_tasks_time_period(self, time_period: str, time_interval: str) -> None: + """Заполнение поля 'Период хранения данных' для категории 'Действия' настроек 'Потоковые данные'""" + + field = self.streaming_data_settings.get_content_item("tasks_time_period_value") + field.clear() + field.input_value(time_period) + + interval = self.streaming_data_settings.get_content_item("tasks_time_period_value_interval_selector") + interval.open_values_list() + interval.select_value(time_interval) + + def input_streaming_data_backup_creation_time(self, value: str) -> None: + """Заполнение поля 'Время создания резервной копии' настроек 'Потоковые данные/Параметры планировщика'""" + + field = self.streaming_data_scheduler_settings.get_content_item("backup_creation_time_input") + field.clear() + field.input_value(value) + + def decrease_inventory_backups_number(self) -> None: + """Уменьшение на единицу значения поля 'Количество резервных копий' настроек + 'Инвентаризация/Параметры планировщика' с помощью стрелочки вниз.""" + + field = self.inventory_scheduler_settings.get_content_item("backups_number_input") + field.decrease_value() + + def increase_inventory_backups_number(self) -> None: + """Увеличение на единицу значения поля 'Количество резервных копий' настроек + 'Инвентаризация/Параметры планировщика' с помощью стрелочки вверх.""" + + field = self.inventory_scheduler_settings.get_content_item("backups_number_input") + field.increase_value() + + def decrease_audit_time_period(self) -> None: + """Уменьшение на единицу значения поля 'Период хранения данных' для категории 'Аудит' настроек + 'Потоковые данные' с помощью стрелочки вниз.""" + + field = self.streaming_data_settings.get_content_item("audit_time_period_value") + field.decrease_value() + + def increase_audit_time_period(self) -> None: + """Увеличение на единицу значения поля 'Период хранения данных' для категории 'Аудит' настроек + 'Потоковые данные' с помощью стрелочки вверх.""" + + field = self.streaming_data_settings.get_content_item("audit_time_period_value") + field.increase_value() + + def decrease_logs_time_period(self) -> None: + """Уменьшение на единицу значения поля 'Период хранения данных' для категории 'Логи' настроек + 'Потоковые данные' с помощью стрелочки вниз.""" + + field = self.streaming_data_settings.get_content_item("logs_time_period_value") + field.decrease_value() + + def increase_logs_time_period(self) -> None: + """Увеличение на единицу значения поля 'Период хранения данных' для категории 'Логи' настроек + 'Потоковые данные' с помощью стрелочки вверх.""" + + field = self.streaming_data_settings.get_content_item("logs_time_period_value") + field.increase_value() + + def decrease_metrics_time_period(self) -> None: + """Уменьшение на единицу значения поля 'Период хранения данных' для категории 'Метрики' настроек + 'Потоковые данные' с помощью стрелочки вниз.""" + + field = self.streaming_data_settings.get_content_item("metrics_time_period_value") + field.decrease_value() + + def increase_metrics_time_period(self) -> None: + """Увеличение на единицу значения поля 'Период хранения данных' для категории 'Метрики' настроек + 'Потоковые данные' с помощью стрелочки вверх.""" + + field = self.streaming_data_settings.get_content_item("metrics_time_period_value") + field.increase_value() + + def decrease_syslog_time_period(self) -> None: + """Уменьшение на единицу значения поля 'Период хранения данных' для категории 'Системный лог' настроек + 'Потоковые данные' с помощью стрелочки вниз.""" + + field = self.streaming_data_settings.get_content_item("syslog_time_period_value") + field.decrease_value() + + def increase_syslog_time_period(self) -> None: + """Увеличение на единицу значения поля 'Период хранения данных' для категории 'Системный лог' настроек + 'Потоковые данные' с помощью стрелочки вверх.""" + + field = self.streaming_data_settings.get_content_item("syslog_time_period_value") + field.increase_value() + + def decrease_tasks_time_period(self) -> None: + """Уменьшение на единицу значения поля 'Период хранения данных' для категории 'Действия' настроек + 'Потоковые данные' с помощью стрелочки вниз.""" + + field = self.streaming_data_settings.get_content_item("tasks_time_period_value") + field.decrease_value() + + def increase_tasks_time_period(self) -> None: + """Увеличение на единицу значения поля 'Период хранения данных' для категории 'Действия' настроек + 'Потоковые данные' с помощью стрелочки вверх.""" + + field = self.streaming_data_settings.get_content_item("tasks_time_period_value") + field.increase_value() + + def select_inventory_dump(self, dump: str) -> None: + """Выбирает дамп для настроек 'Инвентаризация' из списка""" + + dump_selector = self.inventory_settings.get_content_item("inventory_dump_selector") + if dump_selector: + dump_selector.open_values_list() + dump_selector.select_value(dump) + + def select_streaming_data_dump(self, dump: str) -> None: + """Выбирает дамп для настроек 'Потоковые данные' из списка""" + + dump_selector = self.streaming_data_settings.get_content_item("streaming_data_dump_selector") + if dump_selector: + dump_selector.open_values_list() + dump_selector.select_value(dump) + + + def _create_inventory_settings(self) -> SettingsFormComponent: + """ Конструктор для набора полей 'Инвентаризация'""" + + inventory_settings = SettingsFormComponent(self.page) + inventory_settings.add_toolbar_title(" Инвентаризация ") + + inventory_container_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Инвентаризация ").locator("//following-sibling::div[1]") + + # Кнопка 'Создать копию' + inventory_button_create_copy_loc = inventory_container_locator.\ + locator(BackupTabLocators.BUTTON_INVENTORY_CREATE_COPY) + inventory_button_create_copy = Button(self.page, inventory_button_create_copy_loc, + "inventory_button_create_copy") + inventory_settings.add_content_item("inventory_button_create_copy", inventory_button_create_copy) + + # Кнопка 'Загрузить копию' + inventory_button_upload_copy_loc = inventory_container_locator.\ + locator(BackupTabLocators.BUTTON_INVENTORY_UPLOAD_COPY) + inventory_button_upload_copy = Button(self.page, inventory_button_upload_copy_loc, + "inventory_button_upload_copy") + inventory_settings.add_content_item("inventory_button_upload_copy", inventory_button_upload_copy) + + # Кнопка 'Восстановить копию' + inventory_button_restore_copy_loc = inventory_container_locator.\ + locator(BackupTabLocators.BUTTON_INVENTORY_RESTORE_COPY) + inventory_button_restore_copy = Button(self.page, inventory_button_restore_copy_loc, + "inventory_button_restore_copy") + inventory_settings.add_content_item("inventory_button_restore_copy", inventory_button_restore_copy) + + # Кнопка 'Скачать копию' + inventory_button_download_copy_loc = inventory_container_locator.\ + locator(BackupTabLocators.BUTTON_INVENTORY_DOWNLOAD_COPY) + inventory_button_download_copy = Button(self.page, inventory_button_download_copy_loc, + "inventory_button_download_copy") + inventory_settings.add_content_item("inventory_button_download_copy", inventory_button_download_copy) + + # Список дампов + inventory_dump_selector_loc = inventory_container_locator.get_by_role("combobox") + inventory_settings.add_content_item("inventory_dump_selector", + SelectionBarComponent(self.page, inventory_dump_selector_loc)) + + return inventory_settings + + def _create_inventory_scheduler_settings(self) -> SettingsFormComponent: + """ Конструктор для набора полей 'Инвентаризация/Параметры планировщика'""" + + inventory_scheduler_settings = SettingsFormComponent(self.page) + inventory_scheduler_settings.add_toolbar_title(" Параметры планировщика ") + + # Вспомогательные локаторы + div_locator = "div:nth-child(1) > div:nth-child(1)" + input_locator = "div.v-text-field__slot > input" + + # Время создания резервной копии + container_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Параметры планировщика ").locator("//following-sibling::div[1]").first + + loc_backup_creation_time_label = container_locator.locator(div_locator).locator(input_locator).first + + backup_creation_time_label = Text(self.page, loc_backup_creation_time_label, "backup_creation_time_label") + inventory_scheduler_settings.add_content_item("backup_creation_time_label", backup_creation_time_label) + + loc_backup_creation_time_input = container_locator. \ + locator(BackupTabLocators.INPUT_INVENTORY_BACKUP_CREATION_TIME) + backup_creation_time_input = TextInput(self.page, loc_backup_creation_time_input, "backup_creation_time_input") + inventory_scheduler_settings.add_content_item("backup_creation_time_input", backup_creation_time_input) + + # Количество резервных копий + container_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Параметры планировщика ").locator("//following-sibling::div[2]") + + loc_backups_number_label = container_locator.locator(div_locator).locator(input_locator).first + backups_number_label = Text(self.page, loc_backups_number_label, "backups_number_label") + inventory_scheduler_settings.add_content_item("backups_number_label", backups_number_label) + + loc_backups_number_input = container_locator. \ + locator(BackupTabLocators.INPUT_INVENTORY_BACKUP_NUMBERS) + backups_number_input = TextInput(self.page, loc_backups_number_input, "backups_number_input") + inventory_scheduler_settings.add_content_item("backups_number_input", backups_number_input) + + return inventory_scheduler_settings + + def _create_streaming_data_settings(self) -> SettingsFormComponent: + """ Конструктор для набора полей 'Потоковые данные'""" + + streaming_data_settings = SettingsFormComponent(self.page) + streaming_data_settings.add_toolbar_title(" Потоковые данные ") + + # Вспомогательные локаторы + category_label_locator = "div:nth-child(1)" + time_period_label_locator = "div:nth-child(1) > div:nth-child(1) input" + time_period_value_locator = "div:nth-child(1) > div:nth-child(2)" + time_period_interval_locator = "div:nth-child(1) > div:nth-child(3)" + + streaming_data_container_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Потоковые данные ").locator("//following-sibling::div[1]") + + # Кнопка 'Создать копию' + streaming_data_button_create_copy_loc = streaming_data_container_locator.\ + locator(BackupTabLocators.BUTTON_STREAMING_DATA_CREATE_COPY) + streaming_data_button_create_copy = Button(self.page, streaming_data_button_create_copy_loc, + "streaming_data_button_create_copy") + streaming_data_settings.add_content_item("streaming_data_button_create_copy", + streaming_data_button_create_copy) + + # Кнопка 'Загрузить копию' + streaming_data_button_upload_copy_loc = streaming_data_container_locator.\ + locator(BackupTabLocators.BUTTON_STREAMING_DATA_UPLOAD_COPY) + streaming_data_button_upload_copy = Button(self.page, streaming_data_button_upload_copy_loc, + "streaming_data_button_upload_copy") + streaming_data_settings.add_content_item("streaming_data_button_upload_copy", + streaming_data_button_upload_copy) + + # Кнопка 'Восстановить копию' + streaming_data_button_restore_copy_loc = streaming_data_container_locator.\ + locator(BackupTabLocators.BUTTON_STREAMING_DATA_RESTORE_COPY) + streaming_data_button_restore_copy = Button(self.page, streaming_data_button_restore_copy_loc, + "streaming_data_button_restore_copy") + streaming_data_settings.add_content_item("streaming_data_button_restore_copy", + streaming_data_button_restore_copy) + + # Кнопка 'Скачать копию' + streaming_data_button_download_copy_loc = streaming_data_container_locator.\ + locator(BackupTabLocators.BUTTON_STREAMING_DATA_DOWNLOAD_COPY) + streaming_data_button_download_copy = Button(self.page, streaming_data_button_download_copy_loc, + "streaming_data_button_download_copy") + streaming_data_settings.add_content_item("streaming_data_button_download_copy", + streaming_data_button_download_copy) + + # Список дампов + streaming_data_dump_selector_loc = streaming_data_container_locator.get_by_role("combobox") + streaming_data_settings.add_content_item("streaming_data_dump_selector", + SelectionBarComponent(self.page, streaming_data_dump_selector_loc)) + + # Период хранения данных для категории Аудит + audit_category_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Потоковые данные ").locator("//following-sibling::div[2]") + audit_category_label = Text(self.page, + audit_category_locator.locator(category_label_locator).first, + "audit_category_label") + streaming_data_settings.add_content_item("audit_category_label", audit_category_label) + + audit_time_period_label = Text(self.page, + audit_category_locator.locator(time_period_label_locator).first, + "audit_time_period_label") + streaming_data_settings.add_content_item("audit_time_period_label", audit_time_period_label) + + audit_time_period_value = TextInput(self.page, + audit_category_locator.locator(time_period_value_locator). \ + locator(BackupTabLocators.INPUT_AUDIT_TIME_PERIOD), + "audit_time_period_value") + streaming_data_settings.add_content_item("audit_time_period_value", audit_time_period_value) + + audit_time_period_value_interval = TextInput(self.page, + audit_category_locator.locator(time_period_interval_locator). \ + locator(BackupTabLocators.INPUT_AUDIT_TIME_PERIOD_INTERVAL), + "audit_time_period_value_interval") + streaming_data_settings.add_content_item("audit_time_period_value_interval", audit_time_period_value_interval) + + audit_time_period_value_interval_selector_loc = audit_category_locator. \ + locator(time_period_interval_locator). \ + get_by_role("combobox") + streaming_data_settings.add_content_item("audit_time_period_value_interval_selector", + SelectionBarComponent(self.page, + audit_time_period_value_interval_selector_loc)) + + # Период хранения данных для категории Логи + logs_category_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Потоковые данные ").locator("//following-sibling::div[3]") + logs_category_label = Text(self.page, + logs_category_locator.locator(category_label_locator).first, + "logs_category_label") + streaming_data_settings.add_content_item("logs_category_label", logs_category_label) + + logs_time_period_label = Text(self.page, + logs_category_locator.locator(time_period_label_locator).first, + "logs_time_period_label") + streaming_data_settings.add_content_item("logs_time_period_label", logs_time_period_label) + + logs_time_period_value = TextInput(self.page, + logs_category_locator.locator(time_period_value_locator). \ + locator(BackupTabLocators.INPUT_LOGS_TIME_PERIOD), + "logs_time_period_value") + streaming_data_settings.add_content_item("logs_time_period_value", logs_time_period_value) + + logs_time_period_value_interval = TextInput(self.page, + logs_category_locator.locator(time_period_interval_locator). \ + locator(BackupTabLocators.INPUT_LOGS_TIME_PERIOD_INTERVAL), + "logs_time_period_value") + streaming_data_settings.add_content_item("logs_time_period_value_interval", logs_time_period_value_interval) + + logs_time_period_value_interval_selector_loc = logs_category_locator. \ + locator(time_period_interval_locator). \ + get_by_role("combobox") + streaming_data_settings.add_content_item("logs_time_period_value_interval_selector", + SelectionBarComponent(self.page, + logs_time_period_value_interval_selector_loc)) + + # Период хранения данных для категории Метрики + metrics_category_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Потоковые данные ").locator("//following-sibling::div[4]") + metrics_category_label = Text(self.page, + metrics_category_locator.locator(category_label_locator).first, + "metrics_category_label") + streaming_data_settings.add_content_item("metrics_category_label", metrics_category_label) + + metrics_time_period_label = Text(self.page, + metrics_category_locator.locator(time_period_label_locator).first, + "metrics_time_period_label") + streaming_data_settings.add_content_item("metrics_time_period_label", metrics_time_period_label) + + metrics_time_period_value = TextInput(self.page, + metrics_category_locator.locator(time_period_value_locator). \ + locator(BackupTabLocators.INPUT_METRICS_TIME_PERIOD), + "metrics_time_period_value") + streaming_data_settings.add_content_item("metrics_time_period_value", metrics_time_period_value) + + metrics_time_period_value_interval = TextInput(self.page, + metrics_category_locator.locator(time_period_interval_locator). \ + locator(BackupTabLocators.INPUT_METRICS_TIME_PERIOD_INTERVAL), + "metrics_time_period_value_interval") + streaming_data_settings.add_content_item("metrics_time_period_value_interval", + metrics_time_period_value_interval) + + metrics_time_period_value_interval_selector_loc = metrics_category_locator. \ + locator(time_period_interval_locator). \ + get_by_role("combobox") + streaming_data_settings.add_content_item("metrics_time_period_value_interval_selector", + SelectionBarComponent(self.page, + metrics_time_period_value_interval_selector_loc)) + + # Период хранения данных для категории Системный лог + syslog_category_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Потоковые данные ").locator("//following-sibling::div[5]") + syslog_category_label = Text(self.page, + syslog_category_locator.locator(category_label_locator).first, + "syslog_category_label") + streaming_data_settings.add_content_item("syslog_category_label", syslog_category_label) + + syslog_time_period_label = Text(self.page, + syslog_category_locator.locator(time_period_label_locator).first, + "syslog_time_period_label") + streaming_data_settings.add_content_item("syslog_time_period_label", syslog_time_period_label) + + syslog_time_period_value = TextInput(self.page, + syslog_category_locator.locator(time_period_value_locator). \ + locator(BackupTabLocators.INPUT_SYSLOG_TIME_PERIOD), + "syslog_time_period_value") + streaming_data_settings.add_content_item("syslog_time_period_value", syslog_time_period_value) + + syslog_time_period_value_interval = TextInput(self.page, + syslog_category_locator.locator(time_period_interval_locator). \ + locator(BackupTabLocators.INPUT_SYSLOG_TIME_PERIOD_INTERVAL), + "syslog_time_period_value_interval") + streaming_data_settings.add_content_item("syslog_time_period_value_interval", syslog_time_period_value_interval) + + syslog_time_period_value_interval_selector_loc = syslog_category_locator. \ + locator(time_period_interval_locator). \ + get_by_role("combobox") + streaming_data_settings.add_content_item("syslog_time_period_value_interval_selector", + SelectionBarComponent(self.page, + syslog_time_period_value_interval_selector_loc)) + + # Период хранения данных для категории Действия + tasks_category_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Потоковые данные ").locator("//following-sibling::div[6]") + tasks_category_label = Text(self.page, + tasks_category_locator.locator(category_label_locator).first, + "tasks_category_label") + streaming_data_settings.add_content_item("tasks_category_label", tasks_category_label) + + tasks_time_period_label = Text(self.page, + tasks_category_locator.locator(time_period_label_locator).first, + "tasks_time_period_label") + streaming_data_settings.add_content_item("tasks_time_period_label", tasks_time_period_label) + + tasks_time_period_value = TextInput(self.page, + tasks_category_locator.locator(time_period_value_locator). \ + locator(BackupTabLocators.INPUT_TASKS_TIME_PERIOD), + "tasks_time_period_value") + streaming_data_settings.add_content_item("tasks_time_period_value", tasks_time_period_value) + + tasks_time_period_value_interval = TextInput(self.page, + tasks_category_locator.locator(time_period_interval_locator). \ + locator(BackupTabLocators.INPUT_TASKS_TIME_PERIOD_INTERVAL), + "tasks_time_period_value_interval") + streaming_data_settings.add_content_item("tasks_time_period_value_interval", tasks_time_period_value_interval) + + tasks_time_period_value_interval_selector_loc = tasks_category_locator. \ + locator(time_period_interval_locator). \ + get_by_role("combobox") + streaming_data_settings.add_content_item("tasks_time_period_value_interval_selector", + SelectionBarComponent(self.page, + tasks_time_period_value_interval_selector_loc)) + + return streaming_data_settings + + def _create_streaming_data_scheduler_settings(self) -> SettingsFormComponent: + """ Конструктор для набора полей 'Потоковые данные/Параметры планировщика'""" + + streaming_data_scheduler_settings = SettingsFormComponent(self.page) + streaming_data_scheduler_settings.add_toolbar_title(" Параметры планировщика ") + + # Вспомогательные локаторы + div_locator = "div:nth-child(1) > div:nth-child(1)" + input_locator = "div.v-text-field__slot > input" + + # Время создания резервной копии + container_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Параметры планировщика ").locator("//following-sibling::div").last + + loc_backup_creation_time_label = container_locator.locator(div_locator).locator(input_locator).first + backup_creation_time_label = Text(self.page, loc_backup_creation_time_label, "backup_creation_time_label") + streaming_data_scheduler_settings.add_content_item("backup_creation_time_label", backup_creation_time_label) + + loc_backup_creation_time_input = container_locator. \ + locator(BackupTabLocators.INPUT_STREAMING_DATA_BACKUP_CREATION_TIME) + backup_creation_time_input = TextInput(self.page, loc_backup_creation_time_input, "backup_creation_time_input") + streaming_data_scheduler_settings.add_content_item("backup_creation_time_input", backup_creation_time_input) + + return streaming_data_scheduler_settings + + # Проверки: + def check_content(self): + """Проверяет наличие и корректность всех элементов страницы.""" + + self.should_be_toolbar() + + self._check_inventory_settings_content() + self._check_inventory_scheduler_settings_content() + self._check_streaming_data_settings_content() + self._check_streaming_data_scheduler_settings_content() + + def check_inventory_restore_copy_button_disabling(self) -> bool: + """Проверяет доступность кнопки 'Восстановить копию' настройки 'Инвентаризация'""" + + button_restore_copy = self.inventory_settings.get_content_item("inventory_button_restore_copy") + button_restore_copy.check_visibility("Inventory button to restore copy is missing") + return button_restore_copy.is_disabled() + + def check_streaming_data_restore_copy_button_disabling(self) -> bool: + """Проверяет доступность кнопки 'Восстановить копию' настройки 'Потоковые данные'""" + + button_restore_copy = self.streaming_data_settings.get_content_item("streaming_data_button_restore_copy") + button_restore_copy.check_visibility("Streaming data button to restore copy is missing") + return button_restore_copy.is_disabled() + + def should_be_toolbar(self) -> None: + """Проверяет наличие тулбара страницы, наличие и функциональность кнопок тулбара. + + Raises: + AssertionError: Если тулбар или кнопка тулбара отсутствуют. + """ + loc = self.page.get_by_role("navigation").filter( + has_text=re.compile("Резервное копирование")).locator("div").nth(1) + self.toolbar.check_toolbar_presence_by_locator(loc, "Toolbar with title 'Резервное копирование' is missing") + + 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("save") + self.toolbar.check_button_visibility("cancel") + self.toolbar.check_button_tooltip("save", "Сохранить") + self.toolbar.check_button_tooltip("cancel", "Отменить") + + self.toolbar.get_button_by_name("cancel").click() + self.toolbar.check_button_visibility("edit") + + def should_be_inventory_download_button(self) -> None: + """Проверяет наличие кнопки 'Скачать копию' настройки 'Инвентаризация'""" + + button_download_copy = self.inventory_settings.get_content_item("inventory_button_download_copy") + button_download_copy.check_visibility("Inventory button to download copy is missing") + + def should_be_inventory_upload_button(self) -> None: + """Проверяет наличие кнопки 'Загрузить копию' настройки 'Инвентаризация'""" + + button_upload_copy = self.inventory_settings.get_content_item("inventory_button_upload_copy") + button_upload_copy.check_visibility("Inventory button to upload copy is missing") + + def should_be_streaming_data_download_button(self) -> None: + """Проверяет наличие кнопки 'Скачать копию' настройки 'Потоковые данные'""" + + button_download_copy = self.streaming_data_settings.get_content_item("streaming_data_button_download_copy") + button_download_copy.check_visibility("Streaming data button to download copy is missing") + + def should_be_streaming_data_upload_button(self) -> None: + """Проверяет наличие кнопки 'Загрузить копию' настройки 'Потоковые данные'""" + + button_upload_copy = self.streaming_data_settings.get_content_item("streaming_data_button_upload_copy") + button_upload_copy.check_visibility("Streaming data button to upload copy is missing") + + + def _check_inventory_settings_content(self) -> None: + """Проверяет наличие и корректность всех элементов настройки 'Инвентаризация'.""" + + self.inventory_settings.should_be_toolbar() + + button_create_copy = self.inventory_settings.get_content_item("inventory_button_create_copy") + button_create_copy.check_visibility("Inventory button to create copy is missing") + button_text = button_create_copy.get_text(0).strip() + assert button_text == "Создать копию", f"Unexpected inventory button to create copy text: {button_text}" + + button_upload_copy = self.inventory_settings.get_content_item("inventory_button_upload_copy") + button_upload_copy.check_visibility("Inventory button to upload copy is missing") + button_text = button_upload_copy.get_text(0).strip() + assert button_text == "Загрузить копию", f"Unexpected inventory button to upload copy text: {button_text}" + + button_restore_copy = self.inventory_settings.get_content_item("inventory_button_restore_copy") + button_restore_copy.check_visibility("Inventory button to restore copy is missing") + button_text = button_restore_copy.get_text(0).strip() + assert button_text == "Восстановить копию", f"Unexpected inventory button to restore copy text: {button_text}" + + button_download_copy = self.inventory_settings.get_content_item("inventory_button_download_copy") + dump_selector = self.inventory_settings.get_content_item("inventory_dump_selector") + val = dump_selector.get_selected_values() + if len(val) == 0: + assert button_restore_copy.is_disabled(), "Inventory button to restore copy should be disabled" + assert button_download_copy.get_locator().count() == 0, \ + "Inventory button to download copy should be missing" + else: + assert not button_restore_copy.is_disabled(), "Inventory button to restore copy should be enabled" + + button_download_copy.check_visibility("Inventory button to download copy is missing") + button_text = button_download_copy.get_text(0).strip() + assert button_text == "Скачать копию", f"Unexpected inventory button to upload copy text: {button_text}" + + def _check_inventory_scheduler_settings_content(self) -> None: + """Проверяет наличие и корректность всех элементов настройки 'Инвентаризация/Параметры планировщика'.""" + + self.inventory_scheduler_settings.should_be_toolbar() + + backup_creation_time_label = self.inventory_scheduler_settings.get_content_item("backup_creation_time_label") + backup_creation_time_label.check_visibility("Inventory backup creation time label is missing") + label_text = backup_creation_time_label.get_locator().input_value() + assert label_text == "Время создания резервной копии", "Unexpected inventory backup creation time label text" + + backup_creation_time_input = self.inventory_scheduler_settings.get_content_item("backup_creation_time_input") + backup_creation_time_input.check_visibility("Inventory backup creation time input field is missing") + + backups_number_label = self.inventory_scheduler_settings.get_content_item("backups_number_label") + backups_number_label.check_visibility("Inventory backups number label is missing") + label_text = backups_number_label.get_locator().input_value() + assert label_text == "Количество резервных копий", "Unexpected inventory backups number label text" + + backups_number_input = self.inventory_scheduler_settings.get_content_item("backups_number_input") + backups_number_input.check_visibility("Inventory backups number input field is missing") + + def _check_streaming_data_settings_content(self) -> None: + """Проверяет наличие и корректность всех элементов настройки 'Потоковые данные'.""" + + self.streaming_data_settings.should_be_toolbar() + + button_create_copy = self.streaming_data_settings.get_content_item("streaming_data_button_create_copy") + button_create_copy.check_visibility("Streaming data button to create copy is missing") + button_text = button_create_copy.get_text(0).strip() + assert button_text == "Создать копию", f"Unexpected streaming data button to create copy text: {button_text}" + + button_upload_copy = self.streaming_data_settings.get_content_item("streaming_data_button_upload_copy") + button_upload_copy.check_visibility("Streaming data button to upload copy is missing") + button_text = button_upload_copy.get_text(0).strip() + assert button_text == "Загрузить копию", f"Unexpected streaming data button to upload copy text: {button_text}" + + button_restore_copy = self.streaming_data_settings.get_content_item("streaming_data_button_restore_copy") + button_restore_copy.check_visibility("Streaming data button to restore copy is missing") + button_text = button_restore_copy.get_text(0).strip() + assert button_text == "Восстановить копию", \ + f"Unexpected streaming data button to restore copy text: {button_text}" + + button_download_copy = self.streaming_data_settings.get_content_item("streaming_data_button_download_copy") + dump_selector = self.streaming_data_settings.get_content_item("streaming_data_dump_selector") + val = dump_selector.get_selected_values() + if len(val) == 0: + assert button_restore_copy.is_disabled(), "Streaming data button to restore copy should be disabled" + assert button_download_copy.get_locator().count() == 0, \ + "Streaming data button to download copy should be missing" + else: + assert not button_restore_copy.is_disabled(), "Streaming data button to restore copy should be enabled" + + button_download_copy.check_visibility("Streaming data button to download copy is missing") + button_text = button_download_copy.get_text(0).strip() + assert button_text == "Скачать копию", \ + f"Unexpected streaming data button to upload copy text: {button_text}" + + audit_category_label = self.streaming_data_settings.get_content_item("audit_category_label") + audit_category_label.check_visibility("Streaming data Audit category label is missing") + audit_category_label_text = audit_category_label.get_text(0).strip() + assert audit_category_label_text == "Аудит", \ + f"Unexpected streaming data Audit category label text: {audit_category_label_text}" + + audit_time_period_label = self.streaming_data_settings.get_content_item("audit_time_period_label") + audit_time_period_label.check_visibility("Streaming data Audit storage time period label is missing") + audit_time_period_label_text = audit_time_period_label.get_locator().input_value() + assert audit_time_period_label_text == "Период хранения данных", \ + f"Unexpected streaming data Audit storage time period label text: {audit_time_period_label_text}" + + audit_time_period_value = self.streaming_data_settings.get_content_item("audit_time_period_value") + audit_time_period_value.check_visibility("Streaming data Audit storage time period input field is missing") + + audit_time_period_value_interval = self.streaming_data_settings. \ + get_content_item("audit_time_period_value_interval") + audit_time_period_value_interval. \ + check_visibility("Streaming data Audit storage time period interval field is missing") + + logs_category_label = self.streaming_data_settings.get_content_item("logs_category_label") + logs_category_label.check_visibility("Streaming data Logs category label is missing") + logs_category_label_text = logs_category_label.get_text(0).strip() + assert logs_category_label_text == "Логи", \ + f"Unexpected streaming data Logs category label text: {logs_category_label_text}" + + logs_time_period_label = self.streaming_data_settings.get_content_item("logs_time_period_label") + logs_time_period_label.check_visibility("Streaming data Logs storage time period label is missing") + logs_time_period_label_text = logs_time_period_label.get_locator().input_value() + assert logs_time_period_label_text == "Период хранения данных", \ + f"Unexpected streaming data Logs storage time period label text: {logs_time_period_label_text}" + + logs_time_period_value = self.streaming_data_settings.get_content_item("logs_time_period_value") + logs_time_period_value.check_visibility("Streaming data Logs storage time period input field is missing") + + logs_time_period_value_interval = self.streaming_data_settings. \ + get_content_item("logs_time_period_value_interval") + logs_time_period_value_interval. \ + check_visibility("Streaming data Logs storage time period interval field is missing") + + metrics_category_label = self.streaming_data_settings.get_content_item("metrics_category_label") + metrics_category_label.check_visibility("Streaming data Metrics category label is missing") + metrics_category_label_text = metrics_category_label.get_text(0).strip() + assert metrics_category_label_text == "Метрики", \ + f"Unexpected streaming data Metrics category label text: {metrics_category_label_text}" + + metrics_time_period_label = self.streaming_data_settings.get_content_item("metrics_time_period_label") + metrics_time_period_label.check_visibility("Streaming data Metrics storage time period label is missing") + metrics_time_period_label_text = metrics_time_period_label.get_locator().input_value() + assert metrics_time_period_label_text == "Период хранения данных", \ + f"Unexpected streaming data Metrics storage time period label text: {metrics_time_period_label_text}" + + metrics_time_period_value = self.streaming_data_settings.get_content_item("metrics_time_period_value") + metrics_time_period_value.check_visibility("Streaming data Metrics storage time period input field is missing") + + metrics_time_period_value_interval = self.streaming_data_settings. \ + get_content_item("metrics_time_period_value_interval") + metrics_time_period_value_interval. \ + check_visibility("Streaming data Metrics storage time period interval field is missing") + + syslog_category_label = self.streaming_data_settings.get_content_item("syslog_category_label") + syslog_category_label.check_visibility("Streaming data Sys Log category label is missing") + syslog_category_label_text = syslog_category_label.get_text(0).strip() + assert syslog_category_label_text == "Системный лог", \ + f"Unexpected streaming data Sys Log category label text: {syslog_category_label_text}" + + syslog_time_period_label = self.streaming_data_settings.get_content_item("syslog_time_period_label") + syslog_time_period_label.check_visibility("Streaming data Sys Log storage time period label is missing") + syslog_time_period_label_text = syslog_time_period_label.get_locator().input_value() + assert syslog_time_period_label_text == "Период хранения данных", \ + f"Unexpected streaming data Sys Log storage time period label text: {syslog_time_period_label_text}" + + syslog_time_period_value = self.streaming_data_settings.get_content_item("syslog_time_period_value") + syslog_time_period_value.check_visibility("Streaming data Sys Log storage time period input field is missing") + + syslog_time_period_value_interval = self.streaming_data_settings. \ + get_content_item("syslog_time_period_value_interval") + syslog_time_period_value_interval. \ + check_visibility("Streaming data Sys Log storage time period interval field is missing") + + tasks_category_label = self.streaming_data_settings.get_content_item("tasks_category_label") + tasks_category_label.check_visibility("Streaming data Actions category label is missing") + tasks_category_label_text = tasks_category_label.get_text(0).strip() + assert tasks_category_label_text == "Действия", \ + f"Unexpected streaming data Actions category label text: {tasks_category_label_text}" + + tasks_time_period_label = self.streaming_data_settings.get_content_item("tasks_time_period_label") + tasks_time_period_label.check_visibility("Streaming data Actions storage time period label is missing") + tasks_time_period_label_text = tasks_time_period_label.get_locator().input_value() + assert tasks_time_period_label_text == "Период хранения данных", \ + f"Unexpected streaming data Actions storage time period label text: {tasks_time_period_label_text}" + + tasks_time_period_value = self.streaming_data_settings.get_content_item("tasks_time_period_value") + tasks_time_period_value.check_visibility("Streaming data Actions storage time period input field is missing") + + tasks_time_period_value_interval = self.streaming_data_settings. \ + get_content_item("tasks_time_period_value_interval") + tasks_time_period_value_interval. \ + check_visibility("Streaming data Actions storage time period interval field is missing") + + + def _check_streaming_data_scheduler_settings_content(self) -> None: + """Проверяет наличие и корректность всех элементов настройки 'Потоковые данные/Параметры планировщика'.""" + + self.streaming_data_scheduler_settings.should_be_toolbar() + + backup_creation_time_label = self.streaming_data_scheduler_settings. \ + get_content_item("backup_creation_time_label") + backup_creation_time_label.check_visibility("Streaming data backup creation time label is missing") + label_text = backup_creation_time_label.get_locator().input_value() + assert label_text == "Время создания резервной копии", \ + "Unexpected streaming data backup creation time label text" + + backup_creation_time_input = self.streaming_data_scheduler_settings. \ + get_content_item("backup_creation_time_input") + backup_creation_time_input.check_visibility("Streaming data backup creation time input field is missing") diff --git a/tests/e2e/test_backup_settings_tab.py b/tests/e2e/test_backup_settings_tab.py new file mode 100644 index 0000000..5ed584b --- /dev/null +++ b/tests/e2e/test_backup_settings_tab.py @@ -0,0 +1,372 @@ +"""Модуль тестов вкладки 'Резервное копирование'. + +Содержит тесты для проверки корректности отображения +и функциональности элементов вкладки настройки времени жизни сеансов. +""" + +from datetime import datetime, timezone +import os +from pathlib import Path +import pytest +from playwright.sync_api import Page +from pages.login_page import LoginPage +from pages.main_page import MainPage +from pages.backup_settings_tab import BackupSettingsTab + + +# @pytest.mark.smoke +class TestBackupSettingsTab: + """Набор тестов для вкладки 'Сеансы/Настройки'. + + Проверяет корректность отображения и функциональность элементов вкладки настройки времени жизни сеансов. + + Тесты покрывают следующие сценарии: + 1. test_backup_settings_tab_content: Тест содержимого вкладки 'Резервное копирование' + 2. test_edit_session_settings: Тест проверки возможности редактирования выбранных полей формы + настройки времени жизни сеансов. + 3. test_edit_session_setting_by_arrow: Тест проверки возможности увеличения/уменьшения значения + выбранного поля формы с помощью стрелочек Вверх/Вниз. + """ + + + @pytest.fixture(scope="function", autouse=True) + def setup(self, browser: Page) -> None: + """Фикстура для подготовки тестового окружения. + + Выполняет: + 1. Авторизацию в системе + 2. Переход на вкладку 'Резервное копирование' через панель навигации + """ + # Авторизация в системе + login_page = LoginPage(browser) + login_page.do_login() + + # Инициализация главной страницы + main_page = MainPage(browser) + + # Проверка и взаимодействие с элементами навигации + main_page.should_be_navigation_panel() + main_page.click_main_navigation_panel_item("Настройки") + main_page.click_subpanel_item("Обслуживание и диагностика") + main_page.click_subpanel_item("Резервное копирование") + + # @pytest.mark.develop + def test_backup_settings_tab_content(self, browser: Page) -> None: + """Тест содержимого вкладки 'Резервное копирование'. + + Проверяет: + 1. Наличие и корректность элементов интерфейса + 2. Соответствие содержимого полей формы данным из БД + """ + + # Инициализация страницы сеансов + backup_settings_tab = BackupSettingsTab(browser) + + # Проверка элементов интерфейса + backup_settings_tab.check_content() + + # запрос текущих установок настройки 'Инвентаризация/Параметры планировщика' + current_settings = {} + cur_settings_response = backup_settings_tab.send_get_api_request("e-cmdb/api/backupcmdb") + if cur_settings_response.status == 200: + response_body = backup_settings_tab.get_response_body(cur_settings_response) + + if response_body: + current_settings = response_body[0].copy() + + # Проверка соответствия для значений настройки 'Инвентаризация/Параметры планировщика' + inventory_scheduler_settings = backup_settings_tab.get_inventory_scheduler_settings_values() + inventory_auto_backup = inventory_scheduler_settings["auto_backup"] + inventory_backup_limitation = inventory_scheduler_settings["backup_limitation"] + + if len(current_settings) != 0 or len(inventory_auto_backup) != 0 or len(inventory_backup_limitation) != 0: + # запрос дефолтных значений настройки 'Инвентаризация/Параметры планировщика' + default_settings = {} + default_settings_response = backup_settings_tab.send_get_api_request("e-cmdb/api/backupcmdb/meta") + if default_settings_response.status == 200: + response_body = backup_settings_tab.get_response_body(default_settings_response) + + if response_body: + default_settings = response_body["fields"].copy() + + expected = current_settings["auto_backup"] if len(current_settings) != 0 else None + if expected is None: + expected = self._get_default_value("auto_backup", default_settings) + assert inventory_auto_backup == expected,\ + f"Actual value {inventory_auto_backup} \ + is not equal expected {expected} for field 'Время создания резервной копии'" + + expected = current_settings["backup_limitation"] if len(current_settings) != 0 else None + if expected is None: + expected = self._get_default_value("backup_limitation", default_settings) + assert inventory_backup_limitation == expected,\ + f"Actual value {inventory_backup_limitation} \ + is not equal expected {expected} for field 'Количество резервных копий'" + + # запрос текущих установок настройки 'Потоковые данные' + current_sd_settings = {} + cur_settings_response = backup_settings_tab.send_get_api_request("e-cmdb/api/backupstreamingdata") + if cur_settings_response.status == 200: + response_body = backup_settings_tab.get_response_body(cur_settings_response) + + if response_body: + current_sd_settings = response_body[0].copy() + + # Проверка соответствия для значений настройки 'Потоковые данные/Параметры планировщика' + streaming_data_scheduler_settings = backup_settings_tab.get_streaming_data_scheduler_settings_values() + sd_auto_backup = streaming_data_scheduler_settings["auto_backup"] + if len(current_sd_settings) != 0 or len(sd_auto_backup) != 0: + # запрос дефолтных значений настройки 'Потоковые данные' + default_sd_settings = {} + default_settings_response = backup_settings_tab.send_get_api_request("e-cmdb/api/backupstreamingdata/meta") + if default_settings_response.status == 200: + response_body = backup_settings_tab.get_response_body(default_settings_response) + + if response_body: + default_sd_settings = response_body["fields"].copy() + + expected = current_sd_settings["auto_backup"] if len(current_settings) != 0 else None + if expected is None: + expected = self._get_default_value("auto_backup", default_sd_settings) + assert sd_auto_backup == expected,\ + f"Actual value {sd_auto_backup} \ + is not equal expected {expected} for field 'Время создания резервной копии'" + + # @pytest.mark.develop + def test_backup_settings_tab_check_backup_copies_amount(self, browser: Page) -> None: + """Тест проверки количества резервных копий.""" + + # TO-DO: Тест проверки правильности времени их создания + + # Инициализация страницы сеансов + backup_settings_tab = BackupSettingsTab(browser) + + # получение текущих установок настройки 'Инвентаризация/Параметры планировщика' + inventory_scheduler_settings = backup_settings_tab.get_inventory_scheduler_settings_values() + #inventory_auto_backup = inventory_scheduler_settings["auto_backup"] + inventory_backup_limitation = int(inventory_scheduler_settings["backup_limitation"]) + + # получение списка резервных копий настройки 'Инвентаризация' + dumps = backup_settings_tab.get_inventory_dumps_list() + + assert inventory_backup_limitation == len(dumps), \ + f"Required to store {inventory_backup_limitation} but {len(dumps)} stores" + + # @pytest.mark.develop + def test_backup_settings_tab_create_copy(self, browser: Page) -> None: + """Тест проверки создания резервных копий.""" + + # Инициализация страницы сеансов + backup_settings_tab = BackupSettingsTab(browser) + + # проверка создания резервной копии для блока 'Инвентаризация' + current_date = datetime.now(timezone.utc) + current_ts = current_date.timestamp() + + backup_settings_tab.create_inventory_copy() + backup_settings_tab.wait_for_timeout(3000) + + dumps_cmdb = backup_settings_tab.get_inventory_dumps_list() + max_ts, _ = self._get_last_dump(dumps_cmdb, "inventory") + assert max_ts - current_ts < 1000, "New inventory backup copy not found" + + # проверка создания резервной копии для блока 'Потоковые данные' + current_date = datetime.now(timezone.utc) + current_ts = current_date.timestamp() + + backup_settings_tab.create_streaming_data_copy() + backup_settings_tab.wait_for_timeout(3000) + + dumps_streaming_data = backup_settings_tab.get_streaming_data_dumps_list() + max_ts, _ = self._get_last_dump(dumps_streaming_data, "streaming_data") + assert max_ts - current_ts < 1000, "New streaming_data backup copy not found" + + # @pytest.mark.develop + def test_backup_settings_tab_check_backup_buttons(self, browser: Page) -> None: + """Тест проверки поведения кнопок управления резервными копиями.""" + + # Инициализация страницы сеансов + backup_settings_tab = BackupSettingsTab(browser) + + dumps_cmdb = backup_settings_tab.get_inventory_dumps_list() + max_ts, last_dump = self._get_last_dump(dumps_cmdb, "inventory") + + backup_settings_tab.select_inventory_dump(last_dump) + + backup_settings_tab.should_be_inventory_download_button() + is_disabled = backup_settings_tab.check_inventory_restore_copy_button_disabling() + assert not is_disabled, "Inventory button to restore copy should be enabled" + + backup_settings_tab.clear_inventory_dump_selection() + backup_settings_tab.should_be_inventory_upload_button() + is_disabled = backup_settings_tab.check_inventory_restore_copy_button_disabling() + assert is_disabled, "Inventory button to restore copy should be disabled" + + dumps_streaming_data = backup_settings_tab.get_streaming_data_dumps_list() + max_ts, last_dump = self._get_last_dump(dumps_streaming_data, "streaming_data") + + backup_settings_tab.select_streaming_data_dump(last_dump) + + backup_settings_tab.should_be_streaming_data_download_button() + is_disabled = backup_settings_tab.check_streaming_data_restore_copy_button_disabling() + assert not is_disabled, "Streaming data button to restore copy should be enabled" + + backup_settings_tab.clear_streaming_data_dump_selection() + backup_settings_tab.should_be_streaming_data_upload_button() + is_disabled = backup_settings_tab.check_streaming_data_restore_copy_button_disabling() + assert is_disabled, "Streaming data button to restore copy should be disabled" + + # @pytest.mark.develop + def test_backup_settings_tab_check_download_copy(self, browser: Page) -> None: + """Тест проверки возможности загрузки резервной копии.""" + + # TO-DO: Тест проверки возможности загрузки резервной копии для потоковых данных + + # Инициализация страницы сеансов + backup_settings_tab = BackupSettingsTab(browser) + + path_to_download = Path.home() / "Downloads" + + dumps_cmdb = backup_settings_tab.get_inventory_dumps_list() + max_ts, last_dump = self._get_last_dump(dumps_cmdb, "inventory") + + backup_settings_tab.download_inventory_copy(last_dump, path_to_download) + + downloaded = str(path_to_download) + "/" + last_dump + + assert os.path.exists(downloaded), f"The file '{downloaded}' not found" + assert os.path.getsize(downloaded) > 0, f"The file '{downloaded}' is empty" + + os.remove(downloaded) + + @pytest.mark.develop + def test_backup_settings_tab_set_inventory_scheduler_settings(self, browser: Page) -> None: + """Тест проверки возможности изменения значения настроек 'Инвентаризация/Параметры планировщика'.""" + + # Инициализация страницы сеансов + backup_settings_tab = BackupSettingsTab(browser) + + backup_settings_tab.click_edit_button() + + backup_settings_tab.input_inventory_backup_creation_time("0 0 22 * * 7") + + backup_settings_tab.input_inventory_backups_number("6") + backup_settings_tab.decrease_inventory_backups_number() + backup_settings_tab.increase_inventory_backups_number() + + inventory_scheduler_settings = backup_settings_tab.get_inventory_scheduler_settings_values() + inventory_auto_backup = inventory_scheduler_settings["auto_backup"] + inventory_backup_limitation = inventory_scheduler_settings["backup_limitation"] + assert inventory_auto_backup == "0 0 22 * * 7", \ + f"Actual value '{inventory_auto_backup}' \ + is not equal expected '0 0 22 * * 7' for field 'Время создания резервной копии'" + assert inventory_backup_limitation == "6", \ + f"Actual value '{inventory_backup_limitation}' \ + is not equal expected '6' for field 'Количество резервных копий'" + + # temporarily until fix 1280 + backup_settings_tab.click_cancel_button() + + # @pytest.mark.develop + def test_backup_settings_tab_set_streaming_data_settings(self, browser: Page) -> None: + """Тест проверки возможности изменения значения настроек 'Потоковые данные'.""" + + # Инициализация страницы сеансов + backup_settings_tab = BackupSettingsTab(browser) + + backup_settings_tab.click_edit_button() + + backup_settings_tab.input_audit_time_period("3", "месяц") + backup_settings_tab.increase_audit_time_period() + backup_settings_tab.decrease_audit_time_period() + + backup_settings_tab.input_logs_time_period("3", "месяц") + backup_settings_tab.increase_logs_time_period() + backup_settings_tab.decrease_logs_time_period() + + backup_settings_tab.input_metrics_time_period("3", "месяц") + backup_settings_tab.increase_metrics_time_period() + backup_settings_tab.decrease_metrics_time_period() + + backup_settings_tab.input_syslog_time_period("3", "месяц") + backup_settings_tab.increase_syslog_time_period() + backup_settings_tab.decrease_syslog_time_period() + + backup_settings_tab.input_tasks_time_period("3", "месяц") + backup_settings_tab.increase_tasks_time_period() + backup_settings_tab.decrease_tasks_time_period() + + backup_settings_tab.input_streaming_data_backup_creation_time("0 0 22 * * 7") + + streaming_data_settings = backup_settings_tab.get_streaming_data_settings_values() + data_limitation_default = streaming_data_settings["data_limitation_default"] + assert data_limitation_default == "3", \ + f"Actual value '{data_limitation_default}' is not equal expected '3' for category 'Аудит'" + interval_limitation_default = streaming_data_settings["interval_limitation_default"] + assert interval_limitation_default == "месяц", \ + f"Actual value '{interval_limitation_default}' is not equal expected 'месяц' for category 'Аудит'" + data_limitation_logs = streaming_data_settings["data_limitation_logs"] + assert data_limitation_logs == "3", \ + f"Actual value '{data_limitation_logs}' is not equal expected '3' for category 'Логи'" + interval_limitation_logs = streaming_data_settings["interval_limitation_logs"] + assert interval_limitation_logs == "месяц", \ + f"Actual value '{interval_limitation_logs}' is not equal expected 'месяц' for category 'Логи'" + data_limitation_metrics = streaming_data_settings["data_limitation_metrics"] + assert data_limitation_metrics == "3", \ + f"Actual value '{data_limitation_metrics}' is not equal expected '3' for category 'Метрики'" + interval_limitation_metrics = streaming_data_settings["interval_limitation_metrics"] + assert interval_limitation_metrics == "месяц", \ + f"Actual value '{interval_limitation_metrics}' is not equal expected 'месяц' for category 'Метрики'" + data_limitation_syslog = streaming_data_settings["data_limitation_syslog"] + assert data_limitation_syslog == "3", \ + f"Actual value '{data_limitation_syslog}' is not equal expected '3' for category 'Системный лог'" + interval_limitation_syslog = streaming_data_settings["interval_limitation_syslog"] + assert interval_limitation_syslog == "месяц", \ + f"Actual value '{interval_limitation_syslog}' is not equal expected 'месяц' for category 'Системный лог'" + data_limitation_tasks = streaming_data_settings["data_limitation_tasks"] + assert data_limitation_tasks == "3", \ + f"Actual value '{data_limitation_tasks}' is not equal expected '3' for category 'Действия'" + interval_limitation_tasks = streaming_data_settings["interval_limitation_tasks"] + assert interval_limitation_tasks == "месяц", \ + f"Actual value '{interval_limitation_tasks}' is not equal expected 'месяц' for category 'Действия'" + + streaming_data_scheduler_settings = backup_settings_tab.get_streaming_data_scheduler_settings_values() + streaming_data_auto_backup = streaming_data_scheduler_settings["auto_backup"] + assert streaming_data_auto_backup == "0 0 22 * * 7", \ + f"Actual value '{streaming_data_auto_backup}' \ + is not equal expected '0 0 22 * * 7' for field 'Потоковые данные Время создания резервной копии'" + + # temporarily until fix 1280 + backup_settings_tab.click_cancel_button() + + # Вспомогательные функции + def _get_default_value(self, setting_name: str, default_settings: dict) -> str| None: + """ Выбор дефолтного значения из списка по его имени """ + + for setting in default_settings: + if setting["name"] == setting_name: + return setting["default"] + return None + + def _get_last_dump(self, dumps_list: list[str],settings_type : str) -> list: + """ Выбор последнего по времени дампа из списка. + Возвращает timestamp и имя дампа. + """ + + dumps = {} + ret_values = [] + for dump in dumps_list: + if settings_type == "inventory": + dump_date = dump.replace("dump_cmdb_", "").replace(".dump", "") + date_object = datetime.strptime(dump_date, "%Y-%m-%d_%H_%M_%S") + elif settings_type == "streaming_data": + dump_date = dump.replace("monitoring_backup_", "").replace(".zip", "") + date_object = datetime.strptime(dump_date, "%Y-%m-%d_%H-%M-%S") + else: + assert False, "Unsupported backup setting type" + ts = date_object.timestamp() + dumps[ts] = dump + max_ts = sorted(dumps.keys())[-1] + ret_values.append(max_ts) + ret_values.append(dumps[max_ts]) + return ret_values