Search code examples
javascriptseleniumxpathiframe

Selenium Javascript - Access webelements within iframe programatically


I am trying to access web elements within iFrame programatically. Using below method to check the same

  • Compare the URL of elements with the base URI
  • If its same then web element is in main DOM otherwise its in iFrame
  • Use switchTo.frame() to switch to iFrame and perform actions

In above method, the following methods used to get URI of element

document.getElementsByTagName("a")[0].baseURI;

or

document.getElementsByClassName("w3-btn w3-border")[0].baseURI

Queries:

  1. Is there any function or method to get baseURI using xpath? I don't want to use Tagname or classname.

  2. Also, how to achieve same when multiple iFrames or iFrame inside another iFrame.

  3. Kindly suggest if any other method


Solution

  • The following code will help in switch iframes automatically.... This code handles 2 level iframes i.e.

    iframe -1 -------> Level 1
    iframe - 2 -------> Level 1
    ----  child iframe - 1 [under iframe 2 ] -------> Level 2
    iframe - 3 -------> Level 1

    Code

    async function switchtoiframe(wdriver, xpath) {
      //console.log(" ---- Code to switch iframes start ---- ");
    
      wdriver.switchTo().defaultContent();
    
      let parentEleFound = false;   
      let childEleFound = false;
      let parentframeId;
      let childframeId;
      
      // find number iframes in main content
      await wdriver.findElements(By.tagName('iframe')).then(async function (pIframe) {
          console.log("Total iframe count - " + pIframe.length);
          
          // if number of iframes found then switch to iframe
          if (pIframe.length > 0) {
              for (let i = 0; i<pIframe.length; i++)
              {              
                  await wdriver.switchTo().frame(i);   // switch to parent iframe
                  
                  // find number of child iframes in parent frame
                  await wdriver.findElements(By.tagName('iframe')).then(async function (cIframe) {
                      //console.log("total child iframe count - " + cIframe.length + " in parent frame " + i);
                      
                      // if number of iframes found then switch to child iframe
                      if (cIframe.length > 0) {
                          for (let j = 0; j<cIframe.length; j++)
                          {                          
                              await wdriver.switchTo().frame(j);  // switch to child iframe
                                
                              // check whether element is available in child iframe
                              await wdriver.findElements(By.xpath(xpath)).then(async function (cElement) 
                              {                              
                                  console.log("child for loop : j - "+ j);
                                  console.log("child element - "+ cElement.length);
                                  if(cElement.length == 1)
                                  {
                                      childframeId = j;
                                      childEleFound = true;
                                  }                              
                                  
                                  // switch back to parent iframe
                                  wdriver.switchTo().parentFrame(i);
                              });
      
                              console.log("Element found in child iframe - "+ childEleFound)
                              if (childEleFound == true ){  
                                  // switch to child iframe where element is found
                                  await wdriver.switchTo().frame(childframeId)
                                  break; // break for loop [j]
                              }
                          }
                      } 
                  });
                  if (childEleFound == true ){  // if element found in child iframe then break the parent for loop [i] also.
                      break;
                  }
      
                  // if no child iframes then find element in parent iframe
                  await wdriver.findElements(By.xpath(xpath)).then(async function (pElement) 
                  {
                      console.log("parent for loop : i - "+ i);
                      console.log("parent element - "+ pElement.length);
                      if(pElement.length == 1)
                      {
                          parentframeId = i;
                          parentEleFound = true;
                      }
                      
                      // switch back to main content
                      wdriver.switchTo().defaultContent();
                  });
      
                  console.log("Element found in parent iframe - "+ parentEleFound)
                  if (parentEleFound == true ){  
                      
                      // switch to iframe where element is found                        
                      await wdriver.switchTo().frame(parentframeId)
                      break;
                  } 
              }
          } 
      });
      
      console.log(" ---- Code to switch iframes end ---- ");
    }