Skip to content

Commit

Permalink
3.11.0 (#372)
Browse files Browse the repository at this point in the history
* dependency updates, copy to clipboard

* corrected readme java version

* added missing clipboard functionality

* custom logo

* documentation

* fixed image path

* fixed typo

* feature tree wip

* tree view with directories

* sorted tree

* Exception pages

* changelog
  • Loading branch information
bischoffdev authored Feb 19, 2025
1 parent f570d17 commit 4b233aa
Show file tree
Hide file tree
Showing 44 changed files with 844 additions and 114 deletions.
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

Back to [Readme](README.md).

## [3.11.0] - 2025-02-19

### Added

* "Copy to clipboard" button for step outputs, docstrings, text attachments and exception messages (#371)
* Custom logo capability (#367)
* New failures page that shows scenarios based on their exception (#362)
* Tree view now takes the directory structure into account (#366)

### Changed

* Updated junit to `5.12.0-RC2`
* Updated javadoc to `3.11.2`
* Updated dagger to `2.55`
* Updated gson to `2.12.1`

### Fixed

* Correct pluralization for zero elements everywhere

## [3.10.0] - 2025-01-06

### Added
Expand Down Expand Up @@ -962,6 +982,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.11.0]: https://github.com/trivago/cluecumber-report-plugin/tree/v3.11.0

[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
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ Cluecumber generates the following report pages:
* __Scenario Details__: all steps, hooks, stack traces and attachments of a single scenario
* __All Features__: an overview of all features
* __All Tags__: all used tags in scenarios, features and example tables including their individual status information
* __All Exceptions__: all exception types that occurred in the test suite
* __All Steps__: all steps in use including their individual status information
* __Scenarios by Tag__: all scenarios including a specific tag
* __Scenarios by Feature__: all scenarios belonging to a specific feature
* __Scenario by Step__: all scenarios that include a specific step
* __Scenario by Exception__: all scenarios that failed with a specific exception type
* __Tree View__: all features and scenarios in a tree for an easy overview of the test suite

## Changelog
Expand All @@ -48,7 +50,7 @@ All changes are documented in the [full changelog](CHANGELOG.md).

## Building

Cluecumber requires Java >= 17 and Maven >= 3.6.3.
Cluecumber requires Java >= 11 and Maven >= 3.6.3.
It is available in [Maven central](https://central.sonatype.com/search?q=g%3Acom.trivago.rta++a%3Acluecumber-core+a%3Acluecumber-maven&smo=true).

## Star History
Expand Down
15 changes: 14 additions & 1 deletion core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ _Clear and concise JVM reporting for the Cucumber BDD JSON format_
- [Defining the report start page](#defining-the-report-start-page)
- [Defining a custom report title](#defining-a-custom-report-title)
- [Defining a custom CSS file](#defining-a-custom-css-file)
- [Defining a custom logo](#defining-a-custom-logo)
- [Defining a custom favicon](#defining-a-custom-favicon)
- [Defining custom passed, skipped and failed colors](#defining-custom-passed-skipped-and-failed-colors)
- [Enabling a compact view of multiple runs of the same scenarios](#enabling-a-compact-view-of-multiple-runs-of-the-same-scenarios)
Expand All @@ -45,7 +46,7 @@ _Clear and concise JVM reporting for the Cucumber BDD JSON format_
<dependency>
<groupId>com.trivago.rta</groupId>
<artifactId>cluecumber-core</artifactId>
<version>3.5.1</version>
<version>3.11.0</version>
</dependency>
```

Expand Down Expand Up @@ -346,6 +347,18 @@ Likewise, if you want to hide elements from the report, you can also add this to
}
```

## Defining a custom logo

The logo is displayed on every page in the top right corner and can be customized by setting the `customLogo` property. This must be
a png file. It is automatically set to a maximum width of 300px and/or height of 100px if its size exceeds these values.

![Custom Logo](../documentation/img/custom_logo.jpg)

```java
new CluecumberCore.Builder()
.setCustomLogo("custom/logo.png")
.build().generateReports(jsonDirectory, reportDirectory);
```

## Defining a custom favicon

Expand Down
13 changes: 13 additions & 0 deletions core/src/main/java/com/trivago/cluecumber/core/CluecumberCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ private CluecumberCore(final Builder builder) throws CluecumberException {
cluecumberEngine = DaggerCluecumberCoreGraph.create().getCluecumberEngine();
cluecumberEngine.setCustomCssFile(builder.customCssFile);
cluecumberEngine.setCustomFavicon(builder.customFavicon);
cluecumberEngine.setCustomLogo(builder.customLogo);
cluecumberEngine.setCustomNavigationLinks(builder.customNavigationLinks);
cluecumberEngine.setCustomPageTitle(builder.customPageTitle);
cluecumberEngine.setCustomParameters(builder.customParameters);
Expand Down Expand Up @@ -78,6 +79,7 @@ public void generateReports(final String jsonDirectory, final String reportDirec
public static class Builder {
private String customCssFile;
private String customFavicon;
private String customLogo;
private LinkedHashMap<String, String> customNavigationLinks;
private String customPageTitle;
private LinkedHashMap<String, String> customParameters;
Expand Down Expand Up @@ -137,6 +139,17 @@ public Builder setCustomFaviconFile(final String customFavicon) {
return this;
}

/**
* Custom logo to display in the page headers.
*
* @param customLogo The path to a logo png file.
* @return The {@link Builder}.
*/
public Builder setCustomLogoFile(final String customLogo) {
this.customLogo = customLogo;
return this;
}

/**
* Custom navigation links to display at the end of the default navigation.
*
Expand Down
Binary file added documentation/img/custom_logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions engine/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
<tinylog-impl.version>2.8.0-M1</tinylog-impl.version>
<freemarker.version>2.3.34</freemarker.version>
<gson-fire.version>1.9.0</gson-fire.version>
<gson.version>2.11.0</gson.version>
<dagger.version>2.54</dagger.version>
<gson.version>2.12.1</gson.version>
<dagger.version>2.55</dagger.version>
<property-aggregator.version>1.5.0</property-aggregator.version>
<properties-maven-plugin.version>1.1.0</properties-maven-plugin.version>
<openpojo.version>0.9.1</openpojo.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,19 @@ public void setCustomFavicon(final String customFavicon) throws MissingFileExcep
propertyManager.setCustomFaviconFile(customFavicon);
}

/**
* Custom logo image file to use for the report.
*
* @param customLogo The path to a logo file.
* @throws MissingFileException Thrown if the specified file does not exist.
*/
public void setCustomLogo(final String customLogo) throws MissingFileException {
if (customLogo == null) {
return;
}
propertyManager.setCustomLogoFile(customLogo);
}

/**
* Set a custom color for passed scenarios.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public Navigation() {
new Link("tag_summary", "pages/tag-summary.html", LinkType.INTERNAL),
new Link("step_summary", "pages/step-summary.html", LinkType.INTERNAL),
new Link("feature_summary", "pages/feature-summary.html", LinkType.INTERNAL),
new Link("exception_summary", "pages/exception-summary.html", LinkType.INTERNAL),
new Link("tree_view", "pages/tree-view.html", LinkType.INTERNAL)
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@ public Settings() {
* The first part of the name of scenario by tag pages.
*/
public static final String TAG_SCENARIO_PAGE_FRAGMENT = "/" + TAG_SCENARIO_PAGE_PATH + "/tag_";
/**
* The name of the exception summary page.
*/
public final static String EXCEPTION_SUMMARY_PAGE = "exception-summary";
/**
* The folder of the scenarios by exception pages.
*/
public static final String EXCEPTION_SCENARIO_PAGE_PATH = "exception-scenarios";
/**
* The first part of the name of scenario by exception pages.
*/
public static final String EXCEPTION_SCENARIO_PAGE_FRAGMENT = "/" + EXCEPTION_SCENARIO_PAGE_PATH + "/exception_";
/**
* The name of the step summary page.
*/
Expand Down Expand Up @@ -129,6 +141,10 @@ public enum StartPage {
* The tag overview page.
*/
ALL_TAGS(TAG_SUMMARY_PAGE),
/**
* The tag overview page.
*/
ALL_EXCEPTIONS(EXCEPTION_SUMMARY_PAGE),
/**
* The step overview page.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,18 +392,26 @@ public Status getStatus() {
}

/**
* Determine the first exception class in the stack trace to display on the scenario overview page.
* Get the first exception class in the stack trace to display
*
* @return The exception class string.
*/
public String getFirstExceptionClass() {
return getFirstExceptionSummary().split(":")[0].split(" ")[0].trim();
}

/**
* Determine the first exception summary in the stack trace to display on the scenario overview page.
*
* @return The exception class string.
*/
public String getFirstExceptionSummary() {
String firstException = getFirstException();
String exceptionClass = firstException.split("\n")[0].trim();

if (exceptionClass.isEmpty()) {
exceptionClass = "";
}

return exceptionClass;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public class PropertyManager {
private boolean expandPreviousScenarioRuns = false;
private String customCssFile;
private String customFaviconFile;
private String customLogoFile;
private String customParametersFile;
private Settings.CustomParamDisplayMode customParametersDisplayMode =
Settings.CustomParamDisplayMode.ALL_PAGES;
Expand Down Expand Up @@ -451,6 +452,32 @@ public void setCustomFaviconFile(final String customFaviconFile) throws MissingF
}
}

/**
* Get the custom logo file path.
*
* @return The path.
*/
public String getCustomLogoFile() {
return customLogoFile;
}

/**
* Set the custom logo file path.
*
* @param customLogoFile The path.
* @throws MissingFileException Thrown if the file is not found.
*/
public void setCustomLogoFile(final String customLogoFile) throws MissingFileException {
System.out.println("CUSTOM LOGO: " + customLogoFile);
this.customLogoFile = customLogoFile;
if (!isSet(customLogoFile)) {
return;
}
if (!fileIO.isExistingFile(customLogoFile)) {
throw new MissingFileException(customLogoFile + " (customLogoFile)");
}
}

/**
* Get the custom hex color for passed elements.
*
Expand Down Expand Up @@ -585,6 +612,9 @@ public void logProperties() {
if (isSet(customFaviconFile)) {
logger.info("- custom favicon file : " + customFaviconFile, DEFAULT);
}
if (isSet(customLogoFile)) {
logger.info("- custom logo file : " + customLogoFile, DEFAULT);
}

logger.info("- colors (passed, failed, skipped) : " +
customStatusColorPassed + ", " + customStatusColorFailed + ", " + customStatusColorSkipped, DEFAULT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public void generateReport(final AllScenariosPageCollection allScenariosPageColl
copyStaticReportAssets(reportDirectory);
copyCustomCss(reportDirectory);
copyCustomFavicon(reportDirectory);
copyCustomLogo(reportDirectory);

boolean redirectToFirstScenarioPage =
propertyManager.getStartPage() == Settings.StartPage.ALL_SCENARIOS &&
Expand Down Expand Up @@ -126,6 +127,7 @@ private void createDirectories(final String reportDirectory) throws PathCreation
fileSystemManager.createDirectory(pagesDirectory + Settings.SCENARIO_DETAIL_PAGE_PATH);
fileSystemManager.createDirectory(pagesDirectory + Settings.FEATURE_SCENARIOS_PAGE_PATH);
fileSystemManager.createDirectory(pagesDirectory + Settings.TAG_SCENARIO_PAGE_PATH);
fileSystemManager.createDirectory(pagesDirectory + Settings.EXCEPTION_SCENARIO_PAGE_PATH);
fileSystemManager.createDirectory(pagesDirectory + Settings.STEP_SCENARIO_PAGE_PATH);
}

Expand Down Expand Up @@ -161,6 +163,18 @@ private void copyCustomFavicon(final String reportDirectory) throws CluecumberEx
}
}

/**
* Copy custom logo to the specified target directory.
*/
private void copyCustomLogo(final String reportDirectory) throws CluecumberException {
String customLogo = propertyManager.getCustomLogoFile();
if (customLogo != null && !customLogo.isEmpty()) {
fileSystemManager.copyResource(customLogo, reportDirectory + "/img/logo.png");
} else {
copyFileFromJarToReportDirectory("/img/logo.png");
}
}

/**
* Copy all needed static report assets to the specified target directory.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright 2023 trivago N.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.trivago.cluecumber.engine.rendering.pages.pojos.pagecollections;

import com.trivago.cluecumber.engine.json.pojo.Report;
import com.trivago.cluecumber.engine.rendering.pages.pojos.ResultCount;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* Page collection for the exception overview page.
*/
public class AllExceptionsPageCollection extends ScenarioSummaryPageCollection {
private final Map<String, ResultCount> exceptionResultCounts = new HashMap<>();

/**
* Constructor.
*
* @param reports The {@link Report} list.
* @param pageTitle The page title.
*/
public AllExceptionsPageCollection(List<Report> reports, final String pageTitle) {
super(pageTitle);
calculateExceptionResultCounts(reports);
}

/**
* Get a map of {@link ResultCount} lists connected to tag names.
*
* @return a map of {@link ResultCount} lists with tags as keys.
*/
public Map<String, ResultCount> getExceptionResultCounts() {
return exceptionResultCounts;
}

/**
* Get all exceptions.
*
* @return The exception set.
*/
public Set<String> getExceptions() {
return exceptionResultCounts.keySet();
}

/**
* Get the number of exceptions.
*
* @return The count.
*/
public int getTotalNumberOfExceptions() {
return exceptionResultCounts.size();
}

/**
* Calculate the numbers of failures, successes and skips per exception.
*
* @param reports The {@link Report} list.
*/
private void calculateExceptionResultCounts(final List<Report> reports) {
if (reports == null) return;
reports.forEach(report -> report.getElements().forEach(element -> {
String exceptionClass = element.getFirstExceptionClass();
if (exceptionClass != null && !exceptionClass.isEmpty()) {
ResultCount exceptionResultCount = exceptionResultCounts.getOrDefault(exceptionClass, new ResultCount());
updateResultCount(exceptionResultCount, element.getStatus());
exceptionResultCounts.put(exceptionClass, exceptionResultCount);
addScenarioIndexByStatus(element.getStatus(), element.getScenarioIndex());
}
}));
}
}
Loading

0 comments on commit 4b233aa

Please sign in to comment.