233 lines
10 KiB
Python
233 lines
10 KiB
Python
"""Модуль компонента средства выбора даты.
|
||
|
||
Содержит класс для работы с средством выбора даты через 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, exact=True)
|
||
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 = {"01":"январь",
|
||
"02":"февраль",
|
||
"03":"март",
|
||
"04":"апрель",
|
||
"05":"май",
|
||
"06":"июнь",
|
||
"07":"июль",
|
||
"08":"август",
|
||
"09":"сентябрь",
|
||
"10":"октябрь",
|
||
"11":"ноябрь",
|
||
"12":"декабрь"}
|
||
days_per_month = {"01":31,
|
||
"02":28,
|
||
"03":31,
|
||
"04":30,
|
||
"05":31,
|
||
"06":30,
|
||
"07":31,
|
||
"08":31,
|
||
"09":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")).lstrip('0')
|
||
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
|