I have to test an \"old fashioned\" web application which uses inner frames.Just like:
....
No, there isn't.
In fact, handling iframe
elements with Selenium is very tricky.
You have three options for switching into a frame:
WebElement
object that you obtain from the DOMBut you have only one option for switching out:
driver.switchTo().defaultContent()
And once you've switched out of a frame, you in fact switched out "all the way up".
So if you thought you were recursing the frames with a simple DFS, it is most likely you were wrong.
The way I found to do it is by "leaving bread crumbs". In other words, before switching into a frame, I "memorize" the entire path from the root of the DOM to that frame.
After switching out, because I'm "back in the root", I perform the entire path to the frame (except for switching into that frame of course), and then continue to the frame next to it.
Be aware that once you've switched into a frame, all previous WebElement
objects you were storing have become "stale", so you would have to find them again after switching out.
P.S.: I found that almost all websites store advertisements inside iframe
tags, so I doubt it's an "old fashion" thing.
Anyway, here is the code that I used (in Java):
private void searchFrames(List<Integer> route)
{
doWhateverYouWannaDoHere();
if (route.size() < MAX_DEPTH)
{
int numOfFrames = webDriver.findElements(By.tagName("iframe")).size();
for (int i=0; i<numOfFrames; i++)
{
try
{
webDriver.switchTo().frame(i);
List<Integer> newRoute = new ArrayList<Integer>(route);
newRoute.add(i);
searchFrames(newRoute);
webDriver.switchTo().defaultContent();
for (int j : route)
webDriver.switchTo().frame(j);
}
catch (NoSuchFrameException error)
{
break;
}
catch (Exception error)
{
}
}
}
}
In order to start the procedure, call searchFrames(new ArrayList<Integer>())
.
Hope it helps...
UPDATE:
This method performs the desired action not only inside each frame, but also in the DOM itself. If you want to avoid the DOM itself, then move the call to method 'doWhateverYouWannaDoHere' after the first line in the try
clause, i.e., after webDriver.switchTo().frame(i)
.