com.liferay.faces.test.selenium.browser.internal.BrowserDriverImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.faces.test.selenium.browser.internal.BrowserDriverImpl.java

Source

/**
 * Copyright (c) 2000-2018 Liferay, Inc. All rights reserved.
 *
 * 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.liferay.faces.test.selenium.browser.internal;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Action;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.liferay.faces.test.selenium.browser.BrowserDriver;
import com.liferay.faces.test.selenium.browser.TestUtil;
import com.liferay.faces.test.selenium.expectedconditions.ElementEnabled;
import com.liferay.faces.test.selenium.util.ClosableUtil;

/**
 * @author  Kyle Stiemann
 */
public class BrowserDriverImpl implements BrowserDriver {

    // Logger
    private static final Logger logger = LoggerFactory.getLogger(BrowserDriverImpl.class);

    // Private Constants
    private static final String JAVA_IO_TMPDIR;

    static {

        String javaIOTmpdir = System.getProperty("java.io.tmpdir");

        if (!javaIOTmpdir.endsWith(File.separator)) {
            javaIOTmpdir += File.separator;
        }

        JAVA_IO_TMPDIR = javaIOTmpdir;
    }

    // Private Member Variables
    private boolean browserHeadless;
    private boolean browserSimulatingMobile;
    private WebDriver webDriver;
    private WebDriverWait webDriverWait;
    private Integer windowHeight;

    public BrowserDriverImpl(WebDriver webDriver, boolean browserHeadless, boolean browserSimulatingMobile) {

        this.webDriver = webDriver;
        this.browserHeadless = browserHeadless;
        this.browserSimulatingMobile = browserSimulatingMobile;

        int browserWaitTimeOut = TestUtil.getBrowserDriverWaitTimeOut();
        this.webDriverWait = new WebDriverWait(webDriver, browserWaitTimeOut);
    }

    @Override
    public void acceptAlert() {

        WebDriver webDriver = getWebDriver();
        webDriver.switchTo().alert().accept();
    }

    @Override
    public void captureCurrentBrowserState() {

        String outputDirectoryPath = TestUtil.getSystemPropertyOrDefault(
                "integration.captured.browser.state.output.directory", JAVA_IO_TMPDIR + "captured-browser-state");
        captureCurrentBrowserState(outputDirectoryPath, null);
    }

    @Override
    public void captureCurrentBrowserState(String outputDirectoryPath, String fileNamePrefix) {

        File file = new File(outputDirectoryPath);
        file.mkdirs();

        StringBuilder buf = new StringBuilder();
        buf.append(outputDirectoryPath);
        buf.append("/");

        if (fileNamePrefix != null) {

            buf.append(fileNamePrefix);
            buf.append("_");
        }

        buf.append(getBrowserName());
        buf.append("_");

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.SSS", Locale.ENGLISH);
        simpleDateFormat.setTimeZone(TimeZone.getDefault());

        String dateString = simpleDateFormat.format(new Date());
        buf.append(dateString);

        String fileName = buf.toString();
        String htmlFileName = fileName + ".html";
        PrintWriter printWriter = null;

        try {

            printWriter = new PrintWriter(htmlFileName, "UTF-8");

            String currentPageState = getCurrentDocumentMarkup();
            printWriter.write(currentPageState);
        } catch (Exception e) {

            logger.error("Unable to write page source to {} due to the following exception:\n", htmlFileName);
            logger.error("", e);
        } finally {
            ClosableUtil.close(printWriter);
        }

        String currentUrl = getCurrentWindowUrl();
        logger.info("The html of url=\"{}\" has been written to {}", currentUrl, htmlFileName);

        WebDriver webDriver = getWebDriver();

        if (webDriver instanceof TakesScreenshot) {

            TakesScreenshot takesScreenshot = (TakesScreenshot) webDriver;
            byte[] screenshotBytes = takesScreenshot.getScreenshotAs(OutputType.BYTES);
            String screenshotFileName = fileName + ".png";
            FileOutputStream fileOutputStream = null;

            try {

                fileOutputStream = new FileOutputStream(screenshotFileName);
                fileOutputStream.write(screenshotBytes);
            } catch (Exception e) {

                logger.error("Unable to write page source to {} due to the following exception:\n",
                        screenshotFileName);
                logger.error("", e);
            } finally {
                ClosableUtil.close(fileOutputStream);
            }

            logger.info("A screenshot of url=\"{}\" has been saved to {}", currentUrl, screenshotFileName);
        }
    }

    @Override
    public void centerElementInCurrentWindow(String elementXpath) {

        // http://stackoverflow.com/questions/8922107/javascript-scrollintoview-middle-alignment#36499256
        executeScriptInCurrentWindow(
                "window.scrollTo(0, (arguments[0].getBoundingClientRect().top + window.pageYOffset) - (window.innerHeight / 2));",
                findElementByXpath(elementXpath));
    }

    @Override
    public void clearBrowserCookies() {

        WebDriver webDriver = getWebDriver();
        webDriver.manage().deleteAllCookies();
    }

    @Override
    public void clearElement(String elementXpath) {

        centerElementInCurrentWindow(elementXpath);

        WebElement element = findElementByXpath(elementXpath);
        String value = element.getAttribute("value");

        if ((value != null) && !value.equals("")) {

            CharSequence[] clearKeys = new CharSequence[value.length()];

            for (int i = 0; i < value.length(); i++) {
                clearKeys[i] = Keys.BACK_SPACE;
            }

            sendKeysToElement(elementXpath, Keys.END);
            sendKeysToElement(elementXpath, clearKeys);
        }
    }

    @Override
    public void clickElement(String elementXpath) {

        centerElementInCurrentWindow(elementXpath);
        findElementByXpath(elementXpath).click();
    }

    @Override
    public void clickElementAndWaitForRerender(String elementXpath) {
        performAndWaitForRerender(createClickElementAction(elementXpath), elementXpath);
    }

    @Override
    public void closeCurrentWindow() {

        WebDriver webDriver = getWebDriver();
        webDriver.close();
    }

    @Override
    public Actions createActions() {

        WebDriver webDriver = getWebDriver();

        return new Actions(webDriver);
    }

    @Override
    public Actions createActions(String elementXpath) {

        if (windowHeight == null) {
            Long windowHeightLong = (Long) executeScriptInCurrentWindow(
                    "return document.documentElement.clientHeight || window.innerHeight;");
            windowHeight = windowHeightLong.intValue();
        }

        WebElement webElement = findElementByXpath(elementXpath);
        Dimension elementSize = webElement.getSize();
        int elementHeight = elementSize.getHeight();
        Actions actions = createActions();

        return actions.moveToElement(webElement, 0, -(windowHeight / 2) + (elementHeight / 2));
    }

    @Override
    public Action createClickElementAction(String elementXpath) {

        Actions actions = createActions(elementXpath);
        WebElement webElement = findElementByXpath(elementXpath);
        actions = actions.click(webElement);

        return actions.build();
    }

    @Override
    public void dismissAlert() {

        WebDriver webDriver = getWebDriver();
        webDriver.switchTo().alert().dismiss();
    }

    @Override
    public Object executeScriptInCurrentWindow(String script, Object... args) {

        WebDriver webDriver = getWebDriver();

        if (webDriver instanceof JavascriptExecutor) {

            JavascriptExecutor javaScriptExecutor = (JavascriptExecutor) webDriver;

            return javaScriptExecutor.executeScript(script, args);
        } else {
            throw new UnsupportedOperationException(
                    "Executing JavaScript is not supported by: " + getBrowserName());
        }
    }

    @Override
    public WebElement findElementByXpath(String elementXpath) {

        WebDriver webDriver = getWebDriver();

        return webDriver.findElement(By.xpath(elementXpath));
    }

    @Override
    public List<WebElement> findElementsByXpath(String elementXpath) {

        WebDriver webDriver = getWebDriver();

        return webDriver.findElements(By.xpath(elementXpath));
    }

    @Override
    public Set<Cookie> getBrowserCookies() {

        WebDriver webDriver = getWebDriver();

        return webDriver.manage().getCookies();
    }

    @Override
    public String getBrowserName() {

        WebDriver webDriver = getWebDriver();

        if (webDriver instanceof RemoteWebDriver) {

            RemoteWebDriver remoteWebDriver = (RemoteWebDriver) webDriver;

            return remoteWebDriver.getCapabilities().getBrowserName();
        } else {
            throw new UnsupportedOperationException("getBrowserName() not supported by this browser.");
        }
    }

    @Override
    public String getCurrentDocumentMarkup() {

        WebElement documentElement = findElementByXpath("/html");
        String outerHTMLAttrName = "outerHTML";
        String browserName = getBrowserName();

        // https://github.com/SeleniumHQ/htmlunit-driver/issues/45
        if ("htmlunit".equals(browserName)) {
            outerHTMLAttrName = "innerHTML";
        }

        return documentElement.getAttribute(outerHTMLAttrName);
    }

    @Override
    public String getCurrentWindowId() {

        WebDriver webDriver = getWebDriver();

        return webDriver.getWindowHandle();
    }

    @Override
    public String getCurrentWindowUrl() {

        WebDriver webDriver = getWebDriver();

        return webDriver.getCurrentUrl();
    }

    public WebDriver getWebDriver() {
        return webDriver;
    }

    @Override
    public Set<String> getWindowIds() {

        WebDriver webDriver = getWebDriver();

        return webDriver.getWindowHandles();
    }

    @Override
    public boolean isBrowserHeadless() {
        return browserHeadless;
    }

    @Override
    public boolean isBrowserSimulatingMobile() {
        return browserSimulatingMobile;
    }

    @Override
    public void loadCurrentWindowImages() {

        String browserName = getBrowserName();

        if ("htmlunit".equals(browserName)) {

            WebDriver webDriver = getWebDriver();
            HtmlUnitDriverLiferayFacesImpl htmlUnitDriverLiferayFacesImpl = (HtmlUnitDriverLiferayFacesImpl) webDriver;
            htmlUnitDriverLiferayFacesImpl.loadCurrentWindowImages();
        } else {
            logger.warn("Images are automatically loaded by {}", browserName);
        }
    }

    @Override
    public void navigateWindowTo(String url) {

        WebDriver webDriver = getWebDriver();
        webDriver.get(url);
    }

    @Override
    public void performAndWaitForRerender(Action action, String rerenderXpath) {

        WebElement rerenderElement = findElementByXpath(rerenderXpath);
        action.perform();
        logger.info("Waiting for element {} to be stale.", rerenderXpath);
        waitFor(ExpectedConditions.stalenessOf(rerenderElement));
        logger.info("Element {} is stale.", rerenderXpath);
        waitForElementDisplayed(rerenderXpath);
    }

    @Override
    public void quit() {

        WebDriver webDriver = getWebDriver();
        webDriver.quit();
    }

    @Override
    public void sendKeysToElement(String elementXpath, CharSequence... keys) {

        centerElementInCurrentWindow(elementXpath);
        findElementByXpath(elementXpath).sendKeys(keys);
    }

    @Override
    public void setPageLoadTimeout(int waitTimeOutInSeconds) {

        WebDriver webDriver = getWebDriver();
        webDriver.manage().timeouts().pageLoadTimeout(waitTimeOutInSeconds, TimeUnit.SECONDS);
    }

    @Override
    public void setWaitTimeOut(int waitTimeOutInSeconds) {

        WebDriver webDriver = getWebDriver();
        webDriverWait = new WebDriverWait(webDriver, waitTimeOutInSeconds);
    }

    @Override
    public void switchToFrame(String iframeXpath) {

        WebElement webElement = findElementByXpath(iframeXpath);
        WebDriver webDriver = getWebDriver();
        webDriver.switchTo().frame(webElement);
    }

    @Override
    public void switchToWindow(String windowId) {

        WebDriver webDriver = getWebDriver();
        webDriver.switchTo().window(windowId);
    }

    @Override
    public void waitFor(ExpectedCondition expectedCondition) {
        webDriverWait.until(expectedCondition);
    }

    @Override
    public void waitForElementDisplayed(String elementXpath) {

        logger.info("Waiting for element {} to be displayed.", elementXpath);
        waitFor(ExpectedConditions.visibilityOfElementLocated(By.xpath(elementXpath)));
        logger.info("Element {} is displayed.", elementXpath);
    }

    @Override
    public void waitForElementEnabled(String elementXpath) {
        waitForElementEnabled(elementXpath, true);
    }

    @Override
    public void waitForElementEnabled(String elementXpath, boolean elementMustBeDisplayed) {

        logger.info("Waiting for element {} to be enabled.", elementXpath);

        By byXpath = By.xpath(elementXpath);
        ExpectedCondition<?> expectedCondition = ExpectedConditionsUtil.ifNecessaryExpectElementDisplayed(
                new ElementEnabled(elementXpath), elementMustBeDisplayed, byXpath);
        waitFor(expectedCondition);
        logger.info("Element {} is enabled.", elementXpath);
    }

    @Override
    public void waitForElementNotDisplayed(String elementXpath) {

        logger.info("Waiting for element {} not to be displayed.", elementXpath);
        waitFor(ExpectedConditions.invisibilityOfElementLocated(By.xpath(elementXpath)));
        logger.info("Element {} is not displayed.", elementXpath);
    }

    @Override
    public void waitForTextPresentInElement(String text, String elementXpath) {
        waitForTextPresentInElement(text, elementXpath, true);
    }

    @Override
    public void waitForTextPresentInElement(String text, String elementXpath, boolean elementMustBeDisplayed) {

        logger.info("Waiting for text \"{}\" to be present in element {}.", text, elementXpath);

        By byXpath = By.xpath(elementXpath);
        ExpectedCondition<?> expectedCondition = ExpectedConditions.textToBePresentInElementLocated(byXpath, text);
        expectedCondition = ExpectedConditionsUtil.ifNecessaryExpectElementDisplayed(expectedCondition,
                elementMustBeDisplayed, byXpath);
        waitFor(expectedCondition);
        logger.info("Text \"{}\" is present in Element {}.", text, elementXpath);
    }
}