4

Null Pointer Exception on click at the element located inside of the shadow Root (closed)

Tried to handle it with Java Script:

public WebElement getShadowRootElement(WebElement element) {
    return (WebElement)
            ((JavascriptExecutor)
                    driver).executeScript("return 
arguments[0].shadowRoot", element);
}

enter image description here

Result:

Cannot read property 'shadowRoot' of null

Added screenshots: 1. enter image description here

enter image description here

Y_Sh
  • 121
  • 2
  • 4
  • 14
  • What's your element? Is it `use` tag? – supputuri Jun 07 '19 at 20:13
  • @supputuri the element is a button that is above of the root. But when I'm clicking on this button it returns NPE again. That's why I decided to dig dipper to the svg / path – Y_Sh Jun 07 '19 at 20:17
  • `shadow-root` is not attached to button. So you have to use xpath `//button//use[@lightning-primitiveIcon_primitiveIcon]` as the `shadowHost` as mentioned in [my answer](https://stackoverflow.com/questions/27534688/enabling-chrome-extension-in-incognito-mode-via-cli-flags) – supputuri Jun 07 '19 at 20:23
  • Also check if `button` is under shadow-root. – supputuri Jun 07 '19 at 20:26
  • as you can see the button is under the shadow-root. Logically the browser should click on it, but it failed with NPE too. So weird. – Y_Sh Jun 11 '19 at 16:42
  • Check my comment and updated answer (that helps you to find the shadow element path). – supputuri Jun 11 '19 at 19:52
  • I've realized what's wrong with the element identifier. Before clicking that button the driver switched to the iframe that frame prevents driver to locate the "close" button web element. Now need to figure how to get out of that frame. – Y_Sh Jun 13 '19 at 19:01
  • Simply, switch to default window. – supputuri Jun 13 '19 at 20:34

3 Answers3

4

If your usecase is to interact with the <path> element which is within the <svg> tag, is indeed within a #shadow-root (closed).

@hayatoito (creator of Shadow DOM) in this comment clearly mentions:

The original motivation of introducing a closed shadow tree is "Never allow an access to a node in a closed shadow tree, via any APIs, from outside", AFAIK. Like that we can not access a node in the internal hidden shadow tree which is used in <video> element, in Blink.

In fact, I designed a closed shadow tree in such a way. If there is a way to access a node in a closed shadow tree, it should be considered as a bug of the spec.

I think it's totally okay to have an API to allow an access in the layer of Chrome apps or extensions. However, for a normal web app, I think the current agreement is "Never allow it".

If we allowed it, that means we do not need a closed shadow tree. Just having an open shadow tree is enough, I think.


WebDriver perspective

Recently, @AutomatedTester [David Burns, Chief Bacon Officer, Mozilla Corporation] initiated a discussion on WebDriver - Testability of web components

Currently Selenium Team is open for accepting pull requests for the same.


Outro

Here you can find a relevant discussion on How to automate shadow DOM elements using selenium?

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
1

Here is the solution.

WebElement closeElement = (WebElement) js.executeScript("return document.querySelector('button[title='Close Order Status'] svg use').shadowRoot.querySelector('svg path')");
closeElement.click();     

Quick Way to find path

Just providing the screenshot which will give the idea how to find the path. (FYI this screenshot is for the clear data button in the chrome clear history) enter image description here

supputuri
  • 13,644
  • 2
  • 21
  • 39
  • Are you able to click on the path element now? – supputuri Jun 07 '19 at 21:03
  • Thanks, tried that but the xpath: //button[@title='Close Order Status']//use with "//use" identifier could NOT be located through the console neither through selenium: org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//button[@title='Close Order Status']//use"} – Y_Sh Jun 11 '19 at 16:55
  • Can you please share the screenshot of the `Dev Tools > Element tab` base where you see the css path. As shown under `Quick Way to find path` in my updated answer. – supputuri Jun 11 '19 at 19:45
  • Added few screenshots. Please see the main description. – Y_Sh Jun 12 '19 at 15:54
  • Check the updated answer. `button[title='Close Order Status'] svg use` is the correct shadow-host element, this should work now. – supputuri Jun 12 '19 at 16:54
  • nope, it didn't find any element and no output from the DevTools-> Elements. I've change the xpath to //button[@title='Close Order Status']/lightning-primitive-icon//*[@data-key]//* and it finally is searchable on DevTools, but the web driver is still unable to locate this element. – Y_Sh Jun 12 '19 at 17:51
  • org.openqa.selenium.InvalidSelectorException: invalid selector: Unable to locate an element with the xpath expression button[title='Close Order Status'] svg use because of the following error: SyntaxError: Failed to execute 'evaluate' on 'Document': The string 'button[title='Close Order Status'] svg use' is not a valid XPath expression. – Y_Sh Jun 12 '19 at 17:55
  • `button[title='Close Order Status'] svg use` is css, not xpath. – supputuri Jun 12 '19 at 17:59
  • Yes, I got it. Still NPE. The problem with the 'Close Order Status' button is that its element could no be located at all. Tried to get size, location but it always return: element not found. – Y_Sh Jun 12 '19 at 18:28
  • ok, can you try the this xpath `//button[@title='Close Order Status']//*[local-name()='use']`. Check if this return the `use` element, this should be a separate step but in the javascript that I provided. – supputuri Jun 12 '19 at 18:43
  • Let me know if that return the `use` element, then I can update the answer to use the `use` element in javascript. – supputuri Jun 12 '19 at 18:43
  • the above js with return document.querySelector ? – Y_Sh Jun 13 '19 at 15:47
  • `document.querySelector('button[title='Close Order Status'] svg use')` run this in your chrome console and see if you get the `use` element. – supputuri Jun 13 '19 at 15:56
  • NPE when clicking on the return web element: – Y_Sh Jun 13 '19 at 17:31
  • Sorry, can you check it in the browser console. Not in your script – supputuri Jun 13 '19 at 18:17
  • I can find the path in the console(dev tools), but the driver is NOT able to find that element and always returns NPE: element is not found. That's the problem. I've tried all options: xpath, css. Same result. – Y_Sh Jun 13 '19 at 18:46
0

You can use the javascript something like this.

WebElement clearData = (WebElement) js.executeScript("return document.querySelector('button[title='Close Order Status'] svg use').shadowRoot.querySelector('svg path')");

Check How to locate the #shadow-root (open) elements through cssSelector link for more information.

supputuri
  • 13,644
  • 2
  • 21
  • 39
userFollow
  • 39
  • 5