В своем проекте использую следующий подход к описанию элементов - в классах Page Object храню исключительно By локаторы элементов, которые при необходимости использую в коде методов в $ и $$.
private static final By SOME_LOCATOR = By.id("123");
// ...
public void somePageObjectMethod() {
$(SOME_LOCATOR).click();
}
Возникла идея расширить класс локатора элемента (By), чтобы получить следующие возможности:
Сразу указывать user-friendly описание элемента, которое затем используется в toString() (в случае ошибки будет отображаться не только локатор, но и описание)
private static final By SOME_FIELD = By.id("123").as("Элемент Элементович");
Сразу указывать в каком frame живет элемент, чтобы в теле findElement / findElements сначала происходило переключение на нужный фрейм.
private static final By SOME_FIELD = By.id("123").inFrame("parentFrame", "childFrame");
Указывать необходимость ожидания, скажем jQuery.active == 0 в теле findElement / findElements . Сам класс с методом ожидания указывать Селениду единожды
// Где-то в коде автотестов
static {
// SomeAjaxExpectant реализует нужны интерфейс всего с одним методом
// В реализуемом методе описываются некие действия ожидания, например jQuery.active == 0
Selenide.addExpectant(new SomeAjaxExpectant());
}
// В пейдж обжекте
private static final By SOME_FIELD = By.id("123").withWaiting();
Иметь возможность работать с параметризованными локаторами. Например в классе PageObject объявить локатор xpath, который в себе содержит некоторые значение известные лишь в ходе выполнения теста.
private static final By SOME_FIELD = By.xpath("//div[@someAttr='{0}']");
public void someMethod() {
$(SOME_FIELD.withParams("some attribute value")).click();
}
Что думаете? Кому-нибудь это было бы полезным? Плюсы и минусы ?
Первый пункт был бы сразу полезен мне на проектах, т.к. описание элемента в той же строке что и сам элемент упрощает и уменьшает код, не надо использовать большие конструкции комментариев.
Второй пункт полезен будет не всем и не сразу, но для некоторых частей будет полезно, но я так понимаю, что после отработки метода, переключаться на родительский фрейм надо будет вручную? Где фокус остаётся после отработки этого метода?
Третий пункт полезен, т.к. все мы сталкиваемся с аяксами, и у всех есть методы ожидания, надо это всё собрать в одно место, когда мы все используем Селенид.
Четвёртый пункт тоже полезен, много видел вопросов на форумах про такую штуку, здесь всё понятно и просто.
Если это всё реализовано, то почему бы не состыковаться с уважаемым Андреем и обговорить коммиты. Дмитрий, а тесты для этих изменений есть?
Спасибо за комментарий!
Немного проясню по пунктам:
2) Фокус останется в том фрейме, на который произошло переключение перед поиском элемента.
Если фрейм изначально у By не задан, то никакого переключения не будет. Если же элемент живет в корне, то можно объявить локатор так:
private static final By SOME_FIELD = By.id("123").inRoot(); // или для наглядности .inDefaultContent();
Насчет тестов - если все эти пункты действительно стоит включить в Selenide, то я конечно же сделаю PR в т.ч. и с тестами.
Поддерживаю всеми руками за! Главное чтобы Simple Report у селенида обрабатывал такую штуку: если есть метод “.as” то в колонку “Element” писать параметр метода. Или же добавить колонку для подобных описывающих методов
А мне кажется, суть и вся прелесть Selenide - это его простота и что в нем нет ничего лишнего.
А по поводу
Так сейчас и выводится очень удобное описание элемента - особенно когда там какие то атрибуты то есть то нету.
Фреймы - ну такое, далеко не в каждом проекте есть необходимость в них.
Такая ожидалка это по моему прошлый век.
Это не проблема, это НЕ знание как пользоваться xpath-ом.
Например $(SOME_FIELD).$(By.xpath("./self::*[@disabled=‘disabled’]")) будет искать элементы SOME_FIELD с атрибутом disabled=‘disabled’.
@dimand58 Привет!
Я ещё раз сел и внимательно перечитал и понял, что я категорически согласен с @kasheylm
Если ещё первый пункт хоть как-то ок (ну может, и правда у кого-то что-то читаемее станет), то остальные вещи надо просто по-другому решать. Второе, может, стоит ещё обдумать, но третий и четвёртый - это точно оверкил. Это можно и нужно решать проще.
Например,
можно сделать публичный метод типа
public SelenideElement divByAttr(String attributeValue) {
return $(String.format("//div[@someAttr=’%s’]", attributeValue));
}
метод “.withWaiting();” точно не нужен хотя бы потому, что в Selenide все методы и так умеют ждать.
Предложенные примеры могут зайти как кастомная реализация для одного проекта, можете сделать свой форк и его продвигать, но в selenide - это точно не нужно.