3

I'm attempting to use Selenium WebDriver to select a link named cslLogin on a web page. It's located in a child frame called topframe but I can't access it, even after I switch to its parent frame TopLevelFrame which I can do successfully. The html page has this basic layout:

<html>
 <head>...</head>
  <frameset name="ATopLevelFrameSet">
   <frame name="TopLevelFrame">
    #document
     <html>
      <head></head>
       <frameset name="Aframeset">
        <frame name="topframe">
         #document
          <html>
           <head>...</head>
           <body class="clsBgColor">
            <table id="tblTitle">
             <tbody>
              <tr class="clsBackYellow"">
               <td class="clsDeviceStatusLink">
                <a class="clsLogin" href="javascript:void(0);"
                onclick="javascript:fnnLoginClick();">Login</a> == $0
               etc...

I can successfully switch to TopLevelFrame using self.driver.switch_to.frame("TopLevelFrame") but I cannot then access topframe or clsLogin (I get NoSuchFrameException and NoSuchElementException, respectively)

I've tried find_element_by_name, find_element_by_xpath, find_element_by_link_text, find_element_by_css_selector, and have also used

try:
    element = WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.NAME, "TopLevelFrame"))
            )
finally:
    self.driver.quit()

in case it was a time/page loading issue, but it times out long after the page loads.

I know from other posts that I need to switch to the nearest frame first before I can access the element, but of course this isn't working. Any suggestions? Thanks in advance.

ntasker
  • 33
  • 4

3 Answers3

1

To click the link cslLogin first you have to switch to the TopLevelFrame <frame> then to topframe <frame> and then click on the link as follows :

WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it(By.NAME,"TopLevelFrame"))
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it(By.NAME,"topframe"))
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, "Login"))).click()
# Or
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//tr[@class='clsBackYellow']/td[@class='clsDeviceStatusLink']/a[@class='clsLogin']"))).click()
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Thanks! I had tried waits for a few frames/elements, but it turns out I needed the waits for everything. – ntasker Feb 26 '18 at 22:20
0

You should use "find_element_by_xpath" Just open the website, press "ctrl+shift+c" and inspect it what do you want to extract. Find the row in elements, right click and copy xpath, paste in function.

For instance, consider this page source:

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
   <input name="continue" type="button" value="Clear" />
  </form>
</body>
<html>

The form elements can be located like this:

login_form = driver.find_element_by_xpath("/html/body/form[1]")
login_form = driver.find_element_by_xpath("//form[1]")
login_form = driver.find_element_by_xpath("//form[@id='loginForm']")

For more information, check out http://selenium-python.readthedocs.io/locating-elements.html

Orhan Solak
  • 789
  • 2
  • 15
  • 30
  • It still doesn't seem to be working. Here is an example of the code I last ran: `top_level_frame = self.driver.find_element_by_xpath('/html/frameset/frame') self.driver.switch_to.frame(top_level_frame) top_frame = self.driver.find_element_by_xpath('/html/frameset/frame[1]') self.driver.switch_to.frame(top_frame) element = self.driver.find_element_by_xpath('//*[@id="tblTitle"]/tbody/tr[1]/td[3]/a')` I still receive a `NoSuchElementFound` exception when finding `topframe`. It switched to `TopLevelFrame` perfectly fine. – ntasker Feb 20 '18 at 23:17
0

Try this, since you have nested iframes, switch to TopLevelFrame and then switch to topframe and carry out your find_element_* calls

driver.switch_to.frame(driver.find_element_by_name('TopLevelFrame'))
driver.switch_to.frame(driver.find_element_by_name('topframe'))
driver.find_element_by_class_name('clsLogin').click()

let me know if this works

Satish
  • 1,976
  • 1
  • 15
  • 19