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