Поиск дочерних узлов WebElements в селене
Я использую селен для тестирования своего веб-приложения и могу успешно найти теги, используя By.xpath
. Однако время от времени мне нужно найти дочерние узлы в этом узле.
Пример:
<div id="a">
<div>
<span />
<input />
</div>
</div>
Я могу сделать:
WebElement divA = driver.findElement( By.xpath( "//div[@id='a']" ) )
Но теперь мне нужно найти вход, чтобы я мог сделать:
driver.findElement( By.xpath( "//div[@id='a']//input" ) )
Однако в этот момент в коде у меня есть только divA
, а не его xpath... Я хотел бы сделать что-то вроде этого:
WebElement input = driver.findElement( divA, By.xpath( "//input" ) );
Но такой функции не существует. Могу ли я сделать это в любом случае?
Кстати: иногда мне нужно найти <div>
который имеет определенный узел-потомок. Как я могу спросить в xpath для " <div>
который содержит <span>
с текстом 'hello world'
"?
Ответы
Ответ 1
В соответствии с > JavaDocs вы можете сделать это:
WebElement input = divA.findElement(By.xpath(".//input"));
Как я могу спросить в xpath для "тега div, который содержит span с текст" привет мир"?
WebElement elem = driver.findElement(By.xpath("//div[span[text()='hello world']]"));
Спецификация XPath является удивительно хорошей для этого.
Ответ 2
Если вам нужно подождать, существует метод presenceOfNestedElementLocatedBy
, который принимает "родительский" элемент и локатор, например. a By.xpath
:
WebElement subNode = new WebDriverWait(driver,10).until(
ExpectedConditions.presenceOfNestedElementLocatedBy(
divA, By.xpath(".//div/span")
)
);
Ответ 3
Я также оказался в аналогичной позиции пару недель назад. Вы также можете сделать это, создав пользовательский ElementLocatorFactory (или просто передав divA в DefaultElementLocatorFactory), чтобы узнать, является ли он дочерним по отношению к первому div - вы тогда вызываете соответствующий метод initFilements PageFactory.
В этом случае, если вы сделали следующее:
PageFactory.initElements(new DefaultElementLocatorFactory(divA), pageObjectInstance));
// The Page Object instance would then need a WebElement
// annotated with something like the xpath above or @FindBy(tagName = "input")
Ответ 4
Метод toString() Selenium By-Class создает нечто вроде
"By.xpath://XpathFoo"
Итак, вы можете взять подстроку, начинающуюся в двоеточии, примерно так:
String selector = divA.toString().substring(s.indexOf(":") + 2);
С помощью этого вы можете найти свой элемент внутри своего другого элемента с помощью этого:
WebElement input = driver.findElement( By.xpath( selector + "//input" ) );
Преимущество: вам нужно искать только один раз на самом SUT, поэтому он может дать вам бонус в производительности.
Недостаток: Ugly... если вы хотите искать родительский элемент с помощью селектора css и использовать xpath для него childs, вам нужно проверить типы, прежде чем вы объединяетесь...
В этом случае решение Slanec (с использованием findElement в WebElement) намного лучше.
Ответ 5
Для поиска всех дочерних узлов вы можете использовать нижеприведенный сниппет
List<WebElement> childs = MyCurrentWebElement.findElements(By.xpath("./child::*"));
for (WebElement e : childs)
{
System.out.println(e.getTagName());
}
Обратите внимание, что это даст все дочерние узлы на одном уровне → Например, если у вас есть такая структура:
<Html>
<body>
<div> ---suppose this is current WebElement
<a>
<a>
<img>
<a>
<img>
<a>
Он даст мне только теги тэгов из 3 якорных тегов. Если вы хотите, чтобы все дочерние элементы были рекурсивно, вы можете заменить указанный выше код на
MyCurrentWebElement.findElements(By.xpath( ".//*" ));
Надеюсь, что это поможет!