"""Модуль компонента средства выбора даты. Содержит класс для работы с средством выбора даты через 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