Подтвердить что ты не робот

Поиск дочерних узлов 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' "?

4b9b3361

Ответ 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( ".//*" ));

Надеюсь, что это поможет!