Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Get element locator from WebElement #1829

Open
skyhirider opened this issue Jul 12, 2024 · 5 comments
Open

Feature: Get element locator from WebElement #1829

skyhirider opened this issue Jul 12, 2024 · 5 comments

Comments

@skyhirider
Copy link

Feature and motivation

Each WebElement must have a By locator that uniquely locates it.
As far as I can tell, the locator is protected and not available.
There are cases when pulling it out and re-using it would be helpful.
I propose exposing a getter for the By locator.

Usage example

You initialize a web element and it eventually becomes stale.
To refresh it, you either need to

  • remember the locator and re-load it by calling the locator. Not always possible if you pass the element around
  • use the @findby annotation so it auto refresh when stale. Can't use that if locators need to have variables.

If I need to check if an element exists

  • I used @findby, can't do that as it will patiently wait until it times out. Need to do a driver.findElementsBy(locator..).size()>0 , but can't as I can't reach the By to do this. So I copy paste my locator, once in annotation and once as a By in my fields, effectively duplicating code
  • if I do the same thing with a webelemennt I previous located, I can at least catch a stale exception and handle that, but would be nicer if I could get the by and fire up findelements to check if it still exists.

What if, instead, we could get the locator from each element. Would help with duplicating locators, as well as constructing new webelements or running the locators against the page again.

Opening after being told on the Selenium issues I should open one for the driver specification instead
SeleniumHQ/selenium#13660

@skyhirider
Copy link
Author

To illustrate how much this is needed, people have been using inefficient workarounds such as these where the string is parsed to get the By locators and reconstruct them - https://stackoverflow.com/a/56315588/1341887

It works, but it this really how we should be getting the field?

@jgraham
Copy link
Member

jgraham commented Dec 5, 2024

I don't quite understand the feature request here:

Each WebElement must have a By locator that uniquely locates it.

That doesn't seem true. In general locators are not guaranteed to find the same element after a DOM mutation. For example an id selector wouldn't find the same element if its id was changed, an n-th child selector wouldn't find the same element if a previous child was removed from the DOM.

In general the thing that does identify a given element is its WebElement id. If you want to check if a specific element still exists then checking if you can resolve its id would be the correct approach.

As far as I can tell, the locator is protected and not available.

If the request is for an API to return a locator that matches an element, that seems plausible, but the benefits of standardisation (vs letting clients implement this) seem relatively weak. In general there's more than one way to address a specific element, and standardisation would require us to pick a specific algorithm and implement it in all browsers. But I don't immediately see any use case that benefits from that, other than "clients don't have to implement it themselves".

@skyhirider
Copy link
Author

That doesn't seem true. In general locators are not guaranteed to find the same element after a DOM mutation.

Agreed, what I meant was getting the By locator for cases where it makes sense. It will still be up to the programmer to make sane decisions and know when this does not make sense.

In general the thing that does identify a given element is its WebElement id.

I do not need to check if an element exists, the gap is to reload an existing element using the By locator when it makes sense.

The issue I have when writing my page object classes is I define elements with

@By(xpath ='//someElement')
WebElement someElementWebelement

which works and handles stale elements too.

But when I need to check if the element exists, I need to call driver.findElementsBy('//someelement').isEmpty(), which means copy pasting the xpath instead of using a constant or variable.

A cleaner way to write it would be

driver.findElementBy(someElementWebelement.getBy()).isEmpty()

or even

someElementWebelement.exists()

which would bypass the long timeout and would tell me immediately if the element is on the page I have opened.

I could make my own web element and wrap the one that exists inside of it, but would be saner if the real one was updated, as it seems I am not the only one with the same issue, at least based on the stack article and a few others that I have found.

In terms of clients implementing this, when I suggested an update to Selenium the issue was closed with a redirect here, that the spec needs to change first.

@jgraham
Copy link
Member

jgraham commented Dec 5, 2024

Ah, I see. So the use case is having the client remember the selector that was used to select an element, to make it easy to re-run the same selector later? In that case I don't think there's much we can do on the protocol side to help; the browser isn't going to maintain such a mapping. This seems like a client API design question, so I'd suggest reopening the selenium issue with the description above of your use case, which hopefully makes things clearer on their side.

@skyhirider
Copy link
Author

Ah, I see. So the use case is having the client remember the selector that was used to select an element, to make it easy to re-run the same selector later? In that case I don't think there's much we can do on the protocol side to help; the browser isn't going to maintain such a mapping. This seems like a client API design question, so I'd suggest reopening the selenium issue with the description above of your use case, which hopefully makes things clearer on their side.

Thanks, I can open another Selenium issue but I feel I will be redirected to here again and it will be closed, like it was previously here SeleniumHQ/selenium#13660

Does the W3C spec prevent getting the locators out of a web element in any way, or is it up the the client implementers to make a choice to expose the locator ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants