com.qmetry.qaf.automation.ui.UiDriverFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.qmetry.qaf.automation.ui.UiDriverFactory.java

Source

/*******************************************************************************
 * QMetry Automation Framework provides a powerful and versatile platform to
 * author
 * Automated Test Cases in Behavior Driven, Keyword Driven or Code Driven
 * approach
 * Copyright 2016 Infostretch Corporation
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE
 * You should have received a copy of the GNU General Public License along with
 * this program in the name of LICENSE.txt in the root folder of the
 * distribution. If not, see https://opensource.org/licenses/gpl-3.0.html
 * See the NOTICE.TXT file in root folder of this source files distribution
 * for additional information regarding copyright ownership and licenses
 * of other open source software / files used by QMetry Automation Framework.
 * For any inquiry or need additional information, please contact
 * support-qaf@infostretch.com
 *******************************************************************************/

package com.qmetry.qaf.automation.ui;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.LogFactoryImpl;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.Platform;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.qmetry.qaf.automation.core.AutomationError;
import com.qmetry.qaf.automation.core.ConfigurationManager;
import com.qmetry.qaf.automation.core.DriverFactory;
import com.qmetry.qaf.automation.core.LoggingBean;
import com.qmetry.qaf.automation.core.QAFListener;
import com.qmetry.qaf.automation.core.QAFTestBase.STBArgs;
import com.qmetry.qaf.automation.keys.ApplicationProperties;
import com.qmetry.qaf.automation.ui.selenium.webdriver.SeleniumDriverFactory;
import com.qmetry.qaf.automation.ui.webdriver.ChromeDriverHelper;
import com.qmetry.qaf.automation.ui.webdriver.QAFExtendedWebDriver;
import com.qmetry.qaf.automation.ui.webdriver.QAFWebDriverCommandListener;
import com.qmetry.qaf.automation.util.StringUtil;

/**
 * com.qmetry.qaf.automation.ui.UiDriverFactory.java
 * 
 * @author chirag
 */
public class UiDriverFactory implements DriverFactory<UiDriver> {
    private static final Log logger = LogFactoryImpl.getLog(UiDriverFactory.class);

    /*
     * (non-Javadoc)
     * @see
     * com.qmetry.qaf.automation.core.DriverFactory#get(java.lang.String[])
     */
    @Override
    public UiDriver get(ArrayList<LoggingBean> commandLog, String[] stb) {
        WebDriverCommandLogger cmdLogger = new WebDriverCommandLogger(commandLog);
        String browser = STBArgs.browser_str.getFrom(stb);
        logger.info("Driver: " + browser);

        if (browser.toLowerCase().contains("driver") && !browser.startsWith("*")) {
            return getDriver(cmdLogger, stb);
        }

        return new SeleniumDriverFactory().getDriver(cmdLogger, stb);
    }

    @Override
    public void tearDown(UiDriver driver) {
        try {
            driver.stop();
            logger.info("UI-driver tear down complete...");
        } catch (Throwable t) {
            logger.error(t.getMessage());
        }
    }

    /**
     * Utility method to get capability that will be used by factory to create
     * driver object. It will not include any modification done by
     * {@link QAFWebDriverCommandListener#beforeInitialize(Capabilities)}
     * 
     * @param driverName
     * @return
     */
    public static DesiredCapabilities getDesiredCapabilities(String driverName) {
        return Browsers.getBrowser(driverName).getDesiredCapabilities();
    }

    public static String[] checkAndStartServer(String... args) {
        if (!isServerRequired(args)) {
            return args;
        }
        if (isSeverRunning(STBArgs.sel_server.getFrom(args), Integer.parseInt(STBArgs.port.getFrom(args)))) {
            return args;
        }

        // override args values to default
        args = STBArgs.sel_server.set(STBArgs.sel_server.getDefaultVal(), args);
        if (isSeverRunning(STBArgs.sel_server.getFrom(args), Integer.parseInt(STBArgs.port.getFrom(args)))) {
            logger.info("Assigning server running on localhost");

            return args;
        }
        return args;
    }

    private static boolean isServerRequired(String... args) {
        String browser = STBArgs.browser_str.getFrom(args).toLowerCase();
        return browser.contains("*") || browser.contains("remote");
    }

    private static boolean isSeverRunning(String host, int port) {
        boolean isRunning = false;

        Socket socket = null;
        try {
            socket = new Socket(host, (port));
            isRunning = socket.isConnected();
        } catch (Exception exp) {
            logger.error("Error occured while checking Selenium : " + exp.getMessage());
        } finally {
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {

            }
        }
        return isRunning;
    }

    private static void beforeInitialize(Capabilities desiredCapabilities,
            Collection<QAFWebDriverCommandListener> listners) {
        if ((listners != null) && !listners.isEmpty()) {
            for (QAFWebDriverCommandListener listener : listners) {
                listener.beforeInitialize(desiredCapabilities);
            }
        }
    }

    private static void onInitializationFailure(DesiredCapabilities desiredCapabilities, Throwable e,
            Collection<QAFWebDriverCommandListener> listners) {
        if ((listners != null) && !listners.isEmpty()) {
            for (QAFWebDriverCommandListener listener : listners) {
                listener.onInitializationFailure(desiredCapabilities, e);
            }
        }

    }

    private static Collection<QAFWebDriverCommandListener> getDriverListeners() {
        LinkedHashSet<QAFWebDriverCommandListener> listners = new LinkedHashSet<QAFWebDriverCommandListener>();
        String[] clistners = ConfigurationManager.getBundle()
                .getStringArray(ApplicationProperties.WEBDRIVER_COMMAND_LISTENERS.key);
        for (String listenr : clistners) {
            try {
                QAFWebDriverCommandListener cls = (QAFWebDriverCommandListener) Class.forName(listenr)
                        .newInstance();
                listners.add(cls);
            } catch (Exception e) {
                logger.error("Unable to register listener class " + listenr, e);
            }
        }
        clistners = ConfigurationManager.getBundle().getStringArray(ApplicationProperties.QAF_LISTENERS.key);
        for (String listener : clistners) {
            try {
                QAFListener cls = (QAFListener) Class.forName(listener).newInstance();
                if (QAFWebDriverCommandListener.class.isAssignableFrom(cls.getClass()))
                    listners.add((QAFWebDriverCommandListener) cls);
            } catch (Exception e) {
                logger.error("Unable to register class as driver listener:  " + listener, e);
            }
        }
        return listners;
    }

    private static QAFExtendedWebDriver getDriver(WebDriverCommandLogger reporter, String... args) {
        String b = STBArgs.browser_str.getFrom(args).toLowerCase();
        String urlStr = STBArgs.sel_server.getFrom(args).startsWith("http") ? STBArgs.sel_server.getFrom(args)
                : String.format("http://%s:%s/wd/hub", STBArgs.sel_server.getFrom(args),
                        STBArgs.port.getFrom(args));

        Browsers browser = Browsers.getBrowser(b);
        loadDriverResouces(browser.browserName);

        ConfigurationManager.getBundle().setProperty("driver.desiredCapabilities",
                browser.getDesiredCapabilities().asMap());
        QAFExtendedWebDriver driver = b.contains("remote") ? browser.getDriver(urlStr, reporter)
                : browser.getDriver(reporter, urlStr);
        ConfigurationManager.getBundle().setProperty("driver.actualCapabilities", driver.getCapabilities().asMap());
        return driver;

    }

    private static void loadDriverResouces(String browserName) {
        String driverResourcesKey = String.format(ApplicationProperties.DRIVER_RESOURCES_FORMAT.key, browserName);
        String driverResources = ConfigurationManager.getBundle().getString(driverResourcesKey, "");
        if (StringUtil.isNotBlank(driverResources)) {
            ConfigurationManager.addBundle(driverResources);
        }
    }

    private static WebDriver getDriverObj(Class<? extends WebDriver> of, Capabilities capabilities, String urlStr) {
        try {
            Constructor<? extends WebDriver> constructor = of.getConstructor(Capabilities.class);
            return constructor.newInstance(capabilities);
        } catch (Exception e) {
            if (e.getCause() != null && e.getCause() instanceof WebDriverException) {
                throw (WebDriverException) e.getCause();
            }
            try {
                return of.newInstance();
            } catch (Exception e1) {
                try {

                    Constructor<? extends WebDriver> constructor = of.getConstructor(URL.class, Capabilities.class);

                    return constructor.newInstance(new URL(urlStr), capabilities);
                } catch (InvocationTargetException e2) {
                    throw new WebDriverException(e2);
                } catch (InstantiationException e2) {
                    throw new WebDriverException(e2);
                } catch (IllegalAccessException e2) {
                    throw new WebDriverException(e2);
                } catch (IllegalArgumentException e2) {
                    throw new WebDriverException(e2);
                } catch (MalformedURLException e2) {
                    throw new WebDriverException(e2);
                } catch (NoSuchMethodException e2) {
                    throw new WebDriverException(e2);
                } catch (SecurityException e2) {
                    throw new WebDriverException(e2);
                }
            }
        }
    }

    private enum Browsers {
        edge(DesiredCapabilities.edge(), EdgeDriver.class),

        firefox(DesiredCapabilities.firefox(), FirefoxDriver.class), iexplorer(
                DesiredCapabilities.internetExplorer(),
                InternetExplorerDriver.class), chrome(DesiredCapabilities.chrome(), ChromeDriver.class), opera(
                        new DesiredCapabilities("opera", "", Platform.ANY),
                        "com.opera.core.systems.OperaDriver"), android(DesiredCapabilities.android(),
                                "org.openqa.selenium.android.AndroidDriver"), iphone(
                                        new DesiredCapabilities("iPhone", "", Platform.MAC),
                                        "org.openqa.selenium.iphone.IPhoneDriver"), ipad(
                                                new DesiredCapabilities("iPad", "", Platform.MAC),
                                                "org.openqa.selenium.iphone.IPhoneDriver"), safari(
                                                        new DesiredCapabilities("safari", "", Platform.ANY),
                                                        "org.openqa.selenium.safari.SafariDriver"), appium(
                                                                new DesiredCapabilities(),
                                                                "io.appium.java_client.AppiumDriver"), perfecto(
                                                                        new DesiredCapabilities()),

        /**
         * can with assumption that you have set desired capabilities using
         * property. This is to provide support for future drivers or custom
         * drivers if any. You can provide driver class as capability :
         * driver.class, for example :<br>
         * driver.class=org.openqa.selenium.safari.SafariDriver
         */
        other(new DesiredCapabilities());

        private DesiredCapabilities desiredCapabilities;

        private Class<? extends WebDriver> driverCls = null;
        private String browserName = name();

        private Browsers(DesiredCapabilities desiredCapabilities) {
            this.desiredCapabilities = desiredCapabilities;
            this.desiredCapabilities.setJavascriptEnabled(true);
            this.desiredCapabilities.setCapability(CapabilityType.TAKES_SCREENSHOT, true);
            this.desiredCapabilities.setCapability(CapabilityType.SUPPORTS_FINDING_BY_CSS, true);

        }

        @SuppressWarnings("unchecked")
        private Browsers(DesiredCapabilities desiredCapabilities, String drivercls) {
            this(desiredCapabilities);
            if (null == driverCls) {
                // not overridden by extra capability
                try {
                    driverCls = (Class<? extends WebDriver>) Class.forName(drivercls);
                } catch (Exception e) {
                    // throw new AutomationError(e);
                }
            }

        }

        private Browsers(DesiredCapabilities desiredCapabilities, Class<? extends WebDriver> driver) {
            this(desiredCapabilities);
            if (null == driverCls) {
                // not overridden by extra capability
                driverCls = driver;
            }
        }

        @SuppressWarnings("unchecked")
        private DesiredCapabilities getDesiredCapabilities() {
            Map<String, Object> capabilities = new HashMap<String, Object>(desiredCapabilities.asMap());
            Gson gson = new GsonBuilder().create();

            // capabilities provided for all driver
            Map<String, Object> extraCapabilities = gson
                    .fromJson(ApplicationProperties.DRIVER_ADDITIONAL_CAPABILITIES.getStringVal("{}"), Map.class);
            capabilities.putAll(extraCapabilities);

            // individual capability property for all driver
            Configuration config = ConfigurationManager.getBundle()
                    .subset(ApplicationProperties.DRIVER_CAPABILITY_PREFIX.key);
            capabilities.putAll(new ConfigurationMap(config));
            // capabilities specific to this driver
            String driverCapsKey = String.format(ApplicationProperties.DRIVER_ADDITIONAL_CAPABILITIES_FORMAT.key,
                    name());
            extraCapabilities = gson.fromJson(ConfigurationManager.getBundle().getString(driverCapsKey, "{}"),
                    Map.class);
            capabilities.putAll(extraCapabilities);
            // individual capability property with driver name prefix
            String driverCapKey = String.format(ApplicationProperties.DRIVER_CAPABILITY_PREFIX_FORMAT.key,
                    browserName);
            config = ConfigurationManager.getBundle().subset(driverCapKey);
            capabilities.putAll(new ConfigurationMap(config));

            Object driverclass = capabilities.get(ApplicationProperties.CAPABILITY_NAME_DRIVER_CLASS.key);
            if (null == driverclass) {// backward compatibility only
                driverclass = capabilities.get("driver.class");
            }
            if (null != driverclass) {
                try {
                    driverCls = (Class<? extends WebDriver>) Class.forName(String.valueOf(driverclass));
                } catch (Exception e) {
                    // throw new AutomationError(e);
                }
            }

            return new DesiredCapabilities(capabilities);
        }

        private static Browsers getBrowser(String name) {
            for (Browsers browser : Browsers.values()) {
                if (name.contains(browser.name())) {
                    browser.setBrowserName(name);
                    return browser;
                }
            }
            Browsers b = Browsers.other;
            b.setBrowserName(name);
            return b;
        }

        private void setBrowserName(String name) {
            //remove driver and remote from name
            browserName = name.replaceAll("(?i)remote|driver", "");
        }

        private QAFExtendedWebDriver getDriver(WebDriverCommandLogger reporter, String urlstr) {
            DesiredCapabilities desiredCapabilities = getDesiredCapabilities();

            Collection<QAFWebDriverCommandListener> listners = getDriverListeners();
            beforeInitialize(desiredCapabilities, listners);
            try {
                if (this.name().equalsIgnoreCase("chrome")) {
                    return new QAFExtendedWebDriver(ChromeDriverHelper.getService().getUrl(), desiredCapabilities,
                            reporter);
                }
                WebDriver driver = getDriverObj(driverCls, desiredCapabilities, urlstr);// driverCls.newInstance();
                return new QAFExtendedWebDriver(driver, reporter);
            } catch (Throwable e) {
                onInitializationFailure(desiredCapabilities, e, listners);

                throw new AutomationError(
                        "Unable to Create Driver Instance for " + browserName + ": " + e.getMessage(), e);
            }
        }

        private QAFExtendedWebDriver getDriver(String url, WebDriverCommandLogger reporter) {
            DesiredCapabilities desiredCapabilities = getDesiredCapabilities();
            Collection<QAFWebDriverCommandListener> listners = getDriverListeners();

            beforeInitialize(desiredCapabilities, listners);
            try {
                if (StringUtil.isNotBlank(ApplicationProperties.WEBDRIVER_REMOTE_SESSION.getStringVal())
                        || desiredCapabilities.asMap()
                                .containsKey(ApplicationProperties.WEBDRIVER_REMOTE_SESSION.key)) {

                    Constructor<?> constructor = Class
                            .forName("com.qmetry.qaf.automation.ui.webdriver.LiveIsExtendedWebDriver")
                            .getDeclaredConstructor(URL.class, Capabilities.class, WebDriverCommandLogger.class);
                    return (QAFExtendedWebDriver) constructor.newInstance(new URL(url), desiredCapabilities,
                            reporter);
                }
                return new QAFExtendedWebDriver(new URL(url), desiredCapabilities, reporter);
            } catch (Throwable e) {
                onInitializationFailure(desiredCapabilities, e, listners);

                throw new AutomationError("Unable to Create Driver Instance " + e.getMessage(), e);
            }
        }
    }

}