Как класс Selenium ByChained действительно работает?
Я очень смущен тем, что документация для класса ByChained упоминает. Он говорит:
механизм используется для поиска элементов в документе с помощью ряда других поисков. Этот класс найдет все элементы DOM, которые соответствуют каждый из локаторов в последовательности, например, водитель.findElements(новый ByChained(by1, by2)) найдет все элементы, которые соответствуют by2 и отображаются под элементом, который соответствует by1.
есть вопрос для Селена на code.google.com, поднятый для класса ByChained, где кто-то прокомментировал, что он должен использоваться для поиска элемента/элементов с использованием нескольких локаторов.
Я не понимаю. Почему by1 и by2 должны быть локаторами двух разных элементов? Когда я случайно наткнулся на этот класс, я почувствовал, что он поможет в поиске элемента(ов) с помощью разных локаторов. Так что если один локатор не работает, далее будет работать. Но когда я практически использовал этот класс, он вел себя очень странно и все время бросал NoSuchElementException.
например, если мой html:
<html>
<body>
<div id="details">
<input id="firstName" class="personName" type="text"/>
</div>
</body>
</html>
Я хочу найти поле ввода с помощью двух локаторов в ByChained:
1. используя By.id("firstName")
2. используя By.className("personName")
таким образом, мой код становится:
By myBy = new ByChained(By.id("firstName"),By.className("personName"));
driver.findElement(myBy);
на исполнение, я получил NoSuchElementException. Я ожидал, что если сначала не получилось, потом он будет найти элемент с next By в серии.
кто-нибудь может объяснить, как этот класс работает с примером и в каких сценариях он может быть использован?
3 ответов
этот класс позволяет вам найти элемент, используя его heirarchy в dom.
допустим, по какой-то причине у вас есть следующий HTML:
<html>
<body>
<div id="details">
<input id="firstName" class="personName" type="text"/>
</div>
<input id="firstName" class="personName" type="text"/>
</body>
</html>
и вы хотите получить элемент, который находится между div, а не один сам по себе. Вы можете использовать ByChained by, чтобы указать, что вы хотите этот элемент, выполнив следующие действия:
new ByChained(By.id("details"),By.id("firstName"));
что происходит, так это то, что он находит первый элемент, а затем ищет под ним в dom иерархии для селектора, который идет следующим в списке. В основном это просто хороший чистый способ больше не делать следующее:
details = driver.findElement(By.id("details"));
input = details.findElement(By.id("firstName"));
ваш запрос будет удовлетворен чем-то, что можно назвать ByAny
который вернет элементы, соответствующие любому из переданных By
аргументов. Нет такого класса AFAIK.
ByChained
работает по-разному. Он находит элементы, которые соответствуют первому аргументу,затем ищет их потомков, используя второй аргумент и т. д. Итак, если у вас был HTMl, как это:
<html>
<body>
<div id="details">
<input id="firstName" class="personName" type="text"/>
</div>
<div id="notDetails">
<input id="secondName" class="personName" type="text"/>
</div>
</body>
</html>
и вы хотели найти class=personName
элемент под id=details
, вы можете использовать селектор CSS, выражение XPath или
new ByChained(By.id("details"), By.className("personName"))
обратите внимание, что также есть ByAll
класс, который ищет элементы, соответствующие всем By
аргументы.
вероятно, важно отметить (потому что я никогда не вижу, чтобы кто-то упоминал об этом), что ByChained следует использовать так же, как и любой другой By
локатор, вот так:
driver.findElements( new ByChained(By.id("details"), By.className("personName")) )
или
driver.findElements( new ByAll(By.id("err1"), By.className("errBox")) )