Identifying and handling frames

HTML frames allow developers to present documents in multiple views, which may be in a separate child window or sub-window. Multiple views offer developers a way to keep certain information visible while other views are scrolled or replaced. For example, within the same window, one frame might display a static banner, the second a navigation menu, and the third the main document that can be scrolled through or replaced by navigating in the second frame.

A page with frames is created using the <frameset> tag or the <iframe> tag. All frame tags are nested with a <frameset> tag. In the following example, a page will display three frames, each loading different HTML pages:

<html>
    <frameset cols="25%,*,25%" frameborder="NO" framespacing="0" border="0">
      <frame id="left" src="frame_a.htm" />
      <frame src="frame_b.htm" />
      <frame name="right" src="frame_c.htm" />
    </frameset>
</html>

Frames can be identified by an ID or through the name attribute. In this recipe, we will identify and work with frames using the driver.switchTo().frame() method of the WebDriver.TargetLocator interface, which is used to locate a given frame or window using the id, name, instance of WebElement, and the index.

How to do it...

Let's create a test on a simple page that has three frames. We will use id, name and index to identify these frames and interact with contents of these frames, as shown in the following examples:

  1. In the testFrameWithIdOrName test, we will use the name and id attributes to identify frames, as shown in the following code:
    package com.secookbook.examples.chapter06;
    
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebElement;
    
    import org.junit.AfterClass;
    import org.junit.BeforeClass;
    import org.junit.Test;
    import static org.junit.Assert.*;
    
    public class FramesTest {
    
      public static WebDriver driver;
    
      @BeforeClass
      public static void setUp() {
        driver = new FirefoxDriver();
        driver.get("http://cookbook.seleniumacademy.com/Frames.html");
        driver.manage().window().maximize();
      }
    
      @Test
      public void testFrameWithIdOrName() {
        try {
    
          // Activate the frame on left side using it's id attribute
          driver.switchTo().frame("left");
    
          // Get an element from the frame on left side and verify it's
          // contents
          WebElement msg = driver.findElement(By.tagName("p"));
          assertEquals("This is Left Frame", msg.getText());
        } finally {
          // Activate the Page, this will move context from frame back to the
          // Page
          driver.switchTo().defaultContent();
        }
    
        try {
          // Activate the frame on right side using it's name attribute
          driver.switchTo().frame("right");
    
          // Get an element from the frame on right side and verify it's
          // contents
          WebElement msg = driver.findElement(By.tagName("p"));
          assertEquals("This is Right Frame", msg.getText());
        } finally {
          // Activate the Page, this will move context from frame back to the
          // Page
          driver.switchTo().defaultContent();
        }
      }
    
      @AfterClass
      public static void tearDown() {
        // Close the Parent Popup Window
        driver.close();
        driver.quit();
      }
    }
  2. In the second test, testFrameByIndex, we will use index for identifying the frame, as shown in the following code:
    @Test
    public void testFrameByIndex() {
      try {
        // Activate the frame in middle using it's index. Index starts at 0
        driver.switchTo().frame(1);
    
        // Get an element from the frame in the middle and verify it's
        // contents
        WebElement msg = driver.findElement(By.tagName("p"));
        assertEquals("This Frame doesn't have id or name", msg.getText());
      } finally {
        // Activate the Page, this will move context from frame back to the
        // Page
        driver.switchTo().defaultContent();
      }
    }

How it works...

The Selenium WebDriver's WebDriver.TargetLocator interface provides the driver.switchTo().frame() method to activate a frame on a page and perform operations. This method takes the id or name attribute value or instance of a WebElement (the <frame> element can be located using the driver.findElement() method).

In the following example, the id attribute is used to identify a frame:

//Activate the frame on left side using it's id attribute
driver.switchTo().frame("left");

When frames do not have the id or name attributes defined, index can be used to identify a frame. In the preceding example, the frame in the middle does not have the id or name attributes. The middle frame's index will be 1, as it has a frame on the left-hand side with the index as 0, and on the right-hand side with the index 2:

//Activate the frame in middle using it's index. Index starts at 0
driver.switchTo().frame(1);

Once a frame is activated, we can leave the driver instance to interact with the page loaded in the frame. To return to the main page, use the driver.switchTo().defaultContent() method.

Note

Warning: While working with multiple frames, when an operation is completed on a frame and a test flow needs to move to another frame, calling the driver.switchTo().frame() method will not move the context to the desired frame. The test will first need to activate the main page by calling the driver.switchTo().defaultContent() method and then later activating the desired frame.

There's more…

While working with frames, you will find that the id or name attributes are not defined. Still, frames can be identified using their index. This may not be a reliable way when applications are dynamic and there is a need to ensure that the correct frame is activated.

Let's look at an example in which we will identify frames by the contents of the page loaded in these frames to make tests more reliable, as shown in following code example:

@Test
public void testFrameByContents() {
  // Get all frames on the Page, created with <frame> tag
  List<WebElement> frames = driver.findElements(By.tagName("frame"));

  // In this example frame in the middle is activated by checking the
  // contents
  // Activate frame and check if it has the desired content. If found
  // perform the operations
  // if not, then switch back to the Page and continue checking next frame
  try {
    for (WebElement frame : frames) {
      // switchTo().frame() also accepts frame elements apart from id,
      // name or index
      driver.switchTo().frame(frame);
      String title = driver.getTitle();
      if (title.equals("Frame B")) {
        WebElement msg = driver.findElement(By.tagName("p"));
        assertEquals("This is Left Frame", msg.getText());
        break;
      } else
        driver.switchTo().defaultContent();
    }
  } finally {
    // Activate the Page, this will move context from frame back to the
    // Page
    driver.switchTo().defaultContent();
  }
}

In Selenium WebDriver, we can get multiple elements matching the same criteria in a list. Here we will get all frame elements from the page using the tagName() method, as shown in following code example:

//Get all frames on the Page, created with <frame> tag
List<WebElement> frames = driver.findElements(By.tagName("frame"));

The test will iterate through each frame element, passing this element to the driver.switchTo().frame() method and checking its content. If the frame has matching content, then we can continue operations on the frame and later switch back to the main page, as shown in the following code example:

for (WebElement frame : frames) {
      // switchTo().frame() also accepts frame elements apart from id,
      // name or index
      driver.switchTo().frame(frame);
      String title = driver.getTitle();
      if (title.equals("Frame B")) {
        WebElement msg = driver.findElement(By.tagName("p"));
        assertEquals("This is Left Frame", msg.getText());
        break;
      } else
        driver.switchTo().defaultContent();
    }

Tip

You can create a utility method to switch between frames using their content.

See also

  • The Working with IFRAME recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.66.156