diff --git a/components/date_picker_component.py b/components/date_picker_component.py new file mode 100644 index 0000000..20f3f15 --- /dev/null +++ b/components/date_picker_component.py @@ -0,0 +1,232 @@ +"""Модуль компонента средства выбора даты. + +Содержит класс для работы с средством выбора даты через Playwright. +""" + +import datetime +from playwright.sync_api import Page +from tools.logger import get_logger +from locators.date_picker_locators import DatePickerLocators +from elements.text_element import Text +from elements.button_element import Button +from components.base_component import BaseComponent + +logger = get_logger("DATE_PICKER") + + +class DatePickerComponent(BaseComponent): + """Компонент средства выбора даты. + + Предоставляет методы для взаимодействия с элементами средства выбора даты. + """ + + def __init__(self, page: Page): + """Инициализирует компонент средства выбора даты. + + Args: + page: Экземпляр страницы Playwright. + """ + + super().__init__(page) + + self.date_picker_year_button = Button(page, + DatePickerLocators.DATE_PICKER_TITLE_BUTTON_YEAR, + "date_picker_year_button") + + loc = page.locator(DatePickerLocators.DATE_PICKER_HEADER).\ + get_by_role("button").locator("i.mdi-chevron-left") + self.prev_month_button = Button(page, loc, "prev_month_button") + + loc = page.locator(DatePickerLocators.DATE_PICKER_HEADER).\ + get_by_role("button").locator("i.mdi-chevron-right") + self.next_month_button = Button(page, loc, "next_month_button") + + self.current_month_year = Text(page, + DatePickerLocators.DATE_PICKER_HEADER_VALUE, + "current_month_year") + + # Действия: + def click_prev_month_button(self) -> None: + """ Нажатие на кнопку перехода к предыдущему месяцу (стрелочка влево).""" + + self.prev_month_button.click() + + def click_next_month_button(self) -> None: + """ Нажатие на кнопку перехода к следующему месяцу (стрелочка вправо).""" + + self.next_month_button.click() + + def click_year_button(self) -> None: + """ Нажатие на кнопку текущего значения года в заголовке средства выбора даты.""" + + self.date_picker_year_button.click() + + def get_year(self) -> str: + """ Получение текущего значения года из заголовка средства выбора даты.""" + + return self.date_picker_year_button.get_text(0).strip() + + def get_month_year(self) -> str: + """ Получение текущего значения месяца и года.""" + + return self.current_month_year.get_text(0).strip() + + def get_day(self) -> str: + """ Получение текущего номера дня.""" + + days_table_locator = self.page.locator(DatePickerLocators.DATE_PICKER_TABLE_DAYS) + day_button_locator = days_table_locator.locator("//td/button[contains(@class, 'accent--text')]") + + return day_button_locator.text_content().strip() + + def select_day(self, day: str) -> None: + """ Выбор дня месяца по его номеру.""" + + visible = False + + days_table_locator = self.page.locator(DatePickerLocators.DATE_PICKER_TABLE_DAYS) + days_table_locator.wait_for(timeout=300) + day_button_locator = days_table_locator.locator("//td").get_by_role("button", name=day) + visible = day_button_locator.is_visible() + if visible: + day_button_locator.click() + else: + assert False, f"Day number {day} is missing on date picker days table" + + def select_year_and_month(self, year: str, month: str) -> None: + """ Выбор года и месяца по заданным значениям. Значения должны быть в формате гггг и мм""" + + try: + month_index = int(month) + except ValueError: + assert False, f"Incorrect month value {month} for selection" + + assert month_index >= 1, f"Incorrect month value {month} for selection" + assert month_index <= 12, f"Incorrect month value {month} for selection" + + current_year = int(self.get_year()) + if int(year) > current_year + 100 or int(year) < current_year - 100: + assert False, f"Incorrect year value {year} for selection" + + self.click_year_button() + + years_list = self.page.locator(DatePickerLocators.DATE_PICKER_LIST_YEARS) + years_list.wait_for(timeout=300) + year_locator = f"{DatePickerLocators.DATE_PICKER_LIST_YEARS} li:has-text(\"{year}\")" + self.page.locator(year_locator).click() + + months_table = self.page.locator(DatePickerLocators.DATE_PICKER_TABLE_MONTHS) + months_table.wait_for(timeout=300) + month_button = months_table.locator("//td").get_by_role("button").nth(month_index-1) + month_button.click() + + + # Проверки: + def check_prev_month_button_visibility(self) -> None: + """ Проверка видимости кнопки перехода к предыдущему месяцу (стрелочка влево).""" + + self.prev_month_button.check_visibility("Prev Month Button is missing") + + def check_next_month_button_visibility(self) -> None: + """ Проверка видимости кнопки перехода к следующему месяцу (стрелочка вправо).""" + + self.next_month_button.check_visibility("Next Month Button is missing") + + def check_year_button_visibility(self) -> None: + """ Проверка видимости кнопки текущего значения года в заголовке средства выбора даты.""" + + self.date_picker_year_button.check_visibility("Current Year Button is missing") + + def check_content(self) -> None: + """Проверка состава компонент средства выбора даты.""" + + month_dict = {"1":"январь", + "2":"февраль", + "3":"март", + "4":"апрель", + "5":"май", + "6":"июнь", + "7":"июль", + "8":"август", + "9":"сентябрь", + "10":"октябрь", + "11":"ноябрь", + "12":"декабрь"} + days_per_month = {"1":31, + "2":28, + "3":31, + "4":30, + "5":31, + "6":30, + "7":31, + "8":31, + "9":30, + "10":31, + "11":30, + "12":31} + expected_weekdays = ["В", "П", "В", "С", "Ч", "П", "С"] + + expected_date = datetime.datetime.now() + + # Проверка наличия кнопки текущего значения года в заголовке средства выбора даты + self.check_year_button_visibility() + + actual_year = self.get_year() + assert actual_year == str(expected_date.year), \ + f"Expected year {expected_date.year} is not equal actual year {actual_year} on date picker title" + + # Проверка наличия кнопок перехода к предыдущему/следующему месяцу + self.check_prev_month_button_visibility() + self.check_next_month_button_visibility() + + # Проверка наличия и правильности текущей даты + self.current_month_year.check_visibility("Month and Year values is missing on date picker body") + + y = expected_date.year + m = str(expected_date.strftime("%m")) + expected_month_year = f"{month_dict[m]} {y} г." + actual_month_year = self.get_month_year() + assert actual_month_year == expected_month_year, \ + f"Expected value {expected_month_year} is not equal actual value {actual_month_year} on date picker body" + + expected_day = str(expected_date.strftime("%d")) + actual_day = self.get_day() + assert actual_day == expected_day, \ + f"Expected day {expected_day} is not equal actual day {actual_day} on date picker body" + + # Проверка таблицы дней + days_table_locator = self.page.locator(DatePickerLocators.DATE_PICKER_TABLE_DAYS) + headers = days_table_locator.locator("th").all() + actual_weekdays = [] + for header in headers: + actual_weekdays.append(header.text_content()) + + assert actual_weekdays == expected_weekdays, \ + f"Expected weekdays list {expected_weekdays} is not equal actual weekdays list {actual_weekdays} on date picker body" + + rows = days_table_locator.locator("//tbody/tr") + days_counter = 0 + for i in range(rows.count()): + row = rows.nth(i) + cells = row.locator("td") + for j in range(cells.count()): + cell_text = cells.nth(j).inner_text() + if cell_text != "": + days_counter += 1 + + expected_day_counter = days_per_month[m] + if m == "2" and self._is_leap_year(expected_date.year): + expected_day_counter = 29 + + assert days_counter == expected_day_counter, f"Incorrect amount of days {days_counter} on date picker body" + + def _is_leap_year(self, year: str) -> bool: + """Проверка является ли год високосным.""" + + if int(year) % 400 == 0: + return True + if int(year) % 100 == 0: + return False + if int(year) % 4 == 0: + return True + return False diff --git a/components/events_container_component.py b/components/events_container_component.py index 8bce8d6..58013b5 100644 --- a/components/events_container_component.py +++ b/components/events_container_component.py @@ -7,6 +7,7 @@ from locators.toolbar_locators import ToolbarLocators from elements.tooltip_button_element import TooltipButton from elements.tab_button_element import TabButton from elements.button_element import Button +from components_derived.sidebar_filter_component import SidebarFilterComponent from components.toolbar_component import ToolbarComponent from components.table_component import TableComponent from components.base_component import BaseComponent @@ -63,6 +64,10 @@ class EventsContainerComponent(BaseComponent): locator("xpath=..").get_by_role("button").nth(2) self.data_set_number = Button(page, loc, "data_set_number") + self.sidebar_filter_locator = self.container_locator.locator("//aside//div[@class='scrollarea__container']") + self.sidebar_filter = SidebarFilterComponent(self.page, + self.sidebar_filter_locator) + # Действия: def add_tab_to_toolbar(self, locator: str | Locator, name: str) -> None: """Добавление кнопки типа v-tabs к тулбару""" @@ -90,6 +95,14 @@ class EventsContainerComponent(BaseComponent): self.last_page.click() + def click_filter_button(self) -> SidebarFilterComponent: + """Нажатие кнопки перехода на первую сраницу""" + + self.toolbar.click_button("filter_button") + self.sidebar_filter.check_visibility(self.sidebar_filter_locator, + "Filter sidebar is missing") + return self.sidebar_filter + def click_event_table_header_arrow(self, index: int) -> None: """ Нажатие кнопки-стрелочки вверх/вниз в ячейке заголовка таблицы @@ -144,6 +157,11 @@ class EventsContainerComponent(BaseComponent): loc = self.container_locator.locator(self.table_locator) return self.events_table.get_rows_count(loc) + def get_sidebar_filter(self) -> SidebarFilterComponent: + """Возвращает боковую панель фильтрации.""" + + return self.sidebar_filter + def get_toolbar_filter_button(self) -> Button: """Возвращает кнопку фильтрации.""" diff --git a/components_derived/container_system_log_events.py b/components_derived/container_system_log_events.py index 9bcb829..d654dc2 100644 --- a/components_derived/container_system_log_events.py +++ b/components_derived/container_system_log_events.py @@ -9,9 +9,7 @@ from tools.logger import get_logger from locators.toolbar_locators import ToolbarLocators from components.events_container_component import EventsContainerComponent - - -logger = get_logger("USER_SETTINGS_DIALOG") +logger = get_logger("SYSTEM_LOG_EVENTS_CONTAINER") class SystemLogEventsContainer(EventsContainerComponent): @@ -31,6 +29,12 @@ class SystemLogEventsContainer(EventsContainerComponent): super().__init__(page, locator) self.add_tab_to_toolbar(ToolbarLocators.TABS, "events") + + sidebar_filter = self.get_sidebar_filter() + sidebar_filter.add_filtering_parameter("filter_type", "Тип") + sidebar_filter.add_filtering_parameter("filter_strictness", "Строгость") + sidebar_filter.add_filtering_parameter("filter_host", "Хост") + # Действия: # Проверки: def check_content(self) -> None: @@ -58,3 +62,18 @@ class SystemLogEventsContainer(EventsContainerComponent): assert False, "Table body is missing" self.should_be_pagination_buttons() + + sidebar_filter = self.click_filter_button() + sidebar_filter.check_content() + + filter_type_bar = sidebar_filter.get_filtering_parameter("filter_type") + filter_type_title = filter_type_bar.get_filter_parameter_title() + assert filter_type_title == "Тип", "Filtering parameter bar 'Тип' is missing" + + filter_strictness_bar = sidebar_filter.get_filtering_parameter("filter_strictness") + filter_strictness_title = filter_strictness_bar.get_filter_parameter_title() + assert filter_strictness_title == "Строгость", "Filtering parameter bar 'Строгость' is missing" + + filter_host_bar = sidebar_filter.get_filtering_parameter("filter_host") + filter_host_title = filter_host_bar.get_filter_parameter_title() + assert filter_host_title == "Хост", "Filtering parameter bar 'Хост' is missing" diff --git a/components_derived/date_input_component.py b/components_derived/date_input_component.py new file mode 100644 index 0000000..875ee93 --- /dev/null +++ b/components_derived/date_input_component.py @@ -0,0 +1,165 @@ +"""Модуль компонента задания даты и времени. + +Содержит класс для работы с компонентом задания даты и времени через Playwright. +""" + +from playwright.sync_api import Page, Locator, expect +from tools.logger import get_logger +# from elements.text_element import Text +from elements.text_input_element import TextInput +from elements.button_element import Button +from components.date_picker_component import DatePickerComponent +from components.base_component import BaseComponent + +logger = get_logger("DATE_INPUT") + + +class DateInput(BaseComponent): + """Компонент задания даты и времени. + + Предоставляет методы для взаимодействия с элементами компонентом задания даты и времени. + """ + + def __init__(self, page: Page, locator: str | Locator): + """Инициализирует компонент задания даты и времени. + + Args: + page: Экземпляр страницы Playwright. + locator: Локатор формы ввода даты и времени (строка или объект Locator) + """ + + super().__init__(page) + + self.date_input_locator = self.get_locator(locator) + + self.switch_mode_button = Button(page, + self.date_input_locator.get_by_role("button"), + "switch_mode_button") + + loc = self.date_input_locator.get_by_placeholder("дд.мм.гггг") + self.date_input_field = TextInput(page, loc, "date_input") + + loc = self.date_input_locator.get_by_placeholder("00:00") + self.time_input_field = TextInput(page, loc, "time_input") + + self.date_picker = DatePickerComponent(self.page) + + # Действия: + def click_switch_mode_button(self) -> None: + """ Нажатие на кнопку переключения режимов ввода (текстовый или календарь).""" + + self.switch_mode_button.click() + + def get_date_picker(self) -> DatePickerComponent: + """ Возвращает экземпляр компонента средства выбора даты. """ + + return self.date_picker + + def get_date_field_value(self) -> str: + """ Возвращает текущее значение поля ввода даты. """ + + return self.date_input_field.get_input_value() + + def get_time_field_value(self) -> str: + """ Возвращает текущее значение поля ввода времени. """ + + return self.time_input_field.get_input_value() + + def input_date(self, date: str) -> None: + """ Ввод даты в формате дд.мм.гггг """ + + day, month, year = date.split('.') + assert len(day) == 2, "Incorrect day format: should be 'dd.mm.yyyy'" + assert len(month) == 2, "Incorrect month format: should be 'dd.mm.yyyy'" + assert len(year) == 4, "Incorrect year format: should be 'dd.mm.yyyy'" + + try: + _ = int(day) + except ValueError: + assert False, f"Incorrect day value {day} for selection" + + try: + _ = int(month) + except ValueError: + assert False, f"Incorrect month value {month} for selection" + + try: + _ = int(year) + except ValueError: + assert False, f"Incorrect year value {year} for selection" + + if self.is_text_input_mode(): + self.date_input_field.check_editable_input("Text field for date input should be editable") + self.date_input_field.clear() + self.date_input_field.input_value(date) + else: + self.date_picker.select_year_and_month(year, month) + self.date_picker.select_day(day) + + def input_time(self, time: str) -> None: + """ Ввод даты в формате чч:мм """ + + hours, minutes = time.split(':') + assert len(hours) == 2, "Incorrect time format: should be 'hh:mm'" + assert len(minutes) == 2, "Incorrect time format: should be 'hh:mm'" + + try: + _ = int(hours) + except ValueError: + assert False, f"Incorrect hours value {hours} for selection" + + try: + _ = int(minutes) + except ValueError: + assert False, f"Incorrect minutes value {minutes} for selection" + + self.time_input_field.check_editable_input("Text field for date input should be editable") + self.time_input_field.clear() + self.time_input_field.input_value(time) + + # Проверки: + def check_content(self, label: str) -> None: + """Проверка состава компонента ввода даты.""" + + self.check_switch_mode_button_visibility() + + label_locator = self.date_input_locator.get_by_label(label) + expect(label_locator).to_be_visible() + + self.date_input_field.check_visibility("Text field for date input is missing") + self.date_input_field.check_empty_input("Text field for date input should be empty") + + self.click_switch_mode_button() + self.page.wait_for_timeout(300) + self.click_switch_mode_button() + self.page.wait_for_timeout(300) + + self.date_picker.check_content() + + self.click_switch_mode_button() + self.click_switch_mode_button() + + self.page.wait_for_timeout(300) + self.input_date("11.11.2011") + + label_locator = self.date_input_locator.get_by_label("Время") + expect(label_locator).to_be_visible() + self.time_input_field.check_visibility("Text field for time input is missing") + current_time_value = self.get_time_field_value() + assert current_time_value == "00:00", \ + "Should be empty time input field" + + def check_switch_mode_button_visibility(self) -> None: + """ Проверка видимости кнопки переключения режимов ввода.""" + + self.switch_mode_button.check_visibility("Switch Mode Button is missing") + + def is_text_input_mode(self) -> bool: + """ Проверка текстового режима ввода.""" + + result = False + + inner_text = self.switch_mode_button.get_text(0).strip() + if inner_text == "keyboard": + result = True + return result diff --git a/components_derived/sidebar_filter_component.py b/components_derived/sidebar_filter_component.py index a047516..6eb6196 100644 --- a/components_derived/sidebar_filter_component.py +++ b/components_derived/sidebar_filter_component.py @@ -1,20 +1,20 @@ -"""Модуль компонента боковой панели формы ввода полей фильтрации отображения данных в панели событий. Содержит класс для работы -с формами ввода, их элементами и проверками.""" +"""Модуль компонента боковой панели формы ввода полей фильтрации отображения данных в панели событий. Содержит класс +для работы с формами ввода, их элементами и проверками.""" from playwright.sync_api import Page, Locator from tools.logger import get_logger from elements.button_element import Button -from components_derived.selection_bar_component import SelectionBarComponent -from components_derived.date_input_component import DateInput from components.toolbar_component import ToolbarComponent from components.base_component import BaseComponent +from components_derived.selection_bar_component import SelectionBarComponent +from components_derived.date_input_component import DateInput logger = get_logger("SIDEBAR_FILTER") class SidebarFilterComponent(BaseComponent): - """Компонент боковой панели формы ввода полей фильтрации отображения данных в панели событий. Предоставляет методы для - взаимодействия с формой, ее содержимым и проверок.""" + """Компонент боковой панели формы ввода полей фильтрации отображения данных в панели событий. Предоставляет методы + для взаимодействия с формой, ее содержимым и проверок.""" def __init__(self, page: Page, locator: str | Locator): """Инициализирует компонент боковой панели формы ввода параметров фильтрации. @@ -84,15 +84,15 @@ class SidebarFilterComponent(BaseComponent): # Проверки: def check_content(self) -> None: """Проверяет наличие постоянных полей панели параметров фильтрации.""" - + self.should_be_toolbar() self.start_time_filter.check_content("Дата начала") self.finish_time_filter.check_content("Дата окончания") - + self.check_apply_button_visibility() self.check_reset_button_visibility() - - + + def check_vertical_scrolling(self, locator: str| Locator) -> bool: """Проверяет возможность вертикальной прокрутки формы.""" diff --git a/locators/date_picker_locators.py b/locators/date_picker_locators.py new file mode 100644 index 0000000..12884e2 --- /dev/null +++ b/locators/date_picker_locators.py @@ -0,0 +1,21 @@ +"""Модуль date_picker_locators содержит локаторы полей ввода даты. + +Класс DatePickerLocators предоставляет XPath/CSS локаторы для взаимодействия +с полями ввода даты. +""" + +class DatePickerLocators: + """Локаторы для полей ввода на странице. + + Содержит XPath/CSS локаторы для: + DATE_PICKER (str): контейнер средства выбора даты + + """ + + DATE_PICKER = "div.menuable__content__active > div.v-picker" + DATE_PICKER_TITLE_BUTTON_YEAR = "//div[contains(@class,'v-date-picker-title__year')]" + DATE_PICKER_HEADER = "//div[contains(@class, 'v-date-picker-header')]" + DATE_PICKER_HEADER_VALUE = "//div[contains(@class, 'v-date-picker-header__value')]" + DATE_PICKER_TABLE_DAYS = "//div[contains(@class, 'v-date-picker-table--date')]" + DATE_PICKER_LIST_YEARS = "ul.v-date-picker-years" + DATE_PICKER_TABLE_MONTHS = "//div[contains(@class, 'v-date-picker-table--month')]" diff --git a/tests/components/run.bat b/tests/components/scrolling/run.bat similarity index 100% rename from tests/components/run.bat rename to tests/components/scrolling/run.bat diff --git a/tests/components/test_json_container.py b/tests/components/scrolling/test_json_container.py similarity index 100% rename from tests/components/test_json_container.py rename to tests/components/scrolling/test_json_container.py diff --git a/tests/components/test_navigation_panel.py b/tests/components/scrolling/test_navigation_panel.py similarity index 100% rename from tests/components/test_navigation_panel.py rename to tests/components/scrolling/test_navigation_panel.py diff --git a/tests/components/test_services_table.py b/tests/components/scrolling/test_services_table.py similarity index 100% rename from tests/components/test_services_table.py rename to tests/components/scrolling/test_services_table.py diff --git a/tests/components/test_session_settings.py b/tests/components/scrolling/test_session_settings.py similarity index 100% rename from tests/components/test_session_settings.py rename to tests/components/scrolling/test_session_settings.py diff --git a/tests/components/test_user_modal_window.py b/tests/components/scrolling/test_user_modal_window.py similarity index 100% rename from tests/components/test_user_modal_window.py rename to tests/components/scrolling/test_user_modal_window.py diff --git a/tests/components/unit_tests/test_date_input.py b/tests/components/unit_tests/test_date_input.py new file mode 100644 index 0000000..495d517 --- /dev/null +++ b/tests/components/unit_tests/test_date_input.py @@ -0,0 +1,285 @@ +"""Модуль тестов для проверки операций с компонентом ввода даты. + +Содержит тесты для для проверки операций с компонентом ввода даты. +""" + +import pytest +from playwright.sync_api import Page +from pages.main_page import MainPage +from pages.login_page import LoginPage + + +# @pytest.mark.smoke +class TestDateInputComponent: + """Класс тестов для проверки операций с компонентом ввода даты. + + Атрибуты: + browser: Фикстура для работы с браузером. + """ + + # @pytest.mark.develop + def test_date_input_content(self, browser: Page) -> None: + """Проверяет содержимое компонента ввода даты. +put + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + date_input.check_content("Дата начала") + + # @pytest.mark.develop + def test_date_input_by_text_positive(self, browser: Page) -> None: + """Проверяет возможность задания даты с помощью текстового ввода для корректного входного значения. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + + if date_input.is_text_input_mode(): + # выбираем 15 января 2024, проверяем результат + expected_date = "15.01.2024" + date_input.input_date(expected_date) + browser.wait_for_timeout(300) + actual_date = date_input.get_date_field_value() + assert expected_date == actual_date, \ + f"Expected date {expected_date} is not equal actual date {actual_date}" + else: + assert False, "Should be text date input mode" + + # @pytest.mark.develop + def test_date_input_by_text_negative(self, browser: Page) -> None: + """Проверяет возможность задания даты с помощью текстового ввода для некорректных входных значений. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + + if date_input.is_text_input_mode(): + try: + date_input.input_date("1.01.2020") + except AssertionError as e: + actual_err = f"{e}" + expected_err = "Incorrect day format: should be 'dd.mm.yyyy'" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + + try: + date_input.input_date("ff.01.2020") + except AssertionError as e: + actual_err = f"{e}" + expected_err = "Incorrect day value ff for selection" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + + try: + date_input.input_date("01.1.2020") + except AssertionError as e: + actual_err = f"{e}" + expected_err = "Incorrect month format: should be 'dd.mm.yyyy'" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + + try: + date_input.input_date("01.o1.2020") + except AssertionError as e: + actual_err = f"{e}" + expected_err = "Incorrect month value o1 for selection" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + + try: + date_input.input_date("01.01.20") + except AssertionError as e: + actual_err = f"{e}" + expected_err = "Incorrect year format: should be 'dd.mm.yyyy'" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + + try: + date_input.input_date("01.01.2o2o") + except AssertionError as e: + actual_err = f"{e}" + expected_err = "Incorrect year value 2o2o for selection" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + else: + assert False, "Should be text date input mode" + + # @pytest.mark.develop + def test_time_input_after_text_positive(self, browser: Page) -> None: + """Проверяет возможность задания времени для корректного входного значения. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + + if date_input.is_text_input_mode(): + # выбираем 15 января 2024 10:11, проверяем результат + date_input.input_date("15.01.2024") + browser.wait_for_timeout(300) + + expected_time = "10:11" + date_input.input_time(expected_time) + + actual_time = date_input.get_time_field_value() + assert expected_time == actual_time, \ + f"Expected date {expected_time} is not equal actual date {actual_time}" + else: + assert False, "Should be text date input mode" + + # @pytest.mark.develop + def test_time_input_after_date_picker_positive(self, browser: Page) -> None: + """Проверяет возможность задания времени для корректного входного значения. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + + if date_input.is_text_input_mode(): + assert False, "Should be date input mode by date picker" + else: + # выбираем 16 января 2024 08:11, проверяем результат + date_input.input_date("16.01.2024") + browser.wait_for_timeout(300) + + expected_time = "08:11" + date_input.input_time(expected_time) + + actual_time = date_input.get_time_field_value() + assert expected_time == actual_time, \ + f"Expected date {expected_time} is not equal actual date {actual_time}" + + # @pytest.mark.develop + def test_time_input_negative(self, browser: Page) -> None: + """Проверяет возможность задания времени для некорректного входного значения. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + + if date_input.is_text_input_mode(): + # выбираем 15 января 2024 10:11, проверяем результат + date_input.input_date("15.01.2024") + browser.wait_for_timeout(300) + + try: + date_input.time_date("1:01") + except AssertionError as e: + actual_err = f"{e}" + expected_err = "Incorrect time format: should be 'hh:mm'" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + + try: + date_input.input_date("o2.01") + except AssertionError as e: + actual_err = f"{e}" + expected_err = "Incorrect hours value o2 for selection" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + + try: + date_input.input_time("01:1") + except AssertionError as e: + actual_err = f"{e}" + expected_err = "Incorrect time format: should be 'hh:mm'" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + + try: + date_input.input_date("01:o1") + except AssertionError as e: + actual_err = f"{e}" + expected_err = "Incorrect minutes value o1 for selection" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + else: + assert False, "Should be text date input mode" diff --git a/tests/components/unit_tests/test_date_picker.py b/tests/components/unit_tests/test_date_picker.py new file mode 100644 index 0000000..552b534 --- /dev/null +++ b/tests/components/unit_tests/test_date_picker.py @@ -0,0 +1,309 @@ +"""Модуль тестов компонента средства выбора даты. + +Содержит тесты для проверки функциональности +компонента средства выбора даты. +""" + +import pytest +from playwright.sync_api import Page +from pages.main_page import MainPage +from pages.login_page import LoginPage + + +# @pytest.mark.smoke +class TestDatePickerComponent: + """Класс тестов для проверки компонента средства выбора даты. + + Атрибуты: + browser: Фикстура для работы с браузером. + """ + + # @pytest.mark.develop + def test_date_picker_content(self, browser: Page) -> None: + """Проверяет содержимое компонента средства выбора даты. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + date_input.check_switch_mode_button_visibility() + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + + date_picker = date_input.get_date_picker() + date_picker.check_content() + + # @pytest.mark.develop + def test_month_year_selection(self, browser: Page) -> None: + """Проверяет изменение текущего значения месяца и года с помощью кнопок перехода (стрелочек). + + Args: + browser: Экземпляр страницы Playwright. + """ + + months = ["январь", "февраль", "март", "апрель", "май", "июнь", + "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"] + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + date_input.check_switch_mode_button_visibility() + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + + date_picker = date_input.get_date_picker() + + # Проверка наличия кнопок перехода к предыдущему/следующему месяцу + date_picker.check_prev_month_button_visibility() + date_picker.check_next_month_button_visibility() + + current_month_year = date_picker.get_month_year() + start_month, start_year, tmp = current_month_year.split(" ") + + # нажатие на кнопки перехода к предыдущему месяцу (стрелочка влево) и проверка значений + date_picker.click_prev_month_button() + browser.wait_for_timeout(300) + current_month_year = date_picker.get_month_year() + prev_month, prev_year, tmp = current_month_year.split(" ") + + num = months.index(start_month) + expected_month = months[num-1] + expected_year = start_year + + if start_month == "январь": + expected_month = "декабрь" + expected_year = str(int(start_year) - 1) + assert prev_month == expected_month, \ + f"Expected value {expected_month} is not equal actual value {prev_month} on date picker body" + assert prev_year == expected_year, \ + f"Expected value {expected_year} is not equal actual value {prev_year} on date picker body" + + # нажатие на кнопки перехода к следующему месяцу (стрелочка вправо) и проверка возврата к началу + date_picker.click_next_month_button() + browser.wait_for_timeout(300) + current_month_year = date_picker.get_month_year() + next_month, next_year, tmp = current_month_year.split(" ") + + assert next_month == start_month, \ + f"Expected value {start_month} is not equal actual value {next_month} on date picker body" + assert next_year == start_year, \ + f"Expected value {start_year} is not equal actual value {next_year} on date picker body" + + # нажатие на кнопки перехода к следующему месяцу (стрелочка вправо) и проверка значений + date_picker.click_next_month_button() + browser.wait_for_timeout(300) + current_month_year = date_picker.get_month_year() + next_month, next_year, tmp = current_month_year.split(" ") + + num = months.index(start_month) + expected_month = months[num+1] + expected_year = start_year + + if start_month == "декабрь": + expected_month = "январь" + expected_year = str(int(start_year) + 1) + + assert next_month == expected_month, \ + f"Expected value {expected_month} is not equal actual value {next_month} on date picker body" + assert next_year == expected_year, \ + f"Expected value {expected_year} is not equal actual value {next_year} on date picker body" + + # нажатие на кнопки перехода к предыдущему месяцу (стрелочка влево) и проверка возврата к началу + date_picker.click_prev_month_button() + browser.wait_for_timeout(300) + current_month_year = date_picker.get_month_year() + prev_month, prev_year, tmp = current_month_year.split(" ") + + assert prev_month == start_month, \ + f"Expected value {start_month} is not equal actual value {prev_month} on date picker body" + assert prev_year == start_year, \ + f"Expected value {start_year} is not equal actual value {prev_year} on date picker body" + + # @pytest.mark.develop + def test_day_selection_positive(self, browser: Page) -> None: + """Проверяет возможность задания корректного значения дня месяца. + + Args: + browser: Экземпляр страницы Playwright. + """ + + months = ["январь", "февраль", "март", "апрель", "май", "июнь", + "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"] + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + date_input.check_switch_mode_button_visibility() + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + + date_picker = date_input.get_date_picker() + current_month_year = date_picker.get_month_year() + current_month, current_year, tmp = current_month_year.split(" ") + + # выбираем 15 число текущего года и месяца, проверяем результат + date_picker.select_day("15") + browser.wait_for_timeout(300) + + month_num = months.index(current_month) + 1 + expected_date = f"15.{month_num}.{current_year}" + actual_date = date_input.get_date_field_value() + assert expected_date == actual_date, \ + f"Expected date {expected_date} is not equal actual date {actual_date}" + + # @pytest.mark.develop + def test_day_selection_negative(self, browser: Page) -> None: + """Проверяет возможность задания некорректного значения дня месяца. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + date_input.check_switch_mode_button_visibility() + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + + date_picker = date_input.get_date_picker() + + # выбор некорректных значений + incorrect_values = ["0", "32", "ff"] + for value in incorrect_values: + try: + date_picker.select_day(value) + except AssertionError as e: + actual_err = f"{e}" + expected_err =f"Day number {value} is missing on date picker days table" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + + # @pytest.mark.develop + def test_year_and_month_selection_positive(self, browser: Page) -> None: + """Проверяет возможность задания корректных значений года и месяца. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + date_input.check_switch_mode_button_visibility() + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + + date_picker = date_input.get_date_picker() + + # выбираем 15 января 2024, проверяем результат + date_picker.select_year_and_month("2024", "01") + browser.wait_for_timeout(300) + date_picker.select_day("15") + browser.wait_for_timeout(300) + + expected_date = "15.01.2024" + actual_date = date_input.get_date_field_value() + assert expected_date == actual_date, \ + f"Expected date {expected_date} is not equal actual date {actual_date}" + + # @pytest.mark.develop + def test_year_and_month_selection_negative(self, browser: Page) -> None: + """Проверяет возможность задания некорректных значений года и месяца. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + date_input = sidebar_filter.get_start_time_filter() + date_input.check_switch_mode_button_visibility() + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + date_input.click_switch_mode_button() + browser.wait_for_timeout(500) + + date_picker = date_input.get_date_picker() + + # выбор некорректных значений + incorrect_years = ["0", "2222", "1212"] + for value in incorrect_years: + try: + date_picker.select_year_and_month(value, "01") + except AssertionError as e: + actual_err = f"{e}" + expected_err =f"Incorrect year value {value} for selection" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" + + incorrect_months = ["june", "aaaa", "0", "14"] + for value in incorrect_months: + try: + date_picker.select_year_and_month("2012", value) + except AssertionError as e: + actual_err = f"{e}" + expected_err =f"Incorrect month value {value} for selection" + assert expected_err == actual_err, \ + f"Expected error message: '{expected_err}' is nor equal actual error message: '{actual_err}'" diff --git a/tests/components/unit_tests/test_selection_bar.py b/tests/components/unit_tests/test_selection_bar.py new file mode 100644 index 0000000..1b05adb --- /dev/null +++ b/tests/components/unit_tests/test_selection_bar.py @@ -0,0 +1,105 @@ +"""Модуль тестов для проверки операций с компонентом панели выбора значения. + +Содержит тесты для для проверки операций с компонентом панели выбора значения. +""" + +import pytest +from playwright.sync_api import Page +from pages.main_page import MainPage +from pages.login_page import LoginPage + + +# @pytest.mark.smoke +class TestSelectionBarComponent: + """Класс тестов для проверки операций с компонентом панели выбора значения на примере + панели выбора значения 'Тип' в боковой панели фильтрации вкладки 'Системный журнал' + панели событий. + + Атрибуты: + browser: Фикстура для работы с браузером. + """ + + # @pytest.mark.develop + def test_selection_bar_content(self, browser: Page) -> None: + """Проверяет содержимое компонента панели выбора значения. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + sidebar_filter.add_filtering_parameter("filter_type", "Тип") + filter_type_bar = sidebar_filter.get_filtering_parameter("filter_type") + filter_type_title = filter_type_bar.get_selection_bar_title() + assert filter_type_title == "Тип", "Filtering parameter bar 'Тип' is missing" + + # @pytest.mark.develop + def test_selection_values(self, browser: Page) -> None: + """Проверяет возможность выбора значений. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + sidebar_filter.add_filtering_parameter("filter_type", "Тип") + filter_type_bar = sidebar_filter.get_filtering_parameter("filter_type") + + filter_type_bar.open_values_list() + filter_type_bar.select_value("e-nms") + selected_values = filter_type_bar.get_selected_values() + assert len(selected_values) > 0, "No values has been selected" + assert selected_values[0] == "e-nms", f"Got unexpected selected value {selected_values[0]}" + + filter_type_bar.open_values_list() + filter_type_bar.select_value("Технический учет") + selected_values = filter_type_bar.get_selected_values() + assert len(selected_values) > 0, "No values has been selected" + assert selected_values[0] == "e-nms", f"Got unexpected selected value {selected_values[0]}" + assert selected_values[1] == "Технический учет", f"Got unexpected selected value {selected_values[1]}" + + # @pytest.mark.develop + def test_clear_selected_values(self, browser: Page) -> None: + """Проверяет возможность удаления ранее выбранных значений. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + sidebar_filter = system_log_events_container.click_filter_button() + browser.wait_for_timeout(500) + + sidebar_filter.add_filtering_parameter("filter_type", "Тип") + filter_type_bar = sidebar_filter.get_filtering_parameter("filter_type") + filter_type_bar.open_values_list() + filter_type_bar.select_value("e-nms") + browser.wait_for_timeout(300) + + filter_type_bar.clear_selections() + selected_values = filter_type_bar.get_selected_values() + assert len(selected_values) == 0, "Selected values should be deleted"