diff --git a/src/main/java/org/nexial/core/ExecutionThread.java b/src/main/java/org/nexial/core/ExecutionThread.java index d9b1e1ed6..dfd1452fc 100644 --- a/src/main/java/org/nexial/core/ExecutionThread.java +++ b/src/main/java/org/nexial/core/ExecutionThread.java @@ -32,6 +32,7 @@ import org.nexial.commons.logging.LogbackUtils; import org.nexial.commons.utils.FileUtil; import org.nexial.commons.utils.ResourceUtils; +import org.nexial.core.aws.NexialS3Helper; import org.nexial.core.excel.Excel; import org.nexial.core.model.*; import org.nexial.core.plugins.web.CloudWebTestingPlatform; @@ -479,8 +480,18 @@ private void handleBrowserMetrics(ExecutionContext context) { String html = StringUtils.replace(ResourceUtils.loadResource(WEB_METRICS_HTML_LOC + WEB_METRICS_HTML), WEB_METRICS_TOKEN, json); - FileUtils.writeStringToFile(new File(outputBase + WEB_METRICS_HTML), html, DEF_FILE_ENCODING); + File webMetricFile = new File(outputBase + WEB_METRICS_HTML); + FileUtils.writeStringToFile(webMetricFile, html, DEF_FILE_ENCODING); System.setProperty(WEB_METRICS_GENERATED, "true"); + + if (context.isOutputToCloud()) { + NexialS3Helper otc = context.getOtc(); + if (otc != null && otc.isReadyForUse() && FileUtil.isFileReadable(webMetricFile, 1024)) { + // upload HTML report to cloud + String url = otc.importToS3(webMetricFile, otc.resolveOutputDir(), true); + ConsoleUtils.log("Web Performance Metric exported to " + url); + } + } } catch (IOException e) { // unable to read JSON, read HTML or write HTML to output ConsoleUtils.error("Unable to generate browser metrics HTML: " + e.getMessage()); diff --git a/src/main/java/org/nexial/core/Nexial.java b/src/main/java/org/nexial/core/Nexial.java index adc8b677c..a5cb7d226 100755 --- a/src/main/java/org/nexial/core/Nexial.java +++ b/src/main/java/org/nexial/core/Nexial.java @@ -940,7 +940,7 @@ protected void onExecutionComplete(String runId, ExecutionSummary summary) { // upload HTML report to cloud if (FileUtil.isFileReadable(htmlReport, 1024)) { String url = otc.importToS3(htmlReport, outputDir, true); - ConsoleUtils.log("HTML output for this execution export to " + url); + ConsoleUtils.log("HTML output for this execution exported to " + url); System.setProperty(EXEC_OUTPUT_PATH, url); if (StringUtils.isNotBlank(url)) { ExecutionReporter.openExecutionSummaryReport(url); } } @@ -953,7 +953,7 @@ protected void onExecutionComplete(String runId, ExecutionSummary summary) { // upload junit xml if (FileUtil.isFileReadable(junitReport, 100)) { String url = otc.importToS3(junitReport, outputDir, true); - ConsoleUtils.log("JUnit XML output for this execution export to " + url); + ConsoleUtils.log("JUnit XML output for this execution exported to " + url); System.setProperty(JUNIT_XML_LOCATION, url); } } catch (IOException e) { diff --git a/src/main/java/org/nexial/core/excel/Excel.java b/src/main/java/org/nexial/core/excel/Excel.java index ff0fa0731..89f04981f 100755 --- a/src/main/java/org/nexial/core/excel/Excel.java +++ b/src/main/java/org/nexial/core/excel/Excel.java @@ -333,18 +333,15 @@ public void setRowValues(ExcelAddress addr, List values, String styleNam public void setLinkCell(ExcelAddress addr, String link, String text, String styleName, float rowHeight) { assert addr != null; assert text != null; - // assert styleConfig != null; workbook.setMissingCellPolicy(CREATE_NULL_AS_BLANK); - // XSSFCellStyle cellStyle = StyleDecorator.decorate(newCellStyle(), createFont(), styleConfig); - XSSFCellStyle cellStyle = commonStyles.get(styleName); int startRow = addr.getRowStartIndex(); if (sheet.getRow(startRow) == null) { sheet.createRow(startRow); } XSSFRow row = sheet.getRow(startRow); XSSFCell cell = row.getCell(addr.getColumnStartIndex()); - cell.setCellStyle(cellStyle); + cell.setCellStyle(commonStyles.get(styleName)); row.setHeightInPoints(rowHeight); if (StringUtils.isNotBlank(link)) { diff --git a/src/main/java/org/nexial/core/model/ExecutionResultHelper.java b/src/main/java/org/nexial/core/model/ExecutionResultHelper.java index 94e7dad5c..730057c87 100644 --- a/src/main/java/org/nexial/core/model/ExecutionResultHelper.java +++ b/src/main/java/org/nexial/core/model/ExecutionResultHelper.java @@ -172,6 +172,10 @@ protected static int handleNestedMessages(Worksheet worksheet, ExecutionSummary int messageCount = nestedMessages.size(); for (int i = 0; i < messageCount; i++) { NestedMessage nestedMessage = nestedMessages.get(i); + + // nested screen capture will add to new row (after test step) + // step output will output to same row as test step + if (nestedMessage instanceof StepOutput) { addScreenshotLink(excelSheet.getRow(step.getRowIndex()), linkStyle, (StepOutput) nestedMessage); } else { diff --git a/src/main/kotlin/org/nexial/core/plugins/db/RdbmsCommand.kt b/src/main/kotlin/org/nexial/core/plugins/db/RdbmsCommand.kt index 967ddd67d..8c07a6654 100755 --- a/src/main/kotlin/org/nexial/core/plugins/db/RdbmsCommand.kt +++ b/src/main/kotlin/org/nexial/core/plugins/db/RdbmsCommand.kt @@ -24,7 +24,8 @@ import org.apache.commons.lang3.StringUtils import org.nexial.commons.utils.FileUtil import org.nexial.commons.utils.TextUtils import org.nexial.core.NexialConst.* -import org.nexial.core.NexialConst.Rdbms.* +import org.nexial.core.NexialConst.Rdbms.CSV_ROW_SEP +import org.nexial.core.NexialConst.Rdbms.DAO_PREFIX import org.nexial.core.model.ExecutionContext import org.nexial.core.model.StepResult import org.nexial.core.plugins.base.BaseCommand @@ -61,7 +62,7 @@ class RdbmsCommand : BaseCommand() { // requires(dataAccess.validSQL(query), "invalid sql", sql); val result = dataAccess.execute(query, resolveDao(db)) ?: return StepResult.fail( - "FAILED TO EXECUTE SQL '$sql': no result found") + "FAILED TO EXECUTE SQL '$sql': no result found") context.setData(`var`, result) log("executed query in ${result.elapsedTime} ms with " + @@ -202,6 +203,7 @@ class RdbmsCommand : BaseCommand() { if (!db.startsWith(NAMESPACE)) log("found $qualifiedSqlCount qualified query(s) to execute") msgPrefix = "executed $qualifiedSqlCount SQL(s);" + val testStep = context.currentTestStep for (sqlComponent in qualifiedSqlList) { val sql = context.replaceTokens(StringUtils.trim(sqlComponent.sql)) @@ -221,12 +223,19 @@ class RdbmsCommand : BaseCommand() { if (result.hasError()) log("ERROR found while executing $printableSql: ${result.error}") - if (FileUtil.isFileReadable(output, 3)) addLinkRef(null, outFile, targetFile.absolutePath) + if (FileUtil.isFileReadable(output, 3)) { + addLinkRef("result saved as $outFile", outFile, targetFile.absolutePath) + } log("executed $printableSql in ${result.elapsedTime} ms with " + if (result.hasError()) "ERROR ${result.error}" else "${result.rowCount} row(s)") - resultToJson(result, StringUtils.substringBeforeLast(output, ".") + ".json") + val jsonOutput = resultToJson(result, StringUtils.substringBeforeLast(output, ".") + ".json") + if (FileUtil.isFileReadable(jsonOutput, 3)) { + addLinkRef("result metadata saved as ${jsonOutput.name}", + jsonOutput.name, + jsonOutput.absolutePath) + } } else { // not saving result anywhere since this SQL is not mapped to any variable log("executing $printableSql without saving its result") @@ -246,6 +255,7 @@ class RdbmsCommand : BaseCommand() { requiresNotBlank(output, "invalid output", output) val outputFile = if (!StringUtils.endsWithIgnoreCase(output, ".csv")) "$output.csv" else output + val targetFile = File(outputFile) val dao = resolveDao(db) @@ -255,13 +265,22 @@ class RdbmsCommand : BaseCommand() { // so for that reason, we are no longer insisting on the use of standard ANSI sql // requires(dataAccess.validSQL(query), "invalid sql", sql); - val result = dataAccess.execute(query, dao, File(outputFile)) ?: return StepResult.fail( - "FAILED TO EXECUTE SQL '$sql': no result found") + val result = dataAccess.execute(query, dao, targetFile) ?: return StepResult.fail( + "FAILED TO EXECUTE SQL '$sql': no result") log("executed query in ${result.elapsedTime} ms with " + if (result.hasError()) "ERROR ${result.error}" else "${result.rowCount} row(s)") - resultToJson(result, StringUtils.substringBeforeLast(outputFile, ".") + ".json") + if (FileUtil.isFileReadable(targetFile, 3)) { + addLinkRef("result saved as $outputFile", targetFile.name, targetFile.absolutePath) + } + + val jsonOutput = resultToJson(result, StringUtils.substringBeforeLast(outputFile, ".") + ".json") + if (FileUtil.isFileReadable(jsonOutput, 3)) { + addLinkRef("result metadata saved as ${jsonOutput.name}", + jsonOutput.name, + jsonOutput.absolutePath) + } return StepResult.success("executed SQL '$sql'; stored result to '$outputFile'") } catch (e: IOException) { return StepResult.fail("Error when executing '$sql': ${e.message}") @@ -315,7 +334,9 @@ class RdbmsCommand : BaseCommand() { } @Throws(IOException::class) - private fun resultToJson(result: JdbcResult, output: String) { - FileUtils.writeStringToFile(File(output), GSON.toJson(result), DEF_FILE_ENCODING) + private fun resultToJson(result: JdbcResult, output: String): File { + val file = File(output) + FileUtils.writeStringToFile(file, GSON.toJson(result), DEF_FILE_ENCODING) + return file } } diff --git a/src/main/resources/org/nexial/core/reports/browser-metrics.html b/src/main/resources/org/nexial/core/reports/browser-metrics.html index efa0a5225..5eafa1388 100644 --- a/src/main/resources/org/nexial/core/reports/browser-metrics.html +++ b/src/main/resources/org/nexial/core/reports/browser-metrics.html @@ -17,16 +17,16 @@ } - - - - + + + + - - - - - + + + + + Browser Performance Metrics diff --git a/src/main/resources/org/nexial/core/reports/project-inspector-local.html b/src/main/resources/org/nexial/core/reports/project-inspector-local.html index 9a13d9e2d..f3cb1df2b 100644 --- a/src/main/resources/org/nexial/core/reports/project-inspector-local.html +++ b/src/main/resources/org/nexial/core/reports/project-inspector-local.html @@ -2,7 +2,7 @@ - + - - - - + + + + - - - - - + + + + + diff --git a/template/nexial-macro.xlsx b/template/nexial-macro.xlsx index ba41fc877..7d28a96ad 100644 Binary files a/template/nexial-macro.xlsx and b/template/nexial-macro.xlsx differ diff --git a/template/nexial-script.xlsx b/template/nexial-script.xlsx index 422fb8e2a..2f8a2f068 100644 Binary files a/template/nexial-script.xlsx and b/template/nexial-script.xlsx differ