End-to-end Testing
How-tos & Guides
9 min read

Interacting with iframes in Selenium

Essential tips and tricks for building Selenium tests for any variant of iframe.

Ochuko Onojakpor
Published July 27, 2022

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 test automation library, 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:

<iframe src="https://example.com/index" title="description"></iframe>

You can also set the height and width of your iframe using their attributes as seen below.

<iframe src="https://example.com/index" height="200" width="300" title="Iframe Example"></iframe>

Other attributes relating to styling can be set in the style attribute.

<iframe src="https://example.com/index" style="border:2px solid red;" title="Iframe Example"></iframe>

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:

<iframe src="https://example.com/index" name="iframe_a" title="Iframe Example"></iframe>
<p><a href="https://www.reflect.run" target="iframe_a">Reflect.run</a></p>

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.

driver.findElement(By.XPath("//iframe"));

Consider the iframe with the src attribute below.

<iframe src="https:example.com/index" style="border:2px solid red;" title="Iframe Example"></iframe>

To get this iframe, you need to enter the contents of the src as in the code below:

driver.findElement(By.XPath("//iframe[contains(@src,'https:example.com/index')]"));

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:

<iframe srcdoc=”<h1>This is rendered inside the iframe</h1>”> </iframe>

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:

driver.findElement(By.name(iframe1));

driver.findElement(By.id(mainframe));

driver.findElement(By.cssSelector([data-test-id=example]));

To navigate to the iframe directly, we make use of the switchTo function.

driver.switchTo().frame(String name);

or

driver.switchTo().frame(String id);

Consider the iframe below:

<iframe src="https:example.com/index" style="border:2px solid red;" title="Iframe Example" if="”frame1”"></iframe>

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.

driver.switchTo().frame("frame1");

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:

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:

driver.switchTo().frame(0);
driver.switchTo().frame(3);

Switching using a WebElement

A WebElement can be any element returned by the driver.findElement method.

Consider the iframe below:

<iframe
  src="https:example.com/index"
  style="border:2px solid red;"
  title="Iframe Example"
  class="”moneyiframe”
></iframe>
WebElement iframe_element = driver.findElement(By.xpath("//iframe[@class='moneyiframe']"));
driver.switchTo().frame(iframe_element);

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:

<iframe src="https://example.com" id="frame1" width="580px" height="350px">
  <html>
    <head></head>
    <body>
      <h1 id="sampleHeading">This is a sample heading</h1>
    </body>
  </html></iframe
>

Now, let’s try to access the <h1> element using its id sampleHeading in the code below:

WebDriver driver=new ChromeDriver();

// Navigate to url
driver.get("https://www.example.com");

// Locate the frame1 heading
WebElement frame1Heading= driver.findElement(By.id("sampleHeading"));

// Find the text of the frame1 heading
String frame1Text=frame1Heading.getText();

// Print the heading
System.out.println("Text of the frame1 heading is:"+frame1Text);

// Close the driver
driver.close();

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:

// Initialize browser
WebDriver driver=new ChromeDriver();

// Navigate to url
driver.get("https://www.example.com");

// Switch to Frame using Index
driver.switchTo().frame(0);

//Identify the heading in webelement
WebElement frame1Heading= driver.findElement(By.id("sampleHeading"));

//Find the text of the heading
String frame1Text=frame1Heading.getText();

//Print the heading text
System.out.println(frame1Text);

// Close the driver
driver.close();

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

driver.switchTo().frame(frame_10);

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:

try {
  driver.switchTo().frame("frame_10");
} catch (NoSuchFrameException e) {
  // Take some action here
}

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.

try {
  WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
  wait.Until(ExpectedConditions.frameToBeAvaliableAndSwitchToIt(frame_10));

  driver.switchTo().frame("frame_10");

} catch (WebDriverException e) {
  // Unknown exception
}
} catch (TimeOutException e) {
  // Timed out trying to locate the frame
}

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:

<iframe src="https:example.com/index" style="border:2px solid red;" title="Iframe Example" class=”moneyiframe”>
<h1 id="sampleHeading"> This is a sample heading</h1> </iframe> </html>

Since the web element is contained within the iframe, we must first switch to the iframe and then access the web element within it.

driver.switchTo().frame("moneyiframe");   //moneyiframe is the id of the iframe

WebElement insideElement = driver.findElement(By.id("sampleHeading"));

String heading_Value = insideElement.getText();

System.out.println("The heading value is " +heading_Value);

At this point, we need to switch back to the parent page to interact with elements outside the iframe.

driver.switchTo().defaultContent();

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:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
  </head>
  <body>
    <iframe id="”first_iframe”" width="400" height="400" frameboder="0" src="./youtube-iframe.html" allowfullscreen>
    </iframe>
  </body>
</html>

Second iframe page “youtube-iframe.html”:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
  </head>
  <body>
    <iframe
      id="”second_iframe”"
      width="560"
      height="315"
      src="https://www.youtube.com/embed/IvUU8joBb1Q"
      frameborder="0"
      allowfullscreen
    ></iframe>
  </body>
</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:

// Get the number of iframes on the page, this should return 1
driver.findElement(By.tagName(iframe)).getSize();

// Navigate to the outer frame
driver.switchTo().frame(first_iframe);

// Navigate to the inner frame
driver.switchTo().frame(second_iframe);

// Get youtube video title element in the inner frame
WebElement frame2Heading = driver.FindElement(By.CssSelector("[name = 'class="ytp-title-link yt-uix-sessionlink"']"))

// Find the text of the heading
String frame2Text=frame2Heading.getText();

// Print the heading text
System.out.println(frame2Text);

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.

Get started with Reflect today

Create your first test in 2 minutes, no installation or setup required. Accelerate your testing efforts with fast and maintainable test suites without writing a line of code.

Copyright © 2022 Reflect Software Inc. All Rights Reserved.