I have an iFrame in another iFrame, I´am able to switch to the parent iFrame and then to the child iFrame, but I´am just not able to switch back to the parent one. Is it even possible to switch up top to the parent one, as the driver is in the child iFrame?
iFrames are nowadays used in almost all professional software companies and having an experience of 6 years in one of the top IT Security Testing Services companies, I have hardly seen any newly developed application without iFrame. So, to handle these iFrames there are multiple ways as mentioned below -
- SwitchTo().frame(int frameNumber) - This works based on the frame index.
- SwitchTo().frame(string frameName) - This works based on the name of the frame.
- SwitchTo().frame(WebElement frameElement) - This works based on frame webElement
and now if you want to switch back to parent frame, you can use default method as - Switch to Default Content method.
This allows you to navigate back to parent method and can be used as - driver.switchTo().defaultContent();
Welcome to what I call "frame hell". I had a very similar situation.
- Top frame
- navigation frame
- content frame
- sometimes present iframe
- Top frame
The first thing to note is selenium will always allow you to go back up to the document level (aka
defaultContent) regardless of what frame you're currently in. Moving between frames is like moving between directories without the possibility to jump directly to a frame.
Example: If you're currently on the outermost document level, you can't just jump into
content frame, you have to switch to
Top, then switch to
The second problem I ran into is loading states of content and frames. Clicking a button in the navigation frame or content frame might cause the WHOLE page to reload or perhaps just the content frame.
I had to reset to the top and wait for each frame level to load before going into the next level. Here is an example code of switching to
content frame regardless of where you are currently:
def switch_to_frame_content(self, wait: WebDriverWait): """moves to the content frame""" self.driver.switch_to.default_content() wait.until(ec.frame_to_be_available_and_switch_to_it(locators.top_frame)) wait.until(ec.frame_to_be_available_and_switch_to_it(locators.content_frame)) return
Here is a use case where clicking a button in the content frame caused the content frame itself to be reloaded within the Top frame.
self.click(confirm_button) self.switch_to_frame_content(wait) wait.until(ec.element_to_be_clickable(next_button_to_click))