Protractor Tutorial: Handling iFrames and Frames in Selenium
In this Protractor testing tutorial, I’ll take a look at how to handle frames and iFrames in Selenium with Protractor.
Join the DZone community and get the full member experience.
Join For FreeWhile performing Selenium test automation, you’d often come across scenarios where you’d need to handle frames or iframes. Frames are used to split the content into horizontal and vertical splits, while iframes are used to embed content on a web page.
In this Protractor testing tutorial, I’ll take a look at how to handle frames and iframes in Selenium with Protractor. To learn more about Protractor, and how to perform Protractor testing, you can refer to this Protractor testing tutorial to perform cross-browser testing.
Difference Between iFrames And Frames
Frames are used for horizontally and vertically splitting of the screen while iFrames are used to insert content from other sources, such as advertisements on your websites.
The frame is an HTML tag used to split the same web page or domain into separate frames /or windows. Frames are used along with framesets, the < frame > tag in a web page defines each of the frames inside the frameset file tag and so we can say that the framesets include several frames.
In Protractor, you can handle iFrames and Frames in Protractor in the same way.
<frameset rows = "20%,60%,20%">
<frame id= "top" name = "frame1" src = " / html/ frame_top.htm" />
<frame id= "main" name = "frame2" src = " / html / frame_main.htm" />
<frame id= "side" name = "frame3" src = " / html / frame_side.htm" />
</frameset>
Some major differences between frames and iFrames are:
- The frame requires the presence of a frameset, but iframes do not need a frameset.
- The frames do not contain or support nested frames (frames within frames), but iFrames do contain nested iFrames.
- The regulation of height and width of the frame is complicated as opposed to iFrame.
- The placing of frames is a bit challenging compared to iFrames.
- The frames are not allowed in HTML5, but it allows iFrames.
Frame or iFrame is nothing but another web feature on the HTML page that shows another component of the web page. When we look at the DOM structure of a website that includes an iframe, we will never find the inside content of the iframe. So, we are not going to be able to communicate with it through the DOM. We need to turn to the frame to see the elements present in the frame.
Testers need to check whether an element is inside an iframe/frame or just on a web page. In certain cases the element might be inside a frame, you’ll have to switch to that particular frame in order to access those elements. You’ll have to use the switchTo() method in the protractor to manage any of the frames or iframes present on the webpage.
Below is an example of frames present on the selenium.dev website at:
How To Find iFrame Or Frame In Protractor
To handle frames in Selenium with Protractor, you’ll need to identify them first. You can find the frame or iframe by right-clicking in the browser while performing manual testing. But finding frames or iFrames for Selenium test automation can be a bit tricky.
Below are the ways to locate an iframe/frame:
By Element
By Index
By Element
While finding iframes or frames, you’ll come across scenarios where frames or iframes share the same name and id. Also, we cannot use the locators such as link text or partial link text as they are only available for the anchor tag. Refer to this blog to know more about handling locators in Protractor.
In order to identify the elements to handle frames in Selenium, you can use locators like XPath, class name, CSS, etc. to find frames or iframes. This is the widely used approach when finding frames. For our example, we can consider the iframes and use the XPath locator to get the element.
Xpath for 1st iFrame : //iframe[@src='first.html']
Xpath for 2nd iFrame : //iframe[@class='second']
xxxxxxxxxx
//finding frame using xpath to handle frames in Selenium for Protractor testing//
<iframe id="ifr" name="first" src="first.html" height="150" width="250"></iframe>
<iframe id="ifr" name="second" class='second' src="second.html" height="150" width="250"></iframe>
<iframe id="ifr" name="third" src="third.html" height="150" width="250"></iframe>
// navigating to the first frame //
browser.switchTo().frame(element(by.xpath("//iframe[@src='first.html']")).getWebElement())
By Index
When you create a frame in Protractor, it assigns an index in an increment way to every frame on the web page. These indexes can be used to find the frames or iframes. However, the use of the index approach is not preferred, as the index might change whenever a new frame position is introduced before the frames.
xxxxxxxxxx
//finding frame using index to handle frames in Selenium for Protractor testing//
<iframe id="ifr" name="first" src="first.html" height="150" width="250"></iframe>
<iframe id="ifr" name="second" class='second' src="second.html" height="150" width="250"></iframe>
<iframe id="ifr" name="third" src="third.html" height="150" width="250"></iframe>
// navigating to the first frame //
browser.switchTo().frame(1)
How To Handle Frames In Selenium With Protractor?
The most common use case is to handle frames in Selenium with protractor where you locate a frame and then switch to the target frame. Here I’ll handle a single frame in this Protractor testing tutorial.
Below are the steps involved to find the frame in protractor:
Step 1: Navigate to the URL in the browser using the below:
xxxxxxxxxx
// launches the URL in the browser //
browser.get("http://the-internet.herokuapp.com/iframe");
Step 2: Fetch the text from the element and store the value in the string datatype.
xxxxxxxxxx
// using the switchTo() function for switching to the frame //
element(by.xpath(" // label/ span ")).getText().then(function(textValue){
})
Step 3: We use the unique attribute to fetch the element using the attribute id, hence we can use this unique id to switch to the frame.
xxxxxxxxxx
// using the switchTo() function for switching to the frame // browser.switchTo().frame(element(by.id("frame1")).getWebElement());
Step 4: We will find the text in the new frame and store input the text stored from the previous frame.
xxxxxxxxxx
// the value saved is assigned to the value of the text box element(by.xpath("//input[@type='text']")).sendKeys(textValue);
By performing this you can verify that the frame is switched successfully and the text from the first frame is written in the new frame. Example of a single iframe is available at http://the-internet.herokuapp.com/iframe
Below is the complete code for this Protractor testing tutorial that demonstrates this behavior to handle frames in Selenium with Protractor.
xxxxxxxxxx
//Handle frames in Selenium with for Protractor testing//
// import all the required modules from selenium web driver and protractor
import { Alert } from 'selenium-webdriver';
import { browser, element, by, ExpectedConditions, protractor} from 'protractor'
// describing the test to handle frames in Selenium //
describe('Frame Demonstration in Protractor', function() {
browser.ignoreSynchronization = true; // disable synchronization for non angular websites //
// tests to handle single iframe in protractor //
it('Tests to handle single iframe in protractor', function() {
// launch the url in the browser //
browser.get("http://the-internet.herokuapp.com/iframe");
browser.manage().timeouts().implicitlyWait(5000);
// locate the frame element //
element(by.xpath(" // label/ span ")).getAttribute("innerTextValue").then(function(textValue){
// using the switchTo() function for switching to the frame // browser.switchTo().frame(element(by.id("frame1")).getWebElement());
// the value saved is assigned to the value of the text box
element(by.xpath("//input[@type='text']")).sendKeys(textValue);
})
});
});
Handling Multiple Frame and Nested Frames in Protractor
Sometimes there are Selenium test automation scenarios, where you’ll encounter multiple frames in a web page, especially with nested frames. The situation becomes complex when you’ll switch between these frames to handle frames in Selenium with Protractor. Refer to the article on handling multiple windows in Protractor, to know more about how to handle multiple windows
Hence, you need to follow a particular approach when switching a frame inside a frame. You can only access the content of a child frame when we are inside a particular frame as it is not to access them from outside of the frame or from any other frames on the webpage.
Below are the steps involved to handle frames in Selenium with Protractor for nested frames:
Step 1: Navigate to the URL in the browser using the below
xxxxxxxxxx
// open the URL in the browser
browser.get("http://the-internet.herokuapp.com/nested_frames ");
Step 2: Locate the current frame i.e. frame1 and save that as a web element.
xxxxxxxxxx
//find the frame1 and store it in web element //
WebElement frame1 = element(by.id("frame1")).getWebElement();
Step 3: Next, using the switchTo().frame command we will navigate to frame1.
xxxxxxxxxx
// using the switchTo() function for switching to the frame //
browser.switchTo().frame(frame1);
Step 4: From inside the frame1 we will now locate the current frame and switch to the frame. Since we are already inside a frame, we will use xpath location to switch to the inner frame.
xxxxxxxxxx
// locate the frame 3
WebElement frame3 = element(by.xpath("//iframe[@id='frame3']")).getWebElement();
// navigate to the new frame
browser.switchTo().frame(frame3);
Step 5: Then we can perform any operation to validate the switching of the frame such as writing a text or clicking a button
xxxxxxxxxx
// obtain the element of the checkbox //
WebElement checkbox = element(by.xpath("//input[@type='checkbox']"));
checkbox.isSelected().then(function(checked){
// click the checkbox if it is not selected
if( ! checked ){
checkbox.click();
}
})
Below is the complete code for this Protractor testing tutorial that demonstrates this behavior to handle frames in Selenium with Protractor for nested frames.
xxxxxxxxxx
// import all the required modules from selenium web driver and protractor// for this Protractor testing tutorial for Selenium test automation
import { browser, element, by, ExpectedConditions, protractor} from 'protractor'
import { Alert, WebElement } from 'selenium-webdriver';
// describing the test to handle frames in Selenium with Protractor demonstration //
describe(' Frame Demonstration in Protractor ', function() {
browser.ignoreSynchronization = true; // disable synchronization for non angular websites //
// tests to handle frames in Selenium with protractor for nested frames //
it(' Tests to handle nested frame in protractor ', function() {
browser.manage().timeouts().implicitlyWait(5000)
// launch the url in the browser //
browser.get("http://the-internet.herokuapp.com/nested_frames");
// locate the frame element //
// store the value in a webelement
WebElement frame1 = element(by.id("frame1")).getWebElement();
// navigate to the target frame element //
browser.switchTo().frame(frame1);
// locate the frame 3
WebElement frame3 = element(by.xpath("//iframe[@id='frame3']")).getWebElement();
// navigate to the frame 3
browser.switchTo().frame(frame3);
// locate the element with the checkbox
WebElement checkbox = element(by.xpath("//input[@type='checkbox']"));
// verify whether the checkbox is selected else selected the checkbox by clicking it //
//or perform many other operation to validate the change in frame.
checkbox.isSelected().then(function(checked){
if(! checked){
checkbox.click();
}
})
});
});
Navigate to Parent Frame With the Framework
There are certain Selenium test automation scenarios, where after performing actions in the current frame, i.e. the inner frame, you’ll need to navigate out of that frame, so that you can access the elements in the outer frame . For such type of situation, protractor provides us with switchToParentFrame(). It assists in switching the control to the outer frame of the web page to handle frames in Selenium, otherwise, it won’t be possible to interact with the other elements of the webpage in the parent frame without exiting the current frame.
But it is important to note that once we are outside of the inner frame we cannot access the elements inside this frame and need to again navigate to the frame with the nested frame approach.
For our demonstration to handle frames in Selenium with Protractor we will execute the following Selenium test automation scenario:
The inner frame3 is present inside frame 1 and so we will click the checkbox of the inner frame.
Next, we will move to the parent frame i.e. frame 1, and enter a text in the text box.
Now finally we will switch back to the header and validate the text.
Below in this Protractor testing tutorial are the detailed steps that will be involved to handle parent frames in protractor:
Step 1: We will switch to frame 1 and then switch to the inner frame i.e. frame 3 as we did in our previous demonstrations.
Step 2: Now, we will switch back to the outer frame i.e. frame 1 using the switchToParentFrame() method.
xxxxxxxxxx
// using the switchTo() function for switching to the frame //
browser.switchToParentFrame();
Step 3: Next, we will enter the appropriate text after locating the text box in the frame.
xxxxxxxxxx
// the value saved is assigned to the value of the text box //
element(by.xpath("//input[@type='text']")).sendKeys("selenium");
Step 4: Next, we will switch back to the main frame at the page level using the switchToParentFrame() method.
xxxxxxxxxx
// using the switchTo() function navigate to the frame at the page level //
browser.switchToParentFrame();
Step 5: Locate the elements that have the subject and fetch the header text.
xxxxxxxxxx
// using the switchTo() function for switching to the frame //
element(By.xpath(" //label/ span ")).getText().then(function(textValue){
});
Step 6: Finally, to validate we will compare this text with the desired value.
xxxxxxxxxx
if(textValue === " protractor test value"){
System.out.println("Topic value is equal to ' protractor test value '");
}
Below is the complete code that demonstrates the approach of switching back to the parent frame to handle frames in Selenium.
xxxxxxxxxx
// import all the required modules from selenium web driver and protractor to handle frames in Selenium//
import { browser, element, by, ExpectedConditions, protractor} from 'protractor'
import { Alert, WebElement } from 'selenium-webdriver';
// describing the test for the frame demonstration //
describe(' Frame Demonstration in Protractor ', function() {
browser.ignoreSynchronization = true; // disable synchronization for non angular websites //
// tests to handle parent iframe in protractor //
it(' Tests to handle parent iframe in protractor ', function() {
browser.manage().timeouts().implicitlyWait(5000)
// launch the url in the browser //
browser.get("http://the-internet.herokuapp.com/nested_frames");
// locate the frame element //
// store the value in a webelement
WebElement frame1 = element(by.id("frame1")).getWebElement();
// navigate to the next desired frame i.e. frame1
browser.switchTo().frame(frame1);
// locate the new frame i.e. frame 3 //
WebElement frame3 = element(by.xpath("//iframe[@id='frame3']")).getWebElement();
// using the switchTo method to navigate to frame 3
browser.switchTo().frame(frame3);
// search the frame for the checkbox element by xpath locator
WebElement checkbox = element(by.xpath("//input[@type='checkbox']"));
// if check box is not selected then click the checkbox
checkbox.isSelected().then(function(checked){
// if check box is not selected then click the checkbox
if(! checked){
checkbox.click();
}
})
// switch back to the parent frame with the switchToParentFrame i.e, frame 1
browser.switchToParentFrame();
// The stored value is assigned as the value of the text bar
browser.findElement(by.xpath("//input[@type='text']")).sendKeys("protractor");
// again switch to the main parent frame i.e the page level
browser.switchToParentFrame();
// retrieve the value stored in form of the text by xpath locator element(by.xpath("//label/span")).getText().then(function(textValue){
// validate the stored value to check whether it matches with the value of the frame.
if(textValue === "protractor test value"){
console.log("Topic value is equal to 'protractor test value'");
}
});
});
});
Default Content In Protractor
Unlike the switchToParentFrame() method earlier discussed in this Protractor testing tutorial, which is used to exit from the current frame, the default content method in protractor exits from all the frames on the webpage and positions the control of protractor at the page level. Moreover, once the control is moved at the page level, we will not be able to access any elements inside the iframe unless we navigate back to it.
For our example, we need to perform the following steps to handle frames in Selenium.:
Step 1: I’ll perform the operation in the inner frame by navigating to frame 1 and the switch to frame 3 as per the previous demonstration.
Step 2: Now I'll use the switchTo().defaultContent() to exit from all the frames and handle the control to the page level.
xxxxxxxxxx
// switch to the page default content
browser.switchTo().defaultContent();
Step 3: Navigate to the other frame again using the switchTo() method and select the value from the dropdown to store the selected value in the web element
xxxxxxxxxx
// navigate to the new frame using the switch to frame method //
browser.switchTo().frame(frame2);
// search the tag from the drop down element //
element(by.tagName("select"));
Step 4: Finally, we would be able to validate the dropdown using clicks.
xxxxxxxxxx
// select the value from the drop down option //
element(by.xpath("//option[text()='TestValue']")).click()
Below in this Protractor testing tutorial is the complete code that demonstrates the behavior of default content with frames in protractor.
xxxxxxxxxx
// import all the required modules from selenium web driver and protractor to handle frames in Selenium
import { browser, element, by, ExpectedConditions, protractor} from 'protractor'
import { Alert, WebElement } from 'selenium-webdriver';
// describing the test for the frame demonstration //
describe(' Frame Demonstration in Protractor ', function() {
browser.ignoreSynchronization = true; // disable synchronization for non angular websites //
// tests to handle default content in protractor //
it(' Tests to handle default content in protractor ', function() {
browser.manage().timeouts().implicitlyWait(5000)
// launch the url in the browser //
browser.get("http://the-internet.herokuapp.com/nested_frames ");
//find the frame1 and store it in web element
WebElement frame1 = element(by.id("frame1")).getWebElement();
// navigate to the frame1
browser.switchTo().frame(frame1);
// navigate to the frame 3
WebElement frame3 = element(by.xpath("//iframe[@id='frame3']")).getWebElement();
// navigate to frame 3
browser.switchTo().frame(frame3);
// search for the checkbox
WebElement checkbox = element(by.xpath("//input[@type='checkbox']"));
// verify whether the checkbox is selected else selected the checkbox by clicking it //
checkbox.isSelected().then(function(checked){
//or perform many other operation to validate the change in frame.
if(! checked){
checkbox.click();
}
})
// switch to the page default content
browser.switchTo().defaultContent();
// navigate to the new frame using the switch to frame method //
browser.switchTo().frame("frame2");
// search the tag from the drop down element //
element(by.tagName("select")).click()
// select the value from the drop down option //
element(by.xpath("//option[text()='Avatar']")).click()
}
}
Handling Frames on Online Selenium Grid
You can run the same test script to handle frames in Selenium on a cloud selenium grid platform. Using an online Selenium grid. you can run the tests across various real browsers, OS, and devices. You just need to make a few configuration changes to connect with the LambdaTest hub. Below is our revised script with the appropriate modifications to handle frames in Selenium.
x
// test_config.js //
// The test_config.js file serves as a configuration file for out test case //
LT_USERNAME = process.env.LT_USERNAME || "irohitgoyal"; // Lambda Test User name
LT_ACCESS_KEY = process.0012.LT_ACCESS_KEY || "r9JhziRaOvd5T4KCJ9ac4fPXEVYlOTealBrADuhdkhbiqVGdBg"; // Lambda Test Access key
exports.capabilities = {
'build': ' Automation Selenium Webdriver Test Script ', // Build Name to be display in the test logs
'name': ' Protractor Selenium Frame Test on Chrome', // The name of the test to distinguish amongst test cases //
'platform':'Windows 10', // Name of the Operating System
'browserName': 'chrome', // Name of the browser
'version': '79.0', // browser version to be used
'console':false, // flag to check whether to capture console logs.
'tunnel': false // flag to check if it is required to run the localhost through the tunnel
'visual': false, // flag to check whether to take step by step screenshot
'network':false, // flag to check whether to capture network logs
};
// setting required config parameters //
exports.config = {
directConnect: true,
// Desired Capabilities that are passed as an argument to the web driver instance.
capabilities: {
'browserName': 'chrome' // name of the browser used to test //
},
// Flavour of the framework to be used for our test case //
framework: 'jasmine',
// The patterns which are relative to the current working directory when
protractor methods are invoked //
specs: ['test_frame.js'],
// overriding default value of allScriptsTimeout parameter //
allScriptsTimeout: 99999,
jasmineNodeOpts: {
// overriding default value of defaultTimeoutInterval parameter //
defaultTimeoutInterval: 99999
},
onPrepare: function () {
browser.manage().window().maximize();
browser.manage().timeouts().implicitlyWait(3000);
}
};
// test_script.js //
// import all the required modules from selenium web driver and protractor
import { browser, element, by, ExpectedConditions, protractor} from 'protractor'
import { Alert, WebElement } from 'selenium-webdriver';
var script = require (‘protractor’) ;
var webdriver = require (‘selenium-webdriver’) ;
// Build the web driver that we will be using in Lambda Test
var buildDriver = function(caps) {
return new webdriver.Builder()
.usingServer(
"http://" +
LT_USERNAME +
":" +
LT_ACCESS_KEY +
"@hub.lambdatest.com/wd/hub"
)
.withCapabilities(caps)
.build();
};
// describing the test for the frame demonstration //
describe(' Frame Demonstration in Protractor ', function() {
// disable synchronization for non angular websites //
browser.ignoreSynchronization = true;
// adding the before an event that builds the driver and triggers before the test execution
beforeEach(function(done) {
caps.name = this.currentTest.title;
driver = buildDriver(caps);
done();
});
// tests to handle parent iframe in protractor //
it(' Tests to handle parent iframe in protractor ', function() {
browser.manage().timeouts().implicitlyWait(5000)
// launch the url in the browser //
browser.get("http://the-internet.herokuapp.com/nested_frames");
// locate the frame element //
// store the value in a webelement
WebElement frame1 = element(by.id("frame1")).getWebElement();
// navigate to the next desired frame i.e. frame1
browser.switchTo().frame(frame1);
// locate the new frame i.e. frame 3 //
WebElement frame3 = element(by.xpath("//iframe[@id='frame3']")).getWebElement();
// using the switchTo method to navigate to frame 3
browser.switchTo().frame(frame3);
// search the frame for the checkbox element by xpath locator
WebElement checkbox = element(by.xpath("//input[@type='checkbox']"));
// if check box is not selected then click the checkbox
checkbox.isSelected().then(function(checked){
// if check box is not selected then click the checkbox
if(! checked){
checkbox.click();
}
})
// switch back to the parent frame with the switchToParentFrame i.e, frame 1
browser.switchToParentFrame();
// The stored value is assigned as the value of the text bar
browser.findElement(by.xpath("//input[@type='text']")).sendKeys("protractor");
// again switch to the main parent frame i.e the page level
browser.switchToParentFrame();
// retrieve the value stored in form of the text by xpath locator element(by.xpath("//label/span")).getText().then(function(textValue){
// validate the stored value to check whether it matches with the value of the frame.
if(textValue === "protractor test value"){
console.log("Topic value is equal to 'protractor test value'");
}
});
});
});
As we saw in the example for this Protractor testing tutorial, that just by appending a few lines of code we can connect to the LambdaTest Platform and run our previous test script in the cloud by. In order to have this setup, we are required to generate the desired capability matrix.
We can visit LambdaTest Selenium desired capabilities generator for generating the required configuration through which we can specify the environment in which we would like to perform our tests. Also, we just need to pass our LambdaTest username and access key in the configuration file that will uniquely identify us on the LambdaTest platform.
Below is the output on running the test to handle frames in Selenium:
It’s A Wrap!
This brings us to the end of this Protractor testing tutorial on how to handle frames in Selenium with the protractor. I hope it was a great experience in learning about handling frames and iFrames and exploring different approaches that we should keep in mind. I explored how to use the switchTo() frame method to work with a single frame in Protractor and how to navigate to the parent frame or between the nested frames.
This further helps in performing automated browser testing of websites that have multiple frames and browser windows. Moreover, adding frames to our web page enhances the look as the frame helps to allot proper sectional division based on the content which makes it more effective when used to the fullest.
Also since we know that protractor is based on selenium and used mainly for automated selenium test automation on browsers, it inherits many properties from them, including debugging protractor tests. This is the reason we can use the frames with other similar selenium frameworks. That’s all for now. Feel free to share this article with your peers.
Happy Testing!
Published at DZone with permission of Praveen Mishra, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments