From 05b9682ff2861597057a90c8422b0f91d5eec84e Mon Sep 17 00:00:00 2001 From: Benjamin Bischoff <5775857+bischoffdev@users.noreply.github.com> Date: Mon, 6 Jan 2025 14:59:11 +0100 Subject: [PATCH] 3.10.0 (#365) * version bump, changelog, dagger update * removed console logs * started refactoring status consolidation * 3.10.0 --- CHANGELOG.md | 24 +++++++++++++ .../cluecumber/core/CluecumberCore.java | 8 ++--- engine/pom.xml | 4 +-- .../cluecumber/engine/CluecumberEngine.java | 7 ++-- .../engine/constants/ChartConfiguration.java | 25 +++++-------- .../cluecumber/engine/constants/Settings.java | 8 ----- .../cluecumber/engine/constants/Status.java | 32 +++++++++++++---- .../cluecumber/engine/json/pojo/Element.java | 30 +++++++++------- .../cluecumber/engine/json/pojo/Step.java | 30 +++++++++++++--- .../resources/template/macros/navigation.ftl | 4 ++- .../main/resources/template/snippets/js.ftl | 5 --- .../engine/json/pojo/ElementTest.java | 35 ++++++++++--------- examples/core-example/pom.xml | 2 +- examples/maven-example/pom.xml | 2 +- .../cluecumber/maven/CluecumberMaven.java | 1 + pom.xml | 6 ++-- 16 files changed, 139 insertions(+), 84 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8de35ca2..c991c393 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. Back to [Readme](README.md). +## [3.10.0] - 2025-01-06 + +### Added + +* Step and scenario results are now cached to speed up report generation + +### Fixed + +* Unnecessary console logs for dark mode feature (#363) +* Step was reported as passed when a step hook failed (#364) +* Include Hooks in All Steps report to track failures related to Hooks (#364) +* Fixed absolute path to the finished report in the console log + +### Changed + +* Strict adherence to the official cucumber guidelines for scenario states +* Google Dagger updated to `2.54` +* Freemarker updated to `2.3.33` +* Javadoc updated to `3.11.2` +* JUnit Jupiter updated to `5.11.4` +* Mockito updated to `5.15.2` + ## [3.9.0] - 2024-11-05 ### Fixed @@ -940,6 +962,8 @@ the core component is now the reporting engine that is the base for other forms Initial project version on GitHub and Maven Central. +[3.10.0]: https://github.com/trivago/cluecumber-report-plugin/tree/v3.10.0 + [3.9.0]: https://github.com/trivago/cluecumber-report-plugin/tree/v3.9.0 [3.8.2]: https://github.com/trivago/cluecumber-report-plugin/tree/v3.8.2 diff --git a/core/src/main/java/com/trivago/cluecumber/core/CluecumberCore.java b/core/src/main/java/com/trivago/cluecumber/core/CluecumberCore.java index 3c46f590..dbaf1c67 100644 --- a/core/src/main/java/com/trivago/cluecumber/core/CluecumberCore.java +++ b/core/src/main/java/com/trivago/cluecumber/core/CluecumberCore.java @@ -215,9 +215,9 @@ public Builder setCustomStatusColorSkipped(final String customStatusColorSkipped } /** - * Whether to expand sub sections or not. + * Whether to expand subsections or not. * - * @param expandSubSections If true, sub sections will be expanded. + * @param expandSubSections If true, subsections will be expanded. * @return The {@link Builder}. */ public Builder setExpandSubSections(final boolean expandSubSections) { @@ -237,7 +237,7 @@ public Builder setExpandAttachments(final boolean expandAttachments) { } /** - * Whether to expand stepoutputs or not. + * Whether to expand step outputs or not. * * @param expandOutputs If true, outputs will be expanded. * @return The {@link Builder}. @@ -325,7 +325,7 @@ public Builder setStartPage(final Settings.StartPage startPage) { } /** - * Set a custom page tite for the report. + * Set a custom page title for the report. * * @param customPageTitle The custom page title. * @return The {@link Builder}. diff --git a/engine/pom.xml b/engine/pom.xml index b6456d5b..f59ae2be 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -30,10 +30,10 @@ 11 UTF-8 2.8.0-M1 - 2.3.33 + 2.3.34 1.9.0 2.11.0 - 2.52 + 2.54 1.5.0 1.1.0 0.9.1 diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/CluecumberEngine.java b/engine/src/main/java/com/trivago/cluecumber/engine/CluecumberEngine.java index a6c9d507..844c3ead 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/CluecumberEngine.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/CluecumberEngine.java @@ -32,6 +32,7 @@ import com.trivago.cluecumber.engine.rendering.pages.renderering.RenderingUtils; import javax.inject.Inject; +import java.io.File; import java.nio.file.Path; import java.util.LinkedHashMap; import java.util.List; @@ -138,9 +139,11 @@ public void build( elementMultipleRunsPreProcessor.addMultipleRunsInformationToScenarios(allScenariosPageCollection.getReports()); } reportGenerator.generateReport(allScenariosPageCollection); + String absoluteReportPath = new File( + propertyManager.getGeneratedHtmlReportDirectory(), + Settings.START_PAGE + Settings.HTML_FILE_EXTENSION).getAbsolutePath(); logger.info( - "=> Cluecumber Report: file:///" + propertyManager.getGeneratedHtmlReportDirectory() + "/" + - Settings.START_PAGE + Settings.HTML_FILE_EXTENSION, + "=> Cluecumber Report: file:///" + absoluteReportPath, DEFAULT, COMPACT, MINIMAL diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/constants/ChartConfiguration.java b/engine/src/main/java/com/trivago/cluecumber/engine/constants/ChartConfiguration.java index 309116e5..2fa26c2e 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/constants/ChartConfiguration.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/constants/ChartConfiguration.java @@ -23,15 +23,14 @@ import javax.inject.Singleton; /** - * This stores the colors and type of a report chart. + * This stores the colors and type of report chart. */ @Singleton public class ChartConfiguration { - private final PropertyManager propertyManager; - private String passedColorRgbaString; - private String failedColorRgbaString; - private String skippedColorRgbaString; + private final String passedColorRgbaString; + private final String failedColorRgbaString; + private final String skippedColorRgbaString; /** * Constructor for dependency injection. @@ -39,8 +38,11 @@ public class ChartConfiguration { * @param propertyManager The {@link PropertyManager} instance. */ @Inject - public ChartConfiguration(final PropertyManager propertyManager) { - this.propertyManager = propertyManager; + public ChartConfiguration( + final PropertyManager propertyManager) { + this.failedColorRgbaString = getRgbaColorStringFromHex(propertyManager.getCustomStatusColorFailed()); + this.passedColorRgbaString = getRgbaColorStringFromHex(propertyManager.getCustomStatusColorPassed()); + this.skippedColorRgbaString = getRgbaColorStringFromHex(propertyManager.getCustomStatusColorSkipped()); } /** @@ -66,9 +68,6 @@ public String getColorRgbaStringByStatus(final Status status) { * @return The RGBA color. */ public String getPassedColorRgbaString() { - if (passedColorRgbaString == null) { - passedColorRgbaString = getRgbaColorStringFromHex(propertyManager.getCustomStatusColorPassed()); - } return passedColorRgbaString; } @@ -78,9 +77,6 @@ public String getPassedColorRgbaString() { * @return The RGBA color. */ public String getFailedColorRgbaString() { - if (failedColorRgbaString == null) { - failedColorRgbaString = getRgbaColorStringFromHex(propertyManager.getCustomStatusColorFailed()); - } return failedColorRgbaString; } @@ -90,9 +86,6 @@ public String getFailedColorRgbaString() { * @return The RGBA color. */ public String getSkippedColorRgbaString() { - if (skippedColorRgbaString == null) { - skippedColorRgbaString = getRgbaColorStringFromHex(propertyManager.getCustomStatusColorSkipped()); - } return skippedColorRgbaString; } diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/constants/Settings.java b/engine/src/main/java/com/trivago/cluecumber/engine/constants/Settings.java index 828437f9..f6377dc2 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/constants/Settings.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/constants/Settings.java @@ -67,14 +67,6 @@ public Settings() { * The first part of the name of scenario detail pages. */ public static final String SCENARIO_DETAIL_PAGE_FRAGMENT = "/" + SCENARIO_DETAIL_PAGE_PATH + "/scenario_"; - /** - * The folder of the scenario rerun pages. - */ - public final static String SCENARIO_RERUN_PAGE_PATH = "scenario-detail"; - /** - * The first part of the name of scenario rerun pages. - */ - public static final String SCENARIO_RERUN_PAGE_FRAGMENT = "/" + SCENARIO_RERUN_PAGE_PATH + "/scenario_"; /** * The name of the tag summary page. */ diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/constants/Status.java b/engine/src/main/java/com/trivago/cluecumber/engine/constants/Status.java index 5502658a..c1aad474 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/constants/Status.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/constants/Status.java @@ -31,6 +31,7 @@ package com.trivago.cluecumber.engine.constants; import java.util.Arrays; +import java.util.Iterator; import java.util.List; import java.util.Set; @@ -38,10 +39,6 @@ * Enum to manage all states for steps and scenarios. */ public enum Status { - /** - * Passed status. - */ - PASSED("passed"), /** * Failed status. */ @@ -61,7 +58,15 @@ public enum Status { /** * Ambiguous status. */ - AMBIGUOUS("ambiguous"); + AMBIGUOUS("ambiguous"), + /** + * Passed status. + */ + PASSED("passed"), + /** + * Ambiguous unused. + */ + UNUSED("unused"); /** * The three basic states: passed, failed and skipped. @@ -102,8 +107,9 @@ public Status basicStatus() { /** * Return the highest status from the given list of states. + * * @param allStates The list of states. - * @return The status string. + * @return The highest status. */ public static Status getHighestBasicState(Set allStates) { return BASIC_STATES.stream().filter( @@ -111,6 +117,20 @@ public static Status getHighestBasicState(Set allStates) { ).findFirst().orElse(FAILED); } + /** + * Get the highest state from all states. + * + * @param allStates The list of states. + * @return The highest status. + */ + public static Status getHighestState(Set allStates) { + return Arrays.stream(values()) + .filter(state -> allStates.stream() + .anyMatch(allState -> allState == state)) + .findFirst() + .orElse(FAILED); + } + /** * Return the status string from this enum. * diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Element.java b/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Element.java index 3cb21e11..9140b899 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Element.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Element.java @@ -51,6 +51,7 @@ public class Element { private transient int featureIndex = 0; private transient int scenarioIndex = 0; private transient boolean failOnPendingOrUndefined = false; + private Status status; /** * Default constructor. @@ -369,22 +370,25 @@ public boolean isSkipped() { * @return The overall status. */ public Status getStatus() { + if (status != null) { + return status; + } + Set allStates = before.stream().map(ResultMatch::getStatus).collect(Collectors.toSet()); - backgroundSteps.stream().map(ResultMatch::getStatus).forEach(allStates::add); - steps.forEach(step -> step.getBefore().forEach(result -> allStates.add(result.getStatus()))); - steps.stream().map(ResultMatch::getStatus).forEach(allStates::add); - steps.forEach(step -> step.getAfter().forEach(result -> allStates.add(result.getStatus()))); + backgroundSteps.stream().map(Step::getStatus).forEach(allStates::add); + steps.stream().map(Step::getStatus).forEach(allStates::add); after.stream().map(ResultMatch::getStatus).forEach(allStates::add); if (allStates.isEmpty()) { - return Status.SKIPPED; - } - - if (failOnPendingOrUndefined && (allStates.contains(Status.PENDING) || allStates.contains(Status.UNDEFINED))) { - return Status.FAILED; + status = Status.SKIPPED; + } else if (failOnPendingOrUndefined && (allStates.contains(Status.PENDING) || + allStates.contains(Status.UNDEFINED))) { + status = Status.FAILED; + } else { + status = Status.getHighestBasicState(allStates); } - return Status.getHighestBasicState(allStates); + return status; } /** @@ -541,9 +545,9 @@ private int getNumberOfStepsWithStatus(final Status status) { */ public long getTotalDuration() { return before.stream().mapToLong(beforeStep -> beforeStep.getResult().getDuration()).sum() + - backgroundSteps.stream().mapToLong(Step::getTotalDuration).sum() + - steps.stream().mapToLong(Step::getTotalDuration).sum() + - after.stream().mapToLong(afterStep -> afterStep.getResult().getDuration()).sum(); + backgroundSteps.stream().mapToLong(Step::getTotalDuration).sum() + + steps.stream().mapToLong(Step::getTotalDuration).sum() + + after.stream().mapToLong(afterStep -> afterStep.getResult().getDuration()).sum(); } /** diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Step.java b/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Step.java index d125ae39..73dacc5f 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Step.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Step.java @@ -16,13 +16,10 @@ package com.trivago.cluecumber.engine.json.pojo; import com.google.gson.annotations.SerializedName; +import com.trivago.cluecumber.engine.constants.Status; import com.trivago.cluecumber.engine.rendering.pages.renderering.RenderingUtils; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -44,6 +41,7 @@ public class Step extends ResultMatch { private boolean hasSubSections = false; private static final Map stepMatchToNameWithArgumentPlaceholders = new HashMap<>(); + private Status status; /** * Default constructor. @@ -52,6 +50,28 @@ public Step() { // Default constructor } + /** + * Overwritten getStatus method so that hook statuses are considered as well + * + * @return The highest status of the step and its hooks. + */ + public Status getStatus() { + if (status != null) { + return status; + } + + Set allStatuses = new HashSet<>(); + allStatuses.add(super.getStatus()); + before.stream() + .map(beforeStep -> Status.fromString(beforeStep.getResult().getStatus())) + .forEach(allStatuses::add); + after.stream() + .map(afterStep -> Status.fromString(afterStep.getResult().getStatus())) + .forEach(allStatuses::add); + status = Status.getHighestState(allStatuses); + return status; + } + /** * Check if there are before or after step hooks with content. * diff --git a/engine/src/main/resources/template/macros/navigation.ftl b/engine/src/main/resources/template/macros/navigation.ftl index 0d1d77e1..2244e472 100644 --- a/engine/src/main/resources/template/macros/navigation.ftl +++ b/engine/src/main/resources/template/macros/navigation.ftl @@ -22,6 +22,7 @@ limitations under the License. diff --git a/engine/src/main/resources/template/snippets/js.ftl b/engine/src/main/resources/template/snippets/js.ftl index a6aa2c0e..35ca10e6 100644 --- a/engine/src/main/resources/template/snippets/js.ftl +++ b/engine/src/main/resources/template/snippets/js.ftl @@ -139,14 +139,9 @@ limitations under the License. function updateDarkLightModeButton(isDarkMode) { const button = document.getElementById('dark-light-mode-switch'); - console.log("BUTTON: " + button); - console.log("isDarkMode: " + isDarkMode); - console.log("button.textContent: " + button.textContent); button.textContent = isDarkMode ? 'Light Mode' : 'Dark Mode'; } - console.log("The button is " + document.getElementById('dark-light-mode-switch')) - function resizeIframe(iframe) { setInterval(function () { try { diff --git a/engine/src/test/java/com/trivago/cluecumber/engine/json/pojo/ElementTest.java b/engine/src/test/java/com/trivago/cluecumber/engine/json/pojo/ElementTest.java index be8c9348..a53c4d47 100644 --- a/engine/src/test/java/com/trivago/cluecumber/engine/json/pojo/ElementTest.java +++ b/engine/src/test/java/com/trivago/cluecumber/engine/json/pojo/ElementTest.java @@ -39,7 +39,7 @@ public void getPassedStatusTest() { element.setSteps(steps); Status status = element.getStatus(); - assertEquals(status, Status.PASSED); + assertEquals(Status.PASSED, status); assertTrue(element.isPassed()); } @@ -60,7 +60,7 @@ public void skippedStatusOnPassedAndSkippedStepsTest() { element.setSteps(steps); Status status = element.getStatus(); - assertEquals(status, Status.SKIPPED); + assertEquals(Status.SKIPPED, status); } @Test @@ -88,7 +88,7 @@ public void failedStatusOnFailedBeforeHookTest() { element.setSteps(steps); Status status = element.getStatus(); - assertEquals(status, Status.FAILED); + assertEquals(Status.FAILED, status); } @Test @@ -103,6 +103,7 @@ public void failedStatusOnFailedAfterHookTest() { List steps = new ArrayList<>(); Step step = new Step(); + step.setName("Test step"); Result result = new Result(); result.setStatus("passed"); step.setResult(result); @@ -115,8 +116,7 @@ public void failedStatusOnFailedAfterHookTest() { steps.add(step); element.setSteps(steps); - Status status = element.getStatus(); - assertEquals(status, Status.FAILED); + assertEquals(Status.FAILED, element.getStatus()); } @Test @@ -173,7 +173,7 @@ public void failedStatusOnFailedBeforeStepHookTest() { element.setSteps(steps); Status status = element.getStatus(); - assertEquals(status, Status.FAILED); + assertEquals(Status.FAILED, status); } @Test @@ -187,7 +187,7 @@ public void getFailedStatusTest() { element.setSteps(steps); Status status = element.getStatus(); - assertEquals(status, Status.FAILED); + assertEquals(Status.FAILED, status); assertTrue(element.isFailed()); } @@ -210,6 +210,7 @@ public void getUndefinedStatusTest() { public void getUndefinedStatusWithFailureOnUndefinedSetTest() { List steps = new ArrayList<>(); Step step = new Step(); + step.setName("Test step"); Result result = new Result(); result.setStatus("undefined"); step.setResult(result); @@ -256,8 +257,8 @@ public void totalDurationTest() { afterSteps.add(after); element.setAfter(afterSteps); - assertEquals(element.getTotalDuration(), 10117667785L); - assertEquals(element.returnTotalDurationString(), "0m 10s 117ms"); + assertEquals(10117667785L, element.getTotalDuration()); + assertEquals("0m 10s 117ms", element.returnTotalDurationString()); } @Test @@ -292,10 +293,10 @@ public void stepSummaryTest() { element.setSteps(steps); - assertEquals(element.getTotalNumberOfSteps(), 6); - assertEquals(element.getTotalNumberOfPassedSteps(), 3); - assertEquals(element.getTotalNumberOfFailedSteps(), 1); - assertEquals(element.getTotalNumberOfSkippedSteps(), 2); + assertEquals(6, element.getTotalNumberOfSteps()); + assertEquals(3, element.getTotalNumberOfPassedSteps()); + assertEquals(1, element.getTotalNumberOfFailedSteps()); + assertEquals(2, element.getTotalNumberOfSkippedSteps()); } @Test @@ -367,7 +368,7 @@ public void hasStepHooksAfterTest() { @Test public void getStartDateTimeTest() { element.setStartTimestamp("2019-04-11T08:00:23.668Z"); - assertEquals(element.getStartDateTime().format(DateTimeFormatter.ISO_DATE_TIME), "2019-04-11T08:00:23.668Z"); + assertEquals("2019-04-11T08:00:23.668Z", element.getStartDateTime().format(DateTimeFormatter.ISO_DATE_TIME)); } @Test @@ -380,7 +381,7 @@ public void getEndDateTimeTest() { before.setResult(beforeResult); beforeSteps.add(before); element.setBefore(beforeSteps); - assertEquals(element.getEndDateTime().format(DateTimeFormatter.ISO_DATE_TIME), "2019-04-11T10:47:03.668Z"); + assertEquals("2019-04-11T10:47:03.668Z", element.getEndDateTime().format(DateTimeFormatter.ISO_DATE_TIME)); } @Test @@ -398,7 +399,7 @@ public void getEndDateTimeNoStartDateTest() { @Test public void getStartDateStringTest() { element.setStartTimestamp("2019-04-11T08:00:23.668Z"); - assertEquals(element.getStartDateString(), "2019-04-11"); + assertEquals("2019-04-11", element.getStartDateString()); } @Test @@ -417,7 +418,7 @@ public void getEndDateStringTest() { before.setResult(beforeResult); beforeSteps.add(before); element.setBefore(beforeSteps); - assertEquals(element.getEndDateString(), "2019-04-11"); + assertEquals("2019-04-11", element.getEndDateString()); } @Test diff --git a/examples/core-example/pom.xml b/examples/core-example/pom.xml index 7e7a3030..210eb1df 100644 --- a/examples/core-example/pom.xml +++ b/examples/core-example/pom.xml @@ -6,7 +6,7 @@ blog.softwaretester core-example - 3.9.0 + 3.10.0 jar diff --git a/examples/maven-example/pom.xml b/examples/maven-example/pom.xml index 8e3f8389..c9f19523 100644 --- a/examples/maven-example/pom.xml +++ b/examples/maven-example/pom.xml @@ -6,7 +6,7 @@ blog.softwaretester maven-example - 3.9.0 + 3.10.0 pom diff --git a/maven/src/main/java/com/trivago/cluecumber/maven/CluecumberMaven.java b/maven/src/main/java/com/trivago/cluecumber/maven/CluecumberMaven.java index 3a973a18..ade0e57f 100644 --- a/maven/src/main/java/com/trivago/cluecumber/maven/CluecumberMaven.java +++ b/maven/src/main/java/com/trivago/cluecumber/maven/CluecumberMaven.java @@ -29,6 +29,7 @@ /** * The main plugin class. */ +@SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal"}) @Mojo(name = "reporting", requiresProject = false, threadSafe = true) public final class CluecumberMaven extends AbstractMojo { diff --git a/pom.xml b/pom.xml index 9260283a..60cd6a0d 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ - 3.9.0 + 3.10.0 11 11 11 @@ -33,8 +33,8 @@ 3.11.0 3.2.7 1.7.0 - 5.11.3 - 5.14.2 + 5.11.4 + 5.15.2 3.5.2 3.3.1 3.11.1