diff --git a/CHANGELOG.md b/CHANGELOG.md index 007637da..8dca72bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,15 +7,25 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. Back to [Readme](README.md). -## [2.2.0] - UNRELEASED +## [2.2.0] - 2019-07-17 ### Added * Hide scenarios with matching status on the `Scenario Sequence` page when disabling a status in the diagram (#175) +* Clicking a pie chart slice toggles the according scenarios in `All Scenarios` and `Scenario Sequence` (#175) +* Logging can be configured via the `logLevel` property (#189) + +### Changed + +* Changed internal chart generation to simplify future chart features +* Scenario runtimes is now displayed in seconds in the `Scenario Detail` page graph (#193) +* Renamed y axis of `All Steps` page graph to `Number of Usages` (#193) ### Fixed * Wrong wording in `All Tags` page +* Wrong y axis scale labels in stacked bar charts +* Missing `All Features` navigation link ## [2.1.0] - 2019-06-25 @@ -510,6 +520,7 @@ steps with status `pending` or `undefined` (default value is `false`) (#74) Initial project version on GitHub and Maven Central. +[2.2.0]: https://github.com/trivago/cluecumber-report-plugin/tree/2.2.0 [2.1.1]: https://github.com/trivago/cluecumber-report-plugin/tree/2.1.1 [2.1.0]: https://github.com/trivago/cluecumber-report-plugin/tree/2.1.0 [2.0.1]: https://github.com/trivago/cluecumber-report-plugin/tree/2.0.1 diff --git a/README.md b/README.md index 87d16f14..9854482f 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,26 @@ This points to the root directory of the generated Cluecumber HTML report. ## Optional Configuration Parameters +### Plugin Logging + +By default, Cluecumber logs all information including + +* its own name and version +* all passed property values +* the generated report location + +This can be configured by passing the `logLevel` property: + +``` +default|compact|minimal|off +``` + +* _default_ will log all the mentioned information +* _compact_ will only log the source and target directories, plugin name and version and the generated report location +* _minimal_ will only log the generated report location +* _off_ will prevent any logging + + ### Add Custom Information to the Report #### Add Custom Information Using Properties diff --git a/example-project/pom.xml b/example-project/pom.xml index 1043f1da..03e21c86 100644 --- a/example-project/pom.xml +++ b/example-project/pom.xml @@ -6,7 +6,7 @@ de.benjamin-bischoff cluecumber-test-project - 2.1.0 + 2.2.0 UTF-8 @@ -45,9 +45,9 @@ - - - + #017FAF + #C94A38 + #F48F00 My Report @@ -66,7 +66,13 @@ - + + + + minimal + + + diff --git a/plugin-code/pom.xml b/plugin-code/pom.xml index 9a8b0d84..985142f7 100644 --- a/plugin-code/pom.xml +++ b/plugin-code/pom.xml @@ -6,7 +6,7 @@ com.trivago.rta cluecumber-report-plugin - 2.1.1 + 2.2.0 https://github.com/trivago/cluecumber-report-plugin Cluecumber Maven Plugin for Cucumber Reports diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/CluecumberReportPlugin.java b/plugin-code/src/main/java/com/trivago/cluecumber/CluecumberReportPlugin.java index 365c3d6b..9fa25fab 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/CluecumberReportPlugin.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/CluecumberReportPlugin.java @@ -34,6 +34,9 @@ import java.nio.file.Path; import java.util.List; +import static com.trivago.cluecumber.logging.CluecumberLogger.CluecumberLogLevel.COMPACT; +import static com.trivago.cluecumber.logging.CluecumberLogger.CluecumberLogLevel.DEFAULT; + /** * The main plugin class. */ @@ -81,16 +84,18 @@ public CluecumberReportPlugin( */ public void execute() throws CluecumberPluginException { // Initialize logger to be available outside the AbstractMojo class - logger.setMojoLogger(getLog()); + logger.initialize(getLog(), logLevel); if (skip) { - logger.info("Cluecumber report generation was skipped using the property."); + logger.info("Cluecumber report generation was skipped using the property.", + DEFAULT); return; } - logger.logSeparator(); - logger.info(String.format(" Cluecumber Report Maven Plugin, version %s", getClass().getPackage().getImplementationVersion())); - logger.logSeparator(); + logger.logInfoSeparator(DEFAULT); + logger.info(String.format(" Cluecumber Report Maven Plugin, version %s", getClass().getPackage() + .getImplementationVersion()), DEFAULT); + logger.logInfoSeparator(DEFAULT, COMPACT); super.execute(); @@ -105,14 +110,18 @@ public void execute() throws CluecumberPluginException { Report[] reports = jsonPojoConverter.convertJsonToReportPojos(jsonString); allScenariosPageCollection.addReports(reports); } catch (CluecumberPluginException e) { - logger.error("Could not parse JSON in file '" + jsonFilePath.toString() + "': " + e.getMessage()); + logger.warn("Could not parse JSON in file '" + jsonFilePath.toString() + "': " + e.getMessage()); } } elementIndexPreProcessor.addScenarioIndices(allScenariosPageCollection.getReports()); reportGenerator.generateReport(allScenariosPageCollection); logger.info( "=> Cluecumber Report: " + propertyManager.getGeneratedHtmlReportDirectory() + "/" + - PluginSettings.SCENARIO_SUMMARY_PAGE_PATH + PluginSettings.HTML_FILE_EXTENSION); + PluginSettings.SCENARIO_SUMMARY_PAGE_PATH + PluginSettings.HTML_FILE_EXTENSION, + DEFAULT, + COMPACT, + CluecumberLogger.CluecumberLogLevel.MINIMAL + ); } } diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/PropertyCollector.java b/plugin-code/src/main/java/com/trivago/cluecumber/PropertyCollector.java index 3542f9eb..495a172c 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/PropertyCollector.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/PropertyCollector.java @@ -95,6 +95,13 @@ public class PropertyCollector extends AbstractMojo { @Parameter(property = "reporting.customPageTitle") private String customPageTitle; + /** + * Optional log level to control what information is logged in the console. + * Allowed values: default, compact, minimal, off + */ + @Parameter(property = "parallel.logLevel", defaultValue = "default") + String logLevel; + @Inject public PropertyCollector(final PropertyManager propertyManager) { this.propertyManager = propertyManager; diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/constants/ChartConfiguration.java b/plugin-code/src/main/java/com/trivago/cluecumber/constants/ChartConfiguration.java index 390dba96..53c586e8 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/constants/ChartConfiguration.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/constants/ChartConfiguration.java @@ -1,3 +1,19 @@ +/* + * Copyright 2019 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.constants; import com.trivago.cluecumber.properties.PropertyManager; @@ -21,6 +37,17 @@ public ChartConfiguration(final PropertyManager propertyManager) { this.propertyManager = propertyManager; } + public String getColorRgbaStringByStatus(final Status status) { + switch (status) { + case FAILED: + return getFailedColorRgbaString(); + case SKIPPED: + return getSkippedColorRgbaString(); + default: + return getPassedColorRgbaString(); + } + } + public String getPassedColorRgbaString() { if (passedColorRgbaString == null) { passedColorRgbaString = getRgbaColorStringFromHex(propertyManager.getCustomStatusColorPassed()); diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/json/processors/ElementJsonPostProcessor.java b/plugin-code/src/main/java/com/trivago/cluecumber/json/processors/ElementJsonPostProcessor.java index b34f8690..a017c9a2 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/json/processors/ElementJsonPostProcessor.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/json/processors/ElementJsonPostProcessor.java @@ -106,7 +106,7 @@ private String saveEmbeddingToFileAndGetFilename(final Embedding embedding) { try { fileIO.writeContentToFile(dataBytes, propertyManager.getGeneratedHtmlReportDirectory() + "/attachments/" + filename); } catch (FileCreationException e) { - logger.error("Could not process image " + filename + " but will continue report generation..."); + logger.warn("Could not process image " + filename + " but will continue report generation..."); } embedding.encodeData(embedding.getData()); // Clear attachment data to reduce memory diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/logging/CluecumberLogger.java b/plugin-code/src/main/java/com/trivago/cluecumber/logging/CluecumberLogger.java index 18d943c8..b8496d4b 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/logging/CluecumberLogger.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/logging/CluecumberLogger.java @@ -19,25 +19,93 @@ import org.apache.maven.plugin.logging.Log; import javax.inject.Singleton; +import java.util.Arrays; @Singleton public class CluecumberLogger { private Log mojoLogger; + private CluecumberLogLevel currentLogLevel; - public void setMojoLogger(final Log mojoLogger) { + /** + * Set the mojo logger so it can be used in any class that injects a CluecumberLogger. + * + * @param mojoLogger The current {@link Log}. + * @param currentLogLevel the log level that the logger should react to. + */ + public void initialize(final Log mojoLogger, final String currentLogLevel) { this.mojoLogger = mojoLogger; + if (currentLogLevel == null) { + this.currentLogLevel = CluecumberLogLevel.DEFAULT; + return; + } + + try { + this.currentLogLevel = CluecumberLogLevel.valueOf(currentLogLevel.toUpperCase()); + } catch (IllegalArgumentException e) { + this.currentLogLevel = CluecumberLogLevel.DEFAULT; + warn("Log level " + currentLogLevel + " is unknown. Cluecumber will use 'default' logging."); + } + } + + public void logInfoSeparator(final CluecumberLogLevel... cluecumberLogLevels) { + info("------------------------------------------------------------------------", cluecumberLogLevels); + } + + /** + * Info logging based on the provided Cluecumber log levels. + * + * @param logString The {@link String} to be logged. + * @param cluecumberLogLevels The log levels ({@link CluecumberLogLevel} list) in which the message should be displayed. + */ + public void info(final CharSequence logString, CluecumberLogLevel... cluecumberLogLevels) { + log(LogLevel.INFO, logString, cluecumberLogLevels); + } + + /** + * Warn logging. This is always displayed unless logging is off. + * + * @param logString The {@link String} to be logged. + */ + public void warn(final CharSequence logString) { + CluecumberLogLevel[] logLevels = + new CluecumberLogLevel[]{CluecumberLogLevel.DEFAULT, CluecumberLogLevel.COMPACT, CluecumberLogLevel.MINIMAL}; + log(LogLevel.WARN, logString, logLevels); } - public void info(final CharSequence charSequence) { - mojoLogger.info(charSequence); + /** + * Logs a message based on the provided log levels. + * + * @param logString The {@link String} to be logged. + * @param CluecumberLogLevels The log levels ({@link CluecumberLogger} list) in which the message should be displayed. + */ + private void log(final LogLevel logLevel, final CharSequence logString, CluecumberLogLevel... CluecumberLogLevels) { + if (currentLogLevel == CluecumberLogLevel.OFF) { + return; + } + + if (currentLogLevel != null + && CluecumberLogLevels != null + && CluecumberLogLevels.length > 0 + && Arrays.stream(CluecumberLogLevels) + .noneMatch(CluecumberLogLevel -> CluecumberLogLevel == currentLogLevel)) { + return; + } + switch (logLevel) { + case INFO: + mojoLogger.info(logString); + break; + case WARN: + mojoLogger.warn(logString); + break; + } } - public void error(final CharSequence charSequence) { - mojoLogger.error(charSequence); + private enum LogLevel { + INFO, WARN } - public void logSeparator() { - info("------------------------------------------------------------------------"); + public enum CluecumberLogLevel { + DEFAULT, COMPACT, MINIMAL, OFF } } diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/properties/LinkedProperties.java b/plugin-code/src/main/java/com/trivago/cluecumber/properties/LinkedProperties.java index 18879e38..3f9fe12a 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/properties/LinkedProperties.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/properties/LinkedProperties.java @@ -1,3 +1,19 @@ +/* + * Copyright 2019 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.properties; import java.util.Enumeration; diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/properties/PropertiesFileLoader.java b/plugin-code/src/main/java/com/trivago/cluecumber/properties/PropertiesFileLoader.java index e0ba2c83..d792d540 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/properties/PropertiesFileLoader.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/properties/PropertiesFileLoader.java @@ -1,3 +1,19 @@ +/* + * Copyright 2019 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.properties; import com.trivago.cluecumber.exceptions.CluecumberPluginException; diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/properties/PropertyManager.java b/plugin-code/src/main/java/com/trivago/cluecumber/properties/PropertyManager.java index 5719b5cf..e4b00bf3 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/properties/PropertyManager.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/properties/PropertyManager.java @@ -28,6 +28,9 @@ import java.util.Map; import java.util.regex.Pattern; +import static com.trivago.cluecumber.logging.CluecumberLogger.CluecumberLogLevel.COMPACT; +import static com.trivago.cluecumber.logging.CluecumberLogger.CluecumberLogLevel.DEFAULT; + @Singleton public class PropertyManager { @@ -200,39 +203,39 @@ public void setCustomPageTitle(final String customPageTitle) { } public void logProperties() { - logger.info("- source JSON report directory : " + sourceJsonReportDirectory); - logger.info("- generated HTML report directory : " + generatedHtmlReportDirectory); + logger.info("- source JSON report directory : " + sourceJsonReportDirectory, DEFAULT, COMPACT); + logger.info("- generated HTML report directory : " + generatedHtmlReportDirectory, DEFAULT, COMPACT); boolean customParametersFileExists = isSet(customParametersFile); if (customParametersFileExists) { - logger.logSeparator(); - logger.info("- custom parameters file : " + customParametersFile); + logger.logInfoSeparator(DEFAULT); + logger.info("- custom parameters file : " + customParametersFile, DEFAULT); } if (customParameters != null && !customParameters.isEmpty()) { if (!customParametersFileExists) { - logger.logSeparator(); + logger.logInfoSeparator(); } customParameters.entrySet().stream().map(entry -> "- custom parameter : " + - entry.getKey() + " -> " + entry.getValue()).forEach(logger::info); + entry.getKey() + " -> " + entry.getValue()).forEach(logString -> logger.info(logString, DEFAULT)); } - logger.logSeparator(); + logger.logInfoSeparator(DEFAULT); - logger.info("- fail pending/undefined scenarios : " + failScenariosOnPendingOrUndefinedSteps); - logger.info("- expand before/after hooks : " + expandBeforeAfterHooks); - logger.info("- expand step hooks : " + expandStepHooks); - logger.info("- expand doc strings : " + expandDocStrings); - logger.info("- page title : " + customPageTitle); + logger.info("- fail pending/undefined scenarios : " + failScenariosOnPendingOrUndefinedSteps, DEFAULT); + logger.info("- expand before/after hooks : " + expandBeforeAfterHooks, DEFAULT); + logger.info("- expand step hooks : " + expandStepHooks, DEFAULT); + logger.info("- expand doc strings : " + expandDocStrings, DEFAULT); + logger.info("- page title : " + customPageTitle, DEFAULT); if (isSet(customCssFile)) { - logger.info("- custom CSS file : " + customCssFile); + logger.info("- custom CSS file : " + customCssFile, DEFAULT); } logger.info("- colors (passed, failed, skipped) : " + - customStatusColorPassed + ", " + customStatusColorFailed + ", " + customStatusColorSkipped); + customStatusColorPassed + ", " + customStatusColorFailed + ", " + customStatusColorSkipped, DEFAULT); - logger.logSeparator(); + logger.logInfoSeparator(DEFAULT); } private boolean isSet(final String string) { diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/PieChartBuilder.java b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/PieChartBuilder.java new file mode 100644 index 00000000..8dee12f8 --- /dev/null +++ b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/PieChartBuilder.java @@ -0,0 +1,91 @@ +/* + * Copyright 2019 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.rendering.pages.charts; + +import com.trivago.cluecumber.constants.ChartConfiguration; +import com.trivago.cluecumber.constants.Status; +import com.trivago.cluecumber.rendering.pages.charts.pojos.Chart; +import com.trivago.cluecumber.rendering.pages.charts.pojos.Data; +import com.trivago.cluecumber.rendering.pages.charts.pojos.Dataset; +import com.trivago.cluecumber.rendering.pages.charts.pojos.Options; + +import java.util.ArrayList; +import java.util.List; + +public class PieChartBuilder { + private final ChartConfiguration chartConfiguration; + private List valueSets; + + public PieChartBuilder(final ChartConfiguration chartConfiguration) { + this.chartConfiguration = chartConfiguration; + valueSets = new ArrayList<>(); + } + + public PieChartBuilder addValue(final int value, final Status status) { + String color = chartConfiguration.getColorRgbaStringByStatus(status); + valueSets.add(new ValueSet(value, color)); + return this; + } + + public Chart build() { + + List values = new ArrayList<>(); + List colors = new ArrayList<>(); + + for (ValueSet valueSet : valueSets) { + values.add(valueSet.value); + colors.add(valueSet.color); + } + + Dataset dataset = new Dataset(); + dataset.setBackgroundColor(colors); + dataset.setData(values); + + Data data = new Data(); + List labels = new ArrayList<>(); + labels.add(Status.PASSED.getStatusString()); + labels.add(Status.FAILED.getStatusString()); + labels.add(Status.SKIPPED.getStatusString()); + data.setLabels(labels); + + List datasets = new ArrayList<>(); + datasets.add(dataset); + data.setDatasets(datasets); + + Chart chart = new Chart(); + chart.setData(data); + + final Options options = new Options(); + List events = new ArrayList<>(); + events.add("click"); + events.add("mousemove"); + options.setEvents(events); + chart.setOptions(options); + chart.setType(ChartConfiguration.Type.pie); + return chart; + } + + private class ValueSet { + private final int value; + private final String color; + + ValueSet(final int value, final String color) { + this.value = value; + this.color = color; + } + } +} diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/StackedBarChartBuilder.java b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/StackedBarChartBuilder.java new file mode 100644 index 00000000..8ba7c14d --- /dev/null +++ b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/StackedBarChartBuilder.java @@ -0,0 +1,136 @@ +/* + * Copyright 2019 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.rendering.pages.charts; + +import com.trivago.cluecumber.constants.ChartConfiguration; +import com.trivago.cluecumber.constants.Status; +import com.trivago.cluecumber.rendering.pages.charts.pojos.Axis; +import com.trivago.cluecumber.rendering.pages.charts.pojos.Chart; +import com.trivago.cluecumber.rendering.pages.charts.pojos.Data; +import com.trivago.cluecumber.rendering.pages.charts.pojos.Dataset; +import com.trivago.cluecumber.rendering.pages.charts.pojos.Options; +import com.trivago.cluecumber.rendering.pages.charts.pojos.ScaleLabel; +import com.trivago.cluecumber.rendering.pages.charts.pojos.Scales; +import com.trivago.cluecumber.rendering.pages.charts.pojos.Ticks; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class StackedBarChartBuilder { + private final ChartConfiguration chartConfiguration; + private List labels; + private List datasets = new ArrayList<>(); + private String xAxisLabel; + private String yAxisLabel; + private int yAxisStepSize = 1; + private boolean stacked = true; + + public StackedBarChartBuilder(final ChartConfiguration chartConfiguration) { + this.chartConfiguration = chartConfiguration; + } + + public StackedBarChartBuilder addValues(final List values, final Status status) { + String color = chartConfiguration.getColorRgbaStringByStatus(status); + Dataset dataset = new Dataset(); + dataset.setLabel(status.getStatusString()); + dataset.setData(values); + List colors = new ArrayList<>(Collections.nCopies(values.size(), color)); + dataset.setBackgroundColor(colors); + datasets.add(dataset); + return this; + } + + public StackedBarChartBuilder setLabels(final List labels) { + this.labels = labels; + return this; + } + + public StackedBarChartBuilder setxAxisLabel(final String xAxisLabel) { + this.xAxisLabel = xAxisLabel; + return this; + } + + public StackedBarChartBuilder setyAxisLabel(final String yAxisLabel) { + this.yAxisLabel = yAxisLabel; + return this; + } + + public StackedBarChartBuilder setyAxisStepSize(final int yAxisStepSize) { + this.yAxisStepSize = yAxisStepSize; + return this; + } + + public StackedBarChartBuilder setStacked(final boolean stacked) { + this.stacked = stacked; + return this; + } + + public Chart build() { + Chart chart = new Chart(); + chart.setType(ChartConfiguration.Type.bar); + + Data data = new Data(); + data.setLabels(labels); + + for (Dataset dataset : datasets) { + if (!stacked) { + dataset.setStack("complete"); + } + } + + data.setDatasets(datasets); + chart.setData(data); + + Options options = new Options(); + Scales scales = new Scales(); + List xAxes = new ArrayList<>(); + Axis xAxis = new Axis(); + xAxis.setStacked(true); + Ticks xTicks = new Ticks(); + xTicks.setDisplay(false); + xAxis.setTicks(xTicks); + ScaleLabel xScaleLabel = new ScaleLabel(); + xScaleLabel.setDisplay(true); + xScaleLabel.setLabelString(xAxisLabel); + xAxis.setScaleLabel(xScaleLabel); + xAxes.add(xAxis); + scales.setxAxes(xAxes); + + List yAxes = new ArrayList<>(); + Axis yAxis = new Axis(); + yAxis.setStacked(true); + Ticks yTicks = new Ticks(); + yTicks.setStepSize(yAxisStepSize); + yAxis.setTicks(yTicks); + ScaleLabel yScaleLabel = new ScaleLabel(); + yScaleLabel.setDisplay(true); + yScaleLabel.setLabelString(yAxisLabel); + yAxis.setScaleLabel(yScaleLabel); + yAxes.add(yAxis); + scales.setyAxes(yAxes); + + options.setScales(scales); + List events = new ArrayList<>(); + events.add("click"); + events.add("mousemove"); + options.setEvents(events); + chart.setOptions(options); + + return chart; + } +} diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/pojos/Options.java b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/pojos/Options.java index 11e10015..ac7a9462 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/pojos/Options.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/pojos/Options.java @@ -16,9 +16,12 @@ package com.trivago.cluecumber.rendering.pages.charts.pojos; +import java.util.List; + public class Options { private Scales scales; private Legend legend; + private List events; public Scales getScales() { return scales; @@ -35,4 +38,12 @@ public Legend getLegend() { public void setLegend(final Legend legend) { this.legend = legend; } + + public void setEvents(final List events) { + this.events = events; + } + + public List getEvents() { + return events; + } } diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/pojos/Ticks.java b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/pojos/Ticks.java index 974be2fb..9576f45d 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/pojos/Ticks.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/charts/pojos/Ticks.java @@ -18,6 +18,7 @@ public class Ticks { private int min; + private int stepSize; private boolean display = true; public int getMin() { @@ -35,4 +36,12 @@ public boolean isDisplay() { public void setDisplay(final boolean display) { this.display = display; } + + public int getStepSize() { + return stepSize; + } + + public void setStepSize(final int stepSize) { + this.stepSize = stepSize; + } } diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllFeaturesPageRenderer.java b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllFeaturesPageRenderer.java index 5453f99e..c27c085f 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllFeaturesPageRenderer.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllFeaturesPageRenderer.java @@ -20,25 +20,17 @@ import com.trivago.cluecumber.constants.Status; import com.trivago.cluecumber.exceptions.CluecumberPluginException; import com.trivago.cluecumber.rendering.pages.charts.ChartJsonConverter; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Axis; +import com.trivago.cluecumber.rendering.pages.charts.StackedBarChartBuilder; import com.trivago.cluecumber.rendering.pages.charts.pojos.Chart; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Data; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Dataset; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Options; -import com.trivago.cluecumber.rendering.pages.charts.pojos.ScaleLabel; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Scales; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Ticks; import com.trivago.cluecumber.rendering.pages.pojos.Feature; -import com.trivago.cluecumber.rendering.pages.pojos.ResultCount; import com.trivago.cluecumber.rendering.pages.pojos.pagecollections.AllFeaturesPageCollection; import freemarker.template.Template; import javax.inject.Inject; import javax.inject.Singleton; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Map; +import java.util.stream.Collectors; @Singleton public class AllFeaturesPageRenderer extends PageRenderer { @@ -63,85 +55,31 @@ public String getRenderedContent( } private void addChartJsonToReportDetails(final AllFeaturesPageCollection allFeaturesPageCollection) { - Chart chart = new Chart(); - Data data = new Data(); - chart.setData(data); - - List datasets = new ArrayList<>(); - List passed = new ArrayList<>(); List failed = new ArrayList<>(); List skipped = new ArrayList<>(); - int maxY = 0; - for (Map.Entry entry : allFeaturesPageCollection.getFeatureResultCounts().entrySet()) { - passed.add(entry.getValue().getPassed()); - failed.add(entry.getValue().getFailed()); - skipped.add(entry.getValue().getSkipped()); - maxY = entry.getValue().getTotal(); - } - - Dataset passedDataset = new Dataset(); - passedDataset.setLabel(Status.PASSED.getStatusString()); - passedDataset.setData(passed); - List passedBG = new ArrayList<>(Collections.nCopies(passed.size(), chartConfiguration.getPassedColorRgbaString())); - passedDataset.setBackgroundColor(passedBG); - datasets.add(passedDataset); - - Dataset failedDataset = new Dataset(); - failedDataset.setLabel(Status.FAILED.getStatusString()); - failedDataset.setData(failed); - List failedBG = new ArrayList<>(Collections.nCopies(passed.size(), chartConfiguration.getFailedColorRgbaString())); - failedDataset.setBackgroundColor(failedBG); - datasets.add(failedDataset); - - Dataset skippedDataset = new Dataset(); - skippedDataset.setLabel(Status.SKIPPED.getStatusString()); - skippedDataset.setData(skipped); - List skippedBG = new ArrayList<>(Collections.nCopies(passed.size(), chartConfiguration.getSkippedColorRgbaString())); - skippedDataset.setBackgroundColor(skippedBG); - datasets.add(skippedDataset); - - data.setDatasets(datasets); - - List keys = new ArrayList<>(); - for (Feature feature : allFeaturesPageCollection.getFeatureResultCounts().keySet()) { - keys.add(feature.getName()); - } - data.setLabels(keys); - - Options options = new Options(); - Scales scales = new Scales(); - List xAxes = new ArrayList<>(); - Axis xAxis = new Axis(); - xAxis.setStacked(true); - Ticks xTicks = new Ticks(); - xTicks.setDisplay(false); - xAxis.setTicks(xTicks); - ScaleLabel xScaleLabel = new ScaleLabel(); - xScaleLabel.setDisplay(true); - xScaleLabel.setLabelString(allFeaturesPageCollection.getTotalNumberOfFeatures() + " Feature(s)"); - xAxis.setScaleLabel(xScaleLabel); - xAxes.add(xAxis); - scales.setxAxes(xAxes); - - List yAxes = new ArrayList<>(); - Axis yAxis = new Axis(); - yAxis.setStacked(true); - Ticks yTicks = new Ticks(); - yAxis.setTicks(yTicks); - ScaleLabel yScaleLabel = new ScaleLabel(); - yScaleLabel.setDisplay(true); - yScaleLabel.setLabelString("Number of Scenarios"); - yAxis.setScaleLabel(yScaleLabel); - yAxis.setStepSize(maxY); - yAxes.add(yAxis); - scales.setyAxes(yAxes); - - options.setScales(scales); - chart.setOptions(options); - - chart.setType(ChartConfiguration.Type.bar); + allFeaturesPageCollection.getFeatureResultCounts().forEach((key, value) -> { + passed.add(value.getPassed()); + failed.add(value.getFailed()); + skipped.add(value.getSkipped()); + }); + + List keys = allFeaturesPageCollection.getFeatureResultCounts() + .keySet() + .stream() + .map(Feature::getName) + .collect(Collectors.toList()); + + Chart chart = + new StackedBarChartBuilder(chartConfiguration) + .setLabels(keys) + .setxAxisLabel(allFeaturesPageCollection.getTotalNumberOfFeatures() + " Features") + .setyAxisLabel("Number of Scenarios") + .addValues(passed, Status.PASSED) + .addValues(failed, Status.FAILED) + .addValues(skipped, Status.SKIPPED) + .build(); allFeaturesPageCollection.getReportDetails().setChartJson(convertChartToJson(chart)); } diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllScenariosPageRenderer.java b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllScenariosPageRenderer.java index 481146f6..7ae58aaf 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllScenariosPageRenderer.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllScenariosPageRenderer.java @@ -25,9 +25,7 @@ import com.trivago.cluecumber.json.pojo.Tag; import com.trivago.cluecumber.properties.PropertyManager; import com.trivago.cluecumber.rendering.pages.charts.ChartJsonConverter; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Chart; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Data; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Dataset; +import com.trivago.cluecumber.rendering.pages.charts.PieChartBuilder; import com.trivago.cluecumber.rendering.pages.pojos.CustomParameter; import com.trivago.cluecumber.rendering.pages.pojos.Feature; import com.trivago.cluecumber.rendering.pages.pojos.pagecollections.AllScenariosPageCollection; @@ -75,7 +73,10 @@ public String getRenderedContentByTagFilter( AllScenariosPageCollection allScenariosPageCollectionClone = getAllScenariosPageCollectionClone(allScenariosPageCollection); allScenariosPageCollectionClone.setTagFilter(tag); allScenariosPageCollectionClone.getReports().forEach(report -> { - List elements = report.getElements().stream().filter(element -> element.getTags().contains(tag)).collect(Collectors.toList()); + List elements = report.getElements() + .stream() + .filter(element -> element.getTags().contains(tag)) + .collect(Collectors.toList()); report.setElements(elements); }); addChartJsonToReportDetails(allScenariosPageCollectionClone); @@ -90,7 +91,10 @@ public String getRenderedContentByStepFilter( AllScenariosPageCollection allScenariosPageCollectionClone = getAllScenariosPageCollectionClone(allScenariosPageCollection); allScenariosPageCollectionClone.setStepFilter(step); allScenariosPageCollectionClone.getReports().forEach(report -> { - List elements = report.getElements().stream().filter(element -> element.getSteps().contains(step)).collect(Collectors.toList()); + List elements = report.getElements() + .stream() + .filter(element -> element.getSteps().contains(step)) + .collect(Collectors.toList()); report.setElements(elements); }); addChartJsonToReportDetails(allScenariosPageCollectionClone); @@ -104,7 +108,10 @@ public String getRenderedContentByFeatureFilter( AllScenariosPageCollection allScenariosPageCollectionClone = getAllScenariosPageCollectionClone(allScenariosPageCollection); allScenariosPageCollectionClone.setFeatureFilter(feature); - Report[] reportArray = allScenariosPageCollectionClone.getReports().stream().filter(report -> report.getFeatureIndex() == feature.getIndex()).toArray(Report[]::new); + Report[] reportArray = allScenariosPageCollectionClone.getReports() + .stream() + .filter(report -> report.getFeatureIndex() == feature.getIndex()) + .toArray(Report[]::new); allScenariosPageCollectionClone.clearReports(); allScenariosPageCollectionClone.addReports(reportArray); addChartJsonToReportDetails(allScenariosPageCollectionClone); @@ -112,35 +119,13 @@ public String getRenderedContentByFeatureFilter( } private void addChartJsonToReportDetails(final AllScenariosPageCollection allScenariosPageCollection) { - Chart chart = new Chart(); - Data data = new Data(); - - List labels = new ArrayList<>(); - labels.add(Status.PASSED.getStatusString()); - labels.add(Status.FAILED.getStatusString()); - labels.add(Status.SKIPPED.getStatusString()); - data.setLabels(labels); - - List datasets = new ArrayList<>(); - Dataset dataset = new Dataset(); - List values = new ArrayList<>(); - values.add(allScenariosPageCollection.getTotalNumberOfPassedScenarios()); - values.add(allScenariosPageCollection.getTotalNumberOfFailedScenarios()); - values.add(allScenariosPageCollection.getTotalNumberOfSkippedScenarios()); - dataset.setData(values); - datasets.add(dataset); - - List backgroundColors = new ArrayList<>(); - backgroundColors.add(chartConfiguration.getPassedColorRgbaString()); - backgroundColors.add(chartConfiguration.getFailedColorRgbaString()); - backgroundColors.add(chartConfiguration.getSkippedColorRgbaString()); - dataset.setBackgroundColor(backgroundColors); - data.setDatasets(datasets); - - chart.setData(data); - chart.setType(ChartConfiguration.Type.pie); - - allScenariosPageCollection.getReportDetails().setChartJson(convertChartToJson(chart)); + allScenariosPageCollection.getReportDetails() + .setChartJson(convertChartToJson(new PieChartBuilder(chartConfiguration) + .addValue(allScenariosPageCollection.getTotalNumberOfPassedScenarios(), Status.PASSED) + .addValue(allScenariosPageCollection.getTotalNumberOfFailedScenarios(), Status.FAILED) + .addValue(allScenariosPageCollection.getTotalNumberOfSkippedScenarios(), Status.SKIPPED) + .build())); + } private void addCustomParametersToReportDetails(final AllScenariosPageCollection allScenariosPageCollection) { diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllStepsPageRenderer.java b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllStepsPageRenderer.java index 12f547c8..3b5b2794 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllStepsPageRenderer.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllStepsPageRenderer.java @@ -1,26 +1,19 @@ package com.trivago.cluecumber.rendering.pages.renderering; import com.trivago.cluecumber.constants.ChartConfiguration; +import com.trivago.cluecumber.constants.Status; import com.trivago.cluecumber.exceptions.CluecumberPluginException; import com.trivago.cluecumber.json.pojo.Step; import com.trivago.cluecumber.rendering.pages.charts.ChartJsonConverter; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Axis; +import com.trivago.cluecumber.rendering.pages.charts.StackedBarChartBuilder; import com.trivago.cluecumber.rendering.pages.charts.pojos.Chart; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Data; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Dataset; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Options; -import com.trivago.cluecumber.rendering.pages.charts.pojos.ScaleLabel; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Scales; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Ticks; -import com.trivago.cluecumber.rendering.pages.pojos.ResultCount; import com.trivago.cluecumber.rendering.pages.pojos.pagecollections.AllStepsPageCollection; import freemarker.template.Template; import javax.inject.Inject; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Map; +import java.util.stream.Collectors; public class AllStepsPageRenderer extends PageRenderer { @@ -45,85 +38,32 @@ public String getRenderedContent( private void addChartJsonToReportDetails(final AllStepsPageCollection allTagsPageCollection) { - Chart chart = new Chart(); - Data data = new Data(); - chart.setData(data); - - List datasets = new ArrayList<>(); - List passed = new ArrayList<>(); List failed = new ArrayList<>(); List skipped = new ArrayList<>(); - int maxY = 0; - for (Map.Entry entry : allTagsPageCollection.getStepResultCounts().entrySet()) { - passed.add(entry.getValue().getPassed()); - failed.add(entry.getValue().getFailed()); - skipped.add(entry.getValue().getSkipped()); - maxY = entry.getValue().getTotal(); - } - - Dataset passedDataset = new Dataset(); - passedDataset.setLabel("passed"); - passedDataset.setData(passed); - List passedBG = new ArrayList<>(Collections.nCopies(passed.size(), chartConfiguration.getPassedColorRgbaString())); - passedDataset.setBackgroundColor(passedBG); - datasets.add(passedDataset); - - Dataset failedDataset = new Dataset(); - failedDataset.setLabel("failed"); - failedDataset.setData(failed); - List failedBG = new ArrayList<>(Collections.nCopies(passed.size(), chartConfiguration.getFailedColorRgbaString())); - failedDataset.setBackgroundColor(failedBG); - datasets.add(failedDataset); - - Dataset skippedDataset = new Dataset(); - skippedDataset.setLabel("skipped"); - skippedDataset.setData(skipped); - List skippedBG = new ArrayList<>(Collections.nCopies(passed.size(), chartConfiguration.getSkippedColorRgbaString())); - skippedDataset.setBackgroundColor(skippedBG); - datasets.add(skippedDataset); - - data.setDatasets(datasets); - - List keys = new ArrayList<>(); - for (Step step : allTagsPageCollection.getStepResultCounts().keySet()) { - keys.add(step.returnNameWithArgumentPlaceholders()); - } - data.setLabels(keys); - - Options options = new Options(); - Scales scales = new Scales(); - List xAxes = new ArrayList<>(); - Axis xAxis = new Axis(); - xAxis.setStacked(true); - Ticks xTicks = new Ticks(); - xTicks.setDisplay(false); - xAxis.setTicks(xTicks); - ScaleLabel xScaleLabel = new ScaleLabel(); - xScaleLabel.setDisplay(true); - xScaleLabel.setLabelString(allTagsPageCollection.getTotalNumberOfSteps() + " Step(s)"); - xAxis.setScaleLabel(xScaleLabel); - xAxes.add(xAxis); - scales.setxAxes(xAxes); - - List yAxes = new ArrayList<>(); - Axis yAxis = new Axis(); - yAxis.setStacked(true); - Ticks yTicks = new Ticks(); - yAxis.setTicks(yTicks); - ScaleLabel yScaleLabel = new ScaleLabel(); - yScaleLabel.setDisplay(true); - yScaleLabel.setLabelString("Number of Scenarios"); - yAxis.setScaleLabel(yScaleLabel); - yAxis.setStepSize(maxY); - yAxes.add(yAxis); - scales.setyAxes(yAxes); - - options.setScales(scales); - chart.setOptions(options); + allTagsPageCollection.getStepResultCounts().forEach((key, value) -> { + passed.add(value.getPassed()); + failed.add(value.getFailed()); + skipped.add(value.getSkipped()); + }); + + List keys = allTagsPageCollection.getStepResultCounts() + .keySet() + .stream() + .map(Step::returnNameWithArgumentPlaceholders) + .collect(Collectors.toList()); + + Chart chart = + new StackedBarChartBuilder(chartConfiguration) + .setLabels(keys) + .setxAxisLabel(allTagsPageCollection.getTotalNumberOfSteps() + " Steps") + .setyAxisLabel("Number of Usages") + .addValues(passed, Status.PASSED) + .addValues(failed, Status.FAILED) + .addValues(skipped, Status.SKIPPED) + .build(); - chart.setType(ChartConfiguration.Type.bar); allTagsPageCollection.getReportDetails().setChartJson(convertChartToJson(chart)); } diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllTagsPageRenderer.java b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllTagsPageRenderer.java index 9c364f50..1e812288 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllTagsPageRenderer.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/AllTagsPageRenderer.java @@ -17,17 +17,12 @@ package com.trivago.cluecumber.rendering.pages.renderering; import com.trivago.cluecumber.constants.ChartConfiguration; +import com.trivago.cluecumber.constants.Status; import com.trivago.cluecumber.exceptions.CluecumberPluginException; import com.trivago.cluecumber.json.pojo.Tag; import com.trivago.cluecumber.rendering.pages.charts.ChartJsonConverter; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Axis; +import com.trivago.cluecumber.rendering.pages.charts.StackedBarChartBuilder; import com.trivago.cluecumber.rendering.pages.charts.pojos.Chart; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Data; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Dataset; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Options; -import com.trivago.cluecumber.rendering.pages.charts.pojos.ScaleLabel; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Scales; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Ticks; import com.trivago.cluecumber.rendering.pages.pojos.ResultCount; import com.trivago.cluecumber.rendering.pages.pojos.pagecollections.AllTagsPageCollection; import freemarker.template.Template; @@ -35,7 +30,6 @@ import javax.inject.Inject; import javax.inject.Singleton; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -63,85 +57,30 @@ public String getRenderedContent( private void addChartJsonToReportDetails(final AllTagsPageCollection allTagsPageCollection) { - Chart chart = new Chart(); - Data data = new Data(); - chart.setData(data); - - List datasets = new ArrayList<>(); - List passed = new ArrayList<>(); List failed = new ArrayList<>(); List skipped = new ArrayList<>(); - int maxY = 0; for (Map.Entry entry : allTagsPageCollection.getTagResultCounts().entrySet()) { passed.add(entry.getValue().getPassed()); failed.add(entry.getValue().getFailed()); skipped.add(entry.getValue().getSkipped()); - maxY = entry.getValue().getTotal(); } - Dataset passedDataset = new Dataset(); - passedDataset.setLabel("passed"); - passedDataset.setData(passed); - List passedBG = new ArrayList<>(Collections.nCopies(passed.size(), chartConfiguration.getPassedColorRgbaString())); - passedDataset.setBackgroundColor(passedBG); - datasets.add(passedDataset); - - Dataset failedDataset = new Dataset(); - failedDataset.setLabel("failed"); - failedDataset.setData(failed); - List failedBG = new ArrayList<>(Collections.nCopies(passed.size(), chartConfiguration.getFailedColorRgbaString())); - failedDataset.setBackgroundColor(failedBG); - datasets.add(failedDataset); - - Dataset skippedDataset = new Dataset(); - skippedDataset.setLabel("skipped"); - skippedDataset.setData(skipped); - List skippedBG = new ArrayList<>(Collections.nCopies(passed.size(), chartConfiguration.getSkippedColorRgbaString())); - skippedDataset.setBackgroundColor(skippedBG); - datasets.add(skippedDataset); - - data.setDatasets(datasets); - List keys = new ArrayList<>(); for (Tag tag : allTagsPageCollection.getTagResultCounts().keySet()) { keys.add(tag.getName()); } - data.setLabels(keys); - - Options options = new Options(); - Scales scales = new Scales(); - List xAxes = new ArrayList<>(); - Axis xAxis = new Axis(); - xAxis.setStacked(true); - Ticks xTicks = new Ticks(); - xTicks.setDisplay(false); - xAxis.setTicks(xTicks); - ScaleLabel xScaleLabel = new ScaleLabel(); - xScaleLabel.setDisplay(true); - xScaleLabel.setLabelString(allTagsPageCollection.getTotalNumberOfTags() + " Tag(s)"); - xAxis.setScaleLabel(xScaleLabel); - xAxes.add(xAxis); - scales.setxAxes(xAxes); - - List yAxes = new ArrayList<>(); - Axis yAxis = new Axis(); - yAxis.setStacked(true); - Ticks yTicks = new Ticks(); - yAxis.setTicks(yTicks); - ScaleLabel yScaleLabel = new ScaleLabel(); - yScaleLabel.setDisplay(true); - yScaleLabel.setLabelString("Number of Scenarios"); - yAxis.setScaleLabel(yScaleLabel); - yAxis.setStepSize(maxY); - yAxes.add(yAxis); - scales.setyAxes(yAxes); - - options.setScales(scales); - chart.setOptions(options); - chart.setType(ChartConfiguration.Type.bar); + Chart chart = + new StackedBarChartBuilder(chartConfiguration) + .setLabels(keys) + .setxAxisLabel(allTagsPageCollection.getTotalNumberOfTags() + " Tags") + .setyAxisLabel("Number of Scenarios") + .addValues(passed, Status.PASSED) + .addValues(failed, Status.FAILED) + .addValues(skipped, Status.SKIPPED) + .build(); allTagsPageCollection.getReportDetails().setChartJson(convertChartToJson(chart)); } diff --git a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/ScenarioDetailsPageRenderer.java b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/ScenarioDetailsPageRenderer.java index fdee9b02..77e94724 100644 --- a/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/ScenarioDetailsPageRenderer.java +++ b/plugin-code/src/main/java/com/trivago/cluecumber/rendering/pages/renderering/ScenarioDetailsPageRenderer.java @@ -21,25 +21,18 @@ import com.trivago.cluecumber.exceptions.CluecumberPluginException; import com.trivago.cluecumber.json.pojo.Element; import com.trivago.cluecumber.json.pojo.ResultMatch; +import com.trivago.cluecumber.json.pojo.Step; import com.trivago.cluecumber.properties.PropertyManager; import com.trivago.cluecumber.rendering.pages.charts.ChartJsonConverter; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Axis; +import com.trivago.cluecumber.rendering.pages.charts.StackedBarChartBuilder; import com.trivago.cluecumber.rendering.pages.charts.pojos.Chart; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Data; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Dataset; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Options; -import com.trivago.cluecumber.rendering.pages.charts.pojos.ScaleLabel; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Scales; -import com.trivago.cluecumber.rendering.pages.charts.pojos.Ticks; import com.trivago.cluecumber.rendering.pages.pojos.pagecollections.ScenarioDetailsPageCollection; import freemarker.template.Template; import javax.inject.Inject; import javax.inject.Singleton; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.stream.IntStream; @Singleton public class ScenarioDetailsPageRenderer extends PageRenderer { @@ -69,84 +62,43 @@ public String getRenderedContent( } private void addChartJsonToReportDetails(final ScenarioDetailsPageCollection scenarioDetailsPageCollection) { - Chart chart = new Chart(); Element element = scenarioDetailsPageCollection.getElement(); List labels = new ArrayList<>(); - IntStream.rangeClosed(1, element.getBefore().size()).mapToObj(i -> "Before " + i).forEachOrdered(labels::add); - IntStream.rangeClosed(1, element.getSteps().size()).mapToObj(i -> "Step " + i).forEachOrdered(labels::add); + if (element.getBefore().size() > 0) { + element.getBefore().stream().map(ResultMatch::getGlueMethodName).forEach(labels::add); + } + if (element.getSteps().size() > 0) { + element.getSteps().stream().map(Step::getName).forEach(labels::add); + } if (element.getAfter().size() > 0) { - IntStream.rangeClosed(element.getBefore().size(), element.getAfter().size()).mapToObj(i -> "After " + i).forEachOrdered(labels::add); + element.getAfter().stream().map(ResultMatch::getGlueMethodName).forEach(labels::add); } - Data data = new Data(); - data.setLabels(labels); + Chart chart = + new StackedBarChartBuilder(chartConfiguration) + .setxAxisLabel("Steps") + .setyAxisLabel("Step Runtime (seconds)") + .setyAxisStepSize(0) + .setLabels(labels) + .setStacked(false) + .addValues(getValuesByStatus(element, Status.PASSED), Status.PASSED) + .addValues(getValuesByStatus(element, Status.FAILED), Status.FAILED) + .addValues(getValuesByStatus(element, Status.SKIPPED), Status.SKIPPED) + .build(); - List datasets = new ArrayList<>(); - for (Status status : Status.BASIC_STATES) { - Dataset dataset = new Dataset(); - List dataList = new ArrayList<>(); - for (ResultMatch resultMatch : element.getAllResultMatches()) { - if (resultMatch.getConsolidatedStatus() == status) { - dataList.add((int) resultMatch.getResult().getDurationInMilliseconds()); - } else { - dataList.add(0); - } - } - dataset.setData(dataList); - dataset.setLabel(status.getStatusString()); - dataset.setStack("complete"); + scenarioDetailsPageCollection.getReportDetails().setChartJson(convertChartToJson(chart)); + } - String statusColorString; - switch (status) { - case FAILED: - statusColorString = chartConfiguration.getFailedColorRgbaString(); - break; - case SKIPPED: - statusColorString = chartConfiguration.getSkippedColorRgbaString(); - break; - default: - statusColorString = chartConfiguration.getPassedColorRgbaString(); + private List getValuesByStatus(final Element element, final Status status) { + List values = new ArrayList<>(); + element.getAllResultMatches().forEach(resultMatch -> { + if (resultMatch.getConsolidatedStatus() == status) { + values.add((int) resultMatch.getResult().getDurationInMilliseconds() / 1000); + } else { + values.add(0); } - - dataset.setBackgroundColor(new ArrayList<>(Collections.nCopies(dataList.size(), statusColorString))); - datasets.add(dataset); - } - - data.setDatasets(datasets); - chart.setData(data); - - Options options = new Options(); - Scales scales = new Scales(); - List xAxes = new ArrayList<>(); - Axis xAxis = new Axis(); - xAxis.setStacked(true); - Ticks xTicks = new Ticks(); - xAxis.setTicks(xTicks); - ScaleLabel xScaleLabel = new ScaleLabel(); - xScaleLabel.setDisplay(true); - xScaleLabel.setLabelString("Step(s)"); - xAxis.setScaleLabel(xScaleLabel); - xAxes.add(xAxis); - scales.setxAxes(xAxes); - - List yAxes = new ArrayList<>(); - Axis yAxis = new Axis(); - yAxis.setStacked(true); - Ticks yTicks = new Ticks(); - yAxis.setTicks(yTicks); - ScaleLabel yScaleLabel = new ScaleLabel(); - yScaleLabel.setDisplay(true); - yScaleLabel.setLabelString("Step Runtime"); - yAxis.setScaleLabel(yScaleLabel); - yAxes.add(yAxis); - scales.setyAxes(yAxes); - - options.setScales(scales); - chart.setOptions(options); - - chart.setType(ChartConfiguration.Type.bar); - - scenarioDetailsPageCollection.getReportDetails().setChartJson(convertChartToJson(chart)); + }); + return values; } } diff --git a/plugin-code/src/main/resources/template/macros/navigation.ftl b/plugin-code/src/main/resources/template/macros/navigation.ftl index bc7cdefa..f057209c 100644 --- a/plugin-code/src/main/resources/template/macros/navigation.ftl +++ b/plugin-code/src/main/resources/template/macros/navigation.ftl @@ -42,8 +42,8 @@ limitations under the License. <#case "step_summary"> All Steps <#break> - <#case "feature_summary ${highlightClass}"> - All Features + <#case "feature_summary"> + All Features <#break> diff --git a/plugin-code/src/main/resources/template/snippets/js.ftl b/plugin-code/src/main/resources/template/snippets/js.ftl index 56500d80..a7b344b3 100644 --- a/plugin-code/src/main/resources/template/snippets/js.ftl +++ b/plugin-code/src/main/resources/template/snippets/js.ftl @@ -23,67 +23,89 @@ limitations under the License.