Skip to content

Commit

Permalink
Merge pull request #1562 from joelpramos/issue-1560
Browse files Browse the repository at this point in the history
Issue 1560
  • Loading branch information
ptrthomas authored Apr 18, 2021
2 parents f3b8ec9 + 9d6d137 commit 99aae98
Show file tree
Hide file tree
Showing 23 changed files with 542 additions and 108 deletions.
15 changes: 15 additions & 0 deletions karate-core/src/main/java/com/intuit/karate/Runner.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import com.intuit.karate.core.FeatureResult;
import com.intuit.karate.core.FeatureRuntime;
import com.intuit.karate.core.RuntimeHookFactory;
import com.intuit.karate.driver.DriverOptions;
import com.intuit.karate.driver.DriverRunner;
import com.intuit.karate.http.HttpClientFactory;
import com.intuit.karate.job.JobConfig;
import com.intuit.karate.report.SuiteReports;
Expand Down Expand Up @@ -190,6 +192,7 @@ public static class Builder<T extends Builder> {
Map<String, Object> suiteCache;
SuiteReports suiteReports;
JobConfig jobConfig;
Map<String, DriverRunner> drivers;

public List<Feature> resolveAll() {
if (classLoader == null) {
Expand Down Expand Up @@ -291,6 +294,13 @@ public List<Feature> resolveAll() {
if (suiteReports == null) {
suiteReports = SuiteReports.DEFAULT;
}
if (drivers != null) {
Map<String, DriverRunner> customDrivers = drivers;
drivers = DriverOptions.driverRunners();
drivers.putAll(customDrivers); // allows override of Karate drivers (e.g. custom 'chrome')
} else {
drivers = DriverOptions.driverRunners();
}
if (jobConfig != null) {
reportDir = jobConfig.getExecutorDir();
if (threadCount < 1) {
Expand Down Expand Up @@ -503,6 +513,11 @@ public T suiteReports(SuiteReports value) {
return (T) this;
}

public T customDrivers(Map<String, DriverRunner> customDrivers) {
drivers = customDrivers;
return (T) this;
}

public Results jobManager(JobConfig value) {
jobConfig = value;
Suite suite = new Suite(this);
Expand Down
12 changes: 8 additions & 4 deletions karate-core/src/main/java/com/intuit/karate/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
package com.intuit.karate;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
Expand Down Expand Up @@ -259,10 +260,13 @@ public static void removeIgnoreKeyCase(Map<String, ?> map, String name) {
}

public static String throwableToString(Throwable t) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
return sw.toString();
try(final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw, true)) {
t.printStackTrace(pw);
return sw.toString();
} catch (IOException e) {
return null;
}
}

}
5 changes: 5 additions & 0 deletions karate-core/src/main/java/com/intuit/karate/Suite.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.intuit.karate.core.Feature;
import com.intuit.karate.core.FeatureResult;
import com.intuit.karate.core.FeatureRuntime;
import com.intuit.karate.driver.DriverRunner;
import com.intuit.karate.report.ReportUtils;
import com.intuit.karate.core.Scenario;
import com.intuit.karate.core.ScenarioResult;
Expand Down Expand Up @@ -103,6 +104,8 @@ public class Suite implements Runnable {
public final Map<String, Object> suiteCache;
private final ReentrantLock progressFileLock;

public final Map<String, DriverRunner> drivers;

private String read(String name) {
try {
Resource resource = ResourceUtils.getResource(workingDir, name);
Expand Down Expand Up @@ -156,6 +159,7 @@ public Suite(Runner.Builder rb) {
suiteReports = null;
jobManager = null;
progressFileLock = null;
drivers = null;
} else {
startTime = System.currentTimeMillis();
rb.resolveAll();
Expand Down Expand Up @@ -192,6 +196,7 @@ public Suite(Runner.Builder rb) {
} else {
jobManager = null;
}
drivers = rb.drivers;
threadCount = rb.threadCount;
timeoutMinutes = rb.timeoutMinutes;
parallel = threadCount > 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1975,7 +1975,9 @@ private Variable callOnceResult(ScenarioCall.Result result, boolean sharedScope)
if (sharedScope) { // if shared scope
vars.clear(); // clean slate
// deep-clone so that subsequent steps don't modify data / references being passed around
result.vars.forEach((k, v) -> vars.put(k, v.copy(true)));
if (result.vars != null) {
result.vars.forEach((k, v) -> vars.put(k, v.copy(true)));
}
init(); // this will attach and also insert magic variables
// re-apply config from time of snapshot
// and note that setConfig() will attach functions such as configured "headers"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public StepResult addFakeStepResult(String message, Throwable error) {
Result result = error == null ? Result.passed(0) : Result.failed(0, error, step);
StepResult sr = new StepResult(step, result);
if (error != null) {
sr.setStepLog(error.getMessage());
sr.setStepLog(error.getMessage() + "\n" + StringUtils.throwableToString(error));
}
addStepResult(sr);
return sr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ public ScenarioRuntime(FeatureRuntime featureRuntime, Scenario scenario, Scenari
perfMode = featureRuntime.perfHook != null;
if (caller.isNone()) {
logAppender = perfMode ? LogAppender.NO_OP : new StringLogAppender(false);
engine = new ScenarioEngine(new Config(), this, new HashMap(), logger);
engine = new ScenarioEngine(background == null ? new Config() : background.engine.getConfig(), this, new HashMap(), logger);
} else if (caller.isSharedScope()) {
logAppender = caller.parentRuntime.logAppender;
Config config = caller.parentRuntime.engine.getConfig();
Config config = background == null ? caller.parentRuntime.engine.getConfig() : background.engine.getConfig();
Map<String, Variable> vars = caller.parentRuntime.engine.vars;
engine = new ScenarioEngine(config, this, vars, logger);
} else { // new, but clone and copy data
logAppender = caller.parentRuntime.logAppender;
Config config = new Config(caller.parentRuntime.engine.getConfig());
Config config = background == null ? new Config(caller.parentRuntime.engine.getConfig()) : background.engine.getConfig();
Map<String, Variable> vars = caller.parentRuntime.engine.copyVariables(false);
engine = new ScenarioEngine(config, this, vars, logger);
}
Expand Down Expand Up @@ -349,10 +349,19 @@ public void beforeRun() {
if (this.isDynamicBackground()) {
steps = scenario.getBackgroundSteps();
} else {
steps = background == null ? scenario.getStepsIncludingBackground() : scenario.getSteps();
steps = scenario.getStepsIncludingBackground();
}
ScenarioEngine.set(engine);
engine.init();
if (this.background != null) {
ScenarioEngine backgroundEngine = background.engine;
if (backgroundEngine.driver != null) {
engine.setDriver(backgroundEngine.driver);
}
if (backgroundEngine.robot != null) {
engine.setRobot(backgroundEngine.robot);
}
}
result.setExecutorName(Thread.currentThread().getName());
result.setStartTime(System.currentTimeMillis());
if (!dryRun) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,36 +286,13 @@ public static Driver start(Map<String, Object> options, ScenarioRuntime sr) { //
options.put("type", type);
}
try { // to make troubleshooting errors easier
switch (type) {
case Chrome.DRIVER_TYPE:
return Chrome.start(options, sr);
case EdgeChromium.DRIVER_TYPE:
return EdgeChromium.start(options, sr);
case "chromedriver":
return ChromeWebDriver.start(options, sr);
case "geckodriver":
return GeckoWebDriver.start(options, sr);
case "safaridriver":
return SafariWebDriver.start(options, sr);
case "msedgedriver":
return MsEdgeDriver.start(options, sr);
case "mswebdriver":
return MsWebDriver.start(options, sr);
case "iedriver":
return IeWebDriver.start(options, sr);
case "winappdriver":
return WinAppDriver.start(options, sr);
case "android":
return AndroidDriver.start(options, sr);
case "ios":
return IosDriver.start(options, sr);
case "playwright":
return PlaywrightDriver.start(options, sr);
default:
sr.logger.warn("unknown driver type: {}, defaulting to 'chrome'", type);
options.put("type", Chrome.DRIVER_TYPE);
return Chrome.start(options, sr);
DriverRunner driverRunner = sr.featureRuntime.suite.drivers.get(type);
if (driverRunner == null) {
sr.logger.warn("unknown driver type: {}, defaulting to 'chrome'", type);
options.put("type", Chrome.DRIVER_TYPE);
driverRunner = sr.featureRuntime.suite.drivers.get(Chrome.DRIVER_TYPE);
}
return driverRunner.start(options, sr);
} catch (Exception e) {
String message = "driver config / start failed: " + e.getMessage() + ", options: " + options;
sr.logger.error(message, e);
Expand All @@ -326,6 +303,23 @@ public static Driver start(Map<String, Object> options, ScenarioRuntime sr) { //
}
}

public static Map<String, DriverRunner> driverRunners() {
Map<String, DriverRunner> driverRunners = new HashMap<>();
driverRunners.put(Chrome.DRIVER_TYPE, Chrome::start);
driverRunners.put(EdgeChromium.DRIVER_TYPE, EdgeChromium::start);
driverRunners.put(ChromeWebDriver.DRIVER_TYPE, ChromeWebDriver::start);
driverRunners.put(GeckoWebDriver.DRIVER_TYPE, GeckoWebDriver::start);
driverRunners.put(SafariWebDriver.DRIVER_TYPE, SafariWebDriver::start);
driverRunners.put(MsEdgeDriver.DRIVER_TYPE, MsEdgeDriver::start);
driverRunners.put(MsWebDriver.DRIVER_TYPE, MsWebDriver::start);
driverRunners.put(IeWebDriver.DRIVER_TYPE, IeWebDriver::start);
driverRunners.put(WinAppDriver.DRIVER_TYPE, WinAppDriver::start);
driverRunners.put(AndroidDriver.DRIVER_TYPE, AndroidDriver::start);
driverRunners.put(IosDriver.DRIVER_TYPE, IosDriver::start);
driverRunners.put(PlaywrightDriver.DRIVER_TYPE, PlaywrightDriver::start);
return driverRunners;
}

private Map<String, Object> getSession(String browserName) {
Map<String, Object> session = webDriverSession;
if (session == null) {
Expand All @@ -348,16 +342,16 @@ private Map<String, Object> getSession(String browserName) {
// TODO abstract as method per implementation
public Map<String, Object> getWebDriverSessionPayload() {
switch (type) {
case "chromedriver":
case ChromeWebDriver.DRIVER_TYPE:
return getSession("chrome");
case "geckodriver":
case GeckoWebDriver.DRIVER_TYPE:
return getSession("firefox");
case "safaridriver":
case SafariWebDriver.DRIVER_TYPE:
return getSession("safari");
case "msedgedriver":
case "mswebdriver":
case MsEdgeDriver.DRIVER_TYPE:
case MsWebDriver.DRIVER_TYPE:
return getSession("edge");
case "iedriver":
case IeWebDriver.DRIVER_TYPE:
return getSession("internet explorer");
default:
// else user has to specify full payload via webDriverSession
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.intuit.karate.driver;

import com.intuit.karate.core.ScenarioRuntime;

import java.util.Map;

@FunctionalInterface
public interface DriverRunner<D extends Driver> {
D start(Map<String, Object> options, ScenarioRuntime sr);
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
package com.intuit.karate.driver.appium;

import com.intuit.karate.FileUtils;
import com.intuit.karate.core.ScenarioRuntime;
import java.util.Map;

/**
* @author babusekaran
*/
public class AndroidDriver extends AppiumDriver {

protected AndroidDriver(MobileDriverOptions options) {
super(options);
}

public static AndroidDriver start(Map<String, Object> map, ScenarioRuntime sr) {
MobileDriverOptions options = new MobileDriverOptions(map, sr, 4723, FileUtils.isOsWindows() ? "cmd.exe" : "appium");
// additional commands needed to start appium on windows
if (FileUtils.isOsWindows()){
options.arg("/C");
options.arg("cmd.exe");
options.arg("/K");
options.arg("appium");
}
options.arg("--port=" + options.port);
return new AndroidDriver(options);
}

@Override
public void activate() {
super.setContext("NATIVE_APP");
}

}
package com.intuit.karate.driver.appium;

import com.intuit.karate.FileUtils;
import com.intuit.karate.core.ScenarioRuntime;
import java.util.Map;

/**
* @author babusekaran
*/
public class AndroidDriver extends AppiumDriver {

public static final String DRIVER_TYPE = "android";

protected AndroidDriver(MobileDriverOptions options) {
super(options);
}

public static AndroidDriver start(Map<String, Object> map, ScenarioRuntime sr) {
MobileDriverOptions options = new MobileDriverOptions(map, sr, 4723, FileUtils.isOsWindows() ? "cmd.exe" : "appium");
// additional commands needed to start appium on windows
if (FileUtils.isOsWindows()){
options.arg("/C");
options.arg("cmd.exe");
options.arg("/K");
options.arg("appium");
}
options.arg("--port=" + options.port);
return new AndroidDriver(options);
}

@Override
public void activate() {
super.setContext("NATIVE_APP");
}

}
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
package com.intuit.karate.driver.appium;

import com.intuit.karate.core.ScenarioRuntime;
import java.util.Map;

/**
* @author babusekaran
*/
public class IosDriver extends AppiumDriver {

public IosDriver(MobileDriverOptions options) {
super(options);
}

public static IosDriver start(Map<String, Object> map, ScenarioRuntime sr) {
MobileDriverOptions options = new MobileDriverOptions(map, sr, 4723, "appium");
options.arg("--port=" + options.port);
return new IosDriver(options);
}

@Override
public void activate() {
super.setContext("NATIVE_APP");
}

}
package com.intuit.karate.driver.appium;

import com.intuit.karate.core.ScenarioRuntime;
import java.util.Map;

/**
* @author babusekaran
*/
public class IosDriver extends AppiumDriver {

public static final String DRIVER_TYPE = "ios";

public IosDriver(MobileDriverOptions options) {
super(options);
}

public static IosDriver start(Map<String, Object> map, ScenarioRuntime sr) {
MobileDriverOptions options = new MobileDriverOptions(map, sr, 4723, "appium");
options.arg("--port=" + options.port);
return new IosDriver(options);
}

@Override
public void activate() {
super.setContext("NATIVE_APP");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
*/
public class ChromeWebDriver extends WebDriver {

public static final String DRIVER_TYPE = "chromedriver";

public ChromeWebDriver(DriverOptions options) {
super(options);
}
Expand Down
Loading

0 comments on commit 99aae98

Please sign in to comment.