Получить локатор By уже найденного WebElement
Есть ли элегантный способ получить локатор Selenium WebElement, который я уже нашел/идентифицировал?
Чтобы быть понятным в вопросе: я хочу, чтобы "By locator" использовался для поиска элемента. Я в этом случае не заинтересован в конкретном атрибуте или определенном локаторе, таком как css-locator.
Я знаю, что могу проанализировать результат метода WebElement toString():
WebElement element = driver.findElement(By.id("myPreciousElement"));
System.out.println(element.toString());
Выход был бы, например:
[[FirefoxDriver: firefox на WINDOWS (....)] → id: myPreciousElement]
если вы нашли свой элемент по xpath:
WebElement element = driver.findElement(By.xpath("//div[@someId = 'someValue']"));
System.out.println(element.toString());
Тогда ваш вывод будет:
[[FirefoxDriver: firefox на WINDOWS (....)] → xpath://div [@someId = 'someValue']]
Итак, в настоящее время я написал свой собственный метод, который анализирует этот результат и дает мне "воссозданный" по локатору.
НО есть ли более элегантный способ, уже реализованный в Selenium, чтобы получить локатор By, используемый для поиска элемента?
Я пока не смог найти его.
Если вы уверены, что это не так, вы можете подумать о какой-либо причине, почему разработчики API могут не предоставлять эту функцию?
* Несмотря на то, что это не имеет никакого отношения к вопросу, если кто-то задается вопросом, почему вам понадобится эта функциональность, всего 2 примера:
- если вы используете PageFactory, скорее всего, не будете иметь локаторы как переменные-члены в вашем классе страницы, но вам может понадобиться их позже при работе с элементами страницы.
- вы работаете с API-интерфейсами людей, которые просто используют шаблон объекта страницы без PageFactory и, следовательно, ожидают, что вы передадите локаторы вместо самого элемента. *
Ответы
Ответ 1
Ответ Нет. Вы не можете извлечь By
из ранее найденного WebElement по умолчанию.
При этом можно реализовать индивидуальное решение, но Selenium не предлагает этого "из коробки".
Подумайте о том, почему "почему"..
By by = By.id("someId");
WebElement e = driver.findElement(by);
у вас уже есть объект By
, поэтому вам не нужно вызывать что-то вроде e.getBy()
Ответ 2
Нет, нет. Я применил возможное решение как прокси:
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
Для меня работал с commons-lang3
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
Для удаленного веб-элемента используйте метод вроде:
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
Я написал эту служебную функцию, которая возвращает строковую комбинацию стратегии локатора + значение локатора.
private String getLocatorFromWebElement(WebElement element) {
return element.toString().split("->")[1].replaceFirst("(?s)(.*)\\]", "$1" + "");
}
Ответ 5
Нет никакого элегантного способа, предоставленного Selenium. И это ужасно
1) PageObject
и PageFactory
подразумевают, что у нас есть WebElements
в классах Page
, но у нас нет локаторов этих элементов.
2) Если я нахожу элемент в качестве потомка текущего элемента, используя webElement.findElement(By)
, то у меня нет локатора этого потомка, даже если я сохранил родительский локатор в переменной.
3) Если я использую функцию findElements
которая возвращает List
элементов, то у меня нет локатора для каждого конкретного элемента.
4) Наличие локатора для элемента полезно, по крайней мере, потому что ExpectedConditions
с локатором в качестве параметра реализованы намного лучше, чем ExpectedConditions
с WebElement
качестве параметра.
Для меня Selenium - непродуманная и плохо реализованная библиотека
Ответ 6
В настоящее время не существует какого-либо конкретного метода с конца селена, чтобы сделать это. Что вы можете сделать, это написать свой собственный метод. Вы получите представление о том, какой тип селектора и путь используется, просто распечатав имеющийся у вас веб-элемент.
Это выглядит примерно так
[[ChromeDriver: chrome в XP (d85e7e220b2ec51b7faf42210816285e)] → xpath://input [@title= 'Search']]
Теперь, что вам нужно сделать, это извлечь локатор и его значение. Вы можете попробовать что-то вроде этого
'private By getByFromElement (элемент WebElement) {
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;
}
'