diff --git a/components_derived/selection_bar_component.py b/components_derived/selection_bar_component.py index c5f5741..8c8ae80 100644 --- a/components_derived/selection_bar_component.py +++ b/components_derived/selection_bar_component.py @@ -153,7 +153,7 @@ class SelectionBarComponent(BaseComponent): self.selection_bar_locator.click(force=True) # Ждем появления выпадающего списка - self.page.locator(SelectionBarLocators.LIST_ACTIVE).wait_for() + self.page.locator(SelectionBarLocators.LIST_ACTIVE).wait_for(state="attached") # self.wait_for_timeout(1500) def select_value(self, name: str) -> None: diff --git a/pages/backup_settings_tab.py b/pages/backup_settings_tab.py index c5863c5..a3fbe44 100644 --- a/pages/backup_settings_tab.py +++ b/pages/backup_settings_tab.py @@ -16,7 +16,6 @@ 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): """Класс для работы с вкладкой настройки резервного копирования. @@ -81,6 +80,12 @@ class BackupSettingsTab(BasePage): self.toolbar.check_button_visibility("save") self.toolbar.get_button_by_name("save").click() + + 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обновлены') + self.alert.check_alert_absence('Параметры успешно\nобновлены') def clear_inventory_dump_selection(self) -> None: """Удаление ранее выбранного имени дампа""" @@ -147,6 +152,33 @@ class BackupSettingsTab(BasePage): download.save_as(str(path_to_download) + "/" + download.suggested_filename) + def download_streaming_data_copy(self, dump: str, path_to_download: str) -> None: + """Скачать резервную копию Потоковых данных.""" + + wait_download_timeout = 3*60000 + + is_set = self.page.evaluate("window.__PLAYWRIGHT__") + assert is_set, "'window.__PLAYWRIGHT__' should be set to True" + + assert path_to_download.exists(), f"{path_to_download} does not exist" + + 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) + + 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") + + with self.page.expect_download(timeout=wait_download_timeout) 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: """Возвращает текущее значение полей настроек 'Инвентаризация/Параметры планировщика'. diff --git a/tests/e2e/test_backup_settings_tab.py b/tests/e2e/test_backup_settings_tab.py index 5ed584b..fe44038 100644 --- a/tests/e2e/test_backup_settings_tab.py +++ b/tests/e2e/test_backup_settings_tab.py @@ -16,16 +16,9 @@ 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: Тест проверки возможности увеличения/уменьшения значения - выбранного поля формы с помощью стрелочек Вверх/Вниз. + Проверяет корректность отображения и функциональность элементов вкладки 'Резервное копирование'. """ @@ -37,6 +30,9 @@ class TestBackupSettingsTab: 1. Авторизацию в системе 2. Переход на вкладку 'Резервное копирование' через панель навигации """ + + browser.add_init_script("window.__PLAYWRIGHT__ = true;") + # Авторизация в системе login_page = LoginPage(browser) login_page.do_login() @@ -66,20 +62,15 @@ class TestBackupSettingsTab: backup_settings_tab.check_content() # запрос текущих установок настройки 'Инвентаризация/Параметры планировщика' - current_settings = {} + expected_inventory_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: + expected_inventory_settings = response_body[0].copy() + + if len(expected_inventory_settings) == 0: # запрос дефолтных значений настройки 'Инвентаризация/Параметры планировщика' default_settings = {} default_settings_response = backup_settings_tab.send_get_api_request("e-cmdb/api/backupcmdb/meta") @@ -88,34 +79,42 @@ class TestBackupSettingsTab: 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) + expected_inventory_settings["auto_backup"] = self._get_default_value("auto_backup", + default_settings) + expected_inventory_settings["backup_limitation"] = self._get_default_value("backup_limitation", + default_settings) + + # Проверка соответствия для значений настройки 'Инвентаризация/Параметры планировщика' + inventory_scheduler_settings = backup_settings_tab.get_inventory_scheduler_settings_values() + inventory_auto_backup = inventory_scheduler_settings.get("auto_backup") + inventory_backup_limitation = inventory_scheduler_settings.get("backup_limitation") + + if inventory_auto_backup: + expected = expected_inventory_settings["auto_backup"] 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) + else: + assert False, "No value setting for field 'Время создания резервной копии'" + + if inventory_backup_limitation: + expected = expected_inventory_settings["backup_limitation"] assert inventory_backup_limitation == expected,\ f"Actual value {inventory_backup_limitation} \ is not equal expected {expected} for field 'Количество резервных копий'" + else: + assert False, "No value setting for field 'Количество резервных копий'" # запрос текущих установок настройки 'Потоковые данные' - current_sd_settings = {} + expected_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: + expected_sd_settings = response_body[0].copy() + + if len(expected_sd_settings) == 0: # запрос дефолтных значений настройки 'Потоковые данные' default_sd_settings = {} default_settings_response = backup_settings_tab.send_get_api_request("e-cmdb/api/backupstreamingdata/meta") @@ -124,19 +123,60 @@ class TestBackupSettingsTab: if response_body: default_sd_settings = response_body["fields"].copy() + expected_sd_settings["auto_backup"] = self._get_default_value("auto_backup", default_sd_settings) + expected_sd_settings["data_limitation_default"] = self._get_default_value( + "data_limitation_default", default_sd_settings) + expected_sd_settings["interval_limitation_default"] = self._get_default_value( + "interval_limitation_default", default_sd_settings) + + expected_sd_settings["data_limitation_logs"] = self._get_default_value("data_limitation_logs", + default_sd_settings) + expected_sd_settings["interval_limitation_logs"] = self._get_default_value( + "interval_limitation_logs", default_sd_settings) + expected_sd_settings["data_limitation_metrics"] = self._get_default_value("data_limitation_metrics", + default_sd_settings) + expected_sd_settings["interval_limitation_metrics"] = self._get_default_value( + "interval_limitation_metrics", + default_sd_settings) + expected_sd_settings["data_limitation_syslog"] = self._get_default_value("data_limitation_syslog", + default_sd_settings) + expected_sd_settings["interval_limitation_syslog"] = self._get_default_value( + "interval_limitation_syslog", default_sd_settings) + expected_sd_settings["data_limitation_tasks"] = self._get_default_value("data_limitation_tasks", + default_sd_settings) + expected_sd_settings["interval_limitation_tasks"] = self._get_default_value( + "interval_limitation_tasks", default_sd_settings) + - 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) + # Проверка соответствия для значений настроек 'Потоковые данные и Параметры планировщика' + dates = {"day":"ДЕНЬ", "hour":"ЧАС", "month":"МЕСЯЦ", "year":"ГОД"} + streaming_data_scheduler_settings = backup_settings_tab.get_streaming_data_scheduler_settings_values() + sd_auto_backup = streaming_data_scheduler_settings.get("auto_backup") + streaming_data_settings = backup_settings_tab.get_streaming_data_settings_values() + + if sd_auto_backup: + expected = expected_sd_settings["auto_backup"] assert sd_auto_backup == expected,\ f"Actual value {sd_auto_backup} \ is not equal expected {expected} for field 'Время создания резервной копии'" + else: + assert False, "No value setting for field 'Время создания резервной копии' streaming data" + + settings_list = streaming_data_settings.keys() + for setting in settings_list: + expected = expected_sd_settings[setting] + if dates.get(expected): + expected = dates[expected] + actual = streaming_data_settings[setting] + assert actual == expected,\ + f"Actual value {actual} is not equal expected {expected} for field '{setting}'" # @pytest.mark.develop def test_backup_settings_tab_check_backup_copies_amount(self, browser: Page) -> None: """Тест проверки количества резервных копий.""" # TO-DO: Тест проверки правильности времени их создания + # To-DO: Ограничение на количество копий для потоковых данных? # Инициализация страницы сеансов backup_settings_tab = BackupSettingsTab(browser) @@ -148,8 +188,9 @@ class TestBackupSettingsTab: # получение списка резервных копий настройки 'Инвентаризация' dumps = backup_settings_tab.get_inventory_dumps_list() + print(dumps) - assert inventory_backup_limitation == len(dumps), \ + assert inventory_backup_limitation >= len(dumps), \ f"Required to store {inventory_backup_limitation} but {len(dumps)} stores" # @pytest.mark.develop @@ -217,10 +258,8 @@ class TestBackupSettingsTab: 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: Тест проверки возможности загрузки резервной копии для потоковых данных + def test_backup_settings_tab_check_inventory_download_copy(self, browser: Page) -> None: + """Тест проверки возможности загрузки резервной копии 'Инвентаризация'.""" # Инициализация страницы сеансов backup_settings_tab = BackupSettingsTab(browser) @@ -239,7 +278,28 @@ class TestBackupSettingsTab: os.remove(downloaded) - @pytest.mark.develop + #@pytest.mark.develop + def test_backup_settings_tab_check_streaming_data_download_copy(self, browser: Page) -> None: + """Тест проверки возможности загрузки резервной копии 'Потоковые данные'.""" + + # Инициализация страницы сеансов + backup_settings_tab = BackupSettingsTab(browser) + + path_to_download = Path.home() / 'Documents' + + dumps_cmdb = backup_settings_tab.get_streaming_data_dumps_list() + max_ts, last_dump = self._get_last_dump(dumps_cmdb, "streaming_data") + + backup_settings_tab.download_streaming_data_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: """Тест проверки возможности изменения значения настроек 'Инвентаризация/Параметры планировщика'.""" @@ -339,6 +399,52 @@ class TestBackupSettingsTab: # temporarily until fix 1280 backup_settings_tab.click_cancel_button() + # @pytest.mark.develop + @pytest.mark.skip(reason="Временно пока работает неправильно") + def test_backup_settings_tab_check_auto_copy_creation(self, browser: Page) -> None: + """Тест проверки создания резервных копий в автоматическом режиме на примере блока 'Инвентаризация'.""" + + # делать backup один раз в минуту + requested_creation_time = "* */1 * * * *" + + # Инициализация страницы сеансов + backup_settings_tab = BackupSettingsTab(browser) + + current_setings = backup_settings_tab.get_inventory_scheduler_settings_values() + + current_creation_time = current_setings.get("auto_backup") + assert current_creation_time, "No creation time value for 'Inventory' block" + + current_backup_limitation = current_setings.get("backup_limitation") + assert current_backup_limitation, "No backup limitation value for 'Inventory' block" + time_to_wait = int(current_backup_limitation) + 1 + + backup_settings_tab.click_edit_button() + + backup_settings_tab.input_inventory_backup_creation_time(requested_creation_time) + backup_settings_tab.click_save_button() + + current_date = datetime.now(timezone.utc) + current_ts = current_date.timestamp() + + backup_settings_tab.wait_for_timeout(time_to_wait*60000) + + backup_settings_tab.click_edit_button() + + backup_settings_tab.input_inventory_backup_creation_time(current_creation_time) + backup_settings_tab.click_save_button() + + dumps_cmdb = backup_settings_tab.get_inventory_dumps_list() + dumps_amount = len(dumps_cmdb) + assert dumps_amount == int(current_backup_limitation), \ + f"Should be {current_backup_limitation} dumps but got {dumps_amount}" + + for dump in dumps_cmdb: + dump_date = dump.replace("dump_cmdb_", "").replace(".dump", "") + date_object = datetime.strptime(dump_date, "%Y-%m-%d_%H_%M_%S") + ts = date_object.timestamp() + assert current_ts < ts, f"Old backup copy {dump} in backups list" + # Вспомогательные функции def _get_default_value(self, setting_name: str, default_settings: dict) -> str| None: """ Выбор дефолтного значения из списка по его имени """ diff --git a/tests/e2e/users/test_edit_user.py b/tests/e2e/users/test_edit_user.py index 480ce38..e93a293 100644 --- a/tests/e2e/users/test_edit_user.py +++ b/tests/e2e/users/test_edit_user.py @@ -167,6 +167,8 @@ class TestUsersTabEditUser: if len(new_password) == 0: assert False, "Unsuccessful password reset" + ut.close_edit_user_window(user_data["name"]) + mp.do_logout() new_lp = LoginPage(browser) new_lp.do_login(username=user_data["name"], password=new_password)