When you have an iframe, it is a separate DOM. You can look at it as a separate web page inside the current web page. Lets take an example diagram:
If we look at the source code for this it might be something like:
All the rectangles in the diagram are iframes. The iframe with the red border would be the first iframe in the HTML code. Inside each iframe will be a full HTML page. It will have the <html></html> and everything which goes inside an HTML page.<html> <body> <iframe src="frame1.html" style="border: red;"> <html> ... </html> </iframe> <iframe id="2" src="frame2.html" style="border: green;"> <iframe id="2-1" src="frame2-1.html">...</iframe> <iframe id="2-2" src="frame2-2.html">...</iframe><iframe id="2-3" src="frame2-3.html">...</iframe><iframe id="2-4" src="frame2-4.html">....</iframe><iframe id="2-5" src="frame2-5.html">....</iframe><iframe id="2-6" src="frame2-6.html">...</iframe><iframe id="2-7" src="frame2-7.html">...</iframe><iframe id="2-8" src="frame2-8.html">...</iframe><iframe id="2-9" src="frame2-9.html">...</iframe>... </iframe> <iframe id="3" src="frame3.html" style="border: brown;"><iframe id="3-1" src="frame3-1.html">...</iframe><iframe id="3-2" src="frame3-2.html">...</iframe>... </iframe> <iframe id="4" src="frame4.html" style="border: blue;"><iframe id="4-1" src="frame4-1.html">...</iframe><iframe id="4-2" src="frame4-2.html">...</iframe><iframe id="4-3" src="frame4-3.html">...</iframe><iframe id="4-4" src="frame4-4.html">...</iframe><iframe id="4-5" src="frame4-5.html">...</iframe><iframe id="4-6" src="frame4-6.html">...</iframe><iframe id="4-7" src="frame4-7.html">...</iframe><iframe id="4-8" src="frame4-8.html">...</iframe><iframe id="4-9" src="frame4-9.html">...</iframe>... </iframe> </body> </html>
So in WebDriver you have a switchTo method. The switchTo method returns a WebDriver.TargetLocator interface. If we look at the WebDriver.TargetLocator interface we see the following methods:
- frame(int index)
- frame(String nameOrId)
- frame(WebElement frameElement)
- defaultContent()
We can use the index to find the frame. If you have one main page and it contains a set of iframes, this is fine. However, if you have frames within frames it can get a little difficult to follow. Even if you can figure it out today, you will have to go through the whole exercise again if they change the layout by moving, adding or deleting a frame.
The best way to find a frame is with the id attribute or find the frame element using findElement() then use the third version listed above.
Now here is the most important thing to remember: you cannot jump in two or more frames. So if you are at the main content page and want an element in frame3-1.html you have to switch to frame3.html then to frame3.1.html. Assuming we are at the main page, the code for this might look like:
driver.switchTo().frame("3");
driver.switchTo().frame("3-1");
Additionally, if I have switched to frame4-7.html and I want to go to frame2-1.html, I have to go back to the top, then to frame2.html, then to frame2-1.html.
So how do you get to the top? If you are dealing with iframes then the defaultContent() method will take you to the main page, above all the iframes. If you are dealing with frames, defaultContent() will take you to the first frame.
So you can either leave focus were every you last left it then every action in a frame assumes you are at some unknown focus, call driver.switchTo().defaultContent() to get to the top, then go down to the frame you want OR you can start at the top, go to the frame you want then back to the top when you are done. The first way you go to the top as needed. The second way you ensure you are always at the top. Both ways work. It is just a matter of convention.
Sometimes drawing the layout of the page is a little harder then the diagram above. Additionally, if the layout changes, it can be difficult to alter the picture, depending on how you drew it. What I like to do is draw the relationships like a tree. For example, the diagram above might be draw as:
From this tree the rules are that you can go down a branch (switchTo().frame() from the parent) or you can get to the root of the tree (defaultContent() for iframes). You cannot jump across nodes or up levels.
So you can either leave focus were every you last left it then every action in a frame assumes you are at some unknown focus, call driver.switchTo().defaultContent() to get to the top, then go down to the frame you want OR you can start at the top, go to the frame you want then back to the top when you are done. The first way you go to the top as needed. The second way you ensure you are always at the top. Both ways work. It is just a matter of convention.
Sometimes drawing the layout of the page is a little harder then the diagram above. Additionally, if the layout changes, it can be difficult to alter the picture, depending on how you drew it. What I like to do is draw the relationships like a tree. For example, the diagram above might be draw as:
From this tree the rules are that you can go down a branch (switchTo().frame() from the parent) or you can get to the root of the tree (defaultContent() for iframes). You cannot jump across nodes or up levels.

