diff --git a/components/toolbar_component.py b/components/toolbar_component.py index 862366b..d159b41 100644 --- a/components/toolbar_component.py +++ b/components/toolbar_component.py @@ -240,7 +240,7 @@ class ToolbarComponent(BaseComponent): message (str): Сообщение об ошибке если тулбар не виден """ - locator = self.get_locator(locator).filter(has_text=self.title) + locator = self.get_locator(locator).filter(has_text=self.title).first expect(locator).to_be_visible(), message def check_button_visibility(self, name: str) -> None: diff --git a/components_derived/modal_send_test_email.py b/components_derived/modal_send_test_email.py new file mode 100644 index 0000000..cd2de70 --- /dev/null +++ b/components_derived/modal_send_test_email.py @@ -0,0 +1,109 @@ +"""Модуль modal_send_test_email содержит класс для работы с модальным окном для посылки тестового E-mail на +базе настроек вкладки 'Уведомления/E-mail'. + +Класс SendTestEmailModalWindow наследует базовый функционал ModalWindowComponent +и реализует методы просмотра модального окна отображения задачи. +""" + +from playwright.sync_api import Page +from tools.logger import get_logger +from locators.modal_window_locators import ModalWindowLocators +from elements.text_input_element import TextInput +from components.modal_window_component import ModalWindowComponent +from components.alert_component import AlertComponent + +logger = get_logger("SEND_TEST_EMAIL_MODAL_WINDOW") + + +class SendTestEmailModalWindow(ModalWindowComponent): + """Модальное окно для посылки тестового E-mail. + + Наследует ModalWindowComponent и добавляет функционал для: + 1. Инициализации модального окна + 2. Закрытия модального окна через тулбар + 3. Проверки содержимого модального окна + """ + + def __init__(self, page: Page): + """Инициализирует элементы формы модального окна отображения задачи.""" + super().__init__(page) + + + window_locator = page.locator(ModalWindowLocators.MODAL_WINDOW) + + self.window_title_locator = window_locator.locator("//div[@class='v-toolbar__title']") + self.add_toolbar_title("Тест") + + # Настройка кнопки закрытия + toolbar_button_close_locator = window_locator.locator("//button[@data-testid='E_MAIL_CARD__btn__close']") + self.add_toolbar_button(toolbar_button_close_locator, "close") + + # Поле ввода адреса + elements_locators = self.get_input_fields_locators(window_locator) + loc = elements_locators.get("E-mail").locator("div.v-text-field__slot > input") + email_input = TextInput(page, loc, "email_input") + self.add_content_item("email_input", email_input) + + # Добавление кнопок действий + locator_button_test = window_locator.locator("//button[@data-testid='E_MAIL_CARD__footer_btn__test']") + self.add_button(locator_button_test, "test_button") + + locator_button_close = window_locator.locator("//button[@data-testid='E_MAIL_CARD__footer_btn__close']") + self.add_button(locator_button_close, "close_button") + + self.alert = AlertComponent(page) + + # Действия: + def close_by_toolbar_button(self): + """Закрывает окно кнопкой на тулбаре.""" + + self.click_toolbar_close_button() + + def close(self): + """Закрывает окно кнопкой на 'Закрыть'.""" + + close_button = self.get_button_by_name("close_button") + close_button.click() + + def click_test_button(self): + """Отсылка письма по указанному адресу нажатием кнопки 'Тест'.""" + + close_button = self.get_button_by_name("test_button") + close_button.click() + + def input_email(self, address: str) -> None: + """Заполнение поля 'E-MAIL'.""" + + email_input_field = self.get_content_item("email_input") + email_input_field.clear() + email_input_field.input_value(address) + + # Проверки: + def check_content(self) -> None: + """Проверяет наличие элементов окна. + """ + + self.check_by_window_title() + self.check_toolbar_button_visibility("close") + self.check_toolbar_button_tooltip("close", "Закрыть") + + email_input_field = self.get_content_item("email_input") + email_input_field.check_visibility("E-mail input field is missing") + email_input_field.check_editable_input("E-mail input field should be editable") + + + self.check_button_visibility("test_button") + self.check_button_visibility("close_button") + + def should_be_success_alert(self) -> None: + """Проверяет наличие сообщения об успешной отправке тестового сообщения. + + Raises: + AssertionError: Если тулбар отсутствует. + """ + + 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отправлено\n') + self.alert.check_alert_absence('\nТестовое сообщение\nотправлено\n') diff --git a/components_derived/selection_bar_component.py b/components_derived/selection_bar_component.py index 471138b..9cb81a2 100644 --- a/components_derived/selection_bar_component.py +++ b/components_derived/selection_bar_component.py @@ -161,7 +161,6 @@ class SelectionBarComponent(BaseComponent): self.selected_values_list.click_item_with_text(name) # Проверки: - def check_field_error_highlighted(self, field_name: str, field_locator: str) -> None: """Проверяет, что поле подсвечено цветом ошибки (валидация не пройдена). @@ -213,3 +212,40 @@ class SelectionBarComponent(BaseComponent): assert not has_error, f"Field '{field_name}' is highlighted with error" logger.info(f"Field '{field_name}' correctly has no error highlighting") + + def check_field_visibility(self, msg: str) -> None: + """Проверка видимости элемента на странице. + + Args: + msg: сообщение об ошибке при неудачной проверке. + + Raises: + AssertionError: если элемент не виден на странице. + """ + + self.check_visibility(self.selection_bar_locator, msg) + + + def should_be_clear_selection_button(self) -> None: + """Проверяет наличие кнопки отмены выбранного значения. + + Raises: + AssertionError: Если кнопка отсутствует. + """ + + clear_button_locator = self.selection_bar_locator.locator( + SelectionBarLocators.CLEAR_SELECTION_BUTTON + ) + expect(clear_button_locator).to_be_visible(), "Clear selection button is missing" + + def should_be_open_list_button(self) -> None: + """Проверяет наличие кнопки раскрытия списка параметров. + + Raises: + AssertionError: Если кнопка отсутствует. + """ + + open_list_button_locator = self.selection_bar_locator.locator( + SelectionBarLocators.OPEN_PARAMETERS_LIST_BUTTON + ) + expect(open_list_button_locator).to_be_visible(), "Open parameters list button is missing" diff --git a/components_derived/settings_form_component.py b/components_derived/settings_form_component.py index 59ec226..ec7ddd6 100644 --- a/components_derived/settings_form_component.py +++ b/components_derived/settings_form_component.py @@ -94,4 +94,4 @@ class SettingsFormComponent(BaseComponent): """ self.toolbar.check_toolbar_presence_by_locator_and_title(SettingsFormLocators.SETTTINGS_FORM_SCROLL_CONTAINER, - "Session settings form toolbar is missing") + "Settings form toolbar is missing") diff --git a/locators/settings_form_locators.py b/locators/settings_form_locators.py index fc57f85..d59fc1a 100644 --- a/locators/settings_form_locators.py +++ b/locators/settings_form_locators.py @@ -19,6 +19,7 @@ class SettingsFormLocators: SETTTINGS_FORM_TITLE = f"{SETTTINGS_FORM_SCROLL_CONTAINER}//div[contains(@class, 'v-toolbar__title')]" SETTINGS_FORM_INPUT_FORM_CONTAINER = "//nav[contains(@class, 'active v-toolbar')]/following-sibling::div" + SETTINGS_FORM_SMS_INPUT_FORM_CONTAINER = "//nav[contains(@class, 'active v-toolbar')]/../following-sibling::div" SETTINGS_FORM_INPUT_FIELD = "div.v-text-field__slot > input" SETTINGS_FORM_INPUT_VALUE_SUFFIX = ".v-text-field__suffix" diff --git a/pages/email_notifications_settings_tab.py b/pages/email_notifications_settings_tab.py new file mode 100644 index 0000000..b89fda9 --- /dev/null +++ b/pages/email_notifications_settings_tab.py @@ -0,0 +1,477 @@ +"""Модуль вкладки настройки E-mail уведомлений. + +Содержит класс SMSNotificationsSettings для работы с вкладкой настройки E-mail уведомлений. +Позволяет проверять состояние и взаимодействовать с элементами вкладки. +""" + +import re +from playwright.sync_api import Page +from locators.settings_form_locators import SettingsFormLocators +from elements.text_input_element import TextInput +from elements.text_element import Text +from elements.tooltip_button_element import TooltipButton +from elements.checkbox_element import Checkbox +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 components_derived.modal_send_test_email import SendTestEmailModalWindow +from pages.base_page import BasePage + + +class EmailNotificationsSettingsTab(BasePage): + """Класс для работы с вкладкой настройки E-mail уведомлений. + + Предоставляет методы для взаимодействия с вкладкой настройки E-mail уведомлений. + + Args: + page: Экземпляр страницы Playwright. + """ + + def __init__(self, page: Page) -> None: + """Инициализирует компоненты вкладки настройки E-mail уведомлений.""" + + super().__init__(page) + + toolbar_button_1 = self.page.get_by_role("navigation").filter( + has_text=re.compile("e-mail")).get_by_role("button").nth(0) + toolbar_button_2 = self.page.get_by_role("navigation").filter( + has_text=re.compile("e-mail")).get_by_role("button").nth(1) + + self.toolbar = ToolbarComponent(page, "e-mail") + + self.toolbar.add_tooltip_button(toolbar_button_1, "edit") + self.toolbar.add_tooltip_button(toolbar_button_1, "save") + self.toolbar.add_tooltip_button(toolbar_button_2, "cancel") + + # Форма для отображения/редактирования общих полей настроек + self.common_settings = SettingsFormComponent(page) + self.common_settings.add_toolbar_title(" Общие ") + + container_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Общие ").locator("//following-sibling::div") + self.common_input_fields_locators = self.common_settings.get_input_fields_locators(container_locator) + + loc = self.common_input_fields_locators.get("Сервер") + loc_server_input = loc.locator(SettingsFormLocators.SETTINGS_FORM_INPUT_FIELD).first + server_setting_input = TextInput(page, loc_server_input, "server_setting_input") + self.common_settings.add_content_item("server_setting_input", server_setting_input) + + loc = self.common_input_fields_locators.get("Порт") + loc_port_input = loc.locator(SettingsFormLocators.SETTINGS_FORM_INPUT_FIELD).first + port_setting_input = TextInput(page, loc_port_input, "port_setting_input") + self.common_settings.add_content_item("port_setting_input", port_setting_input) + + loc = self.common_input_fields_locators.get("Отправитель") + loc_sender_input = loc.locator(SettingsFormLocators.SETTINGS_FORM_INPUT_FIELD).first + sender_setting_input = TextInput(page, loc_sender_input, "sender_setting_input") + self.common_settings.add_content_item("sender_setting_input", sender_setting_input) + + # Метка "Активировать" + label_activate_locator = container_locator.locator("//label").get_by_text("Активировать") + label_activate = Text(page, label_activate_locator, "checkbox_activate_label") + self.common_settings.add_content_item("checkbox_activate_label", label_activate) + + # Чекбокс "Активировать" + checkbox_activate = Checkbox(page, + label_activate_locator.locator("../..").get_by_role("checkbox"), + "activate" + ) + self.common_settings.add_content_item("checkbox_activate", checkbox_activate) + + # Форма для отображения/редактирования общих настроек TLS + self.tls_settings = SettingsFormComponent(page) + self.tls_settings.add_toolbar_title(" TLS ") + + container_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" TLS ").locator("//following-sibling::div") + self.tls_input_fields_locators = self.tls_settings.get_input_fields_locators(container_locator) + + loc = self.tls_input_fields_locators.get("Использовать TLS-туннель") + self.tls_settings.add_content_item("tunnel_setting_selector", SelectionBarComponent(page, loc)) + + # Метка "Принимать самоподписанные сертификаты" + label_accept_certificates_locator = container_locator. \ + locator("//label").get_by_text("Принимать самоподписанные сертификаты") + label_accept_certificates = Text(page, label_accept_certificates_locator, "checkbox_accept_certificates_label") + self.tls_settings.add_content_item("checkbox_accept_certificates_label", label_accept_certificates) + + # Чекбокс "Принимать самоподписанные сертификаты" + checkbox_accept_certificates = Checkbox(page, + label_accept_certificates_locator.locator("../..").get_by_role("checkbox"), + "accept_certificates" + ) + self.tls_settings.add_content_item("checkbox_accept_certificates", checkbox_accept_certificates) + + # Форма для отображения/редактирования полей настроек аутентификации + self.auth_settings = SettingsFormComponent(page) + self.auth_settings.add_toolbar_title(" Аутентификация ") + + container_locator = self.page.locator("//nav[contains(@class, 'active v-toolbar')]"). \ + filter(has_text=" Аутентификация ").locator("//following-sibling::div") + self.auth_input_fields_locators = self.auth_settings.get_input_fields_locators(container_locator) + + loc = self.auth_input_fields_locators.get("Метод авторизации") + self.auth_settings.add_content_item("auth_method_setting_selector", SelectionBarComponent(page, loc)) + + loc = self.auth_input_fields_locators.get("Имя пользователя") + loc_user_input = loc.locator(SettingsFormLocators.SETTINGS_FORM_INPUT_FIELD).first + user_setting_input = TextInput(page, loc_user_input, "user_setting_input") + self.auth_settings.add_content_item("user_setting_input", user_setting_input) + + loc = self.auth_input_fields_locators.get("Пароль") + loc_password_input = loc.locator(SettingsFormLocators.SETTINGS_FORM_INPUT_FIELD).first + password_setting_input = TextInput(page, loc_password_input, "password_password_input") + self.auth_settings.add_content_item("password_setting_input", password_setting_input) + + loc = self.auth_input_fields_locators.get("Домен") + loc_domain_input = loc.locator(SettingsFormLocators.SETTINGS_FORM_INPUT_FIELD).first + domain_setting_input = TextInput(page, loc_domain_input, "domain_setting_input") + self.auth_settings.add_content_item("domain_setting_input", domain_setting_input) + + loc = self.auth_input_fields_locators.get("Рабочая станция") + loc_workstation_input = loc.locator(SettingsFormLocators.SETTINGS_FORM_INPUT_FIELD).first + workstation_setting_input = TextInput(page, loc_workstation_input, "workstation_setting_input") + self.auth_settings.add_content_item("workstation_setting_input", workstation_setting_input) + + # Кнопка 'Тест' + self.test_button = TooltipButton(page, + page.locator(SettingsFormLocators.SETTTINGS_FORM_SCROLL_CONTAINER).\ + get_by_role("button", name='Тест'), + "test_button") + + self.alert = AlertComponent(page) + + # Действия: + def check_checkbox_activate(self): + """Включает чек-бокс Активировать.""" + + self.common_settings.get_content_item("checkbox_activate").check(force=True) + + def uncheck_checkbox_activate(self): + """Выключает чек-бокс Активировать.""" + + self.common_settings.get_content_item("checkbox_activate").uncheck(force=True) + + def check_checkbox_accept_certificates(self): + """Включает чек-бокс Принимать самоподписанные сертификаты.""" + + self.tls_settings.get_content_item("checkbox_accept_certificates").check(force=True) + + def uncheck_checkbox_accept_certificates(self): + """Выключает чек-бокс Принимать самоподписанные сертификаты.""" + + self.tls_settings.get_content_item("checkbox_accept_certificates").uncheck(force=True) + + 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 click_test_button(self) -> SendTestEmailModalWindow: + """Нажатие кнопки 'Тест' в форме ввода настроек.""" + + self.should_be_test_button() + self.test_button.click() + return SendTestEmailModalWindow(self.page) + + def clear_auth_method_settings(self) -> None: + """Удаление ранее выбранных значений""" + + auth_method_selector = self.auth_settings.get_content_item("auth_method_setting_selector") + auth_method_selector.clear_selections() + + def clear_tls_tunnel_settings(self) -> None: + """Удаление ранее выбранных значений""" + + tls_tunnel_selector = self.tls_settings.get_content_item("tunnel_setting_selector") + tls_tunnel_selector.clear_selections() + + def get_auth_settings_values(self) -> dict: + """Возвращает текущее значение полей настроек 'Аутентификация'. + + Returns: + dict : Текущее значение полей настроек 'Аутентификация'. + """ + + values = {} + + auth_method_selector = self.auth_settings.get_content_item("auth_method_setting_selector") + if auth_method_selector: + val = auth_method_selector.get_selected_values() + values.update({"Метод авторизации": val[0]}) + else: + values.update({"Метод авторизации": ""}) + + field = self.auth_settings.get_content_item("user_setting_input") + values.update({"Имя пользователя": field.get_input_value().strip()}) + + field = self.auth_settings.get_content_item("password_setting_input") + values.update({"Пароль": field.get_input_value().strip()}) + + field = self.auth_settings.get_content_item("domain_setting_input") + values.update({"Домен": field.get_input_value().strip()}) + + field = self.auth_settings.get_content_item("workstation_setting_input") + values.update({"Рабочая станция": field.get_input_value().strip()}) + + return values + + def get_common_settings_values(self) -> dict: + """Возвращает текущее значение полей настроек 'Общие'. + + Returns: + dict : Текущее значение полей настроек 'Общие'. + """ + + values = {} + field = self.common_settings.get_content_item("server_setting_input") + values.update({"Сервер": field.get_input_value().strip()}) + + field = self.common_settings.get_content_item("port_setting_input") + values.update({"Порт": field.get_input_value().strip()}) + + field = self.common_settings.get_content_item("sender_setting_input") + values.update({"Отправитель": field.get_input_value().strip()}) + + return values + + def get_tls_tunnel_setting_value(self) -> str | None: + """Возвращает текущее значение поля 'Использовать TLS-туннель'""" + + tls_tunnel_settings = None + tls_tunnel_selector = self.tls_settings.get_content_item("tunnel_setting_selector") + if tls_tunnel_selector: + values = tls_tunnel_selector.get_selected_values() + tls_tunnel_settings = values[0] + return tls_tunnel_settings + + def input_server(self, text: str) -> None: + """Заполнение поля 'Сервер' настроек 'Общие'.""" + + message_input = self.common_settings.get_content_item("server_setting_input") + message_input.clear() + message_input.input_value(text) + + def input_port(self, text: str) -> None: + """Заполнение поля 'Порт' настроек 'Общие'.""" + + message_input = self.common_settings.get_content_item("port_setting_input") + message_input.clear() + message_input.input_value(text) + + def input_sender(self, text: str) -> None: + """Заполнение поля 'Отправитель' настроек 'Общие'.""" + + message_input = self.common_settings.get_content_item("sender_setting_input") + message_input.clear() + message_input.input_value(text) + + def input_user_name(self, text: str) -> None: + """Заполнение поля 'Имя пользователя' настроек 'Аутентификация'.""" + + message_input = self.auth_settings.get_content_item("user_setting_input") + message_input.clear() + message_input.input_value(text) + + def input_password(self, text: str) -> None: + """Заполнение поля 'Пароль' настроек 'Аутентификация'.""" + + message_input = self.auth_settings.get_content_item("password_setting_input") + message_input.clear() + message_input.input_value(text) + + def input_domain(self, text: str) -> None: + """Заполнение поля 'Домен' настроек 'Аутентификация'.""" + + message_input = self.auth_settings.get_content_item("domain_setting_input") + message_input.clear() + message_input.input_value(text) + + def input_workstation(self, text: str) -> None: + """Заполнение поля 'Рабочая станция' настроек 'Аутентификация'.""" + + message_input = self.auth_settings.get_content_item("workstation_setting_input") + message_input.clear() + message_input.input_value(text) + + def select_auth_method_setting(self, auth_method_setting: str) -> None: + """Выбирает заданное значение поля 'Метод авторизации' из списка""" + + auth_method_selector = self.auth_settings.get_content_item("auth_method_selector") + if auth_method_selector: + auth_method_selector.open_values_list() + auth_method_selector.select_value(auth_method_setting) + + def select_tls_tunnel_setting(self, tls_tunnel_setting: str) -> None: + """Выбирает заданное значение поля 'Использовать TLS-туннель' из списка""" + + tls_tunnel_selector = self.tls_settings.get_content_item("tunnel_setting_selector") + if tls_tunnel_selector: + tls_tunnel_selector.open_values_list() + tls_tunnel_selector.select_value(tls_tunnel_setting) + + # Проверки: + def check_content(self): + """Проверяет наличие и корректность всех элементов страницы.""" + + self.should_be_toolbar() + + self._check_common_settings_content() + self._check_tls_settings_content() + self._check_auth_settings_content() + + self.should_be_test_button() + tooltip_text = self.test_button.get_tooltip_text() + assert tooltip_text == "Тест", "Should be 'Тест' tooltip for test button" + + def should_be_toolbar(self) -> None: + """Проверяет наличие тулбара страницы, наличие и функциональность кнопок тулбара. + + Raises: + AssertionError: Если тулбар или кнопка тулбара отсутствуют. + """ + loc = self.page.get_by_role("navigation").filter( + has_text=re.compile("e-mail")).locator("div").nth(1) + self.toolbar.check_toolbar_presence_by_locator(loc, "Toolbar with title 'E-MAIL' 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_test_button(self) -> None: + """Проверяет наличие кнопки 'Тест'. + + Raises: + AssertionError: Если кнопка отсутствует. + """ + + self.test_button.check_visibility("Test button is missing") + + def should_be_success_alert(self) -> None: + """Проверяет наличие сообщения об успешном обновлении полей настроек . + + Raises: + AssertionError: Если тулбар отсутствует. + """ + + 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обновлены\n') + self.alert.check_alert_absence('\nПараметры успешно\nобновлены\n') + + def _check_common_settings_content(self): + """Проверяет наличие и корректность всех элементов формы ввода настроек 'Общие'.""" + + expected_input_field_names = ["Сервер", "Порт", "Отправитель"] + + self.common_settings.should_be_toolbar() + + actual_input_field_names = self.common_input_fields_locators.keys() + assert set(actual_input_field_names) == set(expected_input_field_names), \ + f"Misscomparison input field names: Expected {expected_input_field_names}, Actual {actual_input_field_names}" + + for name in self.common_settings.content_items.keys(): + item = self.common_settings.get_content_item(name) + item.check_visibility( + f"E-mail notifications Common settings input form item with name '{name}' is missing" + ) + + if name == "checkbox_activate_label": + item.check_have_text( + "Активировать", + "Label 'Активировать' is missing" + ) + + if name == "checkbox_activate": + is_activate_checked = item.is_checked() + assert not is_activate_checked, ( + "Checkbox 'Активировать' should not be checked by default" + ) + + def _check_tls_settings_content(self): + """Проверяет наличие и корректность всех элементов формы ввода настроек 'TLS'.""" + + expected_input_field_names = ["Использовать TLS-туннель"] + + self.tls_settings.should_be_toolbar() + + actual_input_field_names = self.tls_input_fields_locators.keys() + assert set(actual_input_field_names) == set(expected_input_field_names), \ + f"Misscomparison input field names: Expected {expected_input_field_names}, Actual {actual_input_field_names}" + + for name in self.tls_settings.content_items.keys(): + item = self.tls_settings.get_content_item(name) + + if name == "tunnel_setting_selector": + item.check_field_visibility( + f"E-mail notifications TLS settings input form item with name '{name}' is missing" + ) + item.should_be_clear_selection_button() + item.should_be_open_list_button() + + if name == "checkbox_accept_certificates_label": + item.check_visibility( + f"E-mail notifications TLS settings input form item with name '{name}' is missing" + ) + item.check_have_text( + "Принимать самоподписанные сертификаты", + "Label 'Принимать самоподписанные сертификаты' is missing" + ) + + if name == "checkbox_accept_certificates": + item.check_visibility( + f"E-mail notifications TLS settings input form item with name '{name}' is missing" + ) + is_accept_certificates_checked = item.is_checked() + assert is_accept_certificates_checked, ( + "Checkbox 'Принимать самоподписанные сертификаты' should be checked by default" + ) + + def _check_auth_settings_content(self): + """Проверяет наличие и корректность всех элементов формы ввода настроек 'Аутентификация'.""" + + expected_input_field_names = ["Метод авторизации", "Имя пользователя", "Пароль", + "Домен", "Рабочая станция"] + + self.auth_settings.should_be_toolbar() + + actual_input_field_names = self.auth_input_fields_locators.keys() + assert set(actual_input_field_names) == set(expected_input_field_names), \ + f"Misscomparison input field names: Expected {expected_input_field_names}, Actual {actual_input_field_names}" + + for name in self.auth_settings.content_items.keys(): + item = self.auth_settings.get_content_item(name) + + if name == "auth_method_setting_selector": + item.check_field_visibility( + f"E-mail notifications Auth settings input form item with name '{name}' is missing" + ) + item.should_be_clear_selection_button() + item.should_be_open_list_button() + else: + item.check_visibility( + f"E-mail notifications Auth settings input form item with name '{name}' is missing" + ) diff --git a/pages/sms_notifications_settings_tab.py b/pages/sms_notifications_settings_tab.py new file mode 100644 index 0000000..3eadebd --- /dev/null +++ b/pages/sms_notifications_settings_tab.py @@ -0,0 +1,230 @@ +"""Модуль вкладки настройки СМС уведомлений. + +Содержит класс SMSNotificationsSettings для работы с вкладкой настройки СМС уведомлений. +Позволяет проверять состояние и взаимодействовать с элементами вкладки. +""" + +import re +from playwright.sync_api import Page +from locators.text_input_locators import TextInputLocators +from locators.settings_form_locators import SettingsFormLocators +from elements.text_input_element import TextInput +from elements.icon_element import Icon +from components.toolbar_component import ToolbarComponent +# from components.alert_component import AlertComponent +from components_derived.settings_form_component import SettingsFormComponent +from pages.base_page import BasePage + + +class SMSNotificationsSettingsTab(BasePage): + """Класс для работы с вкладкой настройки СМС уведомлений. + + Предоставляет методы для взаимодействия с вкладкой настройки СМС уведомлений. + + Args: + page: Экземпляр страницы Playwright. + """ + + def __init__(self, page: Page) -> None: + """Инициализирует компоненты вкладки настройки СМС уведомлений.""" + + super().__init__(page) + + toolbar_button_1 = self.page.get_by_role("navigation").filter( + has_text=re.compile("СМС")).get_by_role("button").nth(0) + toolbar_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(toolbar_button_1, "edit") + self.toolbar.add_tooltip_button(toolbar_button_1, "save") + self.toolbar.add_tooltip_button(toolbar_button_2, "cancel") + + # Форма для отображения/редактирования полей настроек СМС уведомлений + self.settings_form = SettingsFormComponent(page) + + container_locator = self.page.locator(SettingsFormLocators.SETTINGS_FORM_SMS_INPUT_FORM_CONTAINER) + self.input_fields_locators = self.settings_form.get_input_fields_locators(container_locator) + + loc = self.input_fields_locators.get("ip") + loc_message_input = loc.locator(SettingsFormLocators.SETTINGS_FORM_INPUT_FIELD).first + ip_setting_input = TextInput(page, loc_message_input, "ip_setting_input") + self.settings_form.add_content_item("ip_setting_input", ip_setting_input) + + loc = self.input_fields_locators.get("Имя пользователя") + loc_user_input = loc.locator(SettingsFormLocators.SETTINGS_FORM_INPUT_FIELD).first + user_setting_input = TextInput(page, loc_user_input, "user_setting_input") + self.settings_form.add_content_item("user_setting_input", user_setting_input) + + loc = self.input_fields_locators.get("Пароль") + loc_password_input = loc.locator(SettingsFormLocators.SETTINGS_FORM_INPUT_FIELD).first + password_setting_input = TextInput(page, loc_password_input, "password_setting_input") + self.settings_form.add_content_item("password_setting_input", password_setting_input) + + icon_locator = loc_password_input.locator("../..").locator(TextInputLocators.ICON_PASSWORD_HIDING) + password_hidden_icon = Icon(page, icon_locator, + "password hidden icon") + self.settings_form.add_content_item("password_hidden_icon", password_hidden_icon) + + self.settings_form.add_tooltip_button(page.locator(SettingsFormLocators.SETTTINGS_FORM_SCROLL_CONTAINER).\ + get_by_role("button", name='Тест'), + "test_button") + + # 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 click_password_hidden_icon(self) -> None: + """Нажатие на иконку скрытия пароля.""" + + self.settings_form.get_content_item("password_hidden_icon").click() + + def click_test_button(self) -> None: + """Нажатие кнопки 'Тест' в форме ввода настроек.""" + + self.settings_form.check_button_visibility("test_button") + self.settings_form.get_button_by_name("test_button").click() + + def get_ip_setting_value(self) -> str: + """Возвращает текущее значение поля настроек 'IP'. + + Returns: + str : Текущее значение поля настроек 'IP'. + """ + + input_field = self.settings_form.get_content_item("ip_setting_input") + return input_field.get_input_value().strip() + + def get_user_setting_value(self) -> str: + """Возвращает текущее значение поля настроек 'Имя пользователя'. + + Returns: + str : Текущее значение поля настроек 'Имя пользователя'. + """ + + input_field = self.settings_form.get_content_item("user_setting_input") + return input_field.get_input_value().strip() + + def get_password_setting_value(self) -> str: + """Возвращает текущее значение поля настроек 'Пароль'. + + Returns: + str : Текущее отображение значения поля настроек 'Пароль'. + """ + + input_field = self.settings_form.get_content_item("password_setting_input") + is_hidden_state = self.settings_form.get_content_item("password_hidden_icon").is_password_hidden() + + password_value = input_field.get_input_value().strip() + if is_hidden_state: + password_value = "." * len(password_value) + return password_value + + def input_ip(self, text: str) -> None: + """Заполнение поля 'IP'.""" + + message_input = self.settings_form.get_content_item("ip_setting_input") + message_input.clear() + message_input.input_value(text) + + def input_user(self, text: str) -> None: + """Заполнение поля 'Имя пользователя'.""" + + message_input = self.settings_form.get_content_item("user_setting_input") + message_input.clear() + message_input.input_value(text) + + def input_password(self, text: str) -> None: + """Заполнение поля 'Пароль'.""" + + message_input = self.settings_form.get_content_item("password_setting_input") + message_input.clear() + message_input.input_value(text) + + # Проверки: + def check_content(self): + """Проверяет наличие и корректность всех элементов страницы.""" + + expected_input_field_names = ["ip", "Имя пользователя", "Пароль"] + + self.should_be_toolbar() + + actual_input_field_names = self.input_fields_locators.keys() + assert set(actual_input_field_names) == set(expected_input_field_names), \ + f"Misscomparison input field names: Expected {expected_input_field_names}, Actual {actual_input_field_names}" + + for name in self.settings_form.content_items.keys(): + item = self.settings_form.get_content_item(name) + item.check_visibility( + f"SMS notifications settings input form item with name '{name}' is missing" + ) + + if name == "password_hidden_icon": + is_hidden_state = item.is_password_hidden() + assert is_hidden_state, "Password hidden icon should be in hidden state" + + self.settings_form.check_button_visibility("test_button") + self.settings_form.check_button_tooltip("test_button", "Тест") + + 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_test_button(self) -> None: + """Проверяет наличие кнопки 'Тест'. + + Raises: + AssertionError: Если кнопка отсутствует. + """ + + self.settings_form.check_button_visibility("test_button") + + + # def should_be_success_alert(self) -> None: + # """Проверяет наличие сообщения об успешной отправке СМС-уведомления. + + # Raises: + # AssertionError: Если тулбар отсутствует. + # """ + + # 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успешно отправлено\n') + # self.alert.check_alert_absence('\nСМС-уведомление\nуспешно отправлено\n') diff --git a/tests/e2e/notifications/test_email_notifications_settings_tab.py b/tests/e2e/notifications/test_email_notifications_settings_tab.py new file mode 100644 index 0000000..59746f3 --- /dev/null +++ b/tests/e2e/notifications/test_email_notifications_settings_tab.py @@ -0,0 +1,194 @@ +"""Модуль тестов вкладки настройки E-mail уведомлений. + +Содержит тесты для проверки корректности отображения +и функциональности элементов страницы настройки E-mail уведомлений. +""" + +import pytest +from playwright.sync_api import Page, expect +from pages.login_page import LoginPage +from pages.main_page import MainPage +from pages.email_notifications_settings_tab import EmailNotificationsSettingsTab + + +# @pytest.mark.smoke +class TestEmailNotificationsSettingsTab: + """Набор тестов для вкладки настройки E-mail уведомлений. + + Проверяет корректность отображения и функциональность элементов вкладки настройки E-mail уведомлений. + """ + + @pytest.fixture(scope="function", autouse=True) + def setup(self, browser: Page) -> None: + """Фикстура для подготовки тестового окружения. + + Выполняет: + 1. Авторизацию в системе + 2. Переход на вкладку настройки E-mail уведомлений через панель навигации + """ + # Авторизация в системе + 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("E-mail") + + # @pytest.mark.develop + def test_email_notifications_settings_tab_content(self, browser: Page) -> None: + """Тест содержимого вкладки настройки E-mail уведомлений. + + Проверяет: + Наличие и корректность элементов интерфейса + """ + + current_settings = {} + default_settings = {} + + # Инициализация вкладки + email_notification_settings_tab = EmailNotificationsSettingsTab(browser) + + # запрос текущих установок + cur_settings_response = email_notification_settings_tab.send_get_api_request("e-cmdb/api/email_notifier") + if cur_settings_response.status == 200: + response_body = email_notification_settings_tab.get_response_body(cur_settings_response) + + if response_body: + current_settings = response_body[0].copy() + + # запрос дефолтных значений + default_settings_response = email_notification_settings_tab. \ + send_get_api_request("e-cmdb/api/email_notifier/meta") + if default_settings_response.status == 200: + response_body = email_notification_settings_tab.get_response_body(default_settings_response) + + if response_body: + default_settings = response_body["fields"].copy() + + # Проверка элементов интерфейса + email_notification_settings_tab.check_content() + + # Получение и проверка отображаемых входных значений формы настроек 'Общие' + common_settings = email_notification_settings_tab.get_common_settings_values() + value = common_settings["Сервер"] + expected = current_settings["smtp_host"] + if expected is None: + expected = self._get_default_value("smtp_host", default_settings) + assert value == expected, f"Actual value {value} is not equal expected {expected} for field 'Сервер'" + + value = common_settings["Порт"] + expected = current_settings["smtp_port"] + if expected is None: + expected = self._get_default_value("smtp_port", default_settings) + assert value == expected, f"Actual value {value} is not equal expected {expected} for field 'Порт'" + + value = common_settings["Отправитель"] + expected = current_settings["from_email"] + if expected is None: + expected = self._get_default_value("from_email", default_settings) + assert value == expected, f"Actual value {value} is not equal expected {expected} for field 'Отправитель'" + + # Получение и проверка отображаемых входных значений формы настроек 'TLS' + value = email_notification_settings_tab.get_tls_tunnel_setting_value() + expected = current_settings["secure"] + if expected is None: + expected = self._get_default_value("secure", default_settings) + assert value == expected, \ + f"Actual value {value} is not equal expected {expected} for field 'Использовать TLS-туннель'" + + # Получение и проверка отображаемых входных значений формы настроек 'Аутентификация' + auth_settings = email_notification_settings_tab.get_auth_settings_values() + value = auth_settings["Метод авторизации"] + expected = current_settings["auth_method"] + if expected is None: + expected = self._get_default_value("auth_method", default_settings) + assert value == expected, \ + f"Actual value {value} is not equal expected {expected} for field 'Метод авторизации'" + + value = auth_settings["Имя пользователя"] + expected = current_settings["login"] + if expected is None: + expected = self._get_default_value("login", default_settings) + assert value == expected, \ + f"Actual value {value} is not equal expected {expected} for field 'Имя пользователя'" + + value = auth_settings["Пароль"] + expected = current_settings["password"] + if expected is None: + expected = self._get_default_value("password", default_settings) + assert value == expected, \ + f"Actual value {value} is not equal expected {expected} for field 'Пароль'" + + value = auth_settings["Домен"] + expected = current_settings["domain"] + if expected is None: + expected = self._get_default_value("domain", default_settings) + assert value == expected, \ + f"Actual value {value} is not equal expected {expected} for field 'Домен'" + + value = auth_settings["Рабочая станция"] + expected = current_settings["workstation"] + if expected is None: + expected = self._get_default_value("workstation", default_settings) + assert value == expected, \ + f"Actual value {value} is not equal expected {expected} for field 'Рабочая станция'" + + def test_send_test_email_window_content(self, browser: Page) -> None: + """Тест модального окна для посылки тестового E-mail. + + Проверяет: + Наличие и корректность элементов интерфейса + """ + + # Инициализация вкладки + email_notification_settings_tab = EmailNotificationsSettingsTab(browser) + + send_test_email_window = email_notification_settings_tab.click_test_button() + send_test_email_window.check_content() + + send_test_email_window.close() + + send_test_email_window = email_notification_settings_tab.click_test_button() + send_test_email_window.close_by_toolbar_button() + + # @pytest.mark.develop + # TO-DO: rewrite tescase after feature release + def test_send_test_email(self, browser: Page) -> None: + """Тест модального окна для посылки тестового E-mail. + + Проверяет: + Возможность посылки тестового E-mail. + """ + # Адрес куда отправлять e-mail + # Пока фейковый + fake_address = "test@grandpas_village.com" + + # Инициализация вкладки + email_notification_settings_tab = EmailNotificationsSettingsTab(browser) + + # Заполнить поля настройки + # TO-DO after feature release + + send_test_email_window = email_notification_settings_tab.click_test_button() + + send_test_email_window.input_email(fake_address) + + with browser.expect_response("**/e-nms/email/testEmail") as response_info: + send_test_email_window.click_test_button() + send_test_email_window.should_be_success_alert() + + response = response_info.value + assert response.ok, "Unsuccessful test e-mail request" + + send_test_email_window.close() + + 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 diff --git a/tests/e2e/notifications/test_sms_notifications_settings_tab.py b/tests/e2e/notifications/test_sms_notifications_settings_tab.py new file mode 100644 index 0000000..92301b3 --- /dev/null +++ b/tests/e2e/notifications/test_sms_notifications_settings_tab.py @@ -0,0 +1,97 @@ +"""Модуль тестов вкладки настройки СМС уведомлений. + +Содержит тесты для проверки корректности отображения +и функциональности элементов страницы настройки СМС уведомлений. +""" + +import pytest +from playwright.sync_api import Page +from pages.login_page import LoginPage +from pages.main_page import MainPage +from pages.sms_notifications_settings_tab import SMSNotificationsSettingsTab + + +# @pytest.mark.smoke +class TestSMSNotificationsSettingsTab: + """Набор тестов для вкладки настройки СМС уведомлений. + + Проверяет корректность отображения и функциональность элементов вкладки настройки СМС уведомлений. + """ + + @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_sms_notifications_settings_tab_content(self, browser: Page) -> None: + """Тест содержимого вкладки настройки СМС уведомлений. + + Проверяет: + Наличие и корректность элементов интерфейса + """ + + # Инициализация вкладки + sms_notification_settings_tab = SMSNotificationsSettingsTab(browser) + + # Проверка элементов интерфейса + sms_notification_settings_tab.check_content() + + @pytest.mark.develop + # TO-DO: rewrite tescase after feature release + def test_send_sms_notification(self, browser: Page) -> None: + """Тест содержимого вкладки настройки СМС уведомлений. + + Проверяет: + Заполнение полей и отправку СМС уведомления + """ + + field_values = ["8.8.8.8", "testadmin", "test12345678"] + + # Инициализация вкладки + sms_notification_settings_tab = SMSNotificationsSettingsTab(browser) + + sms_notification_settings_tab.click_edit_button() + + sms_notification_settings_tab.input_ip(field_values[0]) + ip = sms_notification_settings_tab.get_ip_setting_value() + assert ip == field_values[0], f"Actual IP value {ip} is not equal expected value {field_values[0]}" + + sms_notification_settings_tab.input_user(field_values[1]) + user = sms_notification_settings_tab.get_user_setting_value() + assert user == field_values[1], f"Actual user name value {user} is not equal expected value {field_values[1]}" + + sms_notification_settings_tab.input_password(field_values[2]) + password = sms_notification_settings_tab.get_password_setting_value() + dots = password.count(".") + assert dots > 0, "Password should be hidden" + assert len(field_values[2]) == dots, f"Should be {dots} dots for hidden password" + + sms_notification_settings_tab.click_password_hidden_icon() + password = sms_notification_settings_tab.get_password_setting_value() + assert password == field_values[2], \ + f"Actual password value {password} is not equal expected value {field_values[2]}" + + # temporarily, should be rewritten + sms_notification_settings_tab.click_cancel_button() + + sms_notification_settings_tab.should_be_test_button() + + #sms_notification_settings_tab.click_test_button() + # sms_notification_settings_tab.should_be_success_alert()