Вышла Selenide 6.15.0

Вышла Selenide 6.15.0

Нештатный сход фичeприпаса
29.05.23

Доброй ночи!

Есть люди, которые постоянно деплоят, а есть люди, которые один раз в жизни где-то выучили, что должен быть РЕЛИЗ — и копят, копят, копят фичи для этого релиза.
А счастливый дедушка-мейнтейнер думает, что ему хорошо.
И как использовать опенсорс-проект, если вдруг случайно окажется, что этот дедушка — законченный мудак?

Как вы поняли, мы выпустили новую версию 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.


Клик теперь проверяет, что элемент не disabled

Как вы знаете, метод $.click() требует, чтобы элемент был видимым (более точно: либо элемент должен быть видимый, либо иметь css свойство opacity: 0).

НО до сих пор Селенид не проверял, что элемент enabled. Другими словами,

Селенид разрешал кликать на disabled элементы.

  1. В пользу этого решения был такой аргумент: а вдруг автор теста и хочет кликнуть на задизейбленый элемент и убедиться, что ничего не произошло?
  2. Против этого решения был другой аргумент: такое поведение может спровоцировать нестабильные тесты:
    • тест кликает на кнопку, не дожидаясь, пока она станет enabled
    • по факту клик не случится (но и никаких ошибок не возникнет)
    • и позже тест упадёт из-за не случившегося клика (и будет очень сложно понять, что произошло)
    • или ещё хуже: тест может остаться ложно позитивным.

В общем, теперь аргумент №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

Мы поменяли внутреннее устройство условий для коллекций (класс 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)

Что нам это даёт?

В будущем это откроет нам возможности для улучшений проверок коллекций:

  1. Можно будет сильно ускорить проверки: например, быстро получить тексты всех элементов коллекции за один вызов JavaScript кода.
  2. В сообщении об ошибке писать не “актуальные тексты на момент составления сообщения”, а “актуальные тексты на момент последней проверки”. Как в этой проблеме, только с коллекциями.

См. PR 2312 и PR 2307.


Новости

Selenide meme


Андрей Солнцев

ru.selenide.org

29.05.23