Java tutorial
/* * Copyright 2015 www.seleniumtests.com * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.elastica.webelements; import java.util.List; import org.apache.log4j.Logger; import org.openqa.selenium.Alert; import org.openqa.selenium.By; import org.openqa.selenium.Dimension; import org.openqa.selenium.InvalidElementStateException; import org.openqa.selenium.InvalidSelectorException; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.Keys; import org.openqa.selenium.NoAlertPresentException; import org.openqa.selenium.Point; import org.openqa.selenium.StaleElementReferenceException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.interactions.HasInputDevices; import org.openqa.selenium.interactions.Mouse; import org.openqa.selenium.internal.Locatable; import org.openqa.selenium.internal.seleniumemulation.JavascriptLibrary; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.Wait; import org.openqa.selenium.support.ui.WebDriverWait; import com.elastica.driver.BrowserType; import com.elastica.driver.ScreenshotUtil; import com.elastica.driver.WebUIDriver; import com.elastica.helper.ContextHelper; import com.elastica.helper.WaitHelper; import com.elastica.core.TestLogging; //import com.thoughtworks.selenium.webdriven.JavascriptLibrary; /** * Provides methods to interact with a web page. All HTML element (ButtonElement, LinkElement, TextFieldElement, etc.) * extends from this class. */ public class HtmlElement { private static enum LocatorType { ID, NAME, CLASS_NAME, LINK_TEXT, PARTIAL_LINK_TEXT, CSS_SELECTOR, TAG_NAME, XPATH, } private static final int EXPLICIT_WAIT_TIME_OUT = WebUIDriver.getWebUXDriver().getExplicitWait(); protected static final Logger logger = TestLogging.getLogger(HtmlElement.class); protected WebDriver driver = WebUIDriver.getWebDriver(); protected WebUIDriver webUXDriver = WebUIDriver.getWebUXDriver(); protected WebElement element = null; private String label = null; private String locator = null; private By by = null; /** * Find element using BY locator. Make sure to initialize the driver before calling findElement() * * @param label - element name for logging * @param by - By type * * @sample {@code new HtmlElement("UserId", By.id(userid))} */ public HtmlElement(final String label, final By by) { this.label = label; this.by = by; } /** * This constructor locates the element using locator and locator type. * * @param label * @param locator - locator */ public HtmlElement(final String label, final String locator, final LocatorType locatorType) { this.label = label; this.locator = locator; this.by = getLocatorBy(locator, locatorType); } /** * Captures snapshot of the current browser window. */ public void captureSnapshot() { captureSnapshot(ContextHelper.getCallerMethod() + " on "); } /** * Captures snapshot of the current browser window, and prefix the file name with the assigned string. * * @param messagePrefix */ protected void captureSnapshot(final String messagePrefix) { ScreenshotUtil.captureSnapshot(messagePrefix); } public void click() { findElement(); BrowserType browser = WebUIDriver.getWebUXDriver().getConfig().getBrowser(); if (browser != BrowserType.Opera) { try { element.click(); } catch (org.openqa.selenium.TimeoutException ex) { TestLogging.log("Get timeout customexception, ignore"); } } else { // Ignore no response on ECMAScript evaluation command for Opera try { element.sendKeys(Keys.ENTER); WaitHelper.waitForSeconds(2); } catch (WebDriverException e) { } } // IE is "too fast" if (browser == BrowserType.InternetExplore) { WaitHelper.waitForSeconds(2); } // Handle Confirm Navigation pop up for Chrome and IE handleLeaveAlert(); } /** * Click element in native way by Actions. */ public void clickAt() { clickAt("1,1"); } protected void handleLeaveAlert() { BrowserType browser = WebUIDriver.getWebUXDriver().getConfig().getBrowser(); // Handle Confirm Navigation pop up for Chrome and IE if (browser == BrowserType.Chrome || browser == BrowserType.InternetExplore) { try { Alert alert = driver.switchTo().alert(); String text = alert.getText(); if (text.contains("leave")) { alert.accept(); WaitHelper.waitForSeconds(2); } else { System.out.println("Get alert - " + text); } } catch (NoAlertPresentException e) { } } } /** * Click element in native way by Actions. * * <p/> * <pre class="code"> clickAt("1, 1"); * </pre> * * @param value */ public void clickAt(final String value) { captureSnapshot("before clicking"); TestLogging.logWebStep(null, "click on " + toHTML(), false); findElement(); String[] parts = value.split(","); int xOffset = Integer.parseInt(parts[0]); int yOffset = Integer.parseInt(parts[1]); try { new Actions(driver).moveToElement(element, xOffset, yOffset).click().perform(); } catch (InvalidElementStateException e) { e.printStackTrace(); element.click(); } try { BrowserType type = WebUIDriver.getWebUXDriver().getConfig().getBrowser(); if ((type == BrowserType.Chrome || type == BrowserType.InternetExplore) && this.getDriver().switchTo().alert().getText().contains("leave")) { this.getDriver().switchTo().alert().accept(); } } catch (NoAlertPresentException e) { e.printStackTrace(); } } public void simulateClick() { findElement(); String mouseOverScript = "if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj);} else if(document.createEventObject) { arguments[0].fireEvent('onmouseover');}"; JavascriptExecutor js = (JavascriptExecutor) driver; js.executeScript(mouseOverScript, element); WaitHelper.waitForSeconds(2); String clickScript = "if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('click', true, false); arguments[0].dispatchEvent(evObj);} else if(document.createEventObject) { arguments[0].fireEvent('onclick');}"; js.executeScript(clickScript, element); WaitHelper.waitForSeconds(2); } public void simulateMoveToElement(final int x, final int y) { findElement(); ((JavascriptExecutor) driver).executeScript( "function simulate(f,c,d,e){var b,a=null;for(b in eventMatchers)if(eventMatchers[b].test(c)){a=b;break}if(!a)return!1;document.createEvent?(b=document.createEvent(a),a==\"HTMLEvents\"?b.initEvent(c,!0,!0):b.initMouseEvent(c,!0,!0,document.defaultView,0,d,e,d,e,!1,!1,!1,!1,0,null),f.dispatchEvent(b)):(a=document.createEventObject(),a.detail=0,a.screenX=d,a.screenY=e,a.clientX=d,a.clientY=e,a.ctrlKey=!1,a.altKey=!1,a.shiftKey=!1,a.metaKey=!1,a.button=1,f.fireEvent(\"on\"+c,a));return!0} var eventMatchers={HTMLEvents:/^(?:load|unload|abort|errorLogger|select|change|submit|reset|focus|blur|resize|scroll)$/,MouseEvents:/^(?:click|dblclick|mouse(?:down|up|over|move|out))$/}; " + "simulate(arguments[0],\"mousemove\",arguments[1],arguments[2]);", element, x, y); } /** * Finds the element using By type. Implicit Waits is built in createWebDriver() in WebUIDriver to handle dynamic * element problem. This method is invoked before all the basic operations like click, sendKeys, getText, etc. Use * waitForPresent to use Explicit Waits to deal with special element which needs long time to present. */ protected void findElement() { driver = WebUIDriver.getWebDriver(); element = driver.findElement(by); } /** * Fires a Javascript event on the underlying element. * * @param eventName */ public void fireEvent(final String eventName) { findElement(); try { JavascriptLibrary jsLib = new JavascriptLibrary(); jsLib.callEmbeddedSelenium(driver, "doFireEvent", element, eventName); } catch (Exception ex) { // Handle OperaDriver } } /** * Get all elements in the current page with same locator. * * @return */ public List<WebElement> getAllElements() { findElement(); return driver.findElements(by); } /** * Gets an attribute (using standard key-value pair) from the underlying attribute. * * @param name * * @return */ public String getAttribute(final String name) { findElement(); return element.getAttribute(name); } /** * Returns the BY locator stored in the HtmlElement. * * @return */ public By getBy() { return by; } /** * Returns the value for the specified CSS key. * * @param propertyName * * @return */ public String getCssValue(final String propertyName) { findElement(); return element.getCssValue(propertyName); } /** * Get and refresh underlying WebDriver. */ protected WebDriver getDriver() { return WebUIDriver.getWebDriver(); } /** * Returns the underlying WebDriver WebElement. * * @return */ public WebElement getElement() { element = driver.findElement(by); return element; } /** * Executes the given JavaScript against the underlying WebElement. * * @param script * * @return */ public String getEval(final String script) { findElement(); String name = (String) ((JavascriptExecutor) driver).executeScript(script, element); return name; } /** * Returns the 'height' property of the underlying WebElement's Dimension. * * @return */ public int getHeight() { findElement(); return element.getSize().getHeight(); } /** * Returns the label used during initialization. * * @return */ public String getLabel() { return label; } /** * Gets the Point location of the underlying WebElement. * * @return */ public Point getLocation() { findElement(); return element.getLocation(); } /** * Returns the locator used to find the underlying WebElement. * * @return */ public String getLocator() { return locator; } private By getLocatorBy(final String locator, final LocatorType locatorType) { switch (locatorType) { case ID: return By.id(locator); case NAME: return By.name(locator); case CLASS_NAME: return By.className(locator); case LINK_TEXT: return By.linkText(locator); case PARTIAL_LINK_TEXT: return By.partialLinkText(locator); case CSS_SELECTOR: return By.cssSelector(locator); case TAG_NAME: return By.tagName(locator); default: return By.xpath(locator); } } /** * Returns the Dimension property of the underlying WebElement. * * @return */ public Dimension getSize() { findElement(); return element.getSize(); } /** * Returns the HTML Tag for the underlying WebElement (div, a, input, etc). * * @return */ public String getTagName() { findElement(); return element.getTagName(); } /** * Returns the text body of the underlying WebElement. * * @return */ public String getText() { findElement(); return element.getText(); } /** * Returns the 'value' attribute of the underlying WebElement. * * @return */ public String getValue() { findElement(); return element.getAttribute("value"); } /** * Returns the 'width' property of the underlying WebElement's Dimension. * * @return */ public int getWidth() { findElement(); return element.getSize().getWidth(); } /** * Refreshes the WebUIDriver before locating the element, to ensure we have the current version (useful for when the * state of an element has changed via an AJAX or non-page-turn action). */ public void init() { driver = WebUIDriver.getWebDriver(); element = driver.findElement(by); } /** * Indicates whether or not the web element is currently displayed in the browser. * * @return */ public boolean isDisplayed() { findElement(); try { return element.isDisplayed(); } catch (StaleElementReferenceException e) { return false; } } /** * Searches for the element using the BY locator, and indicates whether or not it exists in the page. This can be * used to look for hidden objects, whereas isDisplayed() only looks for things that are visible to the user * * @return */ public boolean isElementPresent() { if (WebUIDriver.getWebDriver() == null) { TestLogging.log("Web Driver is terminated! Exception might caught in last action."); throw new RuntimeException("Web Driver is terminated! Exception might caught in last action."); } int count = 0; try { count = WebUIDriver.getWebDriver().findElements(by).size(); } catch (RuntimeException e) { if (e instanceof InvalidSelectorException) { TestLogging.log("Got InvalidSelectorException, retry"); WaitHelper.waitForSeconds(2); count = WebUIDriver.getWebDriver().findElements(by).size(); } else if (e.getMessage() != null && e.getMessage().contains("TransformedEntriesMap cannot be cast to java.util.List")) { TestLogging.log("Got CastException, retry"); WaitHelper.waitForSeconds(2); count = WebUIDriver.getWebDriver().findElements(by).size(); } else { throw e; } } if (count == 0) { return false; } return true; } /** * Indicates whether or not the element is enabled in the browser. * * @return */ public boolean isEnabled() { findElement(); return element.isEnabled(); } /** * Indicates whether or not the element is selected in the browser. * * @return */ public boolean isSelected() { findElement(); return element.isSelected(); } /** * Whether or not the indicated text is contained in the element's getText() attribute. * * @param text * * @return */ public boolean isTextPresent(final String text) { findElement(); return element.getText().contains(text); } /** * Forces a mouseDown event on the WebElement. */ public void mouseDown() { TestLogging.log("MouseDown " + this.toString()); findElement(); Mouse mouse = ((HasInputDevices) driver).getMouse(); mouse.mouseDown(null); } /** * Forces a mouseOver event on the WebElement. */ public void mouseOver() { TestLogging.log("MouseOver " + this.toString()); findElement(); // build and perform the mouseOver with Advanced User Interactions API // Actions builder = new Actions(driver); // builder.moveToElement(element).build().perform(); Locatable hoverItem = (Locatable) element; Mouse mouse = ((HasInputDevices) driver).getMouse(); mouse.mouseMove(hoverItem.getCoordinates()); } /** * Forces a mouseOver event on the WebElement using simulate by JavaScript way for some dynamic menu. */ public void simulateMouseOver() { findElement(); String mouseOverScript = "if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj);} else if(document.createEventObject) { arguments[0].fireEvent('onmouseover');}"; JavascriptExecutor js = (JavascriptExecutor) driver; js.executeScript(mouseOverScript, element); } /** * Forces a mouseUp event on the WebElement. */ public void mouseUp() { TestLogging.log("MouseUp " + this.toString()); findElement(); Mouse mouse = ((HasInputDevices) driver).getMouse(); mouse.mouseUp(null); } /** * Sends the indicated CharSequence to the WebElement. * * @param arg0 */ public void sendKeys(final CharSequence arg0) { findElement(); element.sendKeys(arg0); } /** * Method, which should never be used. */ protected void sleep(final int waitTime) throws InterruptedException { Thread.sleep(waitTime); } /** * Converts the Type, Locator and LabelElement attributes of the HtmlElement into a readable and report-friendly * string. * * @return */ public String toHTML() { return getClass().getSimpleName().toLowerCase() + " <a style=\"font-style:normal;color:#8C8984;text-decoration:none;\" href=# \">" + getLabel() + ",: " + getBy().toString() + "</a>"; } /** * Returns a friendly string, representing the HtmlElement's Type, LabelElement and Locator. */ public String toString() { return getClass().getSimpleName().toLowerCase() + " " + getLabel() + ", by={" + getBy().toString() + "}"; } /** * Wait element to present using Explicit Waits with default EXPLICIT_WAIT_TIME_OUT = 15 seconds. */ public void waitForPresent() { waitForPresent(EXPLICIT_WAIT_TIME_OUT); } /** * Wait element to present using Explicit Waits with timeout in seconds. This method is used for special element * which needs long time to present. */ public void waitForPresent(final int timeout) { TestLogging.logWebStep(null, "wait for " + this.toString() + " to present.", false); Wait<WebDriver> wait = new WebDriverWait(driver, timeout); wait.until(new ExpectedCondition<WebElement>() { public WebElement apply(final WebDriver driver) { return driver.findElement(by); } }); } }