webentwicklung-frage-antwort-db.com.de

Rufen Sie den By-Locator eines bereits gefundenen WebElement ab

Gibt es einen eleganten Weg, um den By locator eines Selenium WebElement zu erhalten, das ich bereits gefunden/identifiziert habe?

Um es klar zu sagen: Ich möchte, dass der "By locator" das Element findet. Ich bin in diesem Fall nicht an einem bestimmten Attribut oder einem bestimmten Locator wie dem css-locator interessiert. 

Ich weiß, dass ich das Ergebnis der toString () - Methode eines WebElement analysieren konnte:

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

Ausgabe wäre zum Beispiel:

[[FirefoxDriver: Firefox unter WINDOWS (....)] -> id: myPreciousElement]

wenn Sie Ihr Element über xpath gefunden haben:

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

Dann wird Ihre Ausgabe sein:

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

Also habe ich momentan meine eigene Methode geschrieben, die diese Ausgabe analysiert und mir den "neu erstellten" By Locator gibt.


ABERGibt es einen eleganteren Weg, der in Selenium bereits implementiert wurde, um den By-Locator zu verwenden, um das Element zu finden?

Ich konnte bisher keinen finden.

Wenn Sie sicher sind, dass es keinen Standard gibt, können Sie sich einen Grund dafür vorstellen, warum die API-Ersteller diese Funktionalität möglicherweise nicht zur Verfügung stellen.



* Trotz der Tatsache, dass dies nichts mit der Frage zu tun hat, ob sich jemand fragt, warum Sie diese Funktionalität jemals benötigen würden, nur zwei Beispiele: 

  • wenn Sie PageFactory verwenden, werden Sie die Locators höchstwahrscheinlich nicht als Member-Variablen in Ihrer Page-Klasse verwenden. Möglicherweise benötigen Sie sie jedoch später, wenn Sie mit den Seitenelementen arbeiten. 
  • sie arbeiten mit APIs von Personen, die das Page Object Pattern ohne PageFactory verwenden und daher erwarten, dass Sie Locators anstelle des Elements selbst übergeben. *
13
drkthng

Antwort ist Nein . Sie können eine By nicht standardmäßig aus einem zuvor gefundenen WebElement extrahieren.

Das heißt, es ist möglich, eine individuelle Lösung zu implementieren, Selenium bietet diese Option jedoch nicht an.

Betrachten Sie folgendes über "warum" ..

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

sie haben bereits das Objekt By, so dass Sie nicht etwas wie e.getBy() aufrufen müssen.

Ich könnte so etwas in der Zukunft implementieren, aber keine Versprechungen. Wieder - es ist nur Zucker.

6
sircapsalot

Nein, das gibt es nicht. Ich habe eine mögliche Lösung als Proxy implementiert:

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
}
5
Zymus

Für mich arbeitete ich mit commons-lang3

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

Für entfernte Webelemente verwenden Sie eine Methode wie:

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]";
    }
1
alexloiko

Ich habe diese Utility-Funktion geschrieben, die eine String-Kombination aus Locator-Strategie + Locator-Wert zurückgibt.

private String getLocatorFromWebElement(WebElement element) {

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

Es gibt keinen eleganten Weg, den Selen bietet. Und das ist schrecklich

1) PageObject und PageFactory implizieren, dass wir WebElements in Page Klassen haben, aber wir haben keine Locators für diese Elemente.

2) Wenn ich mit webElement.findElement(By) ein Element als Nachkommen des aktuellen Elements finde, habe ich den Locator dieses Nachkommens nicht, auch wenn ich den Locator des übergeordneten Elements in der Variablen gespeichert habe.

3) Wenn ich die Funktion findElements verwende, die List von Elementen zurückgibt, habe ich keinen Locator für jedes bestimmte Element.

4) Ein Locator für ein Element ist zumindest deshalb nützlich, weil ExpectedConditions mit einem Locator als Parameter viel besser implementiert ist als ExpectedConditions mit WebElement als Parameter.

Für mich ist Selen eine schlecht konzipierte und schlecht implementierte Bibliothek

0
zer_ik

Derzeit gibt es keine spezifische Methode von Selen, um dies zu tun. Was Sie tun können, ist Ihre benutzerdefinierte Methode zu schreiben. Sie erhalten einen Hinweis darauf, welcher Auswahltyp und Pfad verwendet wird, indem Sie einfach das vorhandene webElement drucken.

Es sieht ungefähr so ​​aus

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

Nun müssen Sie den Locator und seinen Wert extrahieren. Sie können so etwas versuchen

`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;
}

`

0
Sayantan Dey