iFrames In Selenium Webdriver
What is iFrame?
An iFrame (Inline Frame) is an HTML document embedded inside the current HTML document on a website. iFrame HTML element is used to insert content from another source, such as an advertisement, into a Web page. In Selenium to work with iFrames, we have different ways to handle frame depending on the need.
driver.switchTo().frame(int arg0);
Select a frame by its (zero-based) index. That is, if a page has multiple frames (more than 1), the first frame would be at index "0", the second at index "1" and so on.
Once the frame is selected or navigated , all subsequent calls on the WebDriver interface are made to that frame. i.e the driver focus will be now on the frame.
What ever operations we try to perform on pages will not work and throws element not found as we navigated/switched to Frame.
How to Interact with elements inside an Iframe?
In earlier chapter we learn how to switch between Iframes on a webpage. There were mainly three ways of switching between Iframes.
-
By Frame Index
-
By Frame ID or Name
-
By Frame WebElement
Lets first create a hypothetical test case, here are the steps that we would take in our test.
​
-
Navigate to the page with multiple iFrames. It is here “http://toolsqa.wpengine.com/iframe-practice-page/“
-
Switch to first frame and then find First Name and Last name element.
-
Fill some value in the first name and Last name value
-
Switch to second frame.
-
Find the first image element and then click on it.
​
Step 1: Navigate to the page with multiple iFrames.
driver.get("http://toolsqa.wpengine.com/iframe-practice-page/");
​
Step 2: Switch to first frame and then find First Name and Last name element.
​
/* Switch to the first frame, remember frame index starts from 0 */
driver.switchTo().frame(0);
​
/* now find the First name field */
WebElement firstName = driver.findElement(By.xpath("//*[@id='content']/form/fieldset/div[1]/p[3]/input"));
​
/* now find the Last name field */
WebElement lastName = driver.findElement(By.xpath("//*[@id='content']/form/fieldset/div[1]/p[4]/input"));
​
Once you switch to the frame, you can access the html elements that are inside the frame.
​
Any attempt to access the elements which are inside iFrame without switching to that ifFrame will result in WebDriver exception.
Also notice that once you have switch to the frame find element commands are exactly same as what we would use normally.
​
Step 3: Fill some value in the first name and Last name value
firstName.sendKeys("Glasdon");
lastName.sendKeys("Falcao");
​
Step 4: Switch to second frame (Critical step)
-
I would like you to refer to the image that I have shared above.
-
It shows that main page has two frame 0 and 1.
-
Now if you are inside frame 0 you cannot switch to frame 1.
-
Because frame 1 is not a part of frame 0, but its a part of main page.
-
Any attempt to directly switch to frame 1 from frame 0 will give an exception.
-
Exception will be No Such frame exception.
-
We will reproduce it later in this chapter for learning purpose.
-
So how do we switch to frame 1?
-
Simple switch back to the main page using the SwitchTo().defaultContent() command.
​
​
Once on the main page switch to the frame 1 as shown in the code below:
​
// Step 5: Switching to the 2nd frame, frame index 1
driver.switchTo().defaultContent();
driver.switchTo().frame(1);
​
Step 6: Find the first image element and then click on it
Once you are in second frame, rest is just similar to regular findElement and click command.
As shown in the code below.
//Step 5: Find image element and click on that
WebElement imageElement = driver.findElement(By.xpath("//*[@id='post-9']/div/div[1]/div/p[1]/a/img"));
imageElement.click();
System.out.println("Switching successfull");
​
Complete code listing is here
​
WebDriver driver = new FirefoxDriver();
driver.get("http://toolsqa.wpengine.com/iframe-practice-page/");
driver.switchTo().frame(0);
WebElement firstName = driver.findElement(By.xpath("//*[@id='content']/form/fieldset/div[1]/p[3]/input"));
WebElement lastName = driver.findElement(By.xpath("//*[@id='content']/form/fieldset/div[1]/p[4]/input"));
firstName.sendKeys("Virender");
lastName.sendKeys("Singh");
driver.switchTo().defaultContent();
driver.switchTo().frame(1);
WebElement imageElement = driver.findElement(By.xpath("//*[@id='post-9']/div/div[1]/div/p[1]/a/img"));
imageElement.click();
System.out.println("Switching successfull");
​
​
Code Snippet to find total number of iFrames on a webpage
​
There are two ways to find total number of iFrames in a web page.
-
Executing a JavaScript and
-
Finding total number of web elements with a tag name of iFrame.
​
Here is the code using both these methods:
​
WebDriver driver = new FirefoxDriver();
driver.get("http://toolsqa.wpengine.com/iframe-practice-page/");
//By executing a java script
JavascriptExecutor exe = (JavascriptExecutor) driver;
Integer numberOfFrames = Integer.parseInt(exe.executeScript("return window.length").toString());
System.out.println("Number of iframes on the page are " + numberOfFrames);
​
//By finding all the web elements using iframe tag
List<WebElement> iframeElements = driver.findElements(By.tagName("iframe"));
System.out.println("The total number of iframes are " + iframeElements.size());
WebDriver driver = new FirefoxDriver();
driver.get("http://toolsqa.wpengine.com/iframe-practice-page/");
Code Snippet to switching back to Main page from Frame
​
There is one very important command that will help us to get back to the main page.
Main page is the page in which two iFrames are embedded.
Once you are done with all the task in a particular iFrame you can switch back to the main page using the switchTo().defaultContent().
​
Here is the sample code which switches the driver back to main page.
WebDriver driver = new FirefoxDriver();
driver.get("http://toolsqa.wpengine.com/iframe-practice-page/");
//First find the element using any of locator stratedgy
WebElement iframeElement = driver.findElement(By.id("IF1"));
//now use the switch command
driver.switchTo().frame(0);
//Do all the required tasks in the frame 0
//Switch back to the main window
driver.switchTo().defaultContent();
driver.quit();
WebDriver driver = new FirefoxDriver();
driver.get("http://toolsqa.wpengine.com/iframe-practice-page/");
​
//First find the element using any of locator stratedgy
WebElement iframeElement = driver.findElement(By.id("IF1"));
//now use the switch command
driver.switchTo().frame(0);
//Do all the required tasks in the frame 0
//Switch back to the main window
driver.switchTo().defaultContent();
driver.quit();
Notes:-
In Webdriver, you should use driver.switchTo().defaultContent(); to get out of a frame.
You need to get out of all the frames first, then switch into outer frame again.
​
//between step 4 and step 5
//remove selenium.selectFrame("relative=up");
driver.switchTo().defaultContent(); // you are now outside both frames
driver.switchTo().frame("cq-cf-frame");
​
//now continue step 6
driver.findElement(By.xpath("//button[text()='OK']")).click();
​
​
IFRAME Exceptions
​
Two iframe exceptions are:
​
First one is no such element exception, which comes when you try to access any element inside a frame without switching to the iFrame. We can reproduce this error by simply removing the SwitchTo statements. Here is the minimal code required, try running it.
​
NoSuchElement Exception in Iframe
​
// Step 1: Navigate to the page with multiple iframes say
driver.get("http://toolsqa.wpengine.com/iframe-practice-page/");
// Step 2: Switch to first frame and then find First Name and Last name
// element
/* Switch to the first frame, remember frame index starts from 0 */
//driver.switchTo().frame(0);
/* now find the First name field */
WebElement firstName = driver.findElement(By.xpath("//*[@id='content']/form/fieldset/div[1]/p[3]/input"));
// Step 1: Navigate to the page with multiple iframes say again
driver.get("http://toolsqa.wpengine.com/iframe-practice-page/");
// Step 2: Switch to first frame and then find First Name and Last name
// element
/* Switch to the first frame, remember frame index starts from 0 */
//driver.switchTo().frame(0);
/* now find the First name field */
WebElement firstName = driver.findElement(By.xpath("//*[@id='content']/form/fieldset/div[1]/p[3]/input"));
Note : Notice that I have commented out the switch to frame command. This code will produce following error:
Exception in thread “main” org.openqa.selenium.NoSuchElementException: Unable to locate element: {“method”:”xpath”,”selector”:”//*[@id=’content’]/form/fieldset/div[1]/p[3]/input”}
Command duration or timeout: 226 milliseconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: ‘2.45.0’, revision: ’32a636c’, time: ‘2015-03-05 22:01:35’
System info: host: ‘abc-PC’, ip: ‘192.168.3.3’, os.name: ‘Windows 7’, os.arch: ‘amd64’, os.version: ‘6.1’, java.version: ‘1.8.0_25’
Driver info: org.openqa.selenium.firefox.FirefoxDriver
NoSuchFrame Exception in Iframe
As discussed earlier in this chapter, you will get a no Such frame exception if you try to switch to another frame without switching back to the main page. This can be reproduced by commenting out the driver.switchTo().defaultContent() statement.
Here is the code which will reproduce this exception
​
WebDriver driver = new FirefoxDriver();
driver.get("http://toolsqa.wpengine.com/iframe-practice-page/");
driver.switchTo().frame(0);
//driver.switchTo().defaultContent();
driver.switchTo().frame(1);
System.out.println("Switching successfull");
WebDriver driver = new FirefoxDriver();
driver.get("http://toolsqa.wpengine.com/iframe-practice-page/");
driver.switchTo().frame(0);
//driver.switchTo().defaultContent();
driver.switchTo().frame(1);
System.out.println("Switching successfull");
​
Note :This is the exception that you get
Exception in thread “main” org.openqa.selenium.NoSuchFrameException: Unable to locate frame: 1
Command duration or timeout: 105 milliseconds
Build info: version: ‘2.45.0’, revision: ’32a636c’, time: ‘2015-03-05 22:01:35’
System info: host: ‘abc-PC’, ip: ‘192.168.3.3’, os.name: ‘Windows 7’, os.arch: ‘amd64’, os.version: ‘6.1’, java.version: ‘1.8.0_25’
Driver info: org.openqa.selenium.firefox.FirefoxDriver
​
​
​