Released Selenide 6.15.0

Released Selenide 6.15.0

Accidental release of a feature ordnance
29.05.23

Good night!

We released Selenide 6.15.0 with quite serious internal changes.

Merged project selenide-selenoid into selenide

This allows us to easily change and release these projects. For you, the dependency declaration will change.

Instead of

  testImplementation("org.selenide:selenide-selenoid:2.3.7")

You will need to use:

  testImplementation("com.codeborne:selenide-selenoid:6.15.0")

See PR 2292.


Merged project selenide-appium into selenide

This allows us to easily change and release these projects. For you, just the dependency version will change.

You will need to update selenide-appium from 2.8.1 to 6.15.0.

See PR 2291.


Now Click checks that the element is not disabled

As you know, method $.click() first checks that the element is visible (more specifically, the element should be either visible or have css property opacity: 0).

BUT until now, Selenide didn’t check that the element is enabled. In other words,

Selenide did allow to click disabled elements.

  1. Argument in favor of this decision: what if test author does want to click the disabled element and make sure that nothing happens?
  2. Argument against this decision: this behavior can cause flaky tests:
    • the test clicks a button without waiting until the buttons gets enabled;
    • de-facto click didn’t happen (but no errors were thrown);
    • and later the test fails because the click didn’t happen (and it will be very hard to understand why the test failed).
    • or even worse: the test may remain false positive.

So now argument #2 has won. Now method $.click() will wait until the element gets enabled.
If the element is not enabled, the click will fail.

Now you can shorten your tests even more:

Replace $.shouldBe(enabled).click() by just $.click().

P.S. If you’re in the #1 camp, you can use $.shouldBe(disabled) instead of clicking.

See issue 2288. Thanks to Maksim @Au6ojlut for PR 2290.


Escape newlines in text report

If you tried using a multi-line string in your test:

$.shouldHave(text("Hello\n multi\n line\n world");

Then you might have noticed that in the report this line looked clumsy and broke the entire table.

Now it will look good.

See issue 2283. Thanks to Maksim @Au6ojlut for PR 2284.


Combined selectors for mobile apps

When testing mobile apps, it would be convenient to use two selectors in a check: one for Android, and the other for iOS.
Previously, you had to come up with helper methods or use IFs in tests.

Now you can use a single selector using CombinedBy:

import static com.codeborne.selenide.appium.selector.CombinedBy.android;
import static com.codeborne.selenide.appium.AppiumSelectors.byTagAndName;

$(android(byText("Hello, Android user!")).ios(byText("Hello, iOS user!")))
  .shouldHave(text("Hello, Android user!"));


New checks for mobile apps

A similar solution for checks: now you can declare a single check for Android, and iOS using class 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;

// A single element check:
$.shouldHave(attribute(
  android("content-desc").ios("name"), 
  "To do or not to do"
));

// A collection check:
$$.shouldHave(attributes(android("text"), 
  "First", 
  "Second", 
  "Third"
));


New selectors for mobile apps

We also added a bunch of selectors to find mobile elements by tag, text, substring etc.:

import static com.codeborne.selenide.appium.AppiumSelectors.*;

$(byAttribute("content-desc", "Hello")).click();
$(byContentDescription("Hello")).click();
$(byTagAndAtttribute("android.widget.TextView", "Good")).click();
$(byTagAndName("XCUIElementTypeStaticText", "bye")).click();
$(withTagAndName("XCUIElementTypeText", "ugly xpath world")).click();

See issue 2300. Thanks to Amuthan Sakthivel for PR 135. See also PR 2315.


Switch context in mobile apps

Mobile apps often open some content in an embedded web browser (WebView). Sometimes mobile apps work entire in WebView. When testing such apps, you often need to switch between “native” and “web” context.

Now we have convenient methods to switch between contexts:

// Here we are in the "native" context
open();
$(accessibilityId("URL input field")).setValue("www.google.com");
$(accessibilityId("Go To Site button")).click();

// Oops, and we're already in the "web" context:
switchTo().context("WEBVIEW_com.saucelabs.mydemoapp.rn");
$("#i-am-not-a-robot").click();

assertThat(getContextHandles()).hasSize(2)

See PR 2308.
Thanks to Amuthan Sakthivel for PR 149.


Refactoring of CollectionCondition

We have changed the internal structure of collection conditions (class CollectionCondition).

If you wanted to create a custom collection condition, You had to implement method 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);
  }
}
$$(".moron").shouldHave(allTextsStartingWithZ)

This test method will stay for some time (for backward compatibility), but the recommended method now will be 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);
  }
}
$$(".moron").shouldHave(allTextsStartingWithZ)

What does it give us?

In the future, it will open up opportunities for us to improve collection checks:

  1. It allows us to greatly speed up the checks: for example, quickly get the texts of all elements with just one JS call.
  2. In the error message, we can write “actual texts at the moment of last check” instead of “actual texts at the moment of error message generation”. The same problem for a single element was described here. Now it’s the same for collections.

See PR 2312 and PR 2307.


News

Selenide meme


Andrei Solntsev

selenide.org

29.05.23