All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sugarcrm.candybean.automation.AutomationInterfaceBuilder Maven / Gradle / Ivy

package com.sugarcrm.candybean.automation;

import java.io.File;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Logger;

import com.sugarcrm.candybean.automation.webdriver.*;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.remote.DesiredCapabilities;

import com.sugarcrm.candybean.automation.AutomationInterface.Type;
import com.sugarcrm.candybean.configuration.Configuration;
import com.sugarcrm.candybean.exceptions.CandybeanException;
import com.sugarcrm.candybean.utilities.CandybeanLogger;

public class AutomationInterfaceBuilder {

	/*
	 * The type of interface that the user wants to build.
	 */
	private Type type = null;
	
	/*
	 * The path to the APP. Required for Android and IOS interface.
	 */
	private String appPath = null;
	
	/*
	 * The APP package, required for Android interface.
	 */
	private String appPackage = null;

	/*
	 * The APP activity, required for Android interface.
	 */
	private String appActivity = null;
	
	/*
	 * Logger for this class
	 */
	private Logger logger = Logger.getLogger(this.getClass().getName());
	
	/*
	 * The class that calls this builder, required for logging and mobile interfaces.
	 */
	private Class cls;
	
	/*
	 * Candybean instance
	 */
	private Candybean candybean = null;
	
	/**
	 * @param cls Typically the test class which uses this interface builder
	 */
	public AutomationInterfaceBuilder(Class cls) {
		this.cls = cls;
	}

	/**
	 * Builds the interface specified. If an interface cannot be built using the specified parameters, an attempt
	 * will be made using candybean configuration files. If an interface cannot be built, an exception will be thrown.
	 * 
	 * @return
	 */
	public WebDriverInterface build() throws CandybeanException{
		WebDriverInterface iface = null;
		candybean = Candybean.getInstance();
		CandybeanLogger cbLogger;
		try {
			cbLogger = (CandybeanLogger) Logger.getLogger(Candybean.class.getSimpleName());
			if (!cbLogger.containsHandler(cls.getSimpleName())) {
				FileHandler fh = new FileHandler("./log/" + cls.getSimpleName() + ".log");
				cbLogger.addHandler(fh, cls.getSimpleName());
			}
		} catch (IOException e) {
			logger.severe("Unable to read/write to file " + "./log/" + cls.getSimpleName() + ".log");
		}
		if(type == null) {
			logger.info("Interface type not specified in the builder, attempting to build an interface using 'automation.interfrace' in the configuration.");
			iface = getWebDriverInterface();
		}else {
			iface = getWebDriverInterface(type);
		}
		return iface;
	}
	
	/**
	 * Instantiates an interface given the type
	 * 
	 * @return WebDriverInterface
	 * @throws Exception
	 */
	private WebDriverInterface getWebDriverInterface() throws CandybeanException {
		logger.info("No webdriverinterface type specified from source code; will attempt to retrieve type from candybean configuration.");
		Type configType = AutomationInterface.parseType(candybean.config.getValue("automation.interface", "chrome"));
		logger.info("Found the following webdriverinterface type: " + configType + ", from configuration: " + candybean.config.configFile.getAbsolutePath());
		return this.getWebDriverInterface(configType);
	}

	
	private WebDriverInterface getWebDriverInterface(Type type) throws CandybeanException {
		WebDriverInterface iface = null;
		DesiredCapabilities capabilities;
		String testClassName = cls.getSimpleName();
		// Required if we are using saucelabs.
		SaucelabsInterface sauceInterface = new SaucelabsInterface(type);
		GridInterface gridInterface = new GridInterface(type);
		switch (type) {
		case FIREFOX:
			iface = new FirefoxInterface();
			break;
		case CHROME:
			iface = new ChromeInterface();
			break;
		case IE:
			iface = new InternetExplorerInterface();
			break;
		case SAFARI:
			throw new CandybeanException("Selenium: SAFARI interface type not yet supported");
		case ANDROID:
			if(isAndroidFullyConfigured(true)) {
				capabilities = new DesiredCapabilities();
				capabilities.setCapability("app", appPath);
				capabilities.setCapability("app-package", appPackage);
				capabilities.setCapability("app-activity", appActivity);
				sauceInterface.getCapabilities().setCapability("app", appPath);
				sauceInterface.getCapabilities().setCapability("app-package", appPackage);
				sauceInterface.getCapabilities().setCapability("app-activity", appActivity);
				iface = new AndroidInterface(capabilities);
			}else {
				logger.info("Builder was not fully configured to create an Android interface. \n" +
						"The variables appPath, appPackage, appActivity must all be set to create an android interface. \n" +
						"Trying to create Android interface from configuration file.");
				if(isAndroidFullyConfigured(false)){
					capabilities = new DesiredCapabilities();
					capabilities.setCapability("app", new File(candybean.config.getValue(testClassName + ".app")).getAbsolutePath());
					capabilities.setCapability("app-package", candybean.config.getValue(testClassName + ".app-package"));
					capabilities.setCapability("app-activity", candybean.config.getValue(testClassName + ".app-activity"));
					sauceInterface.getCapabilities().setCapability("app", new File(candybean.config.getValue(testClassName + ".app")).getAbsolutePath());
					sauceInterface.getCapabilities().setCapability("app-package", candybean.config.getValue(testClassName + ".app-package"));
					sauceInterface.getCapabilities().setCapability("app-activity", candybean.config.getValue(testClassName + ".app-activity"));
					iface = new AndroidInterface(capabilities);
				}else {
					String message = "Builder was unable to create an Android Interface from the provided settings in the builder, or \n" +
							"from the configuration file. If creating an android interface using the builder, the variables appPath, appPackage, \n " +
							"appActivity must all be set. If you want the builder to create the interface from the configuration file, please ensure that \n" +
							"the keys " + testClassName + ".app"  + ", " + testClassName + ".app-package" + ", and " + testClassName + ".app-activity" + " have \n" +
							"all been configured.";
					logger.severe(message);
					throw new CandybeanException(message);
				}
			}
			break;
		case IOS:
			if(isIOSFullyConfigured(true)) {
				capabilities = new DesiredCapabilities();
				capabilities.setCapability("app", appPath);
				sauceInterface.getCapabilities().setCapability("app", appPath);
				iface = new IosInterface(capabilities);
			}else {
				logger.info("Builder was not fully configured to create an IOS interface. \n" +
						"The variable appPath must be set to create an ios interface. \n" +
						"Trying to create IOS interface from configuration file.");
				if(isIOSFullyConfigured(false)){
					capabilities = new DesiredCapabilities();
					capabilities.setCapability("app", new File(candybean.config.getValue(testClassName + ".app")).getAbsolutePath());
					sauceInterface.getCapabilities().setCapability("app", new File(candybean.config.getValue(testClassName + ".app")).getAbsolutePath());
					iface = new IosInterface(capabilities);
				}else {
					String message = "Builder was unable to create an IOS Interface from the provided settings in the builder, or \n" +
							"from the configuration file. If creating an IOS interface using the builder, the variable appPath \n " +
							"must be set. If you want the builder to create the interface from the configuration file, please ensure that \n" +
							"the key " + testClassName + ".app"  + " has been configured.";
					logger.severe(message);
					throw new CandybeanException(message);
				}
			}
			break;	
		default:
			throw new CandybeanException("WebDriver automation interface type not recognized: " + type);
		}

		boolean isSaucelabsEnabled = Boolean.parseBoolean(candybean.config.getValue("saucelabs.enabled"));
		boolean isGridEnabled = Boolean.parseBoolean(candybean.config.getValue("grid.enabled"));

		if(isGridEnabled && isSaucelabsEnabled) {
			throw new CandybeanException("Saucelabs and Grid should not be enabled at the same time. Check your config"
					+ " file again.");
		} else if(isGridEnabled) {
			logger.info("Grid was enabled by the user, using grid to carry out the tests for the interface: "+ type);
			return gridInterface;
		} else if (isSaucelabsEnabled) {
			logger.info("Saucelabs was enabled by the user, using saucelabs to carry out the tests for the interface: "
					+ type);
			// Add any desired capabilities if we are running mobile tests on saucelabs.
			return sauceInterface;
		} else {
			return iface;
		}
	}
	
	/*
	 * Checks whether the builder was sufficiently configured to create an IOS interface, but only if
	 * using the builder. If not using the builder, then the method will check if IOS was fully configured 
	 * in the configuration file.
	 * 
	 * @param usingBuilder Whether we are using the builder to completely configure the IOS interface.
	 * @return If IOS is fully configured from the builder, or the configuration.
	 */
	private boolean isIOSFullyConfigured(boolean usingBuilder) {
		String testClassName = cls.getSimpleName();
		if(usingBuilder){
			if(StringUtils.isEmpty(appPath)){
				return false;
			}else {
				return true;
			}
		}else if(candybean.config.hasKey(testClassName+".app")){
			return true;
		}else {
			return false;
		}
	}

	/*
	 * Checks whether the builder was sufficiently configured to create an ANDROID interface, but only if
	 * using the builder. If not using the builder, then the method will check if ANDROID was fully configured 
	 * in the configuration file.
	 * 
	 * @param usingBuilder Whether we are using the builder to completely configure the ANDROID interface.
	 * @return If ANDROID is fully configured from the builder, or the configuration.
	 */
	private boolean isAndroidFullyConfigured(boolean usingBuilder) {
		String testClassName = cls.getSimpleName();
		if(usingBuilder){
			if(StringUtils.isEmpty(appPath) || StringUtils.isEmpty(appPackage) || StringUtils.isEmpty(appActivity)){
				return false;
			}else {
				return true;
			}
		}else if(candybean.config.hasKey(testClassName+".app") && candybean.config.hasKey(testClassName+".app") && candybean.config.hasKey(testClassName+".app")){
			return true;
		}else {
			return false;
		}
	}

	public void setType(Type type) {
		this.type = type;
	}

	/**
	 * Set the path to the APP file. This is required only when you are
	 * building an Android or IOS interface. If an APP path is not specified,
	 * then the builder will attempt to retrieve it from the candybean configuration file.
	 * If it is not found using the {@link Configuration} object, an exception will be thrown.
	 * 
	 * @param appPath The local or remote path to the application package
	 */
	public void setAppPath(String appPath) {
		this.appPath = appPath;
	}
	/**
	 * Set the app package. This is required only when you are
	 * building an Android interface. If an APP package is not specified,
	 * then the builder will attempt to retrieve it from the candybean configuration file.
	 * If it is not found using the {@link Configuration} object, an exception will be thrown.
	 * 
	 * @param appPackage The APP package
	 */
	public void setAppPackage(String appPackage) {
		this.appPackage = appPackage;
	}

	/**
	 * Set the APP activity package. This is required only when you are
	 * building an Android interface. If an APP activity package is not specified,
	 * then the builder will attempt to retrieve it from the candybean configuration file.
	 * If it is not found using the {@link Configuration} object, an exception will be thrown.
	 * 
	 * @param appActivity The APP activity
	 */
	public void setAppActivity(String appActivity) {
		this.appActivity = appActivity;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy