Search code examples
selenium-webdriverpolymer-2.xdomxpath

Locating web elements in Polymer web page with ShadowDom objects


I am automating a web page using Selenium Webdriver and Java ,am hit with the Polymer Web page which has shadowRoot elements in the Html. I am not able to reach the elements required.

enter image description here

I need to access the element with id="Contain" and id="callButton", I have tried to use the examples in the web which gave me an idea to access but i am not able to reach to the element. Can i get this automated with selenium is what i need to understand.

When i try to get the page source dynamically while automating elements below the shadow-root are not accessible.

The above snapshot is while i inspect the element. Dynamically if i take the page source i get the below html. In this i dont get any element after the first shadow-root

   '  <!DOCTYPE html>
     <html lang="en">
      <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta http-equiv="Cache-Control" content="no-cache">
      <meta http-equiv="Cache-Control" content="no-store">
      <meta name="description" content="">
      <meta name="viewport" content="width=device-width,initial- 
      scale=1,minimum-scale=0.5,maximum-scale=3,user-scalable=yes">
      <base href="/">
       <title>Title</title>
      <!--logo Favicon - http://www.favicon-generator.org/--> 
      <link rel="shortcut icon" type="image/x-icon" 
      href="./assets/img/favicon/favicon.ico"> 
      <link rel="apple-touch-icon" sizes="57x57" 
      href="./assets/img/favicon/apple-icon-57x57.png">
      <link rel="apple-touch-icon" sizes="60x60" 
      href="./assets/img/favicon/apple-icon-60x60.png">
     <link rel="apple-touch-icon" sizes="72x72" 
      href="./assets/img/favicon/apple-icon-72x72.png">
     <link rel="apple-touch-icon" sizes="76x76" 
      href="./assets/img/favicon/apple-icon-76x76.png">
      <link rel="apple-touch-icon" sizes="114x114" 
       href="./assets/img/favicon/apple-icon-114x114.png">
       <link rel="apple-touch-icon" sizes="120x120" 
       href="./assets/img/favicon/apple-icon-120x120.png">
       <link rel="apple-touch-icon" sizes="144x144" 
       href="./assets/img/favicon/apple-icon-144x144.png">
       <link rel="apple-touch-icon" sizes="152x152" 
       href="./assets/img/favicon/apple-icon-152x152.png">
       <link rel="apple-touch-icon" sizes="180x180" 
       href="./assets/img/favicon/apple-icon-180x180.png">
       <link rel="icon" type="image/png" sizes="192x192" 
       href="./assets/img/favicon/android-icon-192x192.png">
       <link rel="icon" type="image/png" sizes="32x32" 
        href="./assets/img/favicon/favicon-32x32.png">
        <link rel="icon" type="image/png" sizes="96x96" 
        href="./assets/img/favicon/favicon-96x96.png">
        <link rel="icon" type="image/png" sizes="16x16" 
         href="./assets/img/favicon/favicon-16x16.png">
        <link rel="manifest" href="./assets/img/favicon/manifest.json"> 
        <meta name="msapplication-TileColor" content="#ffffff">
        <meta name="msapplication-TileImage" 
         content="./assets/img/favicon/ms-icon-144x144.png">
        <meta name="theme-color" content="#ffffff">
         <!--End of Favicon section--><!-- Web Fonts -->
         <link href="https://fonts.googleapis.com/css? 
           family=Roboto&subset=latin,latin-ext" rel="stylesheet" 
          type="text/css">
         <link href="styles.6818abb062a6ae399f29.bundle.css" 
         rel="stylesheet"/>
         </head>
         <body>
         <app-login>
         <!--Inline style for loading screen--><style>body, html {
        height: 100%;
        background: #FAFAFA;
    }

    @keyframes spinner {
        to {transform: rotate(360deg);}
    }

    .spinner:before {
        content: '';
        box-sizing: border-box;
        position: absolute;
        top: 50%;
        left: 50%;
        width: 100px;
        height: 100px;
        margin-top: -50px;
        margin-left: -50px;
        border-radius: 50%;
        border: 1px solid #CDCDCD;
        border-top-color: #0277BD;
        animation: spinner .6s linear infinite;
    }

    .app-loading {
        position: relative;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 100%;
       }
       </style>
       <div class="app-loading">
       <div class="spinner">
       </div>
       </div>
       </app-login>
       <script type="text/javascript" 
       src="inline.318b50c57b4eba3d437b.bundle.js"></script>
       <script type="text/javascript" 
       src="polyfills.9a4f082a49343f8da8e1.bundle.js"></script>
       <script type="text/javascript" 
       src="scripts.ccb2e44daa4fd4db3422.bundle.js"></script>
       <script type="text/javascript" 
       src="main.aacb992b6c008772ed3d.bundle.js"></script>
       </body>
       </html>`

Solution

  • I have used a combination of Java script and XPaths to get the :

    1. First element before the shadow-root by tagname // Here i am using the getElementsByTagname to get tag which gets all the elements under the tag which is just before the second shadow-root.
    2. ' WebElement ironPages = (WebElement) jse.executeScript("return arguments[0].shadowRoot.getElementsByTagName('iron-pages')[0]", edgeCallControl); '
    3. once i get the above , i am able to access every element by "id" of each of the element as per the HTml

    Get the button button , where the Button is the ID. ` WebElement button = (WebElement) jse.executeScript("return arguments[0].shadowRoot.querySelector('#Button')", edgeManualDial);'

    this ideas i got from the "Shadow-dom support for selenium"