Skip to content

Commit

Permalink
[web]
Browse files Browse the repository at this point in the history
- [`screenshot(file,locator)`]: now supports output to cloud.

- Release v2.6 candidate

Signed-off-by: automike <[email protected]>
  • Loading branch information
mikeliucc committed Sep 6, 2019
1 parent e5d6ef4 commit 110cce2
Show file tree
Hide file tree
Showing 36 changed files with 160 additions and 77 deletions.
27 changes: 27 additions & 0 deletions src/main/java/org/nexial/commons/utils/TextUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,33 @@ public static String cleanNumber(String text, CleanNumberStrategy howToClean) {
return text;
}

public static String decorateTextRange(String text,
String startsFrom,
String endsWith,
String decorateStart,
String decorateEnd) {
if (StringUtils.isEmpty(text) ||
StringUtils.isEmpty(startsFrom) ||
StringUtils.isEmpty(endsWith) ||
StringUtils.isEmpty(decorateStart) ||
StringUtils.isEmpty(decorateEnd)) { return text; }

int startPos = text.indexOf(startsFrom);
while (startPos != -1) {
int endPos = text.indexOf(endsWith, startPos + startsFrom.length());
if (endPos == -1) { break; }

text = text.substring(0, startPos + startsFrom.length()) +
decorateStart +
text.substring(startPos + startsFrom.length(), endPos) +
decorateEnd +
text.substring(endPos);
startPos = text.indexOf(startsFrom, endPos + decorateEnd.length() + decorateEnd.length());
}

return text;
}

private static Map<String, String> initDefaultEscapeHtmlMapping() {
Map<String, String> searchReplace = new HashMap<>();
searchReplace.put("<", "&lt;");
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/nexial/core/NexialConst.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@ public final class NexialConst {
public static final String WS_ALLOW_CIRCULAR_REDIRECTS = registerSystemVariable(WS_NAMESPACE + "allowCircularRedirects", false);
public static final String WS_ALLOW_RELATIVE_REDIRECTS = registerSystemVariable(WS_NAMESPACE + "allowRelativeRedirects", true);
public static final String WS_REQ_PAYLOAD_COMPACT = registerSystemVariable(WS_NAMESPACE + "requestPayloadCompact", false);
//public static final String WS_REQ_CONTENT_TYPE = WS_NAMESPACE + "requestContentType";
//public static final String WS_RES_PAYLOAD_COMPACT = WS_NAMESPACE + "responsePayloadCompact";
public static final String WS_REQ_FILE_AS_RAW = registerSystemVariable(WS_NAMESPACE + "requestPayloadAsRaw", false);

public static final String WS_REQ_HEADER_PREFIX = WS_NAMESPACE + "header.";
public static final String WS_PROXY_REQUIRED = registerSystemVariable(WS_NAMESPACE + "proxyRequired");
public static final String WS_PROXY_HOST = registerSystemVariable(WS_NAMESPACE + "proxyHost");
Expand Down Expand Up @@ -471,10 +471,10 @@ public enum ImageType {
public static final class ImageDiffColor {
private static final Map<String, Color> COLOR_NAMES = new HashMap<>();

public static Map<String, Color> getColorNames() { return COLOR_NAMES; }

private ImageDiffColor() {}

public static Map<String, Color> getColorNames() { return COLOR_NAMES; }

/** default to red */
public static Color toColor(String colorName) {
return MapUtils.getObject(COLOR_NAMES, colorName, COLOR_NAMES.get(getDefault(OPT_IMAGE_DIFF_COLOR)));
Expand Down
8 changes: 2 additions & 6 deletions src/main/java/org/nexial/core/plugins/io/IoCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -670,9 +670,7 @@ protected StepResult doAction(IoAction action, String source, String regex, Stri

File sourceDir = new File(source);
if (sourceDir.exists()) {
if (sourceDir.isFile()) {
return StepResult.fail("Source path '" + source + "' must be directory");
}
if (sourceDir.isFile()) { return StepResult.fail("Source path '" + source + "' must be directory"); }
} else {
return StepResult.fail("Source directory '" + source + "' does not exist");
}
Expand Down Expand Up @@ -712,9 +710,7 @@ protected StepResult doAction(IoAction action, String source, String regex, Stri
// else if target's parent exist, then its file. else it is directory.
if (!StringUtils.endsWith(target, separator)) {
String parent = StringUtils.substringBeforeLast(target, separator);
if (!new File(parent).exists()) {
FileUtils.forceMkdir(targetDir);
}
if (!new File(parent).exists()) { FileUtils.forceMkdir(targetDir); }
} else {
FileUtils.forceMkdir(targetDir);
}
Expand Down
32 changes: 30 additions & 2 deletions src/main/java/org/nexial/core/plugins/json/JsonCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@
import static org.nexial.core.utils.CheckUtils.*;

public class JsonCommand extends BaseCommand {
private static final String DIFF_HIGHLIGHT_HTML_START = "<span class=\"diff-highlight\"" +
" style=\"background:#fee;color:red;font-weight:bold\">";
private static final String DIFF_HIGHLIGHT_HTML_END = "</span>";
private static final String DIFF_NULL_HTML_START = "<code class=\"diff-null\" style=\"color:#777\">";
private static final String DIFF_NULL_HTML_END = "</code>";
private static final JsonSchemaFactory JSON_SCHEMA_FACTORY = JsonSchemaFactory.byDefault();

@Override
Expand Down Expand Up @@ -549,12 +554,35 @@ private void handleComparisonResults(JsonComparisonResult results) {

if (asJson) { addOutputAsLink(caption, differences, "json"); }

List<String> headers = Arrays.asList("expectedNode", "actualNode", "message");
List<String> headers = Arrays.asList("expected", "actual", "message");
List<List<String>> diffList = results.toList();
if (asCsv) { addOutputAsLink(caption, TextUtils.createCsv(headers, diffList, "\r\n", ",", "\""), "csv"); }

if (asHtml) {
addOutputAsLink(caption, TextUtils.createHtmlTable(headers, diffList, "compare-result-table"), "html");
addOutputAsLink(caption,
TextUtils.createHtmlTable(
headers,
diffList,
(row, position) -> {
String html = row.get(position);
if (html == null || "null".equals(html)) {
return DIFF_NULL_HTML_START + "NOT FOUND" + DIFF_NULL_HTML_END;
}

html = TextUtils.decorateTextRange(html,
"contains ",
" of",
DIFF_HIGHLIGHT_HTML_START,
DIFF_HIGHLIGHT_HTML_END);
html = TextUtils.decorateTextRange(html,
"node '",
"' ",
DIFF_HIGHLIGHT_HTML_START,
DIFF_HIGHLIGHT_HTML_END);
return "<code>" + html + "</code>";
},
"compare-result-table"),
"html");
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/main/java/org/nexial/core/plugins/web/WebCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -1678,7 +1678,13 @@ public StepResult screenshot(String file, String locator) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "PNG", baos);
FileUtils.writeByteArrayToFile(target, baos.toByteArray());
return StepResult.success("Image captured for '" + locator + "' to file '" + file + "'");

if (context.isOutputToCloud()) {
String cloudUrl = context.getOtc().importMedia(target);
return StepResult.success("Image captured for '" + locator + "' to URL " + cloudUrl);
} else {
return StepResult.success("Image captured for '" + locator + "' to file '" + file + "'");
}
} catch (IOException e) {
return StepResult.fail("Unable to write image data to file " + file + ": " + e.getMessage());
}
Expand Down
35 changes: 20 additions & 15 deletions src/main/java/org/nexial/core/utils/OutputFileUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,7 @@ public static String webFriendly(String filename) {

// todo: test for nested file reference - contentOrFile is a file whose content contains reference to another file
public static String resolveContent(String contentOrFile, ExecutionContext context, boolean compact)
throws IOException {
return resolveContent(contentOrFile, context, compact, true);
}
throws IOException { return resolveContent(contentOrFile, context, compact, true); }

public static String resolveRawContent(String contentOrFile, ExecutionContext context) throws IOException {
return resolveContent(contentOrFile, context, false, false);
Expand All @@ -181,9 +179,7 @@ public static String resolveContent(String contentOrFile,
boolean compact,
boolean replaceTokens) throws IOException {

if (StringUtils.isBlank(contentOrFile) || StringUtils.equals(contentOrFile, context.getNullValueToken())) {
return "";
}
if (StringUtils.isBlank(contentOrFile) || context.isNullOrEmptyValue(contentOrFile)) { return ""; }

if (StringUtils.containsNone(contentOrFile, '\n', '\r', '\t') && ResourceUtils.isWebResource(contentOrFile)) {
String content;
Expand All @@ -200,9 +196,7 @@ public static String resolveContent(String contentOrFile,
return replaceTokens ? context.replaceTokens(content) : content;
}

// we can't have NL or CR or TAB character in filename
boolean mightBeFilePath = FileUtil.isSuitableAsPath(contentOrFile);
if (!mightBeFilePath || !FileUtil.isFileReadable(contentOrFile)) {
if (!isContentReferencedAsFile(contentOrFile, context)) {
// must be just content (not file)
String content = compact ? StringUtils.trim(contentOrFile) : contentOrFile;
return replaceTokens ? context.replaceTokens(content) : content;
Expand All @@ -222,13 +216,24 @@ public static String resolveContent(String contentOrFile,
return replaceTokens ? context.replaceTokens(content) : content;
}

public static boolean isContentReferencedAsFile(String contentOrFile, ExecutionContext context) {
if (StringUtils.isBlank(contentOrFile) || StringUtils.equals(contentOrFile, context.getNullValueToken())) {
return false;
}
/**
* read {@literal contentOrFile} as raw file content (i.e. byte array) or, if it is not a file, just the
* content of {@code contentOrFile} as byte array.
*/
public static byte[] resolveContentBytes(String contentOrFile, ExecutionContext context) throws IOException {
return StringUtils.isEmpty(contentOrFile) ?
new byte[0] :
isContentReferencedAsFile(contentOrFile, context) ?
FileUtils.readFileToByteArray(new File(contentOrFile)) :
contentOrFile.getBytes();
}

// we can't have NL or CR or TAB character in filename
return FileUtil.isSuitableAsPath(contentOrFile) && new File(contentOrFile).canRead();
/** we can't have NL or CR or TAB character in filename */
public static boolean isContentReferencedAsFile(String contentOrFile, ExecutionContext context) {
return !StringUtils.isBlank(contentOrFile) &&
!context.isNullOrEmptyValue(contentOrFile) &&
FileUtil.isSuitableAsPath(contentOrFile) &&
new File(contentOrFile).canRead();
}

public static boolean isContentReferencedAsClasspathResource(String schemaLocation, ExecutionContext context) {
Expand Down
21 changes: 12 additions & 9 deletions src/main/kotlin/org/nexial/core/plugins/json/JsonMeta.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,17 @@ data class JsonMeta(val type: Type, var name: String?, var node: String?) {
result
else {
result.addDifference(
Difference(node, actual.node, "EXPECTED contains null but ACTUAL contains $actualValue"))
Difference(node, actual.node,
"EXPECTED is null but ACTUAL contains $actualValue of " +
"type ${JsonUtils.getPrimitiveType(actualValue as JsonPrimitive)}"))
return result
}

if (actualValue == null)
return result.addDifference(
Difference(node, actual.node, "EXPECTED contains $value but ACTUAL contains null"))
Difference(node, actual.node,
"EXPECTED contains $value of type ${JsonUtils.getPrimitiveType(value as JsonPrimitive)} " +
"but ACTUAL is null"))


if (value is JsonPrimitive && actualValue is JsonPrimitive) {
Expand Down Expand Up @@ -136,8 +140,10 @@ data class JsonMeta(val type: Type, var name: String?, var node: String?) {
val expectedMeta = children[i]

if (i >= actualSize) {
result.addDifference(Difference(expectedMeta.node, null,
"EXPECTED node '${displayMetaLabel(this, i)}' NOT FOUND in ACTUAL"))
result.addDifference(Difference(expectedMeta.node,
null,
"EXPECTED node '${displayMetaLabel(expectedMeta, i)}' " +
"NOT FOUND in ACTUAL"))
} else {
val actualMeta = actual.children[i]

Expand Down Expand Up @@ -187,12 +193,9 @@ data class JsonMeta(val type: Type, var name: String?, var node: String?) {
if (meta.isArray)
"item $i"
else if (meta.isLeaf)
if (StringUtils.isEmpty(meta.name))
"${meta.parent!!.name}[$i]"
else
"${meta.name}[$i]"
if (StringUtils.isEmpty(meta.name)) "${meta.parent!!.name}[$i]" else "${meta.name}[$i]"
else
meta.name
meta.name ?: meta.node

private fun findChildNode(nodeName: String) = children.firstOrNull { it.name == nodeName }

Expand Down
Loading

0 comments on commit 110cce2

Please sign in to comment.