Released Selenide 6.8.0

Released Selenide 6.8.0

We will find you even in Shadow

Bad morning!

While the world is going crazy, we are releasing Selenide 6.8.0.
Not so many features, rather dependency updates.

Recursive search in shadow dom

As you probably know, Selenide has methods to find elements inside shadow dom. And even in multiple embedded shadow doms:

     "#shadow-host", "#inner-shadow-host")).click();

But you still need to waste time to investigate these doms and find proper locators for all those shadow roots.

Now you can save time with the help of new method shadowDeepCss - it searches the element recursively in all shadow roots all over the dom.


Naturally, there is still a risk that such “too generic” search can find a wrong element which probably resides in another shadow dom, but occasionally matches your locator.
In this case you will need to return to the old good “exact” search.

As in the case of databases and sausages, “it’s better not to look inside” - there is a bunch of tricky javascript for tree search.

See issue 1946.

Thanks to

  1. Boris Osipov for PR 1947, and
  2. Georgegriff for project query-selector-shadow-dom, from where we stole this code. :)

Added method page() not requiring Class argument

Dear Page Object fans, take a seat, this is for you. There is a turning point in your life.

Now you don’t need to pass Class argument to method page(Class pageObjectClass). Wow!

Instead of

SelectsPage page = page(SelectsPage.class);

you can just write

SelectsPage page = page();

I used to think Java couldn’t do that, but then I found a hack.

See PR 1961, and thanks to Tagir Valeev for the hack.

Added annotation @As

… for giving human-readable aliases for page object fields.

1. Without aliases

Assuming you have a page object with @FindBy annotations:

class PageObject {
  SelenideElement header;

and a test like page.header.shouldBe(visible).

In reports, it looks quite long and unreadable:

| open                                  |  | PASS  |
| By.xpath: //table/div[3]/span[4]/h1   | should be(visible)  | FAIL  |

And when the test fails, it’s quite hard to understand which element was not found:

Element not found {By.xpath: //table/div[3]/span[4]/h1}

People often want to give some human-readable names to elements to avoid seeing long ugly xpath’s in reports.

2. Resistance

I have always been against it. I believe that not only reports, but also the tests themselves should be readable. I stand for clean code. If you don’t like the ugly xpath - well, just change it, don’t hide it!

But still decided to meet people’s need. In Selenide 5.17.0, we added method $.as("alias").

3. With aliases

And in this release you can also add annotation @As to page object fields.

class PageObject {
  @As("Large header")
  @FindBy(tagName = "h1")
  SelenideElement header1;

It will look readable in reports:

| open    |   | PASS   |
| title   | should be(visible)   | FAIL   |

And when the test fails, it’s easier to understand which element was not found:

Element "title" not found {By.xpath: //table/div[3]/span[4]/h1}

See issue 1903 and PR 1956.

Don’t forget: everyone lies.

Documentation lies, comments lie, users lie. Sooner or later, the alias will also lie. Someone changed the locator, but forgot the alias. Or the element was copied, but the alias was forgotten to be changed. Etc.

Reports are good, but in the end, only the code can be trusted.

Updated dependencies

  • BrowserUpProxy from 2.2.2 to 2.2.3
  • LittleProxy from 2.0.11 to 2.0.12
  • Netty from 4.1.80.Final to 4.1.82.Final
  • slf4j from 2.0.0 to 2.0.2
  • JUnit from 5.9.0 to 5.9.1 – see release notes

Announced partial mobilization of dependencies!



Latest Selenide download statistics only makes us happy. We passed the 400 thousands line!

Andrei Solntsev