Java tutorial
package bg.pragmatic.lecture13mvn.waits.utils; import java.util.List; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.Wait; import org.openqa.selenium.support.ui.WebDriverWait; import com.google.common.base.Function; /** * Wait tool class. Provides Wait methods for an elements, and AJAX elements to * load. It uses WebDriverWait (explicit wait) for waiting an element or * javaScript. * * To use implicitlyWait() and WebDriverWait() in the same test, we would have * to nullify implicitlyWait() before calling WebDriverWait(), and reset after * it. This class takes care of it. * * * Generally relying on implicitlyWait slows things down so use WaitTools * explicit wait methods as much as possible. Also, consider * (DEFAULT_WAIT_4_PAGE = 0) for not using implicitlyWait for a certain test. * * @author Chon Chung, Mark Collin, Andre, Tarun Kumar * * @todo check FluentWait -- * http://seleniumsimplified.com/2012/08/22/fluentwait-with-webelement/ * * Copyright [2012] [Chon Chung] * * Licensed under the Apache Open Source License, Version 2.0 * http://www.apache.org/licenses/LICENSE-2.0 * */ public class WaitTool { /** Default wait time for an element. 7 seconds. */ public static final int DEFAULT_WAIT_4_ELEMENT = 7; /** * Default wait time for a page to be displayed. 12 seconds. The average * webpage load time is 6 seconds in 2012. Based on your tests, please set * this value. "0" will nullify implicitlyWait and speed up a test. */ public static final int DEFAULT_WAIT_4_PAGE = 12; /** * Wait for the element to be present in the DOM, and displayed on the page. * And returns the first WebElement using the given method. * * @param WebDriver * The driver object to be used * @param By * selector to find the element * @param int The time in seconds to wait until returning a failure * * @return WebElement the first WebElement using the given method, or null * (if the timeout is reached) */ public static WebElement waitForElement(WebDriver driver, final By by, int timeOutInSeconds) { WebElement element; try { // To use WebDriverWait(), we would have to nullify // implicitlyWait(). // Because implicitlyWait time also set "driver.findElement()" wait // time. // info from: // https://groups.google.com/forum/?fromgroups=#!topic/selenium-users/6VO_7IXylgY driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // nullify // implicitlyWait() WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); element = wait.until(ExpectedConditions.visibilityOfElementLocated(by)); driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS); // reset // implicitlyWait return element; // return the element } catch (Exception e) { e.printStackTrace(); } return null; } /** * Wait for the element to be present in the DOM, regardless of being * displayed or not. And returns the first WebElement using the given * method. * * @param WebDriver * The driver object to be used * @param By * selector to find the element * @param int The time in seconds to wait until returning a failure * * @return WebElement the first WebElement using the given method, or null * (if the timeout is reached) */ public static WebElement waitForElementPresent(WebDriver driver, final By by, int timeOutInSeconds) { WebElement element; try { driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // nullify // implicitlyWait() WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); element = wait.until(ExpectedConditions.presenceOfElementLocated(by)); driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS); // reset // implicitlyWait return element; // return the element } catch (Exception e) { e.printStackTrace(); } return null; } /** * Wait for the List<WebElement> to be present in the DOM, regardless of * being displayed or not. Returns all elements within the current page DOM. * * @param WebDriver * The driver object to be used * @param By * selector to find the element * @param int The time in seconds to wait until returning a failure * * @return List<WebElement> all elements within the current page DOM, or * null (if the timeout is reached) */ public static List<WebElement> waitForListElementsPresent(WebDriver driver, final By by, int timeOutInSeconds) { List<WebElement> elements; try { driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // nullify // implicitlyWait() WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); wait.until((new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driverObject) { return areElementsPresent(driverObject, by); } })); elements = driver.findElements(by); driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS); // reset // implicitlyWait return elements; // return the element } catch (Exception e) { e.printStackTrace(); } return null; } /** * Wait for an element to appear on the refreshed web-page. And returns the * first WebElement using the given method. * * This method is to deal with dynamic pages. * * Some sites I (Mark) have tested have required a page refresh to add * additional elements to the DOM. Generally you (Chon) wouldn't need to do * this in a typical AJAX scenario. * * @param WebDriver * The driver object to use to perform this element search * @param locator * selector to find the element * @param int The time in seconds to wait until returning a failure * * @return WebElement the first WebElement using the given method, or * null(if the timeout is reached) * * @author Mark Collin */ public static WebElement waitForElementRefresh(WebDriver driver, final By by, int timeOutInSeconds) { WebElement element; try { driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // nullify // implicitlyWait() new WebDriverWait(driver, timeOutInSeconds) { }.until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driverObject) { driverObject.navigate().refresh(); // refresh the page // **************** return isElementPresentAndDisplay(driverObject, by); } }); element = driver.findElement(by); driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS); // reset // implicitlyWait return element; // return the element } catch (Exception e) { e.printStackTrace(); } return null; } /** * Wait for the Text to be present in the given element, regardless of being * displayed or not. * * @param WebDriver * The driver object to be used to wait and find the element * @param locator * selector of the given element, which should contain the text * @param String * The text we are looking * @param int The time in seconds to wait until returning a failure * * @return boolean */ public static boolean waitForTextPresent(WebDriver driver, final By by, final String text, int timeOutInSeconds) { boolean isPresent = false; try { driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // nullify // implicitlyWait() new WebDriverWait(driver, timeOutInSeconds) { }.until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driverObject) { return isTextPresent(driverObject, by, text); // is the Text // in the // DOM } }); isPresent = isTextPresent(driver, by, text); driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS); // reset // implicitlyWait return isPresent; } catch (Exception e) { e.printStackTrace(); } return false; } /** * Waits for the Condition of JavaScript. * * * @param WebDriver * The driver object to be used to wait and find the element * @param String * The javaScript condition we are waiting. e.g. * "return (xmlhttp.readyState >= 2 && xmlhttp.status == 200)" * @param int The time in seconds to wait until returning a failure * * @return boolean true or false(condition fail, or if the timeout is * reached) **/ public static boolean waitForJavaScriptCondition(WebDriver driver, final String javaScript, int timeOutInSeconds) { boolean jscondition = false; try { driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // nullify // implicitlyWait() new WebDriverWait(driver, timeOutInSeconds) { }.until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driverObject) { return (Boolean) ((JavascriptExecutor) driverObject).executeScript(javaScript); } }); jscondition = (Boolean) ((JavascriptExecutor) driver).executeScript(javaScript); driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS); // reset // implicitlyWait return jscondition; } catch (Exception e) { e.printStackTrace(); } return false; } /** * Waits for the completion of Ajax jQuery processing by checking * "return jQuery.active == 0" condition. * * @param WebDriver * - The driver object to be used to wait and find the element * @param int - The time in seconds to wait until returning a failure * * @return boolean true or false(condition fail, or if the timeout is * reached) * */ public static boolean waitForJQueryProcessing(WebDriver driver, int timeOutInSeconds) { boolean jQcondition = false; try { driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // nullify // implicitlyWait() new WebDriverWait(driver, timeOutInSeconds) { }.until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driverObject) { return (Boolean) ((JavascriptExecutor) driverObject).executeScript("return jQuery.active == 0"); } }); jQcondition = (Boolean) ((JavascriptExecutor) driver).executeScript("return jQuery.active == 0"); driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS); // reset // implicitlyWait return jQcondition; } catch (Exception e) { e.printStackTrace(); } return jQcondition; } /** * Coming to implicit wait, If you have set it once then you would have to * explicitly set it to zero to nullify it - */ public static void nullifyImplicitWait(WebDriver driver) { driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // nullify // implicitlyWait() } /** * Set driver implicitlyWait() time. */ public static void setImplicitWait(WebDriver driver, int waitTime_InSeconds) { driver.manage().timeouts().implicitlyWait(waitTime_InSeconds, TimeUnit.SECONDS); } /** * Reset ImplicitWait. To reset ImplicitWait time you would have to * explicitly set it to zero to nullify it before setting it with a new time * value. */ public static void resetImplicitWait(WebDriver driver) { driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // nullify // implicitlyWait() driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS); // reset // implicitlyWait } /** * Reset ImplicitWait. * * @param int - a new wait time in seconds */ public static void resetImplicitWait(WebDriver driver, int newWaittime_InSeconds) { driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // nullify // implicitlyWait() driver.manage().timeouts().implicitlyWait(newWaittime_InSeconds, TimeUnit.SECONDS); // reset // implicitlyWait } public static void waitForPageLoad(WebDriver driver) { Wait<WebDriver> wait = new WebDriverWait(driver, 10); wait.until(new Function<WebDriver, Boolean>() { public Boolean apply(WebDriver driver) { //System.out.println("Current window state : " + String.valueOf(((JavascriptExecutor)driver).executeScript("return document.readyState"))); return String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState")) .equals("complete"); } }); } /** * Checks if the text is present in the element. * * @param driver * - The driver object to use to perform this element search * @param by * - selector to find the element that should contain text * @param text * - The Text element you are looking for * @return true or false */ private static boolean isTextPresent(WebDriver driver, By by, String text) { try { return driver.findElement(by).getText().contains(text); } catch (NullPointerException e) { return false; } } /** * Checks if the elment is in the DOM, regardless of being displayed or not. * * @param driver * - The driver object to use to perform this element search * @param by * - selector to find the element * @return boolean */ private static boolean isElementPresent(WebDriver driver, By by) { try { driver.findElement(by);// if it does not find the element throw // NoSuchElementException, which calls // "catch(Exception)" and returns false; return true; } catch (NoSuchElementException e) { return false; } } /** * Checks if the List<WebElement> are in the DOM, regardless of being * displayed or not. * * @param driver * - The driver object to use to perform this element search * @param by * - selector to find the element * @return boolean */ private static boolean areElementsPresent(WebDriver driver, By by) { try { driver.findElements(by); return true; } catch (NoSuchElementException e) { return false; } } /** * Checks if the elment is in the DOM and displayed. * * @param driver * - The driver object to use to perform this element search * @param by * - selector to find the element * @return boolean */ private static boolean isElementPresentAndDisplay(WebDriver driver, By by) { try { return driver.findElement(by).isDisplayed(); } catch (NoSuchElementException e) { return false; } } } /* * References: 1. Mark Collin's post on: * https://groups.google.com/forum/?fromgroups * #!topic/webdriver/V9KqskkHmIs%5B1-25%5D Mark's code inspires me to write this * class. Thank you! Mark. 2. Andre, and Tarun Kumar's post on: * https://groups.google * .com/forum/?fromgroups=#!topic/selenium-users/6VO_7IXylgY 3. Explicit and * Implicit Waits: http://seleniumhq.org/docs/04_webdriver_advanced.html * * Note: 1. Instead of creating new WebDriverWait() instance every time in each * methods, I tried to reuse a single WebDriverWait() instance, but I found and * tested that creating 100 WebDriverWait() instances takes less than one * millisecond. So, it seems not necessary. */