public void selectAllСheckboxes() {
createOrEditMonitorForm.findElements(By.xpath(".//table//input")).
forEach(e -> e.click());
}
Тест падает с “element is not attached to page document” при клике второго чекбокса. Сама причина падения понятна - после нажатия первого чекбокса, страница перерендеривается и второй чекбокс просто не находит. Но как это исправить я пока не могу понять
Сейчас вам тут начнут советовать Selenide) Но вы можете просто переписать функу так: сначала найдите кол-во чекбоксов, потом столько же раз в цикле найдите один чекбокс и кликните по нему. В Selenide это делается вроде автоматом
public void selectAllCheckboxes() {
int monitorsAmount = createOrEditMonitorForm.findElements(By.xpath(".//table//tbody/tr")).size();
for (int i = 1; i <= monitorsAmount; i++)
createOrEditMonitorForm.find(By.xpath(".//tbody//tr[" + i + "]//input")).click();
}
Не согласен что это костыль. Это скорее “понимание происходящих процессов на странице”. Ну вот взяли вы например и захотели все чекбоксы нажать и что теперь в тупую нажимать все подряд и если этот метод не сработал то любой другой алгоритм это костыль? Нет. Мы понимаем что есть перерендер, что id уже другой. Взяли и переписали метод и все. А отложенная инициализация для пачки чекбоксов как у вас бы выглядела?
Делать отложенную инициализацию для пачки чек-боксов не надо, её надо делать для всех элементов.
Сейчас 99% страниц нормальных приложений почти после любого действия что-то меняют на лету, будете писать циклы на каждый такой случай? И как читать такой код, где стопицот циклов?
Любой цикл вносит кучу лишних строк в код. А чем больше строк - тем дольше и труднее этот код читается.
Из-за использования цикла нужно теперь думать, как избавиться от дублирования локаторов. Один костыль порождает другой.
А так, могло бы быть лаконично написано что-то типа (не Java, но там тоже всё это по аналогии делается же)
Ну так у вас же под капотом все равно те же циклы, берутся элементы и отыскиваются заново и ничего вы с этим не поделаете. Ваш профит только в том что вы это из коробки взяли, а человек взял и осознанно написал сам.
Ну да, можно и на машине ездить без знания как устроен двигатель
Лично моё мнение - зачем создавать локатор, если элемент используется только один раз в одном опредёленном методе? Насколько разрастётся страница, если я все используемые локаторы - вынесу в отдельные переменные.
Я создал отдельную переменную для чекбоксов @FindBy(xpath = “//*[@id=‘monitor-form’]//table//input”)
private ListWebElementFacade submonitorsCheckboxes;
Но метод все равно падает, с тем же эксепшином.
Что вы имеете ввиду под “отложенной инициализацией”?
Для этого нужно использовать хотя бы штатную PageFactory (для начала - потом придёт понимание что нужно писать своё)
Просто так эта магия не будет работать.
Я бы сказал отличное решение, если так же озаботиться написанием своих аннотаций/атрибутов и сопутствующих вспомогательных классов, а не только использовать свой декоратор. Ну и конечно реализовать возможность использовать свои классы для типов элементов.
Из полезных вариантов можно выделить:
Название родительского элемента - полезно в так называемых блоках, чтобы элементы искались в нем, а не на всей странице.
Таймаут поиска элемента. Можно указать у конкретного элемента, сколько времени будем его искать прежде чем выкинем эксепшн.
Лично я использую первый вариант, второй редко пока где пригождался.
Ну и учитывая что в атрибутах/аннотациях можно использовать константы, то можно обойтись без хардкода и выделить все настройки в отдельный конфиг файл.