Доброй ночи!
Есть люди, которые постоянно деплоят, а есть люди, которые один раз в жизни где-то выучили, что должен быть РЕЛИЗ — и копят, копят, копят фичи для этого релиза.
А счастливый дедушка-мейнтейнер думает, что ему хорошо.
И как использовать опенсорс-проект, если вдруг случайно окажется, что этот дедушка — законченный мудак?
Как вы поняли, мы выпустили новую версию Selenide 6.15.0 с серьёзными такими внутренними переделками.
selenide-selenoid в selenideЭто позволит нам легче менять и релизить эти проекты. Для вас поменяется объявление зависимости. Вместо
testImplementation("org.selenide:selenide-selenoid:2.3.7")
Теперь нужно будет прописать:
testImplementation("com.codeborne:selenide-selenoid:6.15.0")
См. PR 2292.
selenide-appium в selenideЭто позволит нам легче менять и релизить эти проекты. Вам всего лишь нужно будет обновить версию selenide-appium с 2.8.1 на 6.15.0
См. PR 2291.
Как вы знаете, метод $.click() требует, чтобы элемент был видимым (более точно: либо элемент должен быть видимый, либо иметь css свойство opacity: 0).
НО до сих пор Селенид не проверял, что элемент enabled. Другими словами,
Селенид разрешал кликать на
disabledэлементы.
В общем, теперь аргумент №2 победил. Теперь метод $.click() дождётся, пока элемент станет enabled. А если не станет - клик упадёт.
Теперь вы можете смело сократить все свои тесты:
$.shouldBe(enabled).click()заменить на$.click().
P.S. Если вы из лагеря аргумента №1, то можете вместо клика использовать $.shouldBe(disabled).
См. issue 2288. Спасибо Maksim @Au6ojlut за PR 2290.
Если вы пробовали использовать в тесте многострочную строку:
$.shouldHave(text("Если\n дедушка\n законченный\n мудак");
То могли заметить, что в отчёте эта строка выглядела коряво и ломала всю таблицу.
А теперь будет красиво.
См. issue 2283. Спасибо Maksim @Au6ojlut за PR 2284.
При тестировании мобильных приложений удобно задать в одной проверке два селектора: отдельно для Android и iOS.
Раньше приходилось придумывать вспомогательные методы или городить ифы.
Теперь же можно объявить “комбинированный” селектор с помощью CombinedBy:
import static com.codeborne.selenide.appium.selector.CombinedBy.android;
import static com.codeborne.selenide.appium.AppiumSelectors.byTagAndName;
$(android(byText("Бибер")).ios(byText("Долик")))
.shouldHave(text("Бибер"));
Аналогичное решение для проверок: теперь можно одной строкой задать “комбинированную” проверку и для Android, и для iOS с помощью класса CombinedAttribute:
import static com.codeborne.selenide.appium.conditions.CombinedAttribute.android;
import static com.codeborne.selenide.appium.AppiumCondition.attribute;
import static io.appium.java_client.AppiumBy.accessibilityId;
// Проверка элемента:
$.shouldHave(attribute(
android("content-desc").ios("name"),
"Гойду, Жерасимов, где, сука, ебоприпасы?"
));
// Проверка коллекции:
$$.shouldHave(attributes(android("text"),
"Бздила картонный",
"Болтун безмозглый",
"Вазелиновая коррекция",
"Зять-«у*бок»",
"Сын-отморозок"
));
Для кучи, нас появилась пачка новых селекторов для поиска элементов по тэгу, тексту, подстроке и т.п.:
import static com.codeborne.selenide.appium.AppiumSelectors.*;
$(byAttribute("content-desc", "Hello")).click();
$(byContentDescription("Hello")).click();
$(byTagAndAtttribute("android.widget.TextView", "Не")).click();
$(byTagAndName("XCUIElementTypeStaticText", "вы е")).click();
$(withTagAndName("XCUIElementTypeText", "бываться на красной площади")).click();
См. issue 2300. Спасибо Amuthan Sakthivel за PR 135. Также см. PR 2315.
Зачастую мобильные приложения открывают какой-то контент во встроенном браузере (WebView). А то и полностью построены на WebView. При тестировании таких приложений требуется переключаться между “нативным” и “веб” контекстом.
Теперь для переключения есть удобные методы:
// Тут мы в "нативном" контексте
open();
$(accessibilityId("URL input field")).setValue("www.google.com");
$(accessibilityId("Go To Site button")).click();
// Опа, и мы уже в "веб" контексте:
switchTo().context("WEBVIEW_com.saucelabs.mydemoapp.rn");
$("#i-am-not-a-robot").click();
assertThat(getContextHandles()).hasSize(2)
См. PR 2308.
Спасибо Amuthan Sakthivel за PR 149.
Мы поменяли внутреннее устройство условий для коллекций (класс CollectionCondition).
Раньше, если вы хотели создать кастомную проверку для коллекций, вы должны были реализовать метод test(elements):
var allTextsStartingWithZ = new CollectionCondition() {
public boolean test(List<WebElement> webElements) {
return webElements.stream()
.map(webElement -> webElement.getText().startsWith("Z"))
.reduce(true, (x, y) -> x && y);
}
}
$$(".mudak").shouldHave(allTextsStartingWithZ)
Этот метод останется ещё на какое-то время (для сохранения обратной совместимости), но рекомендуемый метод теперь будет check(CollectionSource collection):
var allTextsStartingWithZ = new CollectionCondition() {
public CheckResult check(CollectionSource collection) {
List<WebElement> elements = collection.getElements();
List<String> actualTexts = ElementsCollection.texts(elements);
boolean allMatched = webElements.stream()
.map(webElement -> webElement.getText().startsWith("Z"))
.reduce(true, (x, y) -> x && y);
return new CheckResult(allMatched, actualTexts);
}
}
$$(".mudak").shouldHave(allTextsStartingWithZ)
В будущем это откроет нам возможности для улучшений проверок коллекций:

29.05.23