Implementing nested Page Object instances

So far, we explored a very simple Page Object implementation for a single page web application. We can use the Page Object model to implement the objects of a page in a complex web application to simplify the testing.

In this recipe, we will create the objects of the Page Object model for the search functionality in an e-commerce application found at http://demo.magentocommerce.com/. We can implement a Page Object model even if the specific functionality is not a page of its own.

Each page of the application provides the user with the ability to search for products on the site by entering a query and hitting the search button. When a search query is submitted, the application returns a new page with a list of products matching the search query. Using the approach described in this recipe, we can build a more modular framework as shown in following diagram:

Implementing nested Page Object instances

In this recipe, we will create this nested hierarchy, where the HomePage class implements the Search class, which in turn returns an object of the SearchResults class to the test.

Getting ready

Identify the page and logical relationship between pages to build a nested component set.

How to do it...

To implement nested Page Object instances, perform the following steps:

  1. Create the Browser class, which will provide a static and shared WebDriver instance for all the pages, as follows:
    package com.secookbook.examples.chapter08.pageobjects;
    
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.chrome.ChromeDriver;
    
    public class Browser {
    
      private static WebDriver driver = new ChromeDriver();
    
      public static WebDriver driver() {
        return driver;
      }
    
      public static void open(String url) {
        driver.get(url);
      }
    
      public static void close() {
        driver.quit();
      }
    }
  2. Create the HomePage class, which allows the test to navigate to the home page of the application. It also provides access to the Search class, which is shared among the various pages of the application, as follows:
    package com.secookbook.examples.chapter08.pageobjects;
    
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.support.PageFactory;
    import org.openqa.selenium.support.ui.LoadableComponent;
    
    import static org.junit.Assert.*;
    
    public class HomePage extends LoadableComponent<HomePage> {
    
      private WebDriver driver;
    
      static String url = "http://demo.magentocommerce.com/";
      private static String title = "Madison Island";
    
      public HomePage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
      }
    
      @Override
      public void load() {
        Browser.open(url);
      }
    
      @Override
      public void isLoaded() {
        assertEquals(title, driver.getTitle());
      }
    
      public Search Search() {
        Search search = new Search(driver);
        return search;
      }
    }
  3. Create the Search class. This class provides all the objects of the Page Object model to search for products in the application, as follows:
    package com.secookbook.examples.chapter08.pageobjects;
    
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.support.FindBy;
    import org.openqa.selenium.support.PageFactory;
    
    public class Search {
    
      private WebDriver driver;
    
      private WebElement search;
    
      @FindBy(css = "button.button")
      private WebElement searchButton;
    
      public Search(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
      }
    
      public SearchResults searchInStore(String query) {
        search.sendKeys(query);
        searchButton.click();
        return new SearchResults(driver, query);
       }
    }
  4. Create the SearchResult class, which is nested in the Search class. The SearchResult class represents the results page when the user submits a search query, as discussed previously. The SearchResult class also provides access to the Search class so that users can search again for a different query. This is done as follows:
    package com.secookbook.examples.chapter08.pageobjects;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.support.PageFactory;
    import org.openqa.selenium.support.ui.LoadableComponent;
    
    import static org.junit.Assert.*;
    
    public class SearchResults extends LoadableComponent<SearchResults> {
    
      private WebDriver driver;
      private String query;
    
      public SearchResults(WebDriver driver, String query) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
      }
    
      @Override
      public void isLoaded() {
        assertEquals("Search results for: '" + this.query + "'", driver.getTitle());
      }
      public List<String> getProducts() {
        List<String> products = new ArrayList<String>();
        List<WebElement> productList = driver.findElements(
            By.cssSelector("ul.products-grid > li"));
        
        for (WebElement item : productList)  {
          products.add(item.findElement(By.cssSelector("h2 > a")).getText());
        }
        return products;
      }
    
      public Search Search() {
        Search search = new Search(driver);
        return search;
      }
    
      @Override
      protected void load() {
        // TODO Auto-generated method stub
      }
    }
  5. Finally, create a test which tests the search functionality from the home page of the application, as follows:
    package com.secookbook.examples.chapter08.tests;
    
    import org.junit.Test;
    
    import com.secookbook.examples.chapter08.pageobjects.Browser;
    import com.secookbook.examples.chapter08.pageobjects.HomePage;
    import com.secookbook.examples.chapter08.pageobjects.SearchResults;
    
    import static org.junit.Assert.*;
    
    public class SearchTest {
    
      @Test
      public void testProductSearch() {
        try {
          // Create an instance of Home page
          HomePage homePage = new HomePage(Browser.driver());
    
          // Navigate to the Home page
          homePage.get();
    
          // Search for 'phones', the searchInStore method will return
          // SerchResults
          SearchResults searchResult = homePage.Search().searchInStore(
              "phones");
    
          // Verify there are 2 products available with this search
          assertEquals(2, searchResult.getProducts().size());
          assertTrue(searchResult.getProducts().contains(
              "MADISON OVEREAR HEADPHONES"));
        } finally {
          Browser.close();
        }
      }
    }

How it works...

The test starts by creating an instance of the HomePage class. As you can see, the application home page provides the user with the ability to search the site. In a similar way, the HomePage class provides the ability to search by using the Search class, as follows:

HomePage homePage = new HomePage(Browser.driver());
homePage.get();
SearchResults searchResult = homePage.Search().searchInStore("phones");

The searchInStore() method of the Search class takes the query string as arguments and interacts with the search form to send the query. It returns the SearchResults class as a page. The SearchResults class provides a list of products that match the query back to the test using the getProducts() method, as follows:

public List<String> getProducts() {
  List<String> products = new ArrayList<String>();
  List<WebElement> productList = driver.findElements(
      By.cssSelector("ul.products-grid > li"));

  for (WebElement item : productList)  {
    products.add(item.findElement(By.cssSelector("h2 > a")).getText());
  }
  return products;
}

The test can verify the number of products as well as the names of the products by checking the return value of the getProducts() method, as follows:

assertEquals(2, searchResult.getProducts().size());
assertTrue(searchResult.getProducts().contains(
  "MADISON OVEREAR HEADPHONES"));

Using the nested objects of the Page Object model, we can build a logical chain of pages within an application and build a robust and maintainable test automation framework.

See also

  • The Using the LoadableComponent class recipe
..................Content has been hidden....................

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