"""Модуль rack_locators содержит локаторы элементов страницы стойки. Класс RackLocators хранит XPath локаторы для взаимодействия с элементами интерфейса стойки оборудования в тестах. """ class RackLocators: """Класс для хранения локаторов элементов страницы стойки. Содержит локаторы в формате XPath для поиска элементов: - Вкладки стойки (верхние вкладки) - Секции лицевой и обратной сторон стойки - Юниты и устройства на стойке - Поля формы редактирования и создания стойки - Контейнеры и структурные элементы """ # Основной контейнер вкладок стойки (верхние вкладки) TABS_CONTAINER = "//div[@class='v-tabs__container']" # Все элементы верхних вкладок стойки ALL_TABS = "//div[@class='v-tabs__container']//a[contains(@class, 'v-tabs__item')]" # Кнопка редактирования свойств стойки EDIT_BUTTON = "//button[@data-v-5f34ceac and contains(@class, 'font-weight-medium')]" # Кнопка "Скрыть стойку" HIDE_RACK_BUTTON = "//div[contains(@class, 'cabinet_hide_button')]//i[contains(@class, 'material-icons') and text()='navigate_before']" # Кнопка "Показать стойку" SHOW_RACK_BUTTON = "//div[contains(@class, 'cabinet_hide_button')]//i[contains(@class, 'material-icons') and text()='navigate_next']" # Универсальный локатор для любой вкладки по имени TAB_BY_NAME = "//div[@class='v-tabs__container']//a[contains(@class, 'v-tabs__item') and contains(., '{}')]" # Конкретные вкладки по тексту GENERAL_INFO_TAB = "//div[@class='v-tabs__container']//a[contains(@class, 'v-tabs__item') and contains(., 'Общая информация')]" MAINTENANCE_TAB = "//div[@class='v-tabs__container']//a[contains(@class, 'v-tabs__item') and contains(., 'Обслуживание')]" EVENTS_TAB = "//div[@class='v-tabs__container']//a[contains(@class, 'v-tabs__item') and contains(., 'События')]" SERVICES_TAB = "//div[@class='v-tabs__container']//a[contains(@class, 'v-tabs__item') and contains(., 'Сервисы')]" # Классы для проверки активности ACTIVE_TAB_CLASSES = ["accent--text", "v-tabs__item--active"] # Локатор для активной вкладки ACTIVE_TAB = "//div[@class='v-tabs__container']//a[contains(@class, 'v-tabs__item--active')]" # Контейнер формы FORM_CONTAINER = "//div[contains(@class, 'container')]" # Локаторы полей формы редактирования стойки NAME_FIELD = "//input[@aria-label='Имя']" SERIAL_NUMBER_FIELD = "//input[@aria-label='Серийный номер']" INVENTORY_NUMBER_FIELD = "//input[@aria-label='Инвентарный номер']" CABLE_ENTRY_FIELD = "//input[@aria-label='Ввод кабеля']" STATUS_FIELD = "//input[@aria-label='Состояние']" HEIGHT_FIELD = "//input[@aria-label='Высота в юнитах']" OWNER_FIELD = "//input[@aria-label='Владелец']" SERVICE_ORG_FIELD = "//input[@aria-label='Обслуживающая организация']" PROJECT_FIELD = "//input[@aria-label='Проект/Титул']" # Локаторы полей формы создания стойки RACK_NAME_FIELD = "//div[contains(@class, 'container')]//label[text()='Имя']/following-sibling::input" RACK_HEIGHT_FIELD = "//div[contains(@class, 'container')]//div[contains(@class, 'v-input__slot') and .//label[text()='Высота в юнитах']]" RACK_DEPTH_FIELD = "//div[contains(@class, 'container')]//div[contains(@class, 'v-input__slot') and .//label[text()='Глубина (мм)']]" RACK_SERIAL_FIELD = "//div[contains(@class, 'container')]//label[text()='Серийный номер']/following-sibling::input" RACK_INVENTORY_FIELD = "//div[contains(@class, 'container')]//label[text()='Инвентарный номер']/following-sibling::input" RACK_COMMENT_FIELD = "//div[contains(@class, 'container')]//label[text()='Комментарий']/following-sibling::input" RACK_CABLE_ENTRY_FIELD = "//div[contains(@class, 'container')]//div[contains(@class, 'v-input__slot') and .//label[text()='Ввод кабеля']]" RACK_STATE_FIELD = "//div[contains(@class, 'container')]//div[contains(@class, 'v-input__slot white') and .//label[text()='Состояние']]" RACK_OWNER_FIELD = "//div[contains(@class, 'container')]//div[contains(@class, 'v-input__slot') and .//label[text()='Владелец']]" RACK_SERVICE_ORG_FIELD = "//div[contains(@class, 'container')]//div[contains(@class, 'v-input__slot') and .//label[text()='Обслуживающая организация']]" RACK_PROJECT_FIELD = "//div[contains(@class, 'container')]//div[contains(@class, 'v-input__slot') and .//label[text()='Проект/Титул']]" # Локатор для родительского контейнера поля ввода INPUT_PARENT_CONTAINER = "xpath=./ancestor::div[contains(@class, 'v-input')]" # CSS селекторы для ошибок валидации ERROR_CSS_SELECTORS = ".error--text, .v-input--error" # ================ ЛОКАТОРЫ ДЛЯ СТРУКТУРЫ СТОЙКИ =================== # Основной контейнер стойки MAIN_CONTAINER = "//div[contains(@class, 'layout cabinet')]" # Кнопки переключения сторон FRONT_SIDE_BUTTON = "//button[contains(@class, 'v-btn')]//div[contains(@class, 'v-btn__content') and normalize-space(text())='Лицевая сторона']" BACK_SIDE_BUTTON = "//button[contains(@class, 'v-btn')]//div[contains(@class, 'v-btn__content') and normalize-space(text())='Обратная сторона']" # Активная кнопка (имеет класс primary, но НЕ имеет outline) ACTIVE_SIDE_BUTTON = "//button[contains(@class, 'v-btn') and contains(@class, 'primary') and not(contains(@class, 'v-btn--outline'))]" ACTIVE_SIDE_BUTTON_TEXT = "//button[contains(@class, 'v-btn') and contains(@class, 'primary') and not(contains(@class, 'v-btn--outline'))]//div[contains(@class, 'v-btn__content')]" # Неактивная кнопка (имеет outline или не имеет primary) INACTIVE_SIDE_BUTTON = "//button[contains(@class, 'v-btn') and (contains(@class, 'v-btn--outline') or not(contains(@class, 'primary')))]" # Кнопка добавления (add_circle) ADD_CIRCLE_BUTTON = "//i[contains(text(), 'add_circle')]" # Все юниты на стойке ALL_UNITS = "//div[contains(@class, 'unit')]" # Позиции юнитов UNIT_POSITIONS = "//div[contains(@class, 'headline') and contains(@class, 'test-xs-center') and contains(@class, 'unit-positions')]" # Локатор для устройств DEVICE_ELEMENTS = "//div[contains(@class, 'parent-class')]" # Локатор для слотов в устройствах DEVICE_SLOTS = "//div[contains(@class, 'slot')]"