Jeffpowrs
Jeffpowrs

Reputation: 4540

Using XPath in Nightwatch.js commands to select Polymer Element's child?

I'm trying to use XPath selectors to target children of Polymer custom elements through nightwatch.js commands. For example:

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

...
})

Yields:

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

The documentation for getAttribute, and other commands, states that you can provide a string selector of either a css selector or xpath: http://nightwatchjs.org/api#getAttribute

Yet I have not been able to get any xpath selector to work. Does anyone know how to get this to work?

### Update

This is the XML markup, using HTML 5 doctype. The element is built using polymer and according to the inspector is nested inside a strange "#shadow-root". Perhaps it's not possible to access elements inside the shadow-root?

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

Upvotes: 3

Views: 6907

Answers (2)

Peter Burns
Peter Burns

Reputation: 45321

You're running into the Shadow DOM here. The shadow dom is used to prevent unintended interactions between a web component and the rest of the page, and to isolate the implementation of a component from its interface.

In practice this means that querying for elements will not pass through a shadow dom boundary unless you explicitly specify that you intend for this to happen. With CSS selectors this is accomplished through the ::shadow and /deep/ operators. So this should work:

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

...
})

// or

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

...
})

I'm not familiar enough with XPath to tell you what operators it has for piercing shadow dom boundaries. I can tell you that when you get hold of a th-compare-chart element you can dive into its shadow dom using the .shadowRoot attribute, and query that in the normal way. e.g. document.querySelector('th-compare-chart').shadowRoot.querySelector('svg')

Note that not all browsers implement the shadow dom. Polymer will still work in all modern browsers, but you may have to do some additional work for your selectors to work across browsers with and without shadow dom support. More info on shadow dom support.

Upvotes: 3

helderdarocha
helderdarocha

Reputation: 23637

Your command is using the default CSS selection. To switch to XPath use:

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

Upvotes: 3

Related Questions