Part 3: Hybrid Framework Development…

This post is a continuation of Part 1: Hybrid Framework Development… and Part 2: Hybrid Framework Development…

Here we will mainly focus on creating Page Objects of our Demo website as well as use the Page Factory concepts.

For better understanding, please go through the following posts:

Part 1: Page Object Model…
Part 2: Page Object Model…
Working with Page Factory…

  • Our first task is to create a Base class. This Base class will have common methods that will be used in all our Page Object classes. Right click on the ‘src/main/java‘ folder and click New -> Package. Name the package as ‘com.testmadness.base’ and click Finish to close the window.
  • Inside ‘com.testmadness.base’ package, we will place our Base class. Right click on ‘com.testmadness.utils’ package and select New -> Class. Name the class as ‘BasePage.java’. Copy the below code into ‘BasePage.java’ file.
    package com.testmadness.base;
    
    import java.io.File;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.TimeUnit;
    import org.apache.commons.io.FileUtils;
    import org.openqa.selenium.NoSuchElementException;
    import org.openqa.selenium.OutputType;
    import org.openqa.selenium.TakesScreenshot;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.chrome.ChromeDriver;
    import org.openqa.selenium.chrome.ChromeOptions;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.openqa.selenium.safari.SafariDriver;
    import org.openqa.selenium.support.PageFactory;
    import org.openqa.selenium.support.ui.ExpectedConditions;
    import org.openqa.selenium.support.ui.Select;
    import org.openqa.selenium.support.ui.WebDriverWait;
    import com.relevantcodes.extentreports.LogStatus;
    import com.testmadness.utils.Config;
    import com.testmadness.utils.Constants;
    import com.testmadness.utils.Log;
    import com.testmadness.utils.Reports;
    
    public class BasePage {
    	
    	public WebDriver driver;
    	private static final int pageElementLoadWait = 30;
    	private static final int pageTimeOutWait = 20;
    	public Reports report = new Reports();
    	public static HashMap<WebElement, String> elementDetails = new HashMap<WebElement, String>();
    	
    	public BasePage(WebDriver driver){
    	    this.driver = driver;
    		if(driver==null){
    			driver = getDriver();	
    		}
    		//Initialize Page Factory. Passing child object
    		PageFactory.initElements(driver, this);
    		Log.info("Page Factory initialized");
    		
    	}
    	
            // Driver Initialization
    	public WebDriver getDriver(){
    		
    		String browser = Config.getProp().getProperty("selenium.browser");
    		
    		if(browser.equals("SAFARI")){
    			System.setProperty("webdriver.safari.driver", Config.getProp().getProperty("webdriver.safari.driver"));
    			driver = new SafariDriver();
    			driver.manage().window().maximize();
    		}
    		else if(browser.equals("FIREFOX")){
    			System.setProperty("webdriver.gecko.driver", Config.getProp().getProperty("webdriver.firefox.driver"));
    			driver = new FirefoxDriver();
    			driver.manage().window().maximize();
    			driver.manage().timeouts().implicitlyWait(pageTimeOutWait, TimeUnit.SECONDS);
    		}
    		else if(browser.equals("CHROME")){
    			System.setProperty("webdriver.chrome.driver", Config.getProp().getProperty("webdriver.chrome.driver"));
    			ChromeOptions options = new ChromeOptions();
    			options.addArguments("--start-maximized");
    			options.addArguments("--disable-web-security");
    			options.addArguments("--no-proxy-server");
    			Map<String, Object> prefs = new HashMap<String, Object>();
    			prefs.put("credentials_enable_service", false);
    			prefs.put("profile.password_manager_enabled", false);
    			options.setExperimentalOption("prefs", prefs);
    			driver = new ChromeDriver(options);
    			driver.manage().timeouts().implicitlyWait(pageTimeOutWait, TimeUnit.SECONDS);
    		}
    		
    //Setting page load time out		driver.manage().timeouts().pageLoadTimeout(pageTimeOutWait, TimeUnit.SECONDS);
    		return driver;
    	}
    	
    	// Wait for Element to be clickable
    	public WebElement waitForElement(WebElement element) {
    		try{
    			WebDriverWait wait = new WebDriverWait(driver, pageElementLoadWait);
    			wait.until(ExpectedConditions.elementToBeClickable(element));
    			Log.info("Wait for element "+ elementDetails.get(element));
    			return element;
    		}catch(Exception e){
    			
    		}
    		return null;
    	}
    	
    	// Navigate to URL
    	public void navigateToURL(String siteURL) {
    		driver.navigate().to(siteURL);
    		report.logStatus(LogStatus.PASS, "OpenBrowser: " + Config.getProp().getProperty("selenium.browser") + "," + siteURL,
    				"Passed");
    		Log.info("Demo URL Launched");
    	}
    	
    	// Take a screenshot
    	public void takeScreenShot(String fileName) {
    		try {
    			File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
    			FileUtils.copyFile(screenshot, new File(Constants.sScreenshotFilepath + fileName + ".jpeg"));
    			Log.info("Screenshot captured");
    		} catch (Exception e) {
    			System.out.println(e.getMessage());
    			Log.info("Screenshot exception");
    		}
    	}
    	
    	// End Extent Reporting
    	public void endReport() {
    		report.endTest();
    	}
    	
    	// End a Test
    	public void endTest() {
    		driver.close();
    		driver.quit();
    	}
    	
    	/*Click Element method.
    	This method will log in Extent Report as well in Log4j.*/
    	public boolean clickElement(WebElement element) {
    		try {
    			element = waitForElement(element);
    			if (element != null) {
    				takeScreenShot(elementDetails.get(element));
    				report.logStatus(LogStatus.PASS, "Click",
    						"Click " + elementDetails.get(element) + " Success");
    				report.screenshotLog(LogStatus.PASS, "Click Success " + elementDetails.get(element),
    						Constants.sScreenshotFilepath + elementDetails.get(element) + ".jpeg");
    				Log.info("Element Clicked: "+elementDetails.get(element));
    				element.click();
    				return true;
    			}
    			else
    				throw new NoSuchElementException("Element not found");
    		} catch (Exception e) {
    			takeScreenShot("Fail_" + Constants.dateTag);
    			report.screenshotLog(LogStatus.FAIL, "Click Failed ",
    					Constants.sScreenshotFilepath + "Fail_" + Constants.dateTag + ".jpeg");
    			Log.info("Element Click Exception");
    			report.endTest();
    			throw new NoSuchElementException("Element not found");
    		}
    	}
    	
    	/*Enter text in text box method.
    	This method will log in Extent Report as well in Log4j.*/
    	public boolean EnterText(WebElement element, String input) {
    		try {
    			element = waitForElement(element);
    			if (element != null) {
    				element.sendKeys(input);
    				report.logStatus(LogStatus.PASS, "Enter Text",
    						"Enter Text into " + elementDetails.get(element) + " Success");
    				Log.info("Enter text: " + elementDetails.get(element));
    				return true;
    			}else
    				throw new NoSuchElementException("Element not found");
    		} catch (Exception e) {
    			takeScreenShot("Fail_" + Constants.dateTag);
    			report.screenshotLog(LogStatus.FAIL, "Enter Text",
    					Constants.sScreenshotFilepath + "Fail_" + Constants.dateTag + ".jpeg");
    			Log.info("Enter text Exception");
    			throw new NoSuchElementException("Element not found");
    		}	
    	}
    	
    	/*Select a value from drop down by text method.
    	This method will log in Extent Report as well in Log4j.*/
    	public boolean SelectElementByText(WebElement element, String input) {
    		try {
    			element = waitForElement(element);
    			if (element != null) {
    				Select dropdown = new Select(element);
    				dropdown.selectByVisibleText(input);
    				report.logStatus(LogStatus.PASS, "Select Element", "Select Element For " + elementDetails.get(element)
    						+ " Success");
    				Log.info("Select element: " + elementDetails.get(element));
    				return true;
    			}else
    				throw new NoSuchElementException("Element not found");
    		} catch (Exception e) {
    			takeScreenShot("Fail_" + Constants.dateTag);
    			report.screenshotLog(LogStatus.FAIL, "Select Element",
    					Constants.sScreenshotFilepath + "Fail_" + Constants.dateTag + ".jpeg");
    			Log.info("Select element Exception ");
    			throw new NoSuchElementException("Element not found");
    		}
    	}
    }
    
  • The above ‘BasePage’ class file has a constructor which creates an instance of the Page Object using ‘PageFactory’ class. It also has a method to initialize the required WebDriver, wait for an element to be clickable, navigate to an URL, take a screenshot and end the test. It also contains different action methods like clicking a web element, entering a text in a text box, selecting a value from a drop down. The action methods not only completes an action on a web element but also logs the information in the report and log file. Notice that we are declaring a HashMap (Collection in Java) public static HashMap<WebElement, String> elementDetails = new HashMap<WebElement, String>(); to store and name the web elements. We will use it to name the screenshot images.
  • Next task is to create Page Objects. Here we will create two Page Objects. This is similar to what we covered in Part 1: Page Object Model…. Right click on the ‘src/main/java‘ folder and click New -> Package. Name the package as ‘com.testmadness.pages’ and click Finish to close the window. Inside ‘com.testmadness.pages’ package, we will place our Page Objects.
  • Right click on ‘com.selenium.pages’ package and click New -> Class. Name the class as ‘HomePage.java’. This ‘HomePage’ class will extend our ‘BasePage’ class. In this class, we will place all the Home Page element locators and methods. Click Finish to close the window. Copy and paste below code into ‘HomePage’ class.
    package com.testmadness.pages;
    
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.support.FindBy;
    import com.testmadness.base.BasePage;
    import com.testmadness.utils.Log;
    
    public class HomePage extends BasePage {
    	
    	
    	public HomePage(WebDriver driver) {
    		super(driver);
    		
    	}
    
    	// Element Locators for username textbox
    	@FindBy(name = "userName")
    	private WebElement userName;
    	public WebElement getUserName(){
    		try{
                            // Store and name the web element into HashMap
    			elementDetails.put(userName, "User Name text box");
    		}catch(Exception e){
    			
    		}
    		return userName;
    	}
    
    	// Element Locators for password textbox
    	@FindBy(name = "password")
    	private WebElement password;
    	public WebElement getPassword(){
    		try{
                            // Store and name the web element into HashMap
    			elementDetails.put(password, "Password text box");
    		}catch(Exception e){
    			
    		}
    		return password;
    	}
    
    	// Element Locators for login button
    	@FindBy(xpath = "//input[@name='login']")
    	private WebElement login;
    	public WebElement getLogin(){
    		try{
                            // Store and name the web element into HashMap
    			elementDetails.put(login, "Login button");
    		}catch(Exception e){
    			
    		}
    		return login;
    	}
    
    	// Login method. Notice there is no return type
    	public FlightFinderPage loginUser(String uname, String pwd) {
    		// Enter username
    		EnterText(getUserName(), uname);
    		// Log4j logging
    		Log.info("HomePage.loginUser - username entered");
    
    		// Enter password
    		EnterText(getPassword(), pwd);
    		// Log4j logging
    		Log.info("HomePage.loginUser - password entered");
    
    		// Click Login button
    		clickElement(getLogin());
    		// Log4j logging
    		Log.info("HomePage.loginUser - login button clicked");
    	
                    // Returns an object of FlightFinderPage class
    		return new FlightFinderPage(driver);
    	}
    }
    
  • We will create one more Page Object. Right click on ‘com.selenium.pages’ package and click New -> Class. Name the class as ‘FlightFinderPage.java’. All our Page Object will extend the ‘BasePage’ class. Copy and paste below code into ‘FlightFinderPage’ class.
    package com.testmadness.pages;
    
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.support.FindBy;
    import com.testmadness.base.BasePage;
    import com.testmadness.utils.Log;
    
    
    public class FlightFinderPage extends BasePage {
    
    	public FlightFinderPage(WebDriver driver) {
    		super(driver);
    	}
    
    	//Element Locators for one way radio button
    	@FindBy(xpath = "//input[@value='oneway']")
    	private WebElement onewayRadio;
    
    	public WebElement getOneWayRadio() {
    		try {
                            // Store and name the web element into HashMap
    			elementDetails.put(onewayRadio, "One Way radio button");
    		} catch (Exception e) {
    
    		}
    		return onewayRadio;
    	}
    	
    	//Select the location from dropdown
    	@FindBy(name = "fromPort")
    	private WebElement fromPortDrop;
    	public WebElement getFromPortDrop(){
    		try{
                            // Store and name the web element into HashMap
    			elementDetails.put(fromPortDrop, "From Port drop down");
    		}catch (Exception e) {
    
    		}	
    		return fromPortDrop;
    	}
    	
    	//Select the day from dropdown
    	@FindBy(xpath = "//select[@name='fromDay']")
    	private WebElement fromDayDrop;
    	public WebElement getFromDayDrop(){
    		try{
                            // Store and name the web element into HashMap
    			elementDetails.put(fromDayDrop, "From Day drop down");
    		}catch (Exception e) {
    
    		}
    		return fromDayDrop;
    	}
    	
    	//Click Business radio button
    	@FindBy(xpath = "//input[@value='Business']")
    	private WebElement businessRadio;
    	public WebElement getBusinessRadio(){
    		try{
                            // Store and name the web element into HashMap
    			elementDetails.put(businessRadio, "Business radio button");
    		}catch (Exception e) {
    
    		}
    		return businessRadio;
    	}
    	
    	//Click find flights button
    	@FindBy(name = "findFlights")
    	private WebElement findFlightsButton;
    	public WebElement getFindFlightsButton(){
    		try{
                            // Store and name the web element into HashMap
    			elementDetails.put(findFlightsButton, "Find Flights button");
    		}catch (Exception e) {
    
    		}
    		return findFlightsButton;
    	}
    
    
    	//Find Flights method. Notice there is no return type
    	public void findFlights(String departFrom, String departDate) {
    		// Click one way radio button
    		clickElement(getOneWayRadio());
    		Log.info("FlightFinderPage.findFlights - One way Radio Button clicked");
    		// Select Departing From dropdown
    		SelectElementByText(getFromPortDrop(), departFrom);
    		Log.info("FlightFinderPage.findFlights - Depart From Dropdown clicked");
    
    		// Select Departing Day dropdown
    		SelectElementByText(getFromDayDrop(), departDate);
    		Log.info("FlightFinderPage.findFlights - Depart Date Dropdown clicked");
    
    		// Click business class
    		clickElement(getBusinessRadio());
    		Log.info("FlightFinderPage.findFlights - Business Radio Button clicked");
    
    		// Click Find Flights button
    		clickElement(getFindFlightsButton());
    		Log.info("FlightFinderPage.findFlights - Find Flights Button clicked");
    
    	}
    
    }
    
  • Our next task is to add the data sheet using which we will input the test data to our test scripts. We will take the same approach as we did in Data Driven Framework Development….
  • Right click on the ‘src/main/java‘ folder and click New -> Package. Name the package as ‘com.testmadness.data’ and click Finish to close the window. Inside the ‘com.testmadness.data’ package, we will place our test data file in ‘xlsx’ format. Always remember to format all cells in the excel sheet to text format. Our test data sheet will look as displayed below.

    Data.xlsx file for storing test data
  • This is how our ‘src/main/java‘ folder look like once we reach here.

    ‘src/main/java’ folder

With this, we have completed the creation of Page Objects. Here we created only two Page Objects. Best practice is to create one Page Object per page in the test application.

In the next post, we will be creating actual scripts in our Hybrid Framework. Till then, Happy Learning!