My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more
Selenium C# Tutorial: Handling Frames & iFrames With Examples

Selenium C# Tutorial: Handling Frames & iFrames With Examples

Himanshu Sheth's photo
Himanshu Sheth
·May 21, 2020

As an automation tester, one of the challenges you might face while writing your Selenium test automation scripts is handling frames or iFrames in Selenium while performing automated browser testing. While frames are used to split-screen vertically or horizontally, iFrames are used to insert content from other sources such as ads into your website.

While writing your Selenium test automation scripts, you need to know how to handle frames and iFrames in Selenium. The switch command in Selenium C# is used for automating scenarios involving frames or iFrames in Selenium.

In this Selenium C# tutorial, I’ll show you how to handle nested frames and iFrames in Selenium, using SwitchTo() command.

Switch Window Commands For Frames & iFrames in (Selenium C#)

In order to handle frames and iFrames in Selenium, you first need to know how to identify them. Every window, frames or iFrame in a website has a unique ID called window handle. This window handle remains unchanged throughout the execution of the test scenario and is used to identify different frames or iFrame in Selenium C#.

The window handle is used to switch from one window to another. The switch commands in Selenium C# is accessed by using the SwitchTo method in Selenium WebDriver API.

switch window command

Here are the Switch Window commands, you’ll require for switching frame or iFrame in Selenium:

1. SwitchTo Frame

A frame is a part of the web page or web browser window that displays content independent of the web container. An inline frame (or iFrame) is an HTML document that is embedded inside another HTML document. Many websites make use of frames and iFrames for showcasing content.

driver.SwitchTo().Frame(frame-id);
driver.SwitchTo().Frame("frame-name");

/* weblocator can be XPath, CssSelector, Id, Name, etc. */
driver.SwitchTo().Frame(driver.FindElement(By.weblocator("web-locator-property")));

2. SwitchTo DefaultContent

This command selects either the first frame on the web page or the main document (i.e. < main >) when the page contains iFrames.

driver.SwitchTo().DefaultContent();

3. SwitchTo ParentFrame

This command selects the parent frame of the currently selected frame.

driver.SwitchTo().ParentFrame();

Whether it is a frame, alert, or new window (or tab), each of these is identified with their unique Window Handle. It is a unique identifier of the type string that is a pointer to the window as it holds the address to the window.

Handling Nested Frames & iFrames in (Selenium C#)

Nested Frames and iFrames in Selenium testing are particularly used in websites that have multiple sections and each section has to load a separate HTML document. A frameset is a collection of frames in the browser window. The frameset acts as a parent to the child frames in the window.

The Selenium Java official website uses frames to divide the content into three different sections. Switching between different frames is done using the SwitchTo() command for frames.

The SwitchTo frame command is used to switch to the intended frame (or iFrame). Frame id, frame name, and web element locator are used with the SwitchTo command for switching to the intended frame.

driver.SwitchTo().Frame(frame-id);
driver.SwitchTo().Frame("frame-name");

/* weblocator can be XPath, CssSelector, Id, Name, etc. */
driver.SwitchTo().Frame(driver.FindElement(By.weblocator("web-locator-property")));

It is necessary to first switch to the Parent Frame before switching to the intended Child Frame.

/* Switching back to the parent frame */
driver.SwitchTo().ParentFrame();

Handling Nested Frames Using SwitchTo() Method

A nested frame is a frameset that contains a collection of frames (or sub-frames). A frameset contains three different frames – LEFT, MIDDLE, and RIGHT. The BOTTOM frame is an independent frame.

I’ve used http://the-internet.herokuapp.com/nested_frames, for the demonstration of a frameset.

iframe

Before switching to frames, we first switch to the frameset (i.e. parent frame) and use the SwitchTo() command to switch to the Child frame. If you want to switch to MIDDLE frame; first you’d have to switch to its container, i.e. frameset – frame-top, then switch to the intended frame i.e. frame-middle.

Similarly, for switching to the BOTTOM frame, you need to switch to the ParentFrame using the driver.SwitchTo().ParentFrame() command, and then switch to the intended frame by using the SwitchTo() command for BOTTOM frame.

I’ve used NUnit framework for this Selenium C# tutorial, In case you want to know about NUnit in detail, you can refer to NUnit framework for Selenium C#.

Here is the implementation for handling Nested frames in Selenium C#:

/* Handling Nested frames in this Selenium C# tutorial for Selenium test automation*/
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Support.UI;
using SeleniumExtras.WaitHelpers;
using System;

namespace Selenium_Frame_Demo
{
    class Selenium_Frame_Demo
    {
        IWebDriver driver;

        [SetUp]
        public void start_Browser()
        {
            // Local Selenium WebDriver
            driver = new ChromeDriver();
            driver.Manage().Window.Maximize();
        }

        [Test, Order(1)]
        public void test_frame_left()
        {
            String test_url = "http://the-internet.herokuapp.com/nested_frames";

            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

            driver.Url = test_url;

            /**************** Switching to the Left Frame ****************/
            /* Switch to the Parent frame before switching to any of the Child frames */
            driver.SwitchTo().ParentFrame();

            /* Since the top frame is a Framset, switch to that frameset first */
            driver.SwitchTo().Frame(driver.FindElement(By.CssSelector("[name = 'frame-top']")));

            /* As we are already in the frameset, we can now switch to the new frame */
            driver.SwitchTo().Frame(driver.FindElement(By.CssSelector("[name = 'frame-left']")));

            /* Reference - https://stackoverflow.com/questions/37791547/selenium-webdriver-get-current-frame-before-switch */

            IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
            var currentFrame = jsExecutor.ExecuteScript("return self.name");
            Console.WriteLine(currentFrame);
        }

        [Test, Order(2)]
        public void test_frame_middle()
        {
            String test_url = "http://the-internet.herokuapp.com/nested_frames";

            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

            driver.Url = test_url;

            /**************** Switching to the Left Frame ****************/
            /* Switch to the Parent frame before switching to any of the Child frames */
            driver.SwitchTo().ParentFrame();

            /* Since the top frame is a Framset, switch to that frameset first */
            driver.SwitchTo().Frame(driver.FindElement(By.CssSelector("[name = 'frame-top']")));

            /* As we are already in the frameset, we can now switch to the new frame */
            driver.SwitchTo().Frame(driver.FindElement(By.CssSelector("[name = 'frame-middle']")));

            /* Reference - https://stackoverflow.com/questions/37791547/selenium-webdriver-get-current-frame-before-switch */

            IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
            var currentFrame = jsExecutor.ExecuteScript("return self.name");
            Console.WriteLine(currentFrame);
        }

        [Test, Order(3)]
        public void test_frame_right()
        {
            String test_url = "http://the-internet.herokuapp.com/nested_frames";

            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

            driver.Url = test_url;

            /**************** Switching to the Left Frame ****************/
            /* Switch to the Parent frame before switching to any of the Child frames */
            driver.SwitchTo().ParentFrame();

            /* Since the top frame is a Framset, switch to that frameset first */
            driver.SwitchTo().Frame(driver.FindElement(By.CssSelector("[name = 'frame-top']")));

            /* As we are already in the frameset, we can now switch to the new frame */
            driver.SwitchTo().Frame(driver.FindElement(By.CssSelector("[name = 'frame-right']")));

            /* Reference - https://stackoverflow.com/questions/37791547/selenium-webdriver-get-current-frame-before-switch */

            IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
            var currentFrame = jsExecutor.ExecuteScript("return self.name");
            Console.WriteLine(currentFrame);
        }

        [Test, Order(4)]
        public void test_single_frame()
        {
            String test_url = "http://the-internet.herokuapp.com/nested_frames";

            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

            driver.Url = test_url;

            /**************** Switching to the Left Frame ****************/
            /* Switch to the Parent frame before switching to any of the Child frames */
            driver.SwitchTo().ParentFrame();

            /* Directly switch to the new frame */
            driver.SwitchTo().Frame(driver.FindElement(By.CssSelector("[name = 'frame-bottom']")));

            /* Reference - https://stackoverflow.com/questions/37791547/selenium-webdriver-get-current-frame-before-switch */

            IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
            var currentFrame = jsExecutor.ExecuteScript("return self.name");
            Console.WriteLine(currentFrame);
        }

        [TearDown]
        public void close_Browser()
        {
            driver.Quit();
        }
    }
}

For switching to the LEFT frame, you need to perform these steps:

  1. Switch to the Parent Frame
  2. Switch to the frameset (or container of the LEFT frame): frame-top
  3. Switch to the LEFT frame using the CssSelector property. Use the Inspect Tool in Chrome/Firefox to get this property.
  4. Use the executescript method of the JavaScriptExecutor interface to run JavaScript on the page so that the current frame can be compared with the intended frame.
[Test, Order(1)]
public void test_frame_left()
{
      String test_url = "http://the-internet.herokuapp.com/nested_frames";

      WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

      driver.Url = test_url;

      /**************** Switching to the Left Frame ****************/
      /* Switch to the Parent frame before switching to any of the Child frames */
      driver.SwitchTo().ParentFrame();

      /* Since the top frame is a Framset, switch to that frameset first */
       driver.SwitchTo().Frame(driver.FindElement(By.CssSelector("[name = 'frame-top']")));

       /* As we are already in the frameset, we can now switch to the new frame */
       driver.SwitchTo().Frame(driver.FindElement(By.CssSelector("[name = 'frame-left']")));

       /* Reference - https://stackoverflow.com/questions/37791547/selenium-webdriver-get-current-frame-before-switch */

       IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
       var currentFrame = jsExecutor.ExecuteScript("return self.name");
       Console.WriteLine(currentFrame);
}

To switch to the BOTTOM frame, first switch to the Parent frame and then to the BOTTOM frame.

[Test, Order(4)]
public void test_single_frame()
{
    String test_url = "http://the-internet.herokuapp.com/nested_frames";

    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

    driver.Url = test_url;
    driver.SwitchTo().ParentFrame();

    /* Directly switch to the new frame */
    driver.SwitchTo().Frame(driver.FindElement(By.CssSelector("[name = 'frame-bottom']")));

     IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
     var currentFrame = jsExecutor.ExecuteScript("return self.name");
     Console.WriteLine(currentFrame);
}

As seen in the Visual Studio snapshot, the test scenarios pass as the SwitchTo() command is successful in switching to the intended frames.

test-frame

test-frame1

Handling iFrames In Selenium Using SwitchTo() Method

For this Selenium C# tutorial, I’ve used Selenium.dev as a test URL for the Selenium test automation case on iFrame handling using SwitchTo(). Switching to an iFrame is done using frame name, frame id, or web selector for the iFrame.

Details of the frames in frameset are obtained using the Inspect Tool in Firefox. The site consists of three separate iFrames – packageListFrame, packageFrame, and classFrame.

selenium-dev

selenium-dev1

selenium-inspect

Three variants of SwitchTo.Frame() are demonstrated in the example for Selenium C# tutorial for Selenium iFrames:

  1. Using Frame Name – SwitchTo().Frame(“frame-name”)
  2. Using Frame ID – SwitchTo().Frame(“frame-id”)
  3. Using web locators – SwitchTo().Frame(web-driver.FindElement(By.web-locator))
/* Selenium C# tutorial: Handling iframes in Selenium test automation for automated browser testing*/
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Support.UI;
using SeleniumExtras.WaitHelpers;
using System;
using System.Collections.ObjectModel;

namespace Selenium_Frame_Demo
{
    class Selenium_Frame_Demo
    {
        IWebDriver driver;
        String final_frame_xpath = "/html/frameset/frame";

        [SetUp]
        public void start_Browser()
        {
            // Local Selenium WebDriver
            driver = new ChromeDriver();
            driver.Manage().Window.Maximize();
        }

        [Test, Order(1)]
        public void test_frame_number()
        {
            String test_url = "https://www.selenium.dev/selenium/docs/api/java/index.html";

            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

            driver.Url = test_url;

            IWebElement SearchResult = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.XPath(final_frame_xpath)));

            /* Switch to the Parent frame before switching to any of the Child frames */
            driver.SwitchTo().ParentFrame();

            /* Frame Number | Frame Name        | Frame XPath */
            /* 0            | packageListFrame  | /html/frameset/frameset/frame[1] */
            /* 1            | packageFrame      | /html/frameset/frameset/frame[2] */
            /* 2            | classFrame        | /html/frameset/frame */

            /* Switching to a new frame by frame number. The new frame will be packageListFrame */
            driver.SwitchTo().Frame(0);

            /* Reference - https://stackoverflow.com/questions/37791547/selenium-webdriver-get-current-frame-before-switch */

            IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
            var currentFrame = jsExecutor.ExecuteScript("return self.name");
            Console.WriteLine(currentFrame);
        }

        [Test, Order(2)]
        public void test_frame_name()
        {
            String test_url = "https://www.selenium.dev/selenium/docs/api/java/index.html";

            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

            driver.Url = test_url;

            IWebElement SearchResult = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.XPath(final_frame_xpath)));

            /* Switch to the Parent frame before switching to any of the Child frames */
            driver.SwitchTo().ParentFrame();

            /* Frame Number | Frame Name        | Frame XPath */
            /* 0            | packageListFrame  | /html/frameset/frameset/frame[1] */
            /* 1            | packageFrame      | /html/frameset/frameset/frame[2] */
            /* 2            | classFrame        | /html/frameset/frame */

            /* Switching to a new frame by frame number for iframe selenium. The new frame will be packageFrame */
            driver.SwitchTo().Frame("packageFrame");

            IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
            var currentFrame = jsExecutor.ExecuteScript("return self.name");
            Console.WriteLine(currentFrame);
        }

        [Test, Order(3)]
        public void test_frame_identifier()
        {
            String test_url = "https://www.selenium.dev/selenium/docs/api/java/index.html";

            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

            driver.Url = test_url;

            IWebElement SearchResult = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.XPath(final_frame_xpath)));

            /* Switch to the Parent frame before switching to any of the Child frames for Selenium iframe for automated browser testing*/
            driver.SwitchTo().ParentFrame();

            /* Frame Number | Frame Name        | Frame XPath */
            /* 0            | packageListFrame  | /html/frameset/frameset/frame[1] */
            /* 1            | packageFrame      | /html/frameset/frameset/frame[2] */
            /* 2            | classFrame        | /html/frameset/frame */

            /* Switching to a new frame by frame number for handing Selenium iframe for automated browser testing. The new frame will be classFrame */
            driver.SwitchTo().Frame(driver.FindElement(By.XPath("/html/frameset/frame")));

            IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
            var currentFrame = jsExecutor.ExecuteScript("return self.name");
            Console.WriteLine(currentFrame);
        }

        [TearDown]
        public void close_Browser()
        {
            driver.Quit();
        }
    }
}

The implementation consists of three test cases. The basic premise of each test case is the same, switching first to the Parent Frame before moving to the intended iFrame. Only difference is the manner in which frames are addressed i.e. id, name, etc.

[Test, Order(3)]
public void test_frame_identifier()
{
    String test_url = "https://www.selenium.dev/selenium/docs/api/java/index.html";

    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
    driver.Url = test_url;

    IWebElement SearchResult = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.XPath(final_frame_xpath)));

    /* Switch to the Parent frame before switching to any of the Child frames for handing Selenium iframe for automated browser testing in Selenium test automation */
    driver.SwitchTo().ParentFrame();

    /* Frame Number | Frame Name        | Frame XPath */
    /* 0            | packageListFrame  | /html/frameset/frameset/frame[1] */
    /* 1            | packageFrame      | /html/frameset/frameset/frame[2] */
    /* 2            | classFrame        | /html/frameset/frame */

    /* Switching to a new frame by frame number. The new frame will be classFrame */
    driver.SwitchTo().Frame(driver.FindElement(By.XPath("/html/frameset/frame")));

    IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
    var currentFrame = jsExecutor.ExecuteScript("return self.name");
    Console.WriteLine(currentFrame);
}

Every Selenium test automation case for handling iframe in Selenium for automated browser testing starts with switching to the Parent Frame.

/* Switch to the Parent frame before switching to any of the Child frames */
driver.SwitchTo().ParentFrame();

Once we are in the Parent frame, we switch to the intended frame using its XPath property.

/* Switch to the Parent frame before switching to any of the Child frames */
driver.SwitchTo().Frame(driver.FindElement(By.XPath("/html/frameset/frame")));

The three Selenium test automation scenarios pass with the SwitchTo() command successful in switching to the requested frame.

xpath

test-name

The examples mentioned in this Selenium C# tutorial can be useful in solving frequently encountered problems by Selenium automation testers. The solution to the problem witnessed here is available in the section Handling Nested Frames & iFrames in Selenium C#

Wrapping it Up

I hope you enjoyed this deep dive into handling frames and iFrames in Selenium C#. By now you should be able to switch between nested frames or iFrames in Selenium C#. In Selenium test automation, by using the SwitchTo() command, you can perform automated browser testing of websites (or web apps) that use pop-up windows, nested frames (or iFrames), and browser windows.

Still up for more learning? In the next article for this Selenium C# tutorial series, I’ll show you how to use Page Object Model in Selenium C#.

Update : We’ve now completed the Selenium C# tutorial series, so in order to help you easily navigate through the tutorials, we’ve compiled the complete list of tutorials, which you can find in the section below.

Selenium C# Tutorials With Examples

Selenium C# Tutorial: Setting Up Selenium In Visual Studio Running First Selenium C# Script With NUnit Selenium C# Tutorial: Using Implicit Wait in Selenium Selenium C# Tutorial: Using Explicit and Fluent Wait in Selenium Selenium C# Tutorial: Handling Alert Windows Selenium C# Tutorial: Handling Multiple Browser Windows Selenium C# Tutorial: Handling Frames & iFrames With Examples Selenium C#: Page Object Model Tutorial With Examples

In case of any doubts, reach out to us in the comments section so that we can put our best foot forward to solve your Selenium test automation problems. Also, share the article with your peers seeking to learn about Selenium testing and handling frame and iframe in Selenium C#. Happy Testing!