【问题标题】:Using XPath in Nightwatch.js commands to select Polymer Element's child?在 Nightwatch.js 命令中使用 XPath 来选择 Polymer Element 的子元素?
【发布时间】:2014-06-26 17:47:27
【问题描述】:

我正在尝试使用 XPath 选择器通过 nightwatch.js 命令来定位 Polymer 自定义元素的子元素。例如:

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 文档类型。该元素是使用聚合物构建的,根据检查员的说法,它嵌套在一个奇怪的“#shadow-root”中。也许无法访问 shadow-root 中的元素?

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

【问题讨论】:

  • 您确定 SVG 标签中没有 xmlns="http://www.w3.org/2000/svg" 吗?除非以某种方式对该文档进行了预处理并且#shadow-root 被XML 元素替换,否则XPath 处理器将简单地将#shadow-root 视为&lt;svg&gt; 的兄弟文本节点。您也可以尝试//th-compare-balance-chart//svg,它会跳过svg 标记之前的任何内容,或者//th-compare-balance-chart//*[local-name()='svg'],以防也以某种方式插入命名空间声明。
  • 呃,这些路径都不起作用。 th-compare-balance-chart 及其子项被动态添加到页面中,因此它不在页面源中。但我正在查看 chrome 中的元素检查器,我看到 svg 元素上的其他属性,但没有 xmlns 属性。我开始认为这与 Polymer 渲染事物的方式有关。
  • 我认为它与聚合物渲染有关的另一个原因是因为使用 getAttribute(, , callback(result)) 结果.value 为空。
  • 试试看你用//th-compare-balance-chart/*//th-compare-balance-chart//*得到了什么
  • 无法定位元素:“//th-compare-balance-chart//*”使用:xpath 和无法定位元素:“//th-compare-balance-chart/*”使用: xpath... 我真的可以访问那些元素吗!这很蹩脚。

标签: node.js selenium xpath polymer nightwatch.js


【解决方案1】:

您的命令正在使用默认的 CSS 选择。要切换到 XPath,请使用:

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

【讨论】:

  • 好的,它现在正在使用 Xpath 选择器搜索 DOM,但它似乎无法通过 id 找到我的元素的任何子元素或任何元素。例如,它可以找到 '//th-compare-chart' 但找不到 '//th-compare-chart/svg' 并且它也找不到 '//svg[@id="#chart"]'。与我能找到的所有参考文献相比,我的语法看起来是正确的。我是否缺少 nightwatch.js 或 selenium xPath 要求?
  • 您可以将您的 XML 添加到问题中吗? &lt;svg&gt; 可能有一个xmlns 声明,这将要求您注册命名空间并为选择器添加前缀,或者忽略它(使用*[local-name()='svg'] 而不是svg)。你的id 可能包含chart 而不是#chart
  • 您好,感谢您的帮助。我已将标记添加到原始问题中。
【解决方案2】:

你在这里遇到the Shadow DOM。 shadow dom 用于防止 Web 组件与页面其余部分之间发生意外交互,并将组件的实现与其接口隔离。

实际上,这意味着查询元素不会通过 shadow dom 边界,除非您明确指定要发生这种情况。使用 CSS 选择器,这是通过 ::shadow/deep/ 运算符完成的。所以这应该有效:

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

...
})

// or

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

...
})

我对 XPath 还不够熟悉,无法告诉您它有哪些运算符用于穿透 shadow dom 边界。我可以告诉你,当你得到一个th-compare-chart 元素时,你可以使用.shadowRoot 属性潜入它的shadow dom,并以正常方式查询它。例如document.querySelector('th-compare-chart').shadowRoot.querySelector('svg')

请注意,并非所有浏览器都实现了 shadow dom。 Polymer 仍然可以在所有现代浏览器中工作,但您可能需要做一些额外的工作才能让选择器在支持和不支持 shadow dom 的浏览器中工作。 More info on shadow dom support.

【讨论】:

  • 感谢您的回答!这看起来很有希望,我尝试了几种不同的组合,它们都产生了这个错误消息:'stale element reference: element is not attach to the page document' 虽然没有用,但我觉得这肯定有很大帮助。
  • 哦,我没有意识到 nightwatch 使用了网络驱动程序(/ selenium)。由于我不完全理解的原因,您需要在 shadowRoot 上调用 switchToSubTree。链接到规范:w3.org/TR/webdriver/#switching-to-hosted-shadow-doms 更多解释:库感到困惑并认为影子 dom 元素不是较大文档的一部分并不少见,因为如果您反复获得影子 dom 中节点的.parent,您以shadowRoot结束。要遍历其宿主节点,您需要访问.host
  • 这真的很有帮助。有没有办法直接与 nightwatch.js 使用的 WebDriver 交互?或者是否有任何关于在这种情况下如何使用 switchToSubTree 的示例?除了您提供的链接之外,我似乎找不到其他任何信息。如果我是正确的,我认为它需要添加到 protocol.js 中提供的接口中?
  • 我知道我要求你为我拼写出来,但我对这一切都很陌生。
  • 看起来 nightwatch 不支持断言 shadow dom 元素:/。为此,我在他们的问题跟踪器中添加了一个问题:github.com/beatfactor/nightwatch/issues/192
猜你喜欢
  • 1970-01-01
  • 2021-02-23
  • 2010-09-11
  • 1970-01-01
  • 1970-01-01
  • 2015-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多