Compare commits

...

5 Commits

Author SHA1 Message Date
Radislav 622eb91474 Merge main into radislav/tests_rack and resolve conflicts 2025-11-22 11:15:39 +03:00
Radislav 1666498a36 Рефакторинг компонента SelectionBar и его локаторов
- Добавлены новые локаторы для расширения функциональности
- Улучшена инициализация компонента с поддержкой поиска по label
- Добавлены методы для работы с ошибками валидации
- Улучшена надежность открытия выпадающих списков
2025-11-22 11:04:52 +03:00
nsubbot 6c6f8c18f2 Добавлена функция выдачи элементов выпвдающего списка для компонента панели выбора значений 2025-11-20 14:11:34 +03:00
nsubbot 42a813180f Добавлен компонент панели выбора значений 2025-11-18 10:46:45 +03:00
nsubbot b4f20aae4c Начальная версия компонента боковой панели параметров фильтрации 2025-11-14 14:44:45 +03:00
17 changed files with 1218 additions and 67 deletions

View File

@ -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

View File

@ -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:
"""Возвращает кнопку фильтрации."""

View File

@ -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"

View File

@ -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

View File

@ -3,7 +3,6 @@
Содержит класс для работы с компонентом панели выбора значения через Playwright.
"""
import re
from playwright.sync_api import Page, Locator, expect
from tools.logger import get_logger
from locators.selection_bar_locators import SelectionBarLocators
@ -20,7 +19,7 @@ class SelectionBarComponent(BaseComponent):
Предоставляет методы для взаимодействия с элементами компонента панели выбора значения.
"""
def __init__(self, page: Page, locator_or_text: str | Locator):
def __init__(self, page: Page, locator_or_text: str | Locator) -> None:
"""Инициализирует компонент панели выбора значения.
Args:
@ -45,15 +44,6 @@ class SelectionBarComponent(BaseComponent):
# При нажатии на панель появляется выпадающий список с параметрами фильтрации для выбора
self.selected_values_list = DropdownList(self.page)
def wait_for_timeout(self, timeout: int) -> None:
"""
Ожидает указанное количество миллисекунд.
Args:
timeout: Время ожидания в миллисекундах
"""
self.page.wait_for_timeout(timeout)
# Действия:
def clear_selections(self) -> None:
"""Удаление ранее выбранных значений"""
@ -64,39 +54,8 @@ class SelectionBarComponent(BaseComponent):
)
clear_button_locator.click()
def get_selection_bar_title(self) -> str:
"""Возвращает название панели выбора значения"""
title_locator = self.selection_bar_locator.locator(SelectionBarLocators.TITLE_LOCATOR)
return title_locator.text_content()
def get_selected_values(self) -> list[str]:
"""Возвращает список выбранных значений"""
selected_values_locator = self.selection_bar_locator.locator(
SelectionBarLocators.PARAMETERS_SELECTED
)
selected_values = selected_values_locator.all_inner_texts()
return selected_values[0].splitlines()
def open_values_list(self) -> None:
"""Открытие выпадающего списка путем нажатия на панель выбора значения"""
expect(self.selection_bar_locator).to_be_visible()
# Проверяем, не открыт ли уже список
parent_class = self.selection_bar_locator.get_attribute("class")
if parent_class and "v-select--is-menu-active" in parent_class:
logger.info("Values list is already open")
return
# Используем force click для обхода перекрывающих элементов
logger.info("Using force click to open the list")
self.selection_bar_locator.click(force=True)
# Ждем появления выпадающего списка
self.wait_for_timeout(1500)
def get_available_options(self) -> list[str]:
"""
Возвращает список всех доступных опций из выпадающего списка.
"""Возвращает список всех доступных опций из выпадающего списка.
Returns:
list[str]: Список доступных опций
@ -121,14 +80,21 @@ class SelectionBarComponent(BaseComponent):
logger.info(f"Found available options: {len(options)} - {options}")
return options
def select_value(self, name: str) -> None:
"""Выбор значения из списка"""
self.selected_values_list.check_item_with_text(name)
self.selected_values_list.click_item_with_text(name)
def get_selection_bar_title(self) -> str:
"""Возвращает название панели выбора значения"""
title_locator = self.selection_bar_locator.locator(SelectionBarLocators.TITLE_LOCATOR)
return title_locator.text_content()
def get_selected_values(self) -> list[str]:
"""Возвращает список выбранных значений"""
selected_values_locator = self.selection_bar_locator.locator(
SelectionBarLocators.PARAMETERS_SELECTED
)
selected_values = selected_values_locator.all_inner_texts()
return selected_values[0].splitlines()
def clear_combobox_field(self, field_name: str, field_locator: str) -> None:
"""
Очищает значение в combobox поле с помощью кнопки закрытия (крестика).
"""Очищает значение в combobox поле с помощью кнопки закрытия (крестика).
Args:
field_name: Название поля для очистки
@ -164,11 +130,40 @@ class SelectionBarComponent(BaseComponent):
msg = f"Close button not found for field '{field_name}', clearing not performed"
logger.info(msg)
def open_values_list(self) -> None:
"""Открытие выпадающего списка путем нажатия на панель выбора значения"""
expect(self.selection_bar_locator).to_be_visible()
# Проверяем, не открыт ли уже список
parent_class = self.selection_bar_locator.get_attribute("class")
if parent_class and SelectionBarLocators.MENU_ACTIVE_CLASS in parent_class:
logger.info("Values list is already open")
return
# Используем force click для обхода перекрывающих элементов
logger.info("Using force click to open the list")
self.selection_bar_locator.click(force=True)
# Ждем появления выпадающего списка
self.wait_for_timeout(1500)
def select_value(self, name: str) -> None:
"""Выбор значения из списка"""
self.selected_values_list.check_item_with_text(name)
self.selected_values_list.click_item_with_text(name)
def wait_for_timeout(self, timeout: int) -> None:
"""Ожидает указанное количество миллисекунд.
Args:
timeout: Время ожидания в миллисекундах
"""
self.page.wait_for_timeout(timeout)
# Проверки:
def check_field_highlighted_error(self, field_name: str, field_locator: str) -> None:
"""
Проверяет, что поле подсвечено цветом ошибки (валидация не пройдена).
"""Проверяет, что поле подсвечено цветом ошибки (валидация не пройдена).
Args:
field_name: Название поля для проверки
@ -194,8 +189,7 @@ class SelectionBarComponent(BaseComponent):
logger.info(f"Field '{field_name}' is correctly highlighted with error color")
def check_field_not_highlighted_error(self, field_name: str, field_locator: str) -> None:
"""
Проверяет, что поле НЕ подсвечено цветом ошибки (валидация успешна).
"""Проверяет, что поле НЕ подсвечено цветом ошибки (валидация успешна).
Args:
field_name: Название поля для проверки

View File

@ -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:
"""Проверяет возможность вертикальной прокрутки формы."""

View File

@ -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')]"

View File

@ -30,4 +30,7 @@ class SelectionBarLocators:
# Локаторы для заголовков и поиска по тексту
TITLE_LOCATOR = "//label"
COMBOBOX_BY_LABEL_XPATH = "//div[@role='combobox' and .//label[text()='{}']]"
COMBOBOX_BY_LABEL_XPATH = "//div[@role='combobox' and .//label[text()='{}']]"
# Класс для проверки активности меню
MENU_ACTIVE_CLASS = "v-select--is-menu-active"

View File

@ -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"

View File

@ -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}'"

View File

@ -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"