ca.nrc.cadc.web.selenium.AbstractTestWebPage.java Source code

Java tutorial

Introduction

Here is the source code for ca.nrc.cadc.web.selenium.AbstractTestWebPage.java

Source

/*
 ************************************************************************
 *******************  CANADIAN ASTRONOMY DATA CENTRE  *******************
 **************  CENTRE CANADIEN DE DONNES ASTRONOMIQUES  **************
 *
 *  (c) 2016.                            (c) 2016.
 *  Government of Canada                 Gouvernement du Canada
 *  National Research Council            Conseil national de recherches
 *  Ottawa, Canada, K1A 0R6              Ottawa, Canada, K1A 0R6
 *  All rights reserved                  Tous droits rservs
 *
 *  NRC disclaims any warranties,        Le CNRC dnie toute garantie
 *  expressed, implied, or               nonce, implicite ou lgale,
 *  statutory, of any kind with          de quelque nature que ce
 *  respect to the software,             soit, concernant le logiciel,
 *  including without limitation         y compris sans restriction
 *  any warranty of merchantability      toute garantie de valeur
 *  or fitness for a particular          marchande ou de pertinence
 *  purpose. NRC shall not be            pour un usage particulier.
 *  liable in any event for any          Le CNRC ne pourra en aucun cas
 *  damages, whether direct or           tre tenu responsable de tout
 *  indirect, special or general,        dommage, direct ou indirect,
 *  consequential or incidental,         particulier ou gnral,
 *  arising from the use of the          accessoire ou fortuit, rsultant
 *  software.  Neither the name          de l'utilisation du logiciel. Ni
 *  of the National Research             le nom du Conseil National de
 *  Council of Canada nor the            Recherches du Canada ni les noms
 *  names of its contributors may        de ses  participants ne peuvent
 *  be used to endorse or promote        tre utiliss pour approuver ou
 *  products derived from this           promouvoir les produits drivs
 *  software without specific prior      de ce logiciel sans autorisation
 *  written permission.                  pralable et particulire
 *                                       par crit.
 *
 *  This file is part of the             Ce fichier fait partie du projet
 *  OpenCADC project.                    OpenCADC.
 *
 *  OpenCADC is free software:           OpenCADC est un logiciel libre ;
 *  you can redistribute it and/or       vous pouvez le redistribuer ou le
 *  modify it under the terms of         modifier suivant les termes de
 *  the GNU Affero General Public        la GNU Affero General Public
 *  License as published by the          License? telle que publie
 *  Free Software Foundation,            par la Free Software Foundation
 *  either version 3 of the              : soit la version 3 de cette
 *  License, or (at your option)         licence, soit ( votre gr)
 *  any later version.                   toute version ultrieure.
 *
 *  OpenCADC is distributed in the       OpenCADC est distribu
 *  hope that it will be useful,         dans lespoir quil vous
 *  but WITHOUT ANY WARRANTY;            sera utile, mais SANS AUCUNE
 *  without even the implied             GARANTIE : sans mme la garantie
 *  warranty of MERCHANTABILITY          implicite de COMMERCIALISABILIT
 *  or FITNESS FOR A PARTICULAR          ni dADQUATION  UN OBJECTIF
 *  PURPOSE.  See the GNU Affero         PARTICULIER. Consultez la Licence
 *  General Public License for           Gnrale Publique GNU Affero
 *  more details.                        pour plus de dtails.
 *
 *  You should have received             Vous devriez avoir reu une
 *  a copy of the GNU Affero             copie de la Licence Gnrale
 *  General Public License along         Publique GNU Affero avec
 *  with OpenCADC.  If not, see          OpenCADC ; si ce nest
 *  <http://www.gnu.org/licenses/>.      pas le cas, consultez :
 *                                       <http://www.gnu.org/licenses/>.
 *
 *
 ************************************************************************
 */

package ca.nrc.cadc.web.selenium;

import ca.nrc.cadc.util.StringUtil;
import junit.framework.AssertionFailedError;
import org.apache.log4j.Logger;
import org.openqa.selenium.*;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

public abstract class AbstractTestWebPage {
    private static final Logger LOGGER = Logger.getLogger(AbstractTestWebPage.class);

    // One minute is just too long.
    private static final int DEFAULT_TIMEOUT_IN_SECONDS = 60;

    static final By PARENT_ELEMENT_BY = By.xpath("..");

    protected final WebDriver driver;
    protected final WebDriverWait wait;
    protected final int timeoutInSeconds;

    public AbstractTestWebPage(final WebDriver driver) {
        this(driver, DEFAULT_TIMEOUT_IN_SECONDS);
    }

    public AbstractTestWebPage(final WebDriver driver, final int timeoutInSeconds) {
        this.driver = driver;
        this.wait = new WebDriverWait(driver, DEFAULT_TIMEOUT_IN_SECONDS);
        this.timeoutInSeconds = timeoutInSeconds;
    }

    /**
     * Like assertTrue, but fails at the end of the test (during tearDown)
     *
     * @param b The boolean flag to check for truthiness.
     */
    protected void verifyTrue(final boolean b) {
        if (!b) {
            throw new IllegalArgumentException("Verification failed.");
        }
    }

    protected void verifyEquals(final Object o1, final Object o2) {
        verifyTrue(o1.equals(o2));
    }

    /**
     * Check the checkbox/radio button located at the given By.
     *
     * @param by The location of the item to check.
     * @throws Exception If anything goes awry.
     */
    protected void check(final By by) throws Exception {
        check(find(by));
    }

    protected void check(final WebElement element) throws Exception {
        if (element.isSelected()) {
            LOGGER.warn(String.format("Checkbox at %s is already checked.", element));
        } else {
            click(element);
        }
    }

    protected void uncheck(final By by) throws Exception {
        uncheck(find(by));
    }

    protected void uncheck(final WebElement element) throws Exception {
        if (!element.isSelected()) {
            LOGGER.warn(String.format("Checkbox at %s is already unchecked.", element));
        } else {
            click(element);
        }
    }

    protected void inputTextValue(final By by, final String value) throws Exception {
        inputTextValue(by, value, true);
    }

    protected void clearTextInput(final By by) throws Exception {
        final WebElement inputElement = waitUntil(ExpectedConditions.presenceOfElementLocated(by));

        // Focus issues.
        hover(by);
        inputElement.click();
        inputElement.clear();
    }

    protected void inputTextValue(final By by, final String value, final boolean clean) throws Exception {
        inputTextValue(by, value, clean, true);
    }

    protected void inputTextValue(final By by, final String value, final boolean clean, final boolean moveToInput)
            throws Exception {
        waitForElementPresent(by);
        final WebElement inputElement = find(by);

        if (moveToInput) {
            hover(by);
            inputElement.click();
        }

        if (clean) {
            clearTextInput(by);
        }

        if (StringUtil.hasText(value)) {
            for (final char c : value.toCharArray()) {
                inputElement.sendKeys(Character.toString(c));
                waitFor(250L);
            }
        }
    }

    /**
     * Allow waiting for less than a second.
     *
     * @param milliseconds Time in milliseconds to wait.
     * @throws Exception For any test execution errors
     */
    protected void waitFor(final long milliseconds) throws Exception {
        Thread.sleep(milliseconds);
    }

    /**
     * Select in a pulldown.
     *
     * @param by    The finder element.
     * @param value The value to set.
     * @throws Exception For any test execution exceptions
     */
    public void select(final By by, final String value) throws Exception {
        final Select select = new Select(find(by));
        select.selectByValue(value);
    }

    public WebElement findParent(final WebElement childElement) throws Exception {
        return childElement.findElement(PARENT_ELEMENT_BY);
    }

    public WebElement find(final By by) throws Exception {
        try {
            return driver.findElement(by);
        } catch (Throwable e) {
            System.out.println("No element found: " + by.toString());
            return null;
        }
    }

    public void sendKeys(final WebElement webElement, final String value) throws Exception {
        webElement.clear();
        webElement.sendKeys(Keys.BACK_SPACE);
        webElement.sendKeys(value);
    }

    public void click(final By by) throws Exception {
        waitForElementPresent(by);
        click(find(by));
    }

    public void click(final WebElement elem) throws Exception {
        final Actions action = new Actions(driver);
        scrollIntoView(elem);
        waitForElementClickable(elem);
        action.moveToElement(elem).click(elem).build().perform();
    }

    public void resetForm() throws Exception {
        resetForm(By.cssSelector("button[type=\"reset\"]"));
    }

    public void resetForm(final By resetButtonBy) throws Exception {
        click(resetButtonBy);
    }

    public <T extends AbstractTestWebPage> T goBack(final Class<T> pageClass) throws Exception {
        driver.navigate().back();
        final Constructor<T> constructor = pageClass.getConstructor(WebDriver.class);
        return constructor.newInstance(driver);
    }

    public void verifyElementChecked(final By by) throws Exception {
        verifyTrue(find(by).isSelected());
    }

    public void verifyElementUnChecked(final By by) throws Exception {
        verifyFalse(find(by).isSelected());
    }

    public boolean elementExists(final By by) throws Exception {
        return (find(by) != null);
    }

    public void verifyElementPresent(final By by) throws Exception {
        final WebElement webElement = find(by);
        verifyFalse(webElement == null);
    }

    public void verifyDisabledInput(final String idSelector) throws Exception {
        final Object obj = executeJavaScript("return document.getElementById('" + idSelector + "').disabled;");
        verifyTrue((obj != null) && ((Boolean) obj));
    }

    public void verifyElementNotPresent(final By by) throws Exception {
        verifyTrue((find(by) == null));
    }

    /**
     * Issue a drag and drop command.
     *
     * @param source      The source element.
     * @param destination The to (target) element to drop into.
     * @throws Exception For any test execution errors.
     */
    protected void dragAndDrop(final By source, final By destination) throws Exception {
        (new Actions(driver)).dragAndDrop(find(source), find(destination)).perform();
    }

    protected void scrollIntoView(final WebElement element) throws Exception {
        executeJavaScript("arguments[0].scrollIntoView(true);", element);
    }

    /**
     * Scroll a container (e.g. div) until the element with elementID is
     * visible.
     *
     * @param elementID           The ID of the element to find.
     * @param containerToScrollID The container to scroll.
     * @throws Exception For any test execution errors
     */
    protected void scrollVerticallyIntoView(final String elementID, final String containerToScrollID)
            throws Exception {
        final String script = "var myElement = document.getElementById('" + elementID + "');"
                + "var topPos = myElement.offsetTop - 35;" + "document.getElementById('" + containerToScrollID
                + "').scrollTop = topPos;";

        ((JavascriptExecutor) driver).executeScript(script);
    }

    /**
     * Scroll the Grid.  This is for cadcVOTV grids.
     * <p>
     * TODO - Make this fail if at bottom of grid and still haven't
     * TODO - found target!!!
     *
     * @param elementIDToScroll The ID of the container.
     * @throws Exception For any test execution errors
     */
    protected void scrollGrid(final String elementIDToScroll) throws Exception {
        final String findByClassNameLoop = "for (i in elems) {"
                + "if((' ' + elems[i].className + ' ').indexOf(' slick-viewport ') > -1) {"
                + "targetDiv = elems[i];break;" + "}}";
        final String script = "var objDiv = document.getElementById('" + elementIDToScroll
                + "'), targetDiv; var elems = objDiv.getElementsByTagName('div'), i;" + findByClassNameLoop
                + " targetDiv.scrollTop += 25;";

        executeJavaScript(script);
    }

    /**
     * Scroll the Grid.  This is for cadcVOTV grids.
     *
     * @param elementIDToScroll The ID of the container.
     * @throws Exception For any test execution errors
     */
    protected void scrollGridHorizontally(final String elementIDToScroll) throws Exception {
        final String findByClassNameLoop = "for (i in elems) {"
                + "if((' ' + elems[i].className + ' ').indexOf(' slick-pane-right ') > -1) {"
                + "targetDiv = elems[i];break;" + "}}";
        final String script = "var objDiv = document.getElementById('" + elementIDToScroll
                + "'), targetDiv; var elems = objDiv.getElementsByTagName('div'), i;" + findByClassNameLoop
                + " targetDiv.scrollRight += 125;";

        executeJavaScript(script);
    }

    public void waitForTextPresent(final By by, final String text) throws Exception {
        waitForElementVisible(by);
        waitUntil(ExpectedConditions.textToBePresentInElementLocated(by, text));
    }

    public void verifyTextPresent(final By by, final String value) throws Exception {
        verifyTextPresent(find(by), value);
    }

    public void verifyTextPresent(final WebElement webElement, final String value) throws Exception {
        verifyTrue(webElement.getText().contains(value));
    }

    protected void verifyTextMatches(final By by, final String regex) throws Exception {
        verifyTrue(getText(by).matches(regex));
    }

    public void verifyText(final By by, final String value) throws Exception {
        verifyEquals(value, getText(by));
    }

    protected String getText(final By by) throws Exception {
        return find(by).getText();
    }

    protected boolean isTextPresent(final String text) throws Exception {
        return driver.getPageSource().contains(text);
    }

    public void verifyTextPresent(final String text) throws Exception {
        verifyTrue(isTextPresent(text));
    }

    protected void verifyTextNotPresent(final String text) throws Exception {
        verifyFalse(isTextPresent(text));
    }

    protected void verifyFalse(final boolean b) {
        if (b) {
            throw new IllegalArgumentException("Verification failed.");
        }
    }

    protected String getName() {
        return this.getClass().getName();
    }

    protected void waitForFormInputTextPresent(final WebElement webElement, final String text) throws Exception {
        waitUntil(ExpectedConditions.textToBePresentInElementValue(webElement, text));
    }

    protected void hover(final By by) throws Exception {
        waitForElementPresent(by);
        waitForElementVisible(by);
        waitForElementClickable(by);

        // Wicked hack.  I hate this.
        // jenkinsd 2014.04.10
        //
        if (getInternetBrowserCommand().contains("afari")) {
            final String byString = by.toString();
            final String value = byString.substring(byString.indexOf(":") + 1).trim();
            final String locatorPrefix;
            final String locatorSuffix;

            if (by instanceof By.ById) {
                locatorPrefix = "\"#";
                locatorSuffix = "\"";
            } else if (by instanceof By.ByClassName) {
                locatorPrefix = "\".";
                locatorSuffix = "\"";
            } else if (by instanceof By.ByLinkText) {
                locatorPrefix = "\"a:contains('";
                locatorSuffix = "')\"";
            } else if (by instanceof By.ByName) {
                locatorPrefix = "\"[name='";
                locatorSuffix = "']\"";
            } else {
                locatorPrefix = "\"";
                locatorSuffix = "\"";
            }

            executeJavaScript("$(" + locatorPrefix + value + locatorSuffix + ").hover();");
        } else {
            hover(find(by));
        }
    }

    protected Object executeJavaScript(final String javaScript, final WebElement webElement) throws Exception {
        return ((JavascriptExecutor) driver).executeScript(javaScript, webElement);
    }

    public final Object executeJavaScript(final String javaScript) throws Exception {
        return ((JavascriptExecutor) driver).executeScript(javaScript);
    }

    protected void hover(final WebElement element) throws Exception {
        final Actions action = new Actions(driver);
        action.moveToElement(element).build().perform();
    }

    protected boolean isElementHidden(final WebElement element) throws Exception {
        return !element.isDisplayed();
    }

    protected void waitForElementVisible(final WebElement element) throws Exception {
        assert (waitUntil(ExpectedConditions.visibilityOf(element)) != null);
    }

    protected void waitForElementVisible(final By by) throws Exception {
        assert (waitUntil(ExpectedConditions.visibilityOfElementLocated(by)) != null);
    }

    protected void waitForElementInvisible(final WebElement webElement) throws Exception {
        final List<WebElement> elementList = new ArrayList<>();
        elementList.add(webElement);

        assert (waitUntil(ExpectedConditions.invisibilityOfAllElements(elementList)));
    }

    protected void waitForElementInvisible(final By by) throws Exception {
        assert (waitUntil(ExpectedConditions.invisibilityOfElementLocated(by)) != null);
    }

    public WebElement waitForElementPresent(final By by) throws Exception {
        return waitUntil(ExpectedConditions.presenceOfElementLocated(by));
    }

    public void waitForElementNotPresent(final By by) throws Exception {
        waitUntil(ExpectedConditions.invisibilityOfElementLocated(by));
    }

    public void waitForElementClickable(final By _by) throws Exception {
        waitForElementClickable(find(_by));
    }

    public void waitForElementClickable(final WebElement element) throws Exception {
        assert (waitUntil(ExpectedConditions.elementToBeClickable(element)) != null);
    }

    protected <V> V waitUntil(final ExpectedCondition<V> expectedCondition) throws Exception {
        return this.wait.until(expectedCondition);
    }

    protected String getCurrentWindowHandle() throws Exception {
        return driver.getWindowHandle();
    }

    protected WebDriver selectWindow(final String windowHandle) throws Exception {
        return driver.switchTo().window(windowHandle);
    }

    protected void closeWindow(final String windowHandle) throws Exception {
        selectWindow(windowHandle).close();
    }

    protected String getInternetBrowserCommand() {
        final Capabilities caps = ((RemoteWebDriver) driver).getCapabilities();
        return caps.getBrowserName();
    }

    /**
     * Fails a test with the given message.
     *
     * @param message Message to display explaining the failure.
     */
    protected void fail(final String message) {
        throw new AssertionFailedError(message);
    }
}