Skip to content

Commit

Permalink
Added page object for etsy.
Browse files Browse the repository at this point in the history
  • Loading branch information
djangofan committed Dec 26, 2013
1 parent 85dd861 commit 638a764
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 21 deletions.
21 changes: 0 additions & 21 deletions commonlib/src/main/java/qa/webdriver/util/WebDriverUtils.java
Expand Up @@ -10,10 +10,8 @@
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.Point;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
Expand All @@ -22,11 +20,7 @@
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.util.StatusPrinter;
import qa.webdriver.util.CoreUtils;
Expand Down Expand Up @@ -282,21 +276,6 @@ public static WebElement getElementByLocator( final By locator ) {
return we;
}

public static WebElement getElementByVisibility( final By locator ) {
LOGGER.info( "Get element by locator: " + locator.toString() );
final long startTime = System.currentTimeMillis();
WebElement we = null;
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class, StaleElementReferenceException.class);
we = wait.until( ExpectedConditions.visibilityOfElementLocated( locator ) );
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
LOGGER.info("Searched for " + totalTime + " milliseconds." );
return we;
}

public void showMessageInBrowser( String message ) {
message = "<HTML><HEAD><TITLE>Message</TITLE></HEAD><BODY>" + message + "</BODY></HTML>";
String script = "document.write( '" + message + "' );";
Expand Down
200 changes: 200 additions & 0 deletions etsy/src/main/java/qa/webdriver/util/EtsySearchPage.java
@@ -0,0 +1,200 @@
package qa.webdriver.util;

import java.util.List;

import org.junit.Assert;
import org.openqa.selenium.By;
import org.openqa.selenium.ElementNotVisibleException;
import org.openqa.selenium.Keys;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.LoadableComponent;
import static qa.webdriver.util.WebDriverUtils.*;

public class EtsySearchPage extends LoadableComponent<EtsySearchPage> {

public ESPFluentInterface espfi;
public static final String searchFieldName = "search_query";
public static final String searchButtonName = "search_submit";
public static final String suggestIons = "div.nav-search-text div#search-suggestions ul li";

@FindBy(name = searchFieldName ) public WebElement searchField;
@FindBy(name = searchButtonName ) public WebElement searchButton;

public EtsySearchPage() {
this.get(); // SlowLoadableComponent.get()
LOGGER.info("EtsySearchPage constructor...");
espfi = new ESPFluentInterface( this ); // use this only if you want to
}

/**
* Method: isLoaded()
* Overidden method from the LoadableComponent class.
* This method must contain an Assert on visibility of an element in order
* to trigger another call of load() if element is not found.
* @return void
* @throws null
*/
@Override
protected void isLoaded() throws Error {
LOGGER.info("EtsySearchPage.isLoaded()...");
boolean loaded = false;
if ( !(searchField == null ) ) {
try {
if ( searchField.isDisplayed() ) {
loaded = true;
}
} catch ( ElementNotVisibleException e ) {
LOGGER.info( "Element may not be displayed yet." );
}
}
Assert.assertTrue( "Etsy search field is not yet displayed.", loaded );
}

/**
* Method: load
* Overidden method from the LoadableComponent class.
* @return void
* @throws null
*/
@Override
protected void load() {
LOGGER.info("EtsySearchPage.load()...");
PageFactory.initElements( driver, this ); // initialize WebElements on page
waitTimer(2, 1000);
}

public void clickSearchButton() {
if ( searchButton == null ) {
searchButton = getElementByLocator( By.id( searchButtonName ) );
} else {
try {
searchButton.click();
} catch ( ElementNotVisibleException e ) {
LOGGER.info( "Element not visible exception clicking search button.\n" + e.getMessage() );
e.printStackTrace();
} catch ( Exception e ) {
LOGGER.info( "Exception clicking search button.\n" + e.getMessage() );
e.printStackTrace();
}
}
}

/**
* Because of how the page object is initialized, we are using getAttribute here
* @param sstr
* @return void
*/
public void setSearchString( String sstr ) {
clearAndType( searchField, sstr );
}

/**
* Because of how the page object is initialized, we are using getAttribute here
* @param sstr
* @return void
*/
public void clickEtsyLogo() {
LOGGER.info("Click Etsy logo...");
WebElement logo = null;
By locator = By.cssSelector( "h1#etsy a" );
logo = getElementByLocator( locator );
logo.click();
waitTimer(2, 1000);
}

/**
* Method: withFluent
* Entrypoint for an object that can start a fluent action thread.
* @return ESPFluentInterface
* @throws null
*/
public ESPFluentInterface withFluent() {
return espfi;
}

/**
* Method: selectInEtsyDropdown
* Selects element in dropdown using keydowns method (just for fun)
* as long as you typed a string first. The thread sleeps and the
* key arrow down are safe to comment out within the below block.
* @return void
* @throws StaleElementReferenceException
*/
public void selectInEtsyDropdown( String match ) {
LOGGER.info("Selecting \"" + match + "\" from Etsy dynamic dropdown.");
List<WebElement> allSuggestions = driver.findElements( By.cssSelector( suggestIons ) );
try {
for ( WebElement suggestion : allSuggestions ) {
Thread.sleep(600);
searchField.sendKeys( Keys.ARROW_DOWN); // show effect of selecting item with keyboard arrow down
if ( suggestion.getText().contains( match ) ) {
suggestion.click();
LOGGER.info("Found item and clicked it.");
Thread.sleep(2000); // just to slow it down so human eyes can see it
break;
}
}
} catch ( StaleElementReferenceException see ) {
LOGGER.info("Error while iterating dropdown list:\n" + see.getMessage() );
} catch ( InterruptedException ie ) {
ie.printStackTrace();
}
LOGGER.info("Finished select in Etsy dropdown.");
}

/**
* Inner class
* A fluent API interface that provides methods for calling normal
* page object methods within this class.
*/
public class ESPFluentInterface {

public ESPFluentInterface(EtsySearchPage EtsySearchPage) {
LOGGER.info("Initialized fluent interface.");
}

public ESPFluentInterface clickLogo() {
clickEtsyLogo();
return this;
}

public ESPFluentInterface clickSearchButton() {
searchButton.click();
return this;
}

public ESPFluentInterface clickSearchField() {
searchField.click();
return this;
}

public ESPFluentInterface selectItem( String match ) {
LOGGER.info("Selecting item in list using fluent API.");
selectInEtsyDropdown( match );
return this;
}

public ESPFluentInterface setSearchString( String sstr ) {
clearAndType( searchField, sstr );
return this;
}

/**
* Method: waitForTime
* This method shows an example of a fluent method that provides
* access to a method from an outside class. In this case the
* waitTimer in the utility class. We cannot call waitTimer in
* the middle of a fluent thread and so we provide a fluent method
* here so that a wait can be defined.
*/
public ESPFluentInterface waitForTime( int units, int ms ) {
waitTimer( units, ms );
return this;
}

}

}

0 comments on commit 638a764

Please sign in to comment.