Использование XPath в Nightwatch.js команды для выбора дочернего элемента полимерного элемента?

#node.js #selenium #xpath #polymer #nightwatch.js

#node.js #селен #xpath #полимер #nightwatch.js

Вопрос:

Я пытаюсь использовать селекторы XPath для создания дочерних элементов пользовательских элементов Polymer с помощью nightwatch.js команды. Например:

 browser
.getAttribute('//th-compare-chart/svg', 'width', function(svgWidth) {

...
})
 

Выдает:

 ERROR: Unable to locate element: "//th-compare-balance-chart/svg" using: css selector
 

В документации для getAttribute и других команд указано, что вы можете предоставить строковый селектор либо селектора css, либо xpath:
http://nightwatchjs.org/api#getAttribute

Тем не менее, я не смог заставить работать какой-либо селектор xpath. Кто-нибудь знает, как заставить это работать?

### Обновить

Это разметка XML, использующая HTML 5 doctype. Элемент построен с использованием polymer и, согласно инспектору, вложен в странный «#shadow-root». Возможно, невозможно получить доступ к элементам внутри теневого корня?

 <th-compare-balance-chart class="element ">
  #shadow-root
    <core-style>...</core-style>
    <svg id="chart">...</svg>
  #shadow-root
</th-compare-balance-chart>
 

Комментарии:

1. Вы уверены xmlns="http://www.w3.org/2000/svg" , что в теге SVG нет? Если этот документ не будет каким-либо образом предварительно обработан и #shadow-root заменен элементами XML, процессор XPath будет просто отображаться #shadow-root как дочерний текстовый узел <svg> . Вы также можете попробовать //th-compare-balance-chart//svg , который пропустит что-либо перед svg тегом, или //th-compare-balance-chart//*[local-name()='svg'] в случае, если объявление пространства имен также каким-то образом вставлено.

2. Тьфу, ни один из этих путей не работает. th-compare-balance-chart и его дочерние элементы динамически добавляются на страницу, поэтому их нет в источнике страницы. Но я смотрю в инспекторе элементов в Chrome и вижу другие атрибуты в элементе svg, но нет атрибута xmlns. Я начинаю думать, что это как-то связано с тем, как Polymer рендерит вещи.

3. Другая причина, по которой я думаю, что это связано с разрывом полимеров, заключается в том, что использование getAttribute(<polymer-element>, <some-attribute-visible-in-the-inspector>, обратный вызов (результат)) результат.значение равно нулю.

4. Попробуйте посмотреть, что вы получаете, используя //th-compare-balance-chart/* и //th-compare-balance-chart//*

5. Не удалось найти элемент: «// th-compare-balance-chart //*» с использованием: xpath и не удалось найти элемент: «// th-compare-balance-chart /*» с использованием: xpath… Могу ли я действительно получить доступ к этим элементам! Это довольно неубедительно.

Ответ №1:

Ваша команда использует выбор CSS по умолчанию. Чтобы переключиться на XPath, используйте:

 browser.
    .useXpath()
    .getAttribute('//th-compare-chart/svg', 'width', function(svgWidth) {
    ...
})
 

Комментарии:

1. Хорошо, теперь он выполняет поиск в DOM с использованием селекторов Xpath, но, похоже, он не может найти дочерних элементов моего элемента или каких-либо элементов по идентификатору. Например, он может найти ‘// th-compare-chart’, но не ‘// th-compare-chart / svg’, и он также не может найти ‘// svg [@id =»#chart»]’. Мой синтаксис выглядит правильно по сравнению со всеми ссылками, которые я могу найти. Я пропускаю nightwatch.js или требование selenium XPath?

2. Можете ли вы добавить свой XML к вопросу? Может быть xmlns объявление для <svg> , которое потребует, чтобы вы либо зарегистрировали пространство имен и префикс селекторов, либо проигнорировали его (используя *[local-name()='svg'] вместо svg ). И ваш id , вероятно, будет содержать chart и нет #chart .

3. Привет, спасибо за вашу помощь. Я добавил разметку к исходному вопросу.

Ответ №2:

Здесь вы сталкиваетесь с теневым DOM. Теневой dom используется для предотвращения непреднамеренных взаимодействий между веб-компонентом и остальной частью страницы и для изоляции реализации компонента от его интерфейса.

На практике это означает, что запрос элементов не будет проходить через границу теневого dom, если вы явно не укажете, что вы намерены это сделать. С помощью селекторов CSS это достигается с помощью операторов ::shadow and /deep/ . Так что это должно сработать:

 browser
.getAttribute('th-compare-chart::shadow svg', 'width', function(svgWidth) {

...
})

// or

browser
.getAttribute('th-compare-chart /deep/ svg', 'width', function(svgWidth) {

...
})
 

Я недостаточно знаком с XPath, чтобы рассказать вам, какие операторы у него есть для проникновения в границы теневого dom. Я могу сказать вам, что когда вы получаете th-compare-chart элемент, вы можете погрузиться в его теневой dom, используя .shadowRoot атрибут, и запросить его обычным способом. например document.querySelector('th-compare-chart').shadowRoot.querySelector('svg')

Обратите внимание, что не все браузеры реализуют shadow dom. Polymer по-прежнему будет работать во всех современных браузерах, но вам, возможно, придется выполнить дополнительную работу, чтобы ваши селекторы работали в браузерах с поддержкой shadow dom и без нее. Дополнительная информация о поддержке shadow dom.

Комментарии:

1. Спасибо за ответ! Это казалось действительно многообещающим, и я попробовал несколько разных комбинаций, и все они выдают это сообщение об ошибке: «устаревшая ссылка на элемент: элемент не прикреплен к документу страницы», Хотя это не сработало, я чувствую, что это определенно очень помогло.

2. О, я не знал, что nightwatch использовал веб-драйвер (/ selenium). По причинам, которые я не совсем понимаю, вам нужно будет вызвать switchToSubTree shadowRoot. Ссылка на спецификацию: w3.org/TR/webdriver/#switching-to-hosted-shadow-doms Дополнительное объяснение: библиотеки нередко путаются и думают, что элементы shadow dom не являются частью более крупного документа, потому что, если вы повторно получаете .parent of узла в shadow dom, вы в конечном итоге получаете shadowRoot. Для перехода к его узлу хоста вам необходимо получить доступ .host

3. Это действительно полезно. Есть ли способ напрямую взаимодействовать с WebDriver, который используется с nightwatch.js ? Или есть какие-либо примеры того, как switchToSubTree будет использоваться в этом контексте? Кажется, я не могу найти ничего другого об этом, кроме предоставленной вами ссылки. Если я прав, я считаю, что его нужно будет добавить в интерфейс, который предоставляется в protocol.js ?

4. Я знаю, что прошу вас объяснить это для меня, но я очень новичок во всем этом.

5. Не похоже, что nightwatch поддерживает утверждение о теневых элементах dom:/ . Для этого я добавил проблему в их систему отслеживания проблем: github.com/beatfactor/nightwatch/issues/192