0

I am able to locate elements other than svg using either JS Path OR by using the plugin created by sukgu (https://github.com/sukgu/shadow-automation-selenium)

The problem is with svg element present inside the Shadow root, I am not able to locate it. Tried below methods:

  1. While trying css selector to find the svg element, got below error:-

    WebElement ele = (WebElement) js.executeScript("return document.querySelector(\"body > sn-component-va-web-client\").shadowRoot.querySelector(\"#Path\")"); ele.click();

Output -

org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element

  1. Using above mentioned plugin to find the svg - Using css selector

    WebElement close = shadow.findElement("div > div.sn-cs-header > div.header-menu > div.menu-item.new-conversation-clicker > div.new-conversation-button > div > svg"); close.click();

Output -

org.openqa.selenium.ElementNotVisibleException: Element with CSS div > div.sn-cs-header > div.header-menu > div.menu-item.new-conversation-clicker > div.new-conversation-button > div > svg is not present on screen

  1. Using Xpath

    WebElement close = shadow.findElementByXPath("//*[local-name()='svg']//g//g//g//path[@id='Path']"); close.click();

Output -

org.openqa.selenium.ElementNotVisibleException: Element with XPath //*[local-name()='svg']//g//g//g//path[@id='Path'] is not present on screen

Below is the HTML :-

<div class="conversation-container" style="display: block;">
    <iframe title="Chat Support" id="myiFrame" class="chat-frame" scrolling="no" horizontalscrolling="no" verticalscrolling="no" frameborder="none" ng-src="/$sn-va-web-client-app.do?sysparm_nostack=true&amp;sysparm_stack=no" src="/$sn-va-web-client-app.do?sysparm_nostack=true&amp;sysparm_stack=no"></iframe>
</div>
<iframe title="Chat Support" id="myiFrame" class="chat-frame" scrolling="no" horizontalscrolling="no" verticalscrolling="no" frameborder="none" ng-src="/$sn-va-web-client-app.do?sysparm_nostack=true&amp;sysparm_stack=no" src="/$sn-va-web-client-app.do?sysparm_nostack=true&amp;sysparm_stack=no"></iframe>
    #document
    
<html>
    <head>
        <body>
            <sn-component-va-web-client component-id="cid1" now-id="cid1"></sn-component-va-web-client>
#shadow-root (open)
            <div class="sn-cs-webclient fill-window text-direction-ltr">
                <div class="sn-cs-accessibility-reader" aria-live="polite" aria-atomic="false"></div>
                <div></div>
                <div class="sn-cs-header" style="z-index: 500;">
                    <div class="chat-title">
                        <div class="header-circle">
                            <img class="header-icon " src="599c06dedbbe6c109005db184b961967.iix" alt="Header Icon">
                            </div>
                        </div>
                        <div class="header-menu">
                            <div class="menu-item new-conversation-clicker " aria-label="End conversation" aria-haspopup="menu" role="button" aria-describedby="new-conversation-tip" tabindex="0">
                                <div class="new-conversation-button">
                                    <div class="new-convo-icon close-icon">
                                        <svg viewBox="0 0 26 23" version="1.1"
                                            xmlns="http://www.w3.org/2000/svg">
                                            <g id="Symbols" stroke="none" stroke-width="1" fill="rgba(0,0,0,0)" fill-rule="evenodd">
                                                <g id="header/New-header-la-no-name" transform="translate(-330.000000, -20.000000)" fill-rule="nonzero" stroke="#ffffff" stroke-width="2">
                                                    <g id="Group" transform="translate(329.000000, 20.000000)">
                                                        <path d="M13.55,1 C7.17042969,1 
                                                            <!-- removed extra numbers -->      19.9295703,1 13.55,1 Z" id="Path">
                                                        </path>
                                                    </g>
                                                </g>
                                            </g>
                                        </svg>
                                    
Dev
  • 2,739
  • 2
  • 21
  • 34

4 Answers4

0

Please try the following:

WebElement root = driver.findElement(By.cssSelector("body > sn-component-va-web-client"));
WebElement shadow_root = expand_shadow_element(root);
WebElement path = shadow_root.findElement(By.cssSelector("g > g > path"));
path.click();


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

Credits to the author

Prophet
  • 32,350
  • 22
  • 54
  • 79
  • Tried this, it is not able to identify the element 'shadow_root' [org.openqa.selenium.remote.RemoteWebElement@bc502e7e -> unknown locator] – Sourabh Fatnani May 06 '21 at 05:01
0

I suppose the problem is the different namespace the svg elements are in. Take a look here : https://www.inflectra.com/support/knowledgebase/kb503.aspx

So probably you need (if the g-elements are irrelevant):

//*[local-name()='svg']//*[local-name()='path' and @id='Path']

If the g-elements are relevant, you need:

//*[local-name()='svg']/*[local-name()='g']/*[local-name()='g']/*[local-name()='g']/*[local-name()='path' and @id='Path']

Or maybe even use the XPath id-function like this:

id('Path')
Siebe Jongebloed
  • 3,906
  • 2
  • 14
  • 19
0

I was able to locate/click on the svg element with a workaround, instead of finding xpath of svg element, I tried locating the element prior to svg.

Steps:-

Identify and click on the non-svg element prior to svg element

Shadow shadow = new Shadow(driver); // Using sukgu plugin
WebElement x = shadow.findElementByXPath("xpath");
x.click();

Move focus to the svg element using actions class and click on it

Actions action = new Actions(driver);
action.sendKeys(Keys.TAB).build().perform();
action.sendKeys(Keys.SPACE).build().perform();
-1

Any answer would be a hit & trial without actually looking into the DOM. ShadowDOM'S are often tricky.

In case you usually struggle around these areas, I suggest you install and use the Selectorshub extension for chrome: https://chrome.google.com/webstore/detail/selectorshub/ndgimibanhlabgdgjcpbbndiehljcpfh?hl=en

Once install check out this link to understand how to right paths for shadow dom: https://www.youtube.com/watch?v=SCOAS86rJ9E

It has many other features which will make you write paths quickly. pretty good extension imo for ui-automation purpose.

Ishan Kumar
  • 21
  • 1
  • 9
  • I have added the relevant html dom. Also, SelectorsHub is not identifying the svg element present inside the shadowDom. Even in the video which you have shared, svg element inside shadow was not getting fetched – Sourabh Fatnani May 06 '21 at 05:05
  • I meant to say 'without looking into the ACTUAL dom on a HTML page'. Nevertheless, selectorshub is not going to auto find everything for you, since you have the actual page, you can validate different xpaths right there without running your selenium code again and again on IDE. the video I shared was to give a kick start and never meant to give the shadow xpath out of the box(check my comment again). In short, You might need to do a little more digging instead of giving us some lines of DOM and expecting a working solution. thanks – Ishan Kumar May 06 '21 at 13:29