1

I have the following page

<body>
  <iframe id="outer_frame">
    <iframe id="search_button_frame">
      <button id="search_button"></button>
    </iframe>
  </iframe>
</body>

Now after I click on the search_button the two frames outer_frame and search_button_frame are no longer in DOM and instead the page becomes like this

<body>
  <iframe id="form_frame">
    ...
  </iframe>
</body>

I'm trying to go to the search_button then get out of the frames into the main page, and then switching to the form_frame using this:

outer_frame = browser.find_element_by_xpath('//*[@id="outer_frame"]')
browser.switch_to.frame(outer_frame)

search_button_frame = browser.find_element_by_xpath('//*[@id="search_button_frame"]')
browser.switch_to.frame(search_button_frame)

search_button = browser.find_element_by_xpath('//*[@id="search_button"]')
search_button.click()

browser.switch_to_default_content()

form_frame = browser.find_element_by_xpath('//*[@id="form_frame"]')
browser.switch_to.frame(form_frame)

but I keep getting the following error:

selenium.common.exceptions.NoSuchElementException: Message: no such element: Una
ble to locate element: {"method":"xpath","selector":"//*[@id="form_frame"]"}

does this mean I'm not positioned in the right frame?

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
Meryem
  • 477
  • 7
  • 17
  • 1
    IMO, you are doing absolutely fine. add some wait before switching to form_frame, and replace your all xpath with id. – cruisepandey Jul 04 '18 at 17:00

2 Answers2

3

As per your question and the DOM Tree structure post clicking on the search_button you need to switch to the default_content() first and then switch to the next desired <iframe> using WebDriverWait as follows:

driver.switch_to.default_content()
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"form_frame")))

You can find a detailed discussion in:

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • 1
    Thank you! it worked! however I think it should be `WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"form_frame")))` because doing it with only one parantheses gives the following error TypeError: `__init__() takes exactly 2 arguments (3 given)` – Meryem Jul 05 '18 at 07:56
1

As per the standard procedure: first, save the parent handle of the browser. String handle = driver.getwindowhandle();

Then try to switch into a frame with the wait so that driver can wait for some time if it is not present now in DOM. After completing the work on the frame then again switch to parentWindow (default window). The same procedure can apply to every frame which would always work perfectly.

Ankit Gupta
  • 776
  • 5
  • 12