
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