Skip to content

Java reorg #245

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

345 changes: 35 additions & 310 deletions java/src/main/java/com/saucelabs/saucebindings/SauceOptions.java
Original file line number Diff line number Diff line change
@@ -1,352 +1,77 @@
package com.saucelabs.saucebindings;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import com.saucelabs.saucebindings.options.CapabilityManager;
import org.openqa.selenium.MutableCapabilities;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.ie.InternetExplorerOptions;
import org.openqa.selenium.safari.SafariOptions;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Accessors(chain = true)
@Setter @Getter
public class SauceOptions {
@Setter(AccessLevel.NONE) private MutableCapabilities seleniumCapabilities;
public TimeoutStore timeout = new TimeoutStore();

// w3c Settings
private Browser browserName = Browser.CHROME;
private String browserVersion = "latest";
private SaucePlatform platformName = SaucePlatform.WINDOWS_10;
private PageLoadStrategy pageLoadStrategy;
private Boolean acceptInsecureCerts = null;
private Proxy proxy;
private Boolean setWindowRect = null;
@Getter(AccessLevel.NONE) private Map<Timeouts, Integer> timeouts;
private Boolean strictFileInteractability = null;
private UnhandledPromptBehavior unhandledPromptBehavior;

// Sauce Settings
private Boolean avoidProxy = null;
private String build;
private Boolean capturePerformance = null;
private String chromedriverVersion;
private Integer commandTimeout = null;
private Map<String, Object> customData = null;
private Boolean extendedDebugging = null;
private Integer idleTimeout = null;
private String iedriverVersion;
private Integer maxDuration = null;
private String name;
private String parentTunnel;
private Map<Prerun, Object> prerun;
private URL prerunUrl;
private Integer priority = null;
private JobVisibility jobVisibility; // the actual key for this is a Java reserved keyword "public"
private Boolean recordLogs = null;
private Boolean recordScreenshots = null;
private Boolean recordVideo = null;
private String screenResolution;
private String seleniumVersion;
private List<String> tags = null;
private String timeZone;
private String tunnelIdentifier;
private Boolean videoUploadOnPass = null;

public static final List<String> primaryEnum = Arrays.asList(
"browserName",
"jobVisibility",
"pageLoadStrategy",
"platformName",
"timeouts",
"unhandledPromptBehavior"
);

public static final List<String> secondaryEnum = Arrays.asList(
"prerun",
"timeouts"
);

public static final List<String> w3cDefinedOptions = Arrays.asList(
"browserName",
"browserVersion",
"platformName",
"pageLoadStrategy",
"acceptInsecureCerts",
"proxy",
"setWindowRect",
"timeouts",
"strictFileInteractability",
"unhandledPromptBehavior");

public static final List<String> sauceDefinedOptions = Arrays.asList(
"avoidProxy",
"build",
"capturePerformance",
"chromedriverVersion",
"commandTimeout",
"customData",
"extendedDebugging",
"idleTimeout",
"iedriverVersion",
"maxDuration",
"name",
"parentTunnel",
"prerun",
"priority",
// public, do not use, reserved keyword, using jobVisibility
"recordLogs",
"recordScreenshots",
"recordVideo",
"screenResolution",
"seleniumVersion",
"tags",
"timeZone",
"tunnelIdentifier",
"videoUploadOnPass");

public static final Map<String, String> knownCITools;
static {
knownCITools = new HashMap<>();
knownCITools.put("Jenkins", "BUILD_TAG");
knownCITools.put("Bamboo", "bamboo_agentId");
knownCITools.put("Travis", "TRAVIS_JOB_ID");
knownCITools.put("Circle", "CIRCLE_JOB");
knownCITools.put("GitLab", "CI");
knownCITools.put("TeamCity", "TEAMCITY_PROJECT_NAME");
}
public class SauceOptions extends com.saucelabs.saucebindings.options.SauceOptions {

/**
* @deprecated Use com.saucelabs.saucebindings.options.SauceOptions() instead
*/
@Deprecated
public SauceOptions() {
this(new MutableCapabilities());
}

/**
* @deprecated Use com.saucelabs.saucebindings.options.SauceOptions(ChromeOptions options) instead
*/
@Deprecated
public SauceOptions(ChromeOptions options) {
this(new MutableCapabilities(options));
}

/**
* @deprecated Use com.saucelabs.saucebindings.options.SauceOptions(EdgeOptions options) instead
*/
@Deprecated
public SauceOptions(EdgeOptions options) {
this(new MutableCapabilities(options));
}

/**
* @deprecated Use com.saucelabs.saucebindings.options.SauceOptions(FirefoxOptions options) instead
*/
@Deprecated
public SauceOptions(FirefoxOptions options) {
this(new MutableCapabilities(options));
}

/**
* @deprecated Use com.saucelabs.saucebindings.options.SauceOptions(InternetExplorerOptions options) instead
*/
@Deprecated
public SauceOptions(InternetExplorerOptions options) {
this(new MutableCapabilities(options));
}

/**
* @deprecated Use com.saucelabs.saucebindings.options.SauceOptions(SafariOptions options) instead
*/
@Deprecated
public SauceOptions(SafariOptions options) {
this(new MutableCapabilities(options));
}

public Map<Timeouts, Integer> getTimeouts() {
if (timeout.getTimeouts().isEmpty()) {
return timeouts;
}
return timeout.getTimeouts();
}

private SauceOptions(MutableCapabilities options) {
seleniumCapabilities = new MutableCapabilities(options.asMap());
capabilities = new MutableCapabilities(options.asMap());
capabilityManager = new CapabilityManager(this);
if (options.getCapability("browserName") != null) {
setCapability("browserName", options.getCapability("browserName"));
}
}

public MutableCapabilities toCapabilities() {
MutableCapabilities sauceCapabilities = addAuthentication();

if (getCapability("jobVisibility") != null) {
sauceCapabilities.setCapability("public", getCapability("jobVisibility"));
}

if (getCapability("prerunUrl") != null) {
sauceCapabilities.setCapability("prerun", getCapability("prerunUrl"));
}

w3cDefinedOptions.forEach((capability) -> {
addCapabilityIfDefined(seleniumCapabilities, capability);
});

sauceDefinedOptions.forEach((capability) -> {
addCapabilityIfDefined(sauceCapabilities, capability);
});

seleniumCapabilities.setCapability("sauce:options", sauceCapabilities);
return seleniumCapabilities;
}

private void addCapabilityIfDefined(MutableCapabilities capabilities, String capability) {
Object value = getCapability(capability);
if (value != null) {
capabilities.setCapability(capability, value);
}
}

public String getBuild() {
if (build != null) {
return build;
} else if (getEnvironmentVariable(knownCITools.get("Jenkins")) != null) {
return getEnvironmentVariable("BUILD_NAME") + ": " + getEnvironmentVariable("BUILD_NUMBER");
} else if (getEnvironmentVariable(knownCITools.get("Bamboo")) != null) {
return getEnvironmentVariable("bamboo_shortJobName") + ": " + getEnvironmentVariable("bamboo_buildNumber");
} else if (getEnvironmentVariable(knownCITools.get("Travis")) != null) {
return getEnvironmentVariable("TRAVIS_JOB_NAME") + ": " + getEnvironmentVariable("TRAVIS_JOB_NUMBER");
} else if (getEnvironmentVariable(knownCITools.get("Circle")) != null) {
return getEnvironmentVariable("CIRCLE_JOB") + ": " + getEnvironmentVariable("CIRCLE_BUILD_NUM");
} else if (getEnvironmentVariable(knownCITools.get("GitLab")) != null) {
return getEnvironmentVariable("CI_JOB_NAME") + ": " + getEnvironmentVariable("CI_JOB_ID");
} else if (getEnvironmentVariable(knownCITools.get("TeamCity")) != null) {
return getEnvironmentVariable("TEAMCITY_PROJECT_NAME") + ": " + getEnvironmentVariable("BUILD_NUMBER");
} else {
return "Build Time: " + System.currentTimeMillis();
}
}

public boolean isKnownCI() {
return !knownCITools.keySet().stream().allMatch((key) -> getEnvironmentVariable(key) == null);
}

// Use Case is pulling serialized information from JSON/YAML, converting it to a HashMap and passing it in
// This is a preferred pattern as it avoids conditionals in code
public void mergeCapabilities(Map<String, Object> capabilities) {
capabilities.forEach(this::setCapability);
}

// This might be made public in future version; For now, no good reason to prefer it over direct accessor
private Object getCapability(String capability) {
try {
String getter = "get" + capability.substring(0, 1).toUpperCase() + capability.substring(1);
Method declaredMethod = null;
declaredMethod = SauceOptions.class.getDeclaredMethod(getter);
return declaredMethod.invoke(this);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
return null;
}
}

public void setCapability(String key, Object value) {
if (primaryEnum.contains(key) && value.getClass().equals(String.class)) {
setEnumCapability(key, (String) value);
} else if (secondaryEnum.contains(key) && isKeyString((HashMap) value)) {
setEnumCapability(key, (HashMap) value);
} else {
try {
Class<?> type = SauceOptions.class.getDeclaredField(key).getType();
String setter = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
Method method = SauceOptions.class.getDeclaredMethod(setter, type);
method.invoke(this, value);
} catch (NoSuchFieldException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
}

private boolean isKeyString(HashMap map) {
return map.keySet().toArray()[0].getClass().equals(String.class);
}

// this method is only used when setting capabilities from mergeCapabilities method
private void setEnumCapability(String key, HashMap value) {
if ("prerun".equals(key)) {
Map<Prerun, Object> prerunMap = new HashMap<>();
value.forEach((oldKey, val) -> {
enumValidator("Prerun", Prerun.keys(), (String) oldKey);
String keyString = Prerun.fromString((String) oldKey);
prerunMap.put(Prerun.valueOf(keyString), val);
});
setPrerun(prerunMap);
} else if ("timeouts".equals(key)) {
Map<Timeouts, Integer> timeoutsMap = new HashMap<>();
value.forEach((oldKey, val) -> {
enumValidator("Timeouts", Timeouts.keys(), (String) oldKey);
String keyString = Timeouts.fromString((String) oldKey);
timeoutsMap.put(Timeouts.valueOf(keyString), (Integer) val);
});
setTimeouts(timeoutsMap);
}
}

// this method is only used when setting capabilities from mergeCapabilities method
private void setEnumCapability(String key, String value) {
switch (key) {
case "browserName":
enumValidator("Browser", Browser.keys(), value);
setBrowserName(Browser.valueOf(Browser.fromString(value)));
break;
case "platformName":
enumValidator("SaucePlatform", SaucePlatform.keys(), value);
setPlatformName(SaucePlatform.valueOf(SaucePlatform.fromString(value)));
break;
case "jobVisibility":
enumValidator("JobVisibility", JobVisibility.keys(), value);
setJobVisibility(JobVisibility.valueOf(JobVisibility.fromString(value)));
break;
case "pageLoadStrategy":
enumValidator("PageLoadStrategy", PageLoadStrategy.keys(), value);
setPageLoadStrategy(PageLoadStrategy.valueOf(PageLoadStrategy.fromString(value)));
break;
case "unhandledPromptBehavior":
enumValidator("UnhandledPromptBehavior", UnhandledPromptBehavior.keys(), value);
setUnhandledPromptBehavior(UnhandledPromptBehavior.valueOf(UnhandledPromptBehavior.fromString(value)));
break;
default:
break;
}
}

private void enumValidator(String name, Set values, String value) {
if (!values.contains(value)) {
String message = value + " is not a valid " + name + ", please choose from: " + values;
throw new InvalidSauceOptionsArgumentException(message);
}
}

private MutableCapabilities addAuthentication() {
MutableCapabilities caps = new MutableCapabilities();
caps.setCapability("username", getSauceUsername());
caps.setCapability("accessKey", getSauceAccessKey());
return caps;
}

protected String getSauceUsername() {
return tryToGetVariable("SAUCE_USERNAME", "Sauce Username was not provided");
}

private String tryToGetVariable(String key, String errorMessage) {
if (getSystemProperty(key) != null) {
return getSystemProperty(key);
} else if (getEnvironmentVariable(key) != null) {
return getEnvironmentVariable(key);
} else {
throw new SauceEnvironmentVariablesNotSetException(errorMessage);
}
}

protected String getSauceAccessKey() {
return tryToGetVariable("SAUCE_ACCESS_KEY", "Sauce Access Key was not provided");
}

protected String getSystemProperty(String key) {
return System.getProperty(key);
}

protected String getEnvironmentVariable(String key) {
return System.getenv(key);
/**
* @deprecated Use getCapabilities() instead
* @return instance capabilities that will get sent to the RemoteWebDriver
*/
@Deprecated
public MutableCapabilities getSeleniumCapabilities() {
return capabilities;
}
}
Loading