2

How can I find the highlighted element in the following html structure.

Target element highlighted

This is the code that I'm using.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


browser = webdriver.Edge()
browser.implicitly_wait(5) # seconds
browser.get(url) # aspx page

browser.find_element_by_id("LoginBtn").click()

browser.find_element_by_id("ReportingMenuName").click()
browser.find_element_by_id("EndpointDataExportSubmenuName").click()
browser.find_element_by_id("EndpointDataExportMenuItem").click()

browser.switch_to_default_content()

browser.switch_to.frame(browser.find_element_by_id("main"))

element = WebDriverWait(browser, 10).until(EC.presence_of_element_located(\
                       (By.ID, "ct100_PageBody_OkButton")))
element.click()

When I run the code I get this error when it reaches the last 2 lines of code: TimeoutException

If I change the last 2 lines of code for this, then I get another error.

browser.find_element_by_id("ct100_PageBody_OkButton").click()

NoSuchElementException: No such element

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
M.Rod
  • 21
  • 2
  • Instead of using find by id , you can try using **find by selector** with value **"input[id$='OkButton']"** .. Since, you are able to switch to frame with id = main without running in to exception and you are getting No such element , most probably the id is dynamic and i am making a wild guess that ct100 part is changing...consider sharing page url if it's a public site . The suggested selector will match input element whose id ends with OkButton. – Nish26 Apr 05 '18 at 16:15
  • one option is sleep (2-3 seconds depends on latency) b/w switching to frame and expected condition element will solve this. I also faced this issue, but could not find better solution. – Naveen Kumar R B Apr 05 '18 at 16:37
  • similar question asked and anwered here https://stackoverflow.com/questions/49677267/how-to-wait-for-a-selenium-frame-to-load-before-waiting-for-an-element-to-load – Naveen Kumar R B Apr 05 '18 at 16:38
  • Nish26, you suggestion to user find by css selector worked. Thank you. I wonder how you got to the conclusion that the element id was dynamic? When you say dynamic is because it could change in different sessions? When I inspect the element with different browsers it always show the same id. – M.Rod Apr 06 '18 at 19:51

1 Answers1

2

There are a couple of things you need to consider :

  • While you access/login to a url Selenium's focus is on the Top Level Browsing Context. So before switching to any frame you don't need to switch_to_default_content(). Hence you can omit the line :

    browser.switch_to_default_content()
    
  • While you switch to frame through switch_to.frame() induce WebDriverWait with the clause frame_to_be_available_and_switch_to_it for the frame to be available for switching as follows :

    WebDriverWait(browser, 10).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"main")))
    
  • Within the frame once you identify the element moving ahead as you are invoking click() so instead of expected_conditions as presence_of_element_located you need to use element_to_be_clickable as follows :

    WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='buttontext' and contains(@id,'_PageBody_OkButton')]"))).click()
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • DebajanB, thank for your answer. I tried the changes you suggested. You were right about no need to "switch_to_default_content()". Also, the change to "EC.frame_to_be_available_and_switch_to_it" worked; but the selection of the element didn't work. How ever, when I used "find_by_css_selector", like Nish26 suggested, then it worked. – M.Rod Apr 06 '18 at 19:55
  • @M.Rod Check out my updated answer and let me know the status. – undetected Selenium Apr 07 '18 at 07:13