package net.thucydides.core.reports.html;
import net.thucydides.core.ThucydidesSystemProperty;
import net.thucydides.core.guice.Injectors;
import net.thucydides.core.model.TestOutcome;
import net.thucydides.core.reports.TestOutcomes;
import net.thucydides.core.reports.ThucydidesReporter;
import net.thucydides.core.reports.templates.ReportTemplate;
import net.thucydides.core.reports.templates.TemplateManager;
import net.thucydides.core.util.EnvironmentVariables;
import org.apache.commons.io.FileUtils;
import org.joda.time.DateTime;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.Map;
/**
* An HTML report generates reports in a given directory and uses resources (images,...) from another.
*
* @author johnsmart
*/
public abstract class HtmlReporter extends ThucydidesReporter {
private static final String DEFAULT_RESOURCE_DIRECTORY = "report-resources";
private static final String DEFAULT_SOURCE_DIR = "target/site/thucydides";
private String resourceDirectory = DEFAULT_RESOURCE_DIRECTORY;
private final TemplateManager templateManager;
private final EnvironmentVariables environmentVariables;
protected static final String TIMESTAMP_FORMAT = "dd-MM-YYYY HH:mm";
public HtmlReporter() {
this(Injectors.getInjector().getProvider(EnvironmentVariables.class).get() );
}
public HtmlReporter(final EnvironmentVariables environmentVariables) {
super();
this.templateManager = Injectors.getInjector().getInstance(TemplateManager.class);
this.environmentVariables = environmentVariables;
}
private TemplateManager getTemplateManager() {
return templateManager;
}
/**
* Resources such as CSS stylesheets or images.
*/
public void setResourceDirectory(final String resourceDirectory) {
this.resourceDirectory = resourceDirectory;
}
public String getResourceDirectory() {
return resourceDirectory;
}
protected EnvironmentVariables getEnvironmentVariables() {
return environmentVariables;
}
private boolean alreadyCopied = false;
protected void copyResourcesToOutputDirectory() throws IOException {
if (!alreadyCopied) {
alreadyCopied = true;
updateResourceDirectoryFromSystemPropertyIfDefined();
copyResources();
}
}
private void copyResources() throws IOException {
HtmlResourceCopier copier = new HtmlResourceCopier(getResourceDirectory());
copier.copyHTMLResourcesTo(getOutputDirectory());
}
protected void copyTestResultsToOutputDirectory() throws IOException {
File testResultsSource = getSourceDirectoryOrDefault();
if ((!getOutputDirectory().getAbsolutePath().equals(testResultsSource.getAbsolutePath())) && testResultsSource.exists()) {
FileUtils.copyDirectory(testResultsSource, getOutputDirectory(), withXMLorHTMLorCSVFiles());
}
}
private FileFilter withXMLorHTMLorCSVFiles() {
return new FileFilter() {
@Override
public boolean accept(File file) {
return file.getName().endsWith(".xml")
|| file.getName().endsWith(".html")
|| file.getName().endsWith(".csv");
}
};
}
private File getSourceDirectoryOrDefault() {
String source = (getSourceDirectory() != null) ? getSourceDirectory().getAbsolutePath() : DEFAULT_SOURCE_DIR;
return new File(source);
}
private void updateResourceDirectoryFromSystemPropertyIfDefined() {
String systemDefinedResourceDirectory
= getEnvironmentVariables().getProperty(ThucydidesSystemProperty.THUCYDIDES_REPORT_RESOURCES.getPropertyName());
if (systemDefinedResourceDirectory != null) {
setResourceDirectory(systemDefinedResourceDirectory);
}
}
/**
* Write the actual HTML report to a file with the specified name in the output directory.
*/
protected File writeReportToOutputDirectory(final String reportFilename, final String htmlContents) throws
IOException {
File report = new File(getOutputDirectory(), reportFilename);
FileUtils.writeStringToFile(report, htmlContents, Charset.forName("UTF-8"));
return report;
}
protected String timestampFrom(TestOutcomes rootOutcomes) {
return timestampFrom(currentTime());
}
protected String timestampFrom(DateTime startTime) {
return startTime == null ? "" : startTime.toString(TIMESTAMP_FORMAT);
}
protected void addTimestamp(TestOutcome testOutcome, Map<String, Object> context) {
context.put("timestamp", timestampFrom(currentTime()));
}
protected DateTime currentTime() {
return new DateTime();
}
protected Merger mergeTemplate(final String templateFile) {
return new Merger(templateFile);
}
protected class Merger {
final String templateFile;
public Merger(final String templateFile) {
this.templateFile = templateFile;
}
public String usingContext(final Map<String, Object> context) {
try {
ReportTemplate template = getTemplateManager().getTemplateFrom(templateFile);
StringWriter sw = new StringWriter();
template.merge(context, sw);
return sw.toString();
} catch (Exception e) {
throw new RuntimeException("Failed to merge template: " + e.getMessage(), e);
}
}
}
}