Skip to content

Commit

Permalink
Fix for issue karatelabs#1225 (error printing in memory JVM classes) …
Browse files Browse the repository at this point in the history
…and additional tweak to pass such classes as parameters and use them
  • Loading branch information
joelpramos committed Jul 28, 2020
1 parent ab78a10 commit bf7b1c8
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 10 deletions.
22 changes: 22 additions & 0 deletions karate-core/src/main/java/com/intuit/karate/JsonUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.util.Map;
import java.util.Set;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONStyle;
import net.minidev.json.JSONValue;
import net.minidev.json.parser.JSONParser;
Expand Down Expand Up @@ -235,6 +236,27 @@ public static String escapeValue(String raw) {
return JSONValue.escape(raw, JSONStyle.LT_COMPRESS);
}

public static Object nashornObjectToJavaJSON(Object jsObj) {
if (jsObj instanceof ScriptObjectMirror) {
ScriptObjectMirror jsObjectMirror = (ScriptObjectMirror) jsObj;
if (jsObjectMirror.isArray()) {
List list = new JSONArray();
for (Map.Entry<String, Object> entry : jsObjectMirror.entrySet()) {
list.add(nashornObjectToJavaJSON(entry.getValue()));
}
return list;
} else {
Map<String, Object> map = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : jsObjectMirror.entrySet()) {
map.put(entry.getKey(), nashornObjectToJavaJSON(entry.getValue()));
}
return map;
}
} else {
return jsObj;
}
}

public static void removeKeysWithNullValues(Object o) {
if (o instanceof Map) {
Map<String, Object> map = (Map) o;
Expand Down
10 changes: 6 additions & 4 deletions karate-core/src/main/java/com/intuit/karate/ScriptValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,20 @@
*/
package com.intuit.karate;

import com.intuit.karate.core.ScenarioContext;
import com.intuit.karate.core.Feature;
import com.intuit.karate.core.ScenarioContext;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.w3c.dom.Node;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.w3c.dom.Node;

/**
*
Expand Down Expand Up @@ -457,7 +458,8 @@ public ScriptValue(Object value, String source) {
if (value instanceof ScriptObjectMirror) {
ScriptObjectMirror som = (ScriptObjectMirror) value;
if (!som.isFunction()) {
value = JsonUtils.toJsonDoc(value).read("$"); // results in Map or List
Object o = JsonUtils.nashornObjectToJavaJSON(value);
value = JsonPath.parse(o).read("$"); // results in Map or List
if (value instanceof Map) {
Map map = (Map) value;
retainRootKeyValuesWhichAreFunctions(som, map, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@
import com.intuit.karate.ScriptValueMap;
import com.intuit.karate.StringUtils;
import com.intuit.karate.exception.KarateException;
import com.jayway.jsonpath.JsonPath;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
*
* @author pthomas3
Expand Down Expand Up @@ -172,7 +172,7 @@ public String getCallArgPretty() {
}
try {
Map temp = JsonUtils.removeCyclicReferences(callArg);
return JsonUtils.toPrettyJsonString(JsonUtils.toJsonDoc(temp));
return JsonUtils.toPrettyJsonString(JsonPath.parse(temp));
} catch (Throwable t) {
return "#error: " + t.getMessage();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@
package com.intuit.karate.core;

import com.intuit.karate.FileUtils;
import com.intuit.karate.core.Engine;
import com.intuit.karate.core.Feature;
import com.intuit.karate.core.FeatureParser;
import com.intuit.karate.core.FeatureResult;
import net.minidev.json.JSONArray;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.Map;
import java.util.function.IntBinaryOperator;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
Expand Down Expand Up @@ -97,4 +96,24 @@ public void testAbortMultiScenarioFeature() throws Exception {
assertTrue(contents.contains("Then assert a != 3 ........................................................ passed"));
assertTrue(contents.contains("And assert a != 4 ......................................................... passed"));
}

/**
* Function used on testLambdaFunctionsInScenarioFeature() unit test to demonstrate the inclusion
* of a functional interface via the Java interloop called from the .feature file
* @param map
*/
public static void addLambdaFunctionToMap(Map<String, Object> map) {
IntBinaryOperator plusOperation = (a, b) -> a + b;
map.put("javaSum", plusOperation);
}

@Test
public void testLambdaFunctionsInScenarioFeature() throws Exception {
FeatureResult result = result("caller-with-lambda-arg.feature");
assertEquals(0, result.getFailedCount());

JSONArray dataArr = (JSONArray) result.getResultAsPrimitiveMap().get("data");
assertTrue( ((Map) dataArr.get(0)).get("javaSum") instanceof IntBinaryOperator);
System.out.println();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
@ignore
Feature:

Background:
* def dataFunc =
"""
function() {
var element = {
"something": "value"
};
var intBinaryOperator = Java.type('java.util.function.IntBinaryOperator');
var plusOperation = Java.extend(intBinaryOperator, {
applyAsInt: function(left, right) {
return left + right;
}
});
var featureResultTestClass = Java.type('com.intuit.karate.core.FeatureResultTest');
featureResultTestClass.addLambdaFunctionToMap(element);
element.sum = new plusOperation();
return element;
}
"""
* def elem = dataFunc()
* def data = [ "#(elem)" ]

Scenario:
# ensuring the called.feature returns success
# passing data with a functional interface should be correctly printed
# in Result obj
* def input = 3
* def result = call read('called.feature') data
* match data[0].something == "value"
* match data[0].javaSum(1,3) == 4
* match data[0].sum(1,3) == 4

* def left = 1
* def right = 2
* def payload = { "leftSide": #(left), "rightSide": #(right), "sum": '#(data[0].sum(left, right))' }
* match payload == { "leftSide": 1, "rightSide": 2, "sum": '#? _ == 1+2' }
* match payload == { "leftSide": 1, "rightSide": 2, "sum": '#? _ == data[0].sum( $.leftSide, $.rightSide)' }

0 comments on commit bf7b1c8

Please sign in to comment.