Get the By locator of an already found WebElement

时光怂恿深爱的人放手 提交于 2019-11-29 11:04:06

问题


Is there an elegant way to get the By locator of a Selenium WebElement, that I already found/identified?

To be clear about the question: I want the "By locator" as used to find the element. I am in this case not interested in a specific attribute or a specific locator like the css-locator.

I know that I could parse the result of a WebElement's toString() method:

WebElement element = driver.findElement(By.id("myPreciousElement"));
System.out.println(element.toString());

Output would be for example:

[[FirefoxDriver: firefox on WINDOWS (....)] -> id: myPreciousElement]

if you found your element by xpath:

WebElement element = driver.findElement(By.xpath("//div[@someId = 'someValue']"));
System.out.println(element.toString());

Then your output will be:

[[FirefoxDriver: firefox on WINDOWS (....)] -> xpath: //div[@someId = 'someValue']]

So I currently wrote my own method that parses this output and gives me the "recreated" By locator.


BUT is there a more elegant way already implemented in Selenium to get the By locator used to find the element?

I couldn't find one so far.

If you are sure, there is none out of the box, can you think of any reason why the API creators might not provide this functionality?



*Despite the fact that this has nothing to do with the question, if someone wonders why you would ever need this functionality, just 2 examples:

  • if you use PageFactory you most likely will not have the locators as as member variables in your Page class, but you might need them later on when working with the page's elements.
  • you're working with APIs of people who just use the Page Object Pattern without PageFactory and thus expect you to hand over locators instead of the element itself.*

回答1:


Answer is No. You cannot extract a By from a previously found WebElement by default.

That being said - it's possible to implement a custom solution, but Selenium does not offer this out-of-the-box.

Consider the following, on "why"..

By by = By.id("someId");
WebElement e = driver.findElement(by);

you already have the By object, so you wouldn't need to call something like e.getBy()




回答2:


No, there's not. I have implemented a possible solution as a proxy:

public class RefreshableWebElement implements WebElement {

    public RefreshableWebElement(Driver driver, By by) {
        this.driver = driver;
        this.by = by;
    }

    // ...

    public WebElement getElement() {
        return driver.findElement(by);
    }

    public void click() {
        getElement().click();
    }

    // other methods here
}



回答3:


For me worked with commons-lang3

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.7</version>
</dependency>

For remote web element use method like:

protected String getLocator(WebElement element) {
        try {
            Object proxyOrigin = FieldUtils.readField(element, "h", true);
            Object locator = FieldUtils.readField(proxyOrigin, "locator", true);
            Object findBy = FieldUtils.readField(locator, "by", true);
            if (findBy != null) {
                return findBy.toString();
            }
        } catch (IllegalAccessException ignored) {
        }
        return "[unknown]";
    }



回答4:


I had written this utility function which returns a string combination of locator strategy + locator value.

private String getLocatorFromWebElement(WebElement element) {

    return element.toString().split("->")[1].replaceFirst("(?s)(.*)\\]", "$1" + "");
}



回答5:


There is no elegant way provided by Selenium. And this is horrible

1) PageObject and PageFactory implies that we have WebElements in Page classes, but we don't have locators of those elements.

2) If I find element as descendant of current element using webElement.findElement(By), then I don't have the locator of this descendant even if I stored parent's locator in the variable.

3) If I use findElements function that returns List of elemetns, then I don't have locator for each specific element.

4) Having locator for element is useful at least because ExpectedConditions with locator as parameter are much better implemented than ExpectedConditions with WebElement as parameter.

For me Selenium is ill-conceived and poorly implemented library




回答6:


Currently there is no specific method from selenium's end to do so. What you can do is write your custom method. You will get the clue of what selector type and path is used by just printing the webElement you have.

It looks something like this

[[ChromeDriver: chrome on XP (d85e7e220b2ec51b7faf42210816285e)] -> xpath: //input[@title='Search']]

Now, what you need to do is to extract the locator and its value. You can try something like this

`private By getByFromElement(WebElement element) {

    By by = null;
    //[[ChromeDriver: chrome on XP (d85e7e220b2ec51b7faf42210816285e)] -> xpath: //input[@title='Search']]
    String[] pathVariables = (element.toString().split("->")[1].replaceFirst("(?s)(.*)\\]", "$1" + "")).split(":");

    String selector = pathVariables[0].trim();
    String value = pathVariables[1].trim();

    switch (selector) {
        case "id":
            by = By.id(value);
            break;
        case "className":
            by = By.className(value);
            break;
        case "tagName":
            by = By.tagName(value);
            break;
        case "xpath":
            by = By.xpath(value);
            break;
        case "cssSelector":
            by = By.cssSelector(value);
            break;
        case "linkText":
            by = By.linkText(value);
            break;
        case "name":
            by = By.name(value);
            break;
        case "partialLinkText":
            by = By.partialLinkText(value);
            break;
        default:
            throw new IllegalStateException("locator : " + selector + " not found!!!");
    }
    return by;
}

`



来源:https://stackoverflow.com/questions/31676964/get-the-by-locator-of-an-already-found-webelement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!