diff --git a/src/main/java/net/masterthought/cucumber/Configuration.java b/src/main/java/net/masterthought/cucumber/Configuration.java index e9b6ff533..448644853 100755 --- a/src/main/java/net/masterthought/cucumber/Configuration.java +++ b/src/main/java/net/masterthought/cucumber/Configuration.java @@ -1,17 +1,26 @@ package net.masterthought.cucumber; -import java.io.File; -import java.util.*; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - import net.masterthought.cucumber.json.support.Status; +import net.masterthought.cucumber.outputhandlers.FilesystemOutputHandler; +import net.masterthought.cucumber.outputhandlers.OutputHandler; import net.masterthought.cucumber.presentation.PresentationMode; import net.masterthought.cucumber.reducers.ReducingMethod; import net.masterthought.cucumber.sorting.SortingMethod; import org.apache.commons.lang.StringUtils; import org.checkerframework.checker.nullness.qual.NonNull; +import java.io.File; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + public class Configuration { private static final String EMBEDDINGS_DIRECTORY = "embeddings"; @@ -29,7 +38,7 @@ public class Configuration { private Collection tagsToExcludeFromChart = new ArrayList<>(); private SortingMethod sortingMethod = SortingMethod.NATURAL; private List reducingMethods = new ArrayList<>(); - + private List outputHandlers = new ArrayList<>(); private List presentationModes = new ArrayList<>(); private List classificationFiles; @@ -40,6 +49,7 @@ public class Configuration { public Configuration(File reportDirectory, String projectName) { this.reportDirectory = reportDirectory; this.projectName = projectName; + outputHandlers.add(new FilesystemOutputHandler()); } /** @@ -71,6 +81,7 @@ public boolean isTrendsStatsFile() { /** * Calls {@link #setTrends(File, int)} with zero limit. + * * @param trendsFile file with trends */ public void setTrendsStatsFile(File trendsFile) { @@ -88,10 +99,11 @@ public int getTrendsLimit() { /** * Checks if the trends page should be generated and displayed. + * * @return true if the page with trends should be displayed */ public boolean isTrendsAvailable() { - return getTrendsLimit() > -1 && isTrendsStatsFile(); + return getTrendsLimit() > -1 && isTrendsStatsFile(); } /** @@ -100,12 +112,12 @@ public boolean isTrendsAvailable() { * To disable saving and displaying trends page set to -1. * Otherwise number of previous builds is equal to provided limit. * - * @param trendsFile file where information about previous builds is stored - * @param limit number of builds that should be presented (older builds are skipped) + * @param trendsFile file where information about previous builds is stored + * @param limit number of builds that should be presented (older builds are skipped) */ public void setTrends(File trendsFile, int limit) { this.trendsFile = trendsFile; - this.trendsLimit = limit; + trendsLimit = limit; } /** @@ -169,7 +181,7 @@ public String getDirectorySuffixWithSeparator() { */ public File getEmbeddingDirectory() { return new File(getReportDirectory().getAbsolutePath(), ReportBuilder.BASE_DIRECTORY + - this.getDirectorySuffixWithSeparator() + File.separatorChar + Configuration.EMBEDDINGS_DIRECTORY); + getDirectorySuffixWithSeparator() + File.separatorChar + Configuration.EMBEDDINGS_DIRECTORY); } /** @@ -226,7 +238,7 @@ public void setSortingMethod(SortingMethod sortingMethod) { * Returns the default sorting method. */ public SortingMethod getSortingMethod() { - return this.sortingMethod; + return sortingMethod; } /** @@ -235,7 +247,7 @@ public SortingMethod getSortingMethod() { * @param reducingMethod type of reduction */ public void addReducingMethod(ReducingMethod reducingMethod) { - this.reducingMethods.add(reducingMethod); + reducingMethods.add(reducingMethod); } /** @@ -249,6 +261,7 @@ public List getReducingMethods() { /** * Checks if the configuration has given {@link ReducingMethod} set. + * * @param reducingMethod method to validate * @return true if method was set, otherwise false */ @@ -262,7 +275,7 @@ public boolean containsReducingMethod(ReducingMethod reducingMethod) { * @param presentationMode method used for presentation */ public void addPresentationModes(PresentationMode presentationMode) { - this.presentationModes.add(presentationMode); + presentationModes.add(presentationMode); } /** @@ -288,7 +301,7 @@ public void addClassificationFiles(List classificationFiles) { * Returns the list of properties files. */ public List getClassificationFiles() { - return this.classificationFiles; + return classificationFiles; } /** @@ -310,8 +323,9 @@ public void setNotFailingStatuses(Set notFailingStatuses) { /** * Sets explicit qualifier to use for the given json file. - * @param jsonFileName JSON file name - without the extension - * @param qualifier Qualifier to use + * + * @param jsonFileName JSON file name - without the extension + * @param qualifier Qualifier to use */ public void setQualifier(@NonNull String jsonFileName, @NonNull String qualifier) { qualifiers.put(jsonFileName, qualifier); @@ -319,8 +333,9 @@ public void setQualifier(@NonNull String jsonFileName, @NonNull String qualifier /** * Retrieves explicit qualifier to use for a given json file. - * @param jsonFileName JSON file name - without the extension - * @return Qualifier specified for this file or null if none specified + * + * @param jsonFileName JSON file name - without the extension + * @return Qualifier specified for this file or null if none specified */ public String getQualifier(@NonNull String jsonFileName) { return qualifiers.get(jsonFileName); @@ -328,8 +343,9 @@ public String getQualifier(@NonNull String jsonFileName) { /** * Checks whether an explicit qualifier was specified for a given json file. - * @param jsonFileName JSON file name - without the extension - * @return true if the qualifier was specified, false otherwise + * + * @param jsonFileName JSON file name - without the extension + * @return true if the qualifier was specified, false otherwise */ public boolean containsQualifier(@NonNull String jsonFileName) { return qualifiers.containsKey(jsonFileName); @@ -337,9 +353,45 @@ public boolean containsQualifier(@NonNull String jsonFileName) { /** * Removes explicit qualifier for a given json file. - * @param jsonFileName JSON file name - without the extension + * + * @param jsonFileName JSON file name - without the extension */ public void removeQualifier(@NonNull String jsonFileName) { qualifiers.remove(jsonFileName); } + + /** + * Adds the given OutputHandler to the List of OutputHandlers + * + * @param outputHandler Handler that will be called with the generated files + */ + public void addOutputHandler(OutputHandler outputHandler) { + outputHandlers.add(outputHandler); + } + + /** + * Removes the given OutputHandler from the List of OutputHandlers + * + * @param outputHandlerToRemove OutputHandler to be removed + */ + public void removeOutputHandler(OutputHandler outputHandlerToRemove) { + outputHandlers.remove(outputHandlerToRemove); + } + + /** + * Gets the List of all currently configured OutputHandlers + * By default the {@link FilesystemOutputHandler} is configured + * + * @return the List of OutputHandlers + */ + public List getOutputHandlers() { + return outputHandlers; + } + + /** + * Clears all OutputHandlers from the List of OutputHandlers + */ + public void clearOutputHandlers() { + outputHandlers.clear(); + } } diff --git a/src/main/java/net/masterthought/cucumber/ReportBuilder.java b/src/main/java/net/masterthought/cucumber/ReportBuilder.java index 8c5c514d0..6d2b7624c 100755 --- a/src/main/java/net/masterthought/cucumber/ReportBuilder.java +++ b/src/main/java/net/masterthought/cucumber/ReportBuilder.java @@ -4,6 +4,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; @@ -27,7 +28,7 @@ import net.masterthought.cucumber.generators.TrendsOverviewPage; import net.masterthought.cucumber.json.Feature; import net.masterthought.cucumber.json.support.TagObject; -import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; public class ReportBuilder { @@ -83,9 +84,6 @@ public Reportable generateReports() { // first copy static resources so ErrorPage is displayed properly copyStaticResources(); - // create directory for embeddings before files are generated - createEmbeddingsDirectory(); - // add metadata info sourced from files reportParser.parseClassificationsFiles(configuration.getClassificationFiles()); @@ -133,18 +131,14 @@ private void copyStaticResources() { copyResources("images", "favicon.png"); } - private void createEmbeddingsDirectory() { - configuration.getEmbeddingDirectory().mkdirs(); - } - private void copyResources(String resourceLocation, String... resources) { for (String resource : resources) { File tempFile = new File(configuration.getReportDirectory().getAbsoluteFile(), BASE_DIRECTORY + configuration.getDirectorySuffixWithSeparator() + File.separatorChar + resourceLocation + File.separatorChar + resource); // don't change this implementation unless you verified it works on Jenkins - try { - FileUtils.copyInputStreamToFile( - this.getClass().getResourceAsStream("/" + resourceLocation + "/" + resource), tempFile); + try (InputStream resourceAsStream = getClass().getResourceAsStream("/" + resourceLocation + "/" + resource)) { + final byte[] resourceAsBytes = IOUtils.toByteArray(resourceAsStream); + configuration.getOutputHandlers().forEach(outputHandler -> outputHandler.handle(tempFile, resourceAsBytes)); } catch (IOException e) { // based on FileUtils implementation, should never happen even is declared throw new ValidationException(e); diff --git a/src/main/java/net/masterthought/cucumber/generators/AbstractPage.java b/src/main/java/net/masterthought/cucumber/generators/AbstractPage.java index e8d8a7981..209417c00 100644 --- a/src/main/java/net/masterthought/cucumber/generators/AbstractPage.java +++ b/src/main/java/net/masterthought/cucumber/generators/AbstractPage.java @@ -1,15 +1,5 @@ package net.masterthought.cucumber.generators; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.nio.charset.StandardCharsets; -import java.util.Properties; -import java.util.logging.Level; -import java.util.logging.Logger; - import net.masterthought.cucumber.Configuration; import net.masterthought.cucumber.ReportBuilder; import net.masterthought.cucumber.ReportResult; @@ -27,6 +17,12 @@ import org.apache.velocity.app.event.EventCartridge; import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; + /** * Delivers common methods for page generation. * @@ -57,7 +53,7 @@ protected AbstractPage(ReportResult reportResult, String templateFileName, Confi this.reportResult = reportResult; this.configuration = configuration; - this.engine.init(buildProperties()); + engine.init(buildProperties()); buildGeneralParameters(); } @@ -81,8 +77,12 @@ private void generateReport() { Template template = engine.getTemplate("templates/generators/" + templateFileName); File reportFile = new File(configuration.getReportDirectory(), ReportBuilder.BASE_DIRECTORY + configuration.getDirectorySuffixWithSeparator() + File.separatorChar + getWebPage()); - try (Writer writer = new OutputStreamWriter(new FileOutputStream(reportFile), StandardCharsets.UTF_8)) { + + try (ByteArrayOutputStream out = new ByteArrayOutputStream(2048); + Writer writer = new OutputStreamWriter(new BufferedOutputStream(out), StandardCharsets.UTF_8)) { template.merge(context, writer); + writer.flush(); + configuration.getOutputHandlers().forEach(outputHandler -> outputHandler.handle(reportFile, out.toByteArray())); } catch (IOException e) { throw new ValidationException(e); } diff --git a/src/main/java/net/masterthought/cucumber/json/deserializers/EmbeddingDeserializer.java b/src/main/java/net/masterthought/cucumber/json/deserializers/EmbeddingDeserializer.java index 401b5c1d8..2d21a6a00 100644 --- a/src/main/java/net/masterthought/cucumber/json/deserializers/EmbeddingDeserializer.java +++ b/src/main/java/net/masterthought/cucumber/json/deserializers/EmbeddingDeserializer.java @@ -2,13 +2,10 @@ import com.fasterxml.jackson.databind.JsonNode; import net.masterthought.cucumber.Configuration; -import net.masterthought.cucumber.ValidationException; import net.masterthought.cucumber.json.Embedding; import java.io.File; -import java.io.IOException; import java.nio.file.FileSystems; -import java.nio.file.Files; import java.nio.file.Path; import java.util.Base64; @@ -37,18 +34,18 @@ public Embedding deserialize(JsonNode rootNode, Configuration configuration) { embedding = new Embedding(mimeType, encodedData); } - storeEmbedding(embedding, configuration.getEmbeddingDirectory()); + storeEmbedding(embedding, configuration); return embedding; } private String getBase64EncodedData(String data) { - try{ + try { // If we can successfully decode the data we consider it to be base64 encoded, // so we do not need to do anything here Base64.getDecoder().decode(data); return data; - }catch (IllegalArgumentException e){ + } catch (IllegalArgumentException e) { // decoding failed, therefore we consider the data not to be encoded, // so we need to encode it return new String(Base64.getEncoder().encode(data.getBytes(UTF_8)), UTF_8); @@ -65,15 +62,12 @@ private String findMimeType(JsonNode rootNode) { return rootNode.get("mime_type").asText(); } - private void storeEmbedding(Embedding embedding, File embeddingDirectory) { - Path file = FileSystems.getDefault().getPath(embeddingDirectory.getAbsolutePath(), + private void storeEmbedding(Embedding embedding, Configuration configuration) { + Path path = FileSystems.getDefault().getPath(configuration.getEmbeddingDirectory().getAbsolutePath(), embedding.getFileId() + "." + embedding.getExtension()); + final File file = new File(path.toUri()); byte[] decodedData = Base64.getDecoder().decode(embedding.getData().getBytes(UTF_8)); - try { - Files.write(file, decodedData); - } catch (IOException e) { - throw new ValidationException(e); - } + configuration.getOutputHandlers().forEach(outputHandler -> outputHandler.handle(file, decodedData)); } } diff --git a/src/main/java/net/masterthought/cucumber/outputhandlers/FilesystemOutputHandler.java b/src/main/java/net/masterthought/cucumber/outputhandlers/FilesystemOutputHandler.java new file mode 100644 index 000000000..0b1a36510 --- /dev/null +++ b/src/main/java/net/masterthought/cucumber/outputhandlers/FilesystemOutputHandler.java @@ -0,0 +1,22 @@ +package net.masterthought.cucumber.outputhandlers; + +import net.masterthought.cucumber.ValidationException; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.IOException; + +/** + * @author Florian Kaemmerer (FlorianKaemmerer@github) + */ +public class FilesystemOutputHandler implements OutputHandler { + + @Override + public void handle(File file, byte[] fileContent) { + try { + FileUtils.writeByteArrayToFile(file, fileContent); + } catch (IOException e) { + throw new ValidationException(e); + } + } +} diff --git a/src/main/java/net/masterthought/cucumber/outputhandlers/OutputHandler.java b/src/main/java/net/masterthought/cucumber/outputhandlers/OutputHandler.java new file mode 100644 index 000000000..89e39c602 --- /dev/null +++ b/src/main/java/net/masterthought/cucumber/outputhandlers/OutputHandler.java @@ -0,0 +1,23 @@ +package net.masterthought.cucumber.outputhandlers; + +import net.masterthought.cucumber.ValidationException; + +import java.io.File; + +/** + * OutputHandlers are used to handle the generated Report Files. + * for every configured OutputHandler the handle method will be called during the generation process of the report. + * + * @author Florian Kaemmerer (FlorianKaemmerer@github) + */ +public interface OutputHandler { + + /** + * For every configured OutputHandler the handle method will be called during the generation process of the report. + * + * @param file the file to be handled + * @param fileContent content of the file to be handled + * @throws ValidationException + */ + void handle(File file, byte[] fileContent) throws ValidationException; +} diff --git a/src/test/java/net/masterthought/cucumber/ConfigurationTest.java b/src/test/java/net/masterthought/cucumber/ConfigurationTest.java index 2638e588a..92e11f7e0 100644 --- a/src/test/java/net/masterthought/cucumber/ConfigurationTest.java +++ b/src/test/java/net/masterthought/cucumber/ConfigurationTest.java @@ -1,18 +1,19 @@ package net.masterthought.cucumber; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; +import net.masterthought.cucumber.json.support.Status; +import net.masterthought.cucumber.outputhandlers.FilesystemOutputHandler; +import net.masterthought.cucumber.outputhandlers.OutputHandler; +import net.masterthought.cucumber.presentation.PresentationMode; +import net.masterthought.cucumber.reducers.ReducingMethod; +import net.masterthought.cucumber.sorting.SortingMethod; +import org.junit.Test; import java.io.File; import java.util.*; import java.util.regex.Pattern; -import org.junit.Test; - -import net.masterthought.cucumber.json.support.Status; -import net.masterthought.cucumber.presentation.PresentationMode; -import net.masterthought.cucumber.reducers.ReducingMethod; -import net.masterthought.cucumber.sorting.SortingMethod; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; /** * @author Damian Szczepanik (damianszczepanik@github) @@ -420,4 +421,57 @@ public void setNotFailingStatuses_SkipsNullValues() { // then assertThat(configuration.getNotFailingStatuses()).containsExactly(notFailingStatus); } + + @Test + public void getOutputHandlers_containsFilesystemOutputHandler() { + Configuration configuration = new Configuration(outputDirectory, projectName); + + assertThat(configuration.getOutputHandlers()).hasSize(1); + assertThat(configuration.getOutputHandlers().get(0)).isInstanceOf(FilesystemOutputHandler.class); + } + + @Test + public void clearOutputHandlers_removesAllOutputHandlersFromOutputHandlersList() { + //given + Configuration configuration = new Configuration(outputDirectory, projectName); + configuration.addOutputHandler(new FilesystemOutputHandler()); + + //when + configuration.clearOutputHandlers(); + + //then + assertThat(configuration.getOutputHandlers()).isEmpty(); + } + + @Test + public void addOutputHandler_addsGivenHandlerToListOfOutputHandlers() { + //given + Configuration configuration = new Configuration(outputDirectory, projectName); + configuration.clearOutputHandlers(); + + //when + FilesystemOutputHandler outputHandler = new FilesystemOutputHandler(); + configuration.addOutputHandler(outputHandler); + + //then + assertThat(configuration.getOutputHandlers().size()).isOne(); + assertThat(configuration.getOutputHandlers().get(0)).isEqualTo(outputHandler); + } + + @Test + public void removeOutputHandler_removesOnlyTheGivenOutputHandlerFromOutputHandlersList() { + //given + Configuration configuration = new Configuration(outputDirectory, projectName); + OutputHandler handlerThatShouldStayInTheList = configuration.getOutputHandlers().get(0); + final FilesystemOutputHandler outputHandlerThatShouldBeRemoved = new FilesystemOutputHandler(); + configuration.addOutputHandler(outputHandlerThatShouldBeRemoved); + + //when + configuration.removeOutputHandler(outputHandlerThatShouldBeRemoved); + + //then + assertThat(configuration.getOutputHandlers().size()).isOne(); + assertThat(configuration.getOutputHandlers()).contains(handlerThatShouldStayInTheList); + assertThat(configuration.getOutputHandlers()).doesNotContain(outputHandlerThatShouldBeRemoved); + } } diff --git a/src/test/java/net/masterthought/cucumber/ReportBuilderTest.java b/src/test/java/net/masterthought/cucumber/ReportBuilderTest.java index 8328f8761..046f16064 100644 --- a/src/test/java/net/masterthought/cucumber/ReportBuilderTest.java +++ b/src/test/java/net/masterthought/cucumber/ReportBuilderTest.java @@ -1,27 +1,20 @@ package net.masterthought.cucumber; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.fail; - -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - import mockit.Deencapsulation; +import net.masterthought.cucumber.generators.OverviewReport; +import net.masterthought.cucumber.json.Feature; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.WildcardFileFilter; import org.junit.After; import org.junit.Before; import org.junit.Test; -import net.masterthought.cucumber.generators.OverviewReport; -import net.masterthought.cucumber.json.Feature; +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.util.*; + +import static org.assertj.core.api.Assertions.*; /** * @author Damian Szczepanik (damianszczepanik@github) @@ -50,8 +43,8 @@ public void setUp() throws IOException { public void cleanUp() throws IOException { FileUtils.deleteDirectory(reportDirectory); if (configuration != null) { - FileUtils.deleteDirectory(new File(configuration.getReportDirectory(), - ReportBuilder.BASE_DIRECTORY + configuration.getDirectorySuffixWithSeparator())); + FileUtils.deleteDirectory(new File(configuration.getReportDirectory(), + ReportBuilder.BASE_DIRECTORY + configuration.getDirectorySuffixWithSeparator())); } } @@ -173,22 +166,6 @@ public void copyStaticResources_CopiesRequiredFiles() { assertThat(files).hasSize(21); } - @Test - public void createEmbeddingsDirectory_CreatesDirectory() { - - // given - File subDirectory = new File(reportDirectory, "sub"); - - Configuration configuration = new Configuration(subDirectory, "myProject"); - ReportBuilder builder = new ReportBuilder(Collections.emptyList(), configuration); - - // when - Deencapsulation.invoke(builder, "createEmbeddingsDirectory"); - - // then - assertThat(subDirectory).exists(); - } - @Test public void copyResources_OnInvalidPath_ThrowsException() { @@ -485,10 +462,10 @@ public void generateErrorPage_GeneratesErrorPage() { // then assertPageExists(reportDirectory, configuration.getDirectorySuffixWithSeparator(), ReportBuilder.HOME_PAGE); } - + private File[] countHtmlFiles(Configuration configuration) { - FileFilter fileFilter = new WildcardFileFilter("*.html"); - File dir = new File(configuration.getReportDirectory(), ReportBuilder.BASE_DIRECTORY + configuration.getDirectorySuffixWithSeparator()); + FileFilter fileFilter = new WildcardFileFilter("*.html"); + File dir = new File(configuration.getReportDirectory(), ReportBuilder.BASE_DIRECTORY + configuration.getDirectorySuffixWithSeparator()); return dir.listFiles(fileFilter); } diff --git a/src/test/java/net/masterthought/cucumber/generators/integrations/OutputHandlerConfigurationIntegrationTest.java b/src/test/java/net/masterthought/cucumber/generators/integrations/OutputHandlerConfigurationIntegrationTest.java new file mode 100644 index 000000000..710b36e22 --- /dev/null +++ b/src/test/java/net/masterthought/cucumber/generators/integrations/OutputHandlerConfigurationIntegrationTest.java @@ -0,0 +1,54 @@ +package net.masterthought.cucumber.generators.integrations; + +import net.masterthought.cucumber.ReportBuilder; +import net.masterthought.cucumber.ValidationException; +import net.masterthought.cucumber.generators.FeaturesOverviewPage; +import net.masterthought.cucumber.outputhandlers.OutputHandler; +import org.junit.Test; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class OutputHandlerConfigurationIntegrationTest extends PageTest { + + private final InMemoryOutputHandler inMemoryOutputHandler = new InMemoryOutputHandler(); + + @Test + public void addOutputHandler_addedOutputHandlerIsUsedDuringReportGeneration() { + // Given + // We want the default filesystemOutputHandler and a inMemoryHandler, + // to assert that both Handlers are used and called with the same files. + // So we add an inMemoryHandler + configuration.addOutputHandler(inMemoryOutputHandler); + + //When + setUpWithJson(SAMPLE_JSON); + page = new FeaturesOverviewPage(reportResult, configuration); + page.generatePage(); + + //Then + Map files = inMemoryOutputHandler.getFiles(); + + // The FilesystemOutputHandler writes the Files to the filesystem, + // to assert if all files that are handled by the inMemoryHandler are also + // handled by the filesystemHandler we assert if the files exist on the filesystem. + assertThat(files.keySet().stream().allMatch(File::exists)).isTrue(); + } + + + private static class InMemoryOutputHandler implements OutputHandler { + private final Map files = new HashMap<>(); + + @Override + public void handle(File file, byte[] fileContent) throws ValidationException { + files.put(file, fileContent); + } + + public Map getFiles() { + return files; + } + } +} diff --git a/src/test/java/net/masterthought/cucumber/outputhandlers/FilesystemOutputHandlerTest.java b/src/test/java/net/masterthought/cucumber/outputhandlers/FilesystemOutputHandlerTest.java new file mode 100644 index 000000000..601b3a504 --- /dev/null +++ b/src/test/java/net/masterthought/cucumber/outputhandlers/FilesystemOutputHandlerTest.java @@ -0,0 +1,42 @@ +package net.masterthought.cucumber.outputhandlers; + +import org.apache.commons.io.FileUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.nio.file.Files; +import java.util.UUID; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.assertj.core.api.Assertions.assertThat; + +public class FilesystemOutputHandlerTest { + + private File outputDirectory; + + @Before + public void setup() throws Exception { + outputDirectory = new File("target", UUID.randomUUID().toString()); + Files.createDirectories(outputDirectory.toPath()); + } + + @After + public void cleanup() throws Exception { + FileUtils.deleteDirectory(outputDirectory); + } + + @Test + public void handle_writesGivenFileContentToGivenFile() throws Exception { + final File filesystemOutputHandlerTestOutputFile = new File(outputDirectory, "FilesystemOutputHandler_Testoutput.txt"); + FilesystemOutputHandler fileSystemOutputHandler = new FilesystemOutputHandler(); + final String expectedOutput = "This is the FilesystemOutputHandler output"; + fileSystemOutputHandler.handle(filesystemOutputHandlerTestOutputFile, expectedOutput.getBytes(UTF_8)); + + assertThat(filesystemOutputHandlerTestOutputFile).exists(); + + String writtenOutput = new String(Files.readAllBytes(filesystemOutputHandlerTestOutputFile.toPath()), UTF_8); + assertThat(writtenOutput).isEqualTo(expectedOutput); + } +}