How To Work with Frames (iframe) in Selenium Java, Python, Ruby, C#

Yosuva ArulanthuC#, Java, Python, Ruby, Selenium, Test Automation, TestingLeave a Comment

On occasion, you’ll run into a relic of the front-end world — frames. And when writing a test against them, you can easily get tripped if you’re not paying attention.

Rather than gnash your teeth when authoring your tests, you can easily work with the elements in a frame by telling Selenium to switch to that frame first. Then the rest of your test should be business as usual.

Sometimes you might be getting a NoSuchElementException even though you have written the correct XPath or any other locators(id, name, CSS selector). In such cases, you need to check whether elements are there inside the iframe or not. if is there in the iframe you need to switch to frame(driver.switchTo().frame(“frame-top”);) and then you need to interact to that element

Also, don’t forget to switch to default content(driver.switchTo().defaultContent();) after interacting with iframe elements

Let’s check the examples.

Sample Code

Java

// filename: Frames.java

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;

public class Frames {
    WebDriver driver;

    @Before
    public void setUp() throws Exception {
        driver = new FirefoxDriver();
    }

    @After
    public void tearDown() throws Exception {
        driver.quit();
    }

    @Test
    public void nestedFrames() throws Exception {
        driver.get("http://the-internet.herokuapp.com/nested_frames");
        driver.switchTo().frame("frame-top");
        driver.switchTo().frame("frame-middle");
        assertThat(driver.findElement(By.id("content")).getText(), is(equalTo("MIDDLE")));
        driver.switchTo().defaultContent();
    }

    @Test
    public void iFrames() throws Exception {
        driver.get("http://the-internet.herokuapp.com/tinymce");
        driver.switchTo().frame("mce_0_ifr");
        WebElement editor = driver.findElement(By.id("tinymce"));
        String beforeText = editor.getText();
        editor.clear();
        editor.sendKeys("Hello World!");
        String afterText = editor.getText();
        assertThat(afterText, not(equalTo((beforeText))));
        driver.switchTo().defaultContent();
        assertThat(driver.findElement(By.cssSelector("u")).getText(),
                is("An iFrame containing the TinyMCE WYSIWYG Editor"));
    }

}

Python

# filename: frames.py

import unittest
from selenium import webdriver


class Frames(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Firefox()

    def tearDown(self):
        self.driver.quit()

    def test_example_1(self):
        driver = self.driver
        driver.get('http://the-internet.herokuapp.com/nested_frames')
        driver.switch_to.frame('frame-top')
        driver.switch_to.frame('frame-middle')
        assert driver.find_element_by_id('content').text == "MIDDLE", "content should be MIDDLE"
        driver.switch_to.default_content()

    def test_example_2(self):
        driver = self.driver
        driver.get('http://the-internet.herokuapp.com/tinymce')
        driver.switch_to.frame('mce_0_ifr')
        editor = driver.find_element_by_id('tinymce')
        before_text = editor.text
        editor.clear()
        editor.send_keys('Hello World!')
        after_text = editor.text
        assert after_text != before_text, "%s equals %s" % (before_text, after_text)
        driver.switch_to.default_content()
  assert driver.find_element_by_css_selector('u').text != "", "element should not be empty"


if __name__ == "__main__":
    unittest.main()

Ruby

# filename: frames.rb

require 'selenium-webdriver'
require 'rspec/expectations'
include RSpec::Matchers

def setup
  @driver = Selenium::WebDriver.for :firefox
end

def teardown
  @driver.quit
end

def run
  setup
  yield
  teardown
end

#Test 1
run do
  @driver.get 'http://the-internet.herokuapp.com/nested_frames'
  @driver.switch_to.frame('frame-top')
  @driver.switch_to.frame('frame-middle')
  expect(@driver.find_element(id: 'content').text).to eql 'MIDDLE'
  @driver.switch_to.default_content
end

#Test 2
run do
  @driver.get 'http://the-internet.herokuapp.com/tinymce'
  @driver.switch_to.frame('mce_0_ifr')
  editor = @driver.find_element(id: 'tinymce')
  before_text = editor.text
  editor.clear
  editor.send_keys 'Hello World!'
  after_text = editor.text
  expect(after_text).not_to eql before_text
  @driver.switch_to.default_content
  expect(@driver.find_element(css: 'h3').text).not_to be_empty
end

C#

// filename: Frames.cs
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;

public class Frames
{
    IWebDriver Driver;

    [SetUp]
    public void SetUp()
    {
        Driver = new FirefoxDriver();
    }

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

    [Test]
    public void NestedFrames()
    {
        Driver.Navigate().GoToUrl("http://the-internet.herokuapp.com/nested_frames");
        Driver.SwitchTo().Frame("frame-top");
        Driver.SwitchTo().Frame("frame-middle");
        Assert.That(Driver.FindElement(By.Id("content")).Text.Equals("MIDDLE"));
    }

    [Test]
    public void Iframes()
    {
        Driver.Navigate().GoToUrl("http://the-internet.herokuapp.com/tinymce");
        Driver.SwitchTo().Frame("mce_0_ifr");
        IWebElement Editor = Driver.FindElement(By.Id("tinymce"));
        string StartText = Editor.Text;
        Editor.Clear();
        Editor.SendKeys("Hello World!");
        string EndText = Editor.Text;
        Assert.AreNotEqual(EndText, StartText);
        Driver.SwitchTo().DefaultContent();
        string HeaderText = Driver.FindElement(By.CssSelector("u")).Text;
        Assert.That(HeaderText.Equals("An iFrame containing the TinyMCE WYSIWYG Editor"));
    }
}

When you save this file and run it here is what will happen:

Test 1

  • Open the browser
  • Visit the page
  • Switch to the nested frame
  • Grab the text from the frame and assert that Selenium is in the correct place
  • Close the browser

Test 2

  • Open the browser
  • Visit the page
  • Switch to the frame that contains the TinyMCE editor
  • Find and store the text in the editor
  • Clear the text in the editor
  • Input new text in the editor
  • Find and store the new text in the editor
  • Assert that the original and new text entries don’t match
  • Switch to the top level of the page
  • Grab the text from the top of the page and assert it’s what we expect
  • Close the browser

Leave a Reply

Your email address will not be published.