Skip to content

Commit

Permalink
Merge branch 'master' into 409-csvsource-from-file
Browse files Browse the repository at this point in the history
  • Loading branch information
authorjapps authored Jan 26, 2024
2 parents 9763ffd + c1cc7db commit 082dc1a
Show file tree
Hide file tree
Showing 20 changed files with 645 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jsmart.zerocode.core.engine.preprocessor;

import org.jsmart.zerocode.core.domain.Step;
import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher;
import org.jsmart.zerocode.core.engine.assertion.JsonAsserter;

Expand All @@ -18,4 +19,7 @@ public interface ZeroCodeAssertionsProcessor {
List<JsonAsserter> createJsonAsserters(String resolvedAssertionJson);

List<FieldAssertionMatcher> assertAllAndReturnFailed(List<JsonAsserter> asserters, String executionResult);

Step resolveJsonContent(Step thisStep, ScenarioExecutionState scenarioExecutionState);

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jsmart.zerocode.core.engine.preprocessor;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand All @@ -20,22 +21,31 @@
import java.util.Properties;
import net.minidev.json.JSONArray;
import org.apache.commons.lang.text.StrSubstitutor;
import org.jsmart.zerocode.core.domain.Step;
import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher;
import org.jsmart.zerocode.core.engine.assertion.JsonAsserter;
import org.jsmart.zerocode.core.engine.assertion.array.ArrayIsEmptyAsserterImpl;
import org.jsmart.zerocode.core.engine.assertion.array.ArraySizeAsserterImpl;
import org.jsmart.zerocode.core.engine.assertion.field.*;
import org.jsmart.zerocode.core.utils.SmartUtils;

import static java.lang.Integer.valueOf;
import static java.lang.String.format;
import static org.apache.commons.lang.StringEscapeUtils.escapeJava;
import static org.apache.commons.lang.StringUtils.substringBetween;
import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.*;
import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.$VALUE;
import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.JSON_CONTENT;
import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.JSON_PAYLOAD_FILE;
import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.YAML_PAYLOAD_FILE;
import static org.jsmart.zerocode.core.utils.FieldTypeConversionUtils.deepTypeCast;
import static org.jsmart.zerocode.core.utils.FieldTypeConversionUtils.fieldTypes;
import static org.jsmart.zerocode.core.utils.PropertiesProviderUtils.loadAbsoluteProperties;
import static org.jsmart.zerocode.core.utils.SmartUtils.isValidAbsolutePath;
import static org.jsmart.zerocode.core.utils.SmartUtils.readJsonAsString;
import static org.jsmart.zerocode.core.utils.SmartUtils.readYamlAsString;
import static org.jsmart.zerocode.core.utils.SmartUtils.checkDigNeeded;;
import static org.jsmart.zerocode.core.utils.SmartUtils.getJsonFilePhToken;;
import static org.jsmart.zerocode.core.utils.TokenUtils.getTestCaseTokens;
import static org.jsmart.zerocode.core.utils.TokenUtils.populateParamMap;
import static org.slf4j.LoggerFactory.getLogger;
Expand Down Expand Up @@ -337,6 +347,39 @@ public List<FieldAssertionMatcher> assertAllAndReturnFailed(List<JsonAsserter> a
return failedReports;
}

/**
* Resolves JSON.CONTENT as object or array
*
* First the logic checks if dig-deep needed to avoid unwanted recursions. If not needed, the step definition is
* returned intact. Otherwise calls the dig deep method to perform the operation.
*
* @param thisStep
* @return The effective step definition
*/
@Override
public Step resolveJsonContent(Step thisStep, ScenarioExecutionState scenarioExecutionState) {
try {
if (!checkDigNeeded(mapper, thisStep, JSON_CONTENT)) {
return thisStep;
}

JsonNode stepNode = mapper.convertValue(thisStep, JsonNode.class);

Map<String, Object> stepMap = mapper.readValue(stepNode.toString(), new TypeReference<Map<String, Object>>() {
});

digReplaceContent(stepMap, scenarioExecutionState);

JsonNode jsonStepNode = mapper.valueToTree(stepMap);

return mapper.treeToValue(jsonStepNode, Step.class);

} catch (Exception e) {
LOGGER.error("Json content reading exception - {}", e.getMessage());
throw new RuntimeException("Json content reading exception. Details - " + e);
}
}

private void loadAnnotatedHostProperties() {
try {
if(isValidAbsolutePath(hostFileName)){
Expand Down Expand Up @@ -408,4 +451,39 @@ private boolean hasNoTypeCast(String resolvedJson) {
}


void digReplaceContent(Map<String, Object> map, ScenarioExecutionState scenarioExecutionState) {
map.entrySet().forEach(entry -> {
Object value = entry.getValue();

if (value instanceof Map) {
digReplaceContent((Map<String, Object>) value, scenarioExecutionState);
} else {
LOGGER.debug("Leaf node found = {}, checking for any json content...", value);
if (value != null && (value.toString().contains(JSON_CONTENT))) {
LOGGER.debug("Found JSON content place holder = {}. Replacing with content", value);
String valueString = value.toString();
String token = getJsonFilePhToken(valueString);

if (token != null && (token.startsWith(JSON_CONTENT))) {
try {
String resolvedRequestJson = resolveStringJson(
"${" + token.substring(JSON_CONTENT.length()) + "}",
scenarioExecutionState.getResolvedScenarioState());
resolvedRequestJson = resolvedRequestJson.replaceAll("\\\\", "");
try {
JsonNode jsonNode = mapper.readTree(resolvedRequestJson);
entry.setValue(jsonNode);
} catch (JsonParseException e) {
//value is not a json string, but a string value
entry.setValue(resolvedRequestJson);
}
} catch (Exception exx) {
LOGGER.error("External file reference exception - {}", exx.getMessage());
throw new RuntimeException(exx);
}
}
}
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@

import com.google.inject.name.Named;
import org.jsmart.zerocode.core.domain.Step;
import org.jsmart.zerocode.core.utils.SmartUtils;
import org.slf4j.Logger;

import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.JSON_PAYLOAD_FILE;
import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.YAML_PAYLOAD_FILE;
import static org.jsmart.zerocode.core.utils.SmartUtils.readJsonAsString;
import static org.jsmart.zerocode.core.utils.SmartUtils.readYamlAsString;
import static org.jsmart.zerocode.core.utils.SmartUtils.checkDigNeeded;
import static org.jsmart.zerocode.core.utils.SmartUtils.getJsonFilePhToken;
import static org.jsmart.zerocode.core.utils.TokenUtils.getTestCaseTokens;
import static org.slf4j.LoggerFactory.getLogger;

Expand Down Expand Up @@ -69,7 +72,7 @@ public Step resolveExtJsonFile(Step thisStep) {

try {

if (!checkDigNeeded(thisStep)) {
if (!checkDigNeeded(objectMapper, thisStep, JSON_PAYLOAD_FILE, YAML_PAYLOAD_FILE)) {
return thisStep;
}

Expand Down Expand Up @@ -176,22 +179,4 @@ else if (token != null && token.startsWith(OTHER_FILE)) {
}
});
}

private String getJsonFilePhToken(String valueString) {
if (valueString != null) {
List<String> allTokens = getTestCaseTokens(valueString);
if (allTokens != null && !allTokens.isEmpty()) {
return allTokens.get(0);
}
}
return null;
}

boolean checkDigNeeded(Step thisStep) throws JsonProcessingException {
String stepJson = objectMapper.writeValueAsString(thisStep);
List<String> allTokens = getTestCaseTokens(stepJson);

return allTokens.toString().contains(JSON_PAYLOAD_FILE) || allTokens.toString().contains(YAML_PAYLOAD_FILE);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class ZeroCodeValueTokens {
public static final String SYSTEM_ENV = "SYSTEM.ENV:";
public static final String $VALUE = ".$VALUE";
public static final String ABS_PATH = "ABS.PATH:";
public static final String JSON_CONTENT = "JSON.CONTENT:";


public static Map<String, Object> globalTokenCache = new HashMap<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public static void buildOtherRequestParams(Map<String, Object> fileFieldNameValu
if (entry.getKey().equals(FILES_FIELD) || entry.getKey().equals(BOUNDARY_FIELD)) {
continue;
}
multipartEntityBuilder.addPart(entry.getKey(), new StringBody((String) entry.getValue(), TEXT_PLAIN));
multipartEntityBuilder.addPart(entry.getKey(), new StringBody(entry.getValue().toString(), TEXT_PLAIN));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ private Boolean executeRetryWithSteps(RunNotifier notifier,
ScenarioExecutionState scenarioExecutionState,
ScenarioSpec scenario, Step thisStep) {
thisStep = extFileProcessor.resolveExtJsonFile(thisStep);
thisStep = zeroCodeAssertionsProcessor.resolveJsonContent(thisStep, scenarioExecutionState);

List<Step> thisSteps = extFileProcessor.createFromStepFile(thisStep, thisStep.getId());
if(null == thisSteps || thisSteps.isEmpty()) thisSteps.add(thisStep);
Boolean wasExecSuccess = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang.text.StrSubstitutor;
import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider;
import org.jsmart.zerocode.core.domain.ScenarioSpec;
import org.jsmart.zerocode.core.domain.Step;
import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -39,7 +39,10 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aMatchingMessage;
import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aNotMatchingMessage;
import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.JSON_PAYLOAD_FILE;
import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.YAML_PAYLOAD_FILE;
import static org.jsmart.zerocode.core.utils.PropertiesProviderUtils.loadAbsoluteProperties;
import static org.jsmart.zerocode.core.utils.TokenUtils.getTestCaseTokens;
import static org.skyscreamer.jsonassert.JSONAssert.assertEquals;
import static org.skyscreamer.jsonassert.JSONCompareMode.STRICT;

Expand Down Expand Up @@ -240,4 +243,42 @@ public static String getEnvPropertyValue(String envPropertyKey) {
return System.getenv(envPropertyKey);
}
}

/**
*
* @param thisStep --> Currently executing step
* @param tokenString --> JSON_PAYLAOD_FILE or JSON_CONTENT
* @return if there is a match for the token, then the json traversal will happen
* @throws JsonProcessingException
*/
public static boolean checkDigNeeded(ObjectMapper mapper, Step thisStep, String tokenString) throws JsonProcessingException {
String stepJson = mapper.writeValueAsString(thisStep);
List<String> allTokens = getTestCaseTokens(stepJson);

return allTokens.toString().contains(tokenString);
}
public static boolean checkDigNeeded(ObjectMapper mapper, Step thisStep, String tokenString, String alternateTokenString) throws JsonProcessingException {
String stepJson = mapper.writeValueAsString(thisStep);
List<String> allTokens = getTestCaseTokens(stepJson);

return allTokens.toString().contains(tokenString) || allTokens.toString().contains(alternateTokenString);
}

/**
* Retrieves the first token from the given value string that matches the format "${token}".
* Ph = Placeholder (e.g. ${JSON.FILE:unit_test_files/filebody_unit_test/common/common_content.json} )
*
* @param valueString The string from which to extract the jsonfile path
* @return The extracted token, or null if no token is found
*/
public static String getJsonFilePhToken(String valueString) {
if (valueString != null) {
List<String> allTokens = getTestCaseTokens(valueString);
if (allTokens != null && !allTokens.isEmpty()) {
return allTokens.get(0);
}
}
return null;
}

}
Loading

0 comments on commit 082dc1a

Please sign in to comment.