Iframes, also known as inline frames, allow you to embed web pages within another web page. The <iframe>
tag is
extremely useful in web development because it can be used to load external web pages into the current page without the
two pages interfering with each other.
This article will explain iframes and show you how to use Selenium, a popular open-source library used for regression testing, to automate operations that interact properly with iframes on your website.
How to use iframes
To embed an iframe on a web page, you need to add the <iframe>
tag in the location where the external content should
be rendered. A common way to define what external content should be rendered within the iframe is to use the src
attribute.
Here’s an example below:
|
|
You can also set the height and width of your iframe using their attributes as seen below.
|
|
Other attributes relating to styling can be set in the style
attribute.
|
|
Iframes can also be used as the target frame for a link. The target attribute of the link must correspond to the iframe’s name attribute, as seen in the code below:
|
|
When a link’s target property matches the name of an iframe, the link opens in the iframe.
How to interact with iframes in Selenium
Now that we understand how to use iframes, let’s learn about the various cases to handle when interacting with iframes in Selenium.
Iframes with src
For iframes with the src
attribute, we can easily get the frame using the XPath
method.
|
|
Consider the iframe with the src
attribute below.
|
|
To get this iframe, you need to enter the contents of the src as in the code below:
|
|
Iframes without src
Not all iframes will have a src attribute. It’s possible to create and populate the contents of an iframe using
Javascript. It’s also possible to define the contents of the iframe inline by using the srcdoc
attribute:
|
|
For iframes without the src
attribute, we need to take a different approach. Selenium can target an iframe using any
attribute associated with its parent elements, such as an id
or name
attribute. Here are a few examples:
|
|
To navigate to the iframe directly, we make use of the switchTo
function.
|
|
or
|
|
Consider the iframe below:
|
|
In the iframe above, we can find the id of the frame which we can use to interact with it. To do this, pass the id of
the frame to the switchTo
function.
|
|
The “switchTo” function
To interact or verify behavior within an iframe, we must first switch Selenium’s context to that specific iframe. In Selenium, we may switch between iframes using one of three methods:
- By their id or name
- By index
- By WebElement.
Switching using id or name
If an id or name attribute is defined on the iframe you’re targeting, you can access that iframe using the following approach:
driver.switchTo().frame(“myName”)
Switching by index
Iframes can be referenced based on the order they appear within the current page’s markup. References to iframes in this manner use a 0-based index, meaning that iframes are counted starting from zero instead of one. So for example, the first iframe will have an index of 0 and the 4th iframe will have an index of 3:
|
|
Switching using a WebElement
A WebElement can be any element returned by the driver.findElement method.
Consider the iframe below:
|
|
|
|
NoSuchElementException
Selenium WebDriver cannot directly access and find the elements included within the iframes. Selenium can only access items in a certain context, which differs between the main web page and the embedded iframe. Selenium must manually swap the context in order to access the components within the iframe.
Consider the iframe below:
|
|
Now, let’s try to access the <h1>
element using its id sampleHeading
in the code below:
|
|
When run, this code will throw a NoSuchElementException
since the Selenium WebDriver is unable to detect the web
element with the specified id in the current context.
Selenium cannot access the components contained within the iframe. It must first change the context to the specific iframe in order to access all of the web components included within that iframe.
To switch the execution context to the detected iframe, we can use the switchTo().frame()
function as seen in the code
below:
|
|
The code will then print the content of the <h1>
element, “This is an example page.”
NoSuchFrameException
One common exception that can occur when interacting with iframes is NoSuchFrameException. This occurs when WebDriver tries to switch to an incorrect frame.
In the code below, if no frame with the name “frame_10” exists, you will get a NoSuchFrameException
|
|
If the frame “frame 10” does not exist or is unavailable, a “NoSuchFrameException” is thrown.
You can use a try-catch
to handle this exception as seen in the code below:
|
|
You can also wait for the frame to be available before loading it. To achieve this, use the WebDriverWait
function.
In the following example, WebDriver waits 30 seconds for the frame to become available before trying to access it. If the frame is not available the error is caught.
|
|
Accessing elements within an iframe and switching back to its parent
We now understand how to work with components within an iframe. How can you get back to components outside the iframe?
In such a situation, we must return to the main content and begin accessing the main frame’s web components. You can
achieve this using either the switchTo.defaultContent()
method or the switchTo.parentFrame()
method.
But what is the difference between these two methods? The difference is that driver.switchTo().defaultContent()
returns to the main page regardless of the number of frames on the page, whereas driver.switchTo().parentFrame() returns
to the current frame’s parent frame.
Consider the iframe below:
|
|
Since the web element is contained within the iframe, we must first switch to the iframe and then access the web element within it.
|
|
At this point, we need to switch back to the parent page to interact with elements outside the iframe.
|
|
The above line will allow us to return to the main frame and access the other web components on the website. If this is not handled in our code, an exception will be issued because the control is still in the iframe.
This operation is useful when you want to get the data within an iframe for use with elements outside the iframe like in an embedded login page where the signup button uses the data inside the iframe for authentication.
Testing an app with multiple nested iframes
A nested iframe is basically one iframe within another. The HTML structure of a nested iframe is seen below, with the first iframe in the parent page carrying the second iframe embedded in it using the src attribute.
Parent page:
|
|
Second iframe page “youtube-iframe.html”:
|
|
The output of the nested iframes in your browser:
To access a nested iframe, we must first switch to the outermost iframe, then switch to the inner iframe, before getting the targeted web element.
For the example above we can access the elements in the inner iframe using the code below:
|
|
The text printed out of the heading element in the inner frame will be “ Wintergatan - Marble Machine (music instrument using 2000 marbles)”.
Conclusion
As we demonstrated, testing any flavor of iframe is possible with Selenium, but the approach to accessing an iframe is sometimes not straightforward. Being able to interact with iframes, including iframes hosting content that you do not control, is often essential in meeting your test coverage requirements and testing critical workflows. With more and more third party applications integrating with sites via iframes (especially in verticals like SaaS and e-commerce), the demand for testing iframe content is unlikely to decrease any time soon.
Reflect: A testing tool with built-in support for iframes
Reflect is a no-code testing tool that can test virtually any action you can take on a browser. In addition to testing workflows that contain iframes, you can also test more complex actions like drag-and-drops, hovers, and file uploads. Creating a test in Reflect is easy: the tool records your actions as you use your site and automatically translates those actions into a repeatable test that you can run any time.
Get automated test coverage for your web app today — try it for free.