package sft.integration.set;
import org.jsoup.nodes.Document;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import sft.Decorate;
import sft.DefaultConfiguration;
import sft.Displayable;
import sft.FixturesHelper;
import sft.SimpleFunctionalTest;
import sft.Text;
import sft.decorators.Breadcrumb;
import sft.integration.fixtures.JUnitHtmlHelper;
import sft.integration.fixtures.JavaResource;
import sft.integration.set.sut.InkConfiguration;
import sft.integration.set.sut.InkStyleUseCase;
import sft.report.HtmlReport;
import sft.report.HtmlResources;
import java.io.File;
import java.io.IOException;
/*
<div>
The DefaultConfiguration provide an HtmlReport to write test result in HTML.<br /><br />
The target of the HtmlReport resourcePath, will be copied to provide facilities files. <br />
This resourcePath is a directory that contains all image, css and js files needed for the report generation and display.<br />
For example, all css and js file of this directory will be included in the html head close.
</div>
*/
@RunWith(SimpleFunctionalTest.class)
@Decorate(decorator = Breadcrumb.class)
public class HtmlReportSettings {
private DefaultConfiguration configuration;
private Document htmlReport;
@Displayable
private String configurationResource;
@FixturesHelper
private JUnitHtmlHelper jUnitHtmlHelper = new JUnitHtmlHelper();
/*
The DefaultConfiguration provide an HtmlReport to write test result in HTML.<br /><br />
The target of the HtmlReport resourcePath, will be copied to provide facilities files. <br />
This resourcePath is a directory that contains all image, css and js files needed for the report generation and display.<br />
For example, all css and js file of this directory will be included in the html head close.
*/
@Test
public void defaultReport(){
theDefaultConfigurationProvideAnHtmlReport();
}
/*
The HtmlReport write report in a specific folder target/sft-result/.
*/
@Test
public void changeHtmlReportDestination() throws Exception {
defaultReportPathOfHtmlReportIs("target/sft-result/");
thenAllReportFilesWillBeCreatedIntoThisFolder("sft.integration.set.HtmlReportSettings", "target/sft-result/sft/integration/set/HtmlReportSettings.html");
bySettingTheReportPathTo("site/");
thenAllReportFilesWillBeCreatedIntoThisFolder("sft.integration.set.HtmlReportSettings", "site/sft/integration/set/HtmlReportSettings.html");
}
@Text("Default report path of html report is ${reportPath}")
private void defaultReportPathOfHtmlReportIs(String reportPath) {
configuration = new DefaultConfiguration();
Assert.assertEquals(reportPath, configuration.getReport(HtmlReport.class).getReportFolder().path);
}
@Text("By setting the report path to ${reportPath}")
private void bySettingTheReportPathTo(String reportPath) {
configuration.getReport(HtmlReport.class).setReportPath(reportPath);
}
@Text("Simple functional test will load classes from this folder( for example the class ${useCaseClass} will generate the html report ${reportFile})")
private void thenAllReportFilesWillBeCreatedIntoThisFolder(String useCaseClass, String reportFile) throws Exception {
File sourceFile = configuration.getReport(HtmlReport.class).getReportFolder().getFileFromClass(Class.forName(useCaseClass), ".html");
String initialPath = sourceFile.getPath();
Assert.assertTrue("expecting "+ initialPath+ " ending with "+ reportFile,initialPath.endsWith(reportFile));
}
/*
The most convenient way to custom your html report, is changing resourcePath.<br />
You can modify native css and js file provide by SimpleFunctionalTest (copied in ./target/sft-result/sft-html-default/)
in an local directory and then set its location as the resourcePath.<br /><br />
Css class used by HtmlReport are:
<ul>
<li>ignored</li>
<li>failed</li>
<li>succeeded</li>
<li>useCase</li>
<li>useCaseName</li>
<li>beforeUseCase</li>
<li>afterUseCase</li>
<li>comment</li>
<li>scenario</li>
<li>scenarioName</li>
<li>beforeScenario</li>
<li>afterScenario</li>
<li>instruction</li>
<li>exception</li>
<li>relatedUseCase</li>
</ul>
*/
@Test
public void changeCssAndJs() throws Exception {
whenHtmlReportUseTheDefaultEmbeddedResource("sft-html-default");
thenHtmlReportIncludePathToJsFile("../../../sft-html-default/bootstrap.min.js, ../../../sft-html-default/jquery-1.10.2.min.js");
andIncluedPathToCssFile("../../../sft-html-default/bootstrap-theme.min.css, ../../../sft-html-default/bootstrap.min.css, ../../../sft-html-default/sft.css");
bySettingTheResourcePathTo("sut-html-resources");
thenHtmlReportIncludePathToJsFile("../../../sut-html-resources/override.js");
andIncluedPathToCssFile("../../../sut-html-resources/override.css");
}
@Text("When html report use the default embedded resource ${path}")
private void whenHtmlReportUseTheDefaultEmbeddedResource(String path) {
configuration = new DefaultConfiguration();
HtmlReport report = configuration.getReport(HtmlReport.class);
HtmlResources htmlResources = report.getHtmlResources();
String actual = htmlResources.path;
Assert.assertEquals(path, actual);
}
@Text("Then html report include path to js files ${pathToJsFiles}")
private void thenHtmlReportIncludePathToJsFile(String pathToJsFiles) {
String includeJs = configuration.getReport(HtmlReport.class).getHtmlResources().getIncludeJsDirectives(this.getClass());
includeJs=includeJs.replaceAll("<script src=\"","");
includeJs=includeJs.replaceAll("\"></script>\n",", ");
includeJs=includeJs.substring(0,includeJs.length()-2);
Assert.assertEquals(pathToJsFiles, includeJs);
}
@Text("And include path to css files ${pathToCssFiles}")
private void andIncluedPathToCssFile(String pathToCssFiles) {
String includeCss = configuration.getReport(HtmlReport.class).getHtmlResources().getIncludeCssDirectives(this.getClass());
includeCss=includeCss.replaceAll("<link rel=\"stylesheet\" href=\"","");
includeCss=includeCss.replaceAll("\" />\n", ", ");
includeCss=includeCss.substring(0,includeCss.length()-2);
Assert.assertEquals(pathToCssFiles, includeCss);
}
@Text("By setting the resource path to ${newResourcePath}")
private void bySettingTheResourcePathTo(String newResourcePath) {
configuration.getReport(HtmlReport.class).setResourcePath(newResourcePath);
}
private void theDefaultConfigurationProvideAnHtmlReport() {
configuration = new DefaultConfiguration();
Assert.assertNotNull(configuration.getReport(HtmlReport.class));
}
/*
The html report could be customized matching your UI design vision.<br />
A basic template engine is used. <br />
You can modify each <a href='#' onclick='$(templates).toggle();return false;'>templates</a>. <br />
All templates are surround by '@@@', excepts for successClass, failedClass and ignoredClass that are values. <br />
<table id='templates' class='table' style='display: none;'>
<tr><th>template</th><th>inner template</th><th>detail of uses</th></tr>
<tr><td rowspan='9'>useCaseTemplate</td><td>useCase.name</td><td>Name of the use case</td></tr>
<tr> <td>useCase.css</td><td>Injection of css available in resource folder</td></tr>
<tr> <td>useCase.js</td><td>Injection of javascript files available in resource folder</td></tr>
<tr> <td>useCase.issue</td><td>Issue of the use case (depending of successClass, failedClass, ignoredClass defined as below)</td></tr>
<tr> <td>useCaseCommentTemplate</td><td>Inclusion of use case comment</td></tr>
<tr> <td>beforeUseCaseTemplate</td><td>Inclusion of use case context raised</td></tr>
<tr> <td>scenarioTemplates</td><td>Inclusion of scenario</td></tr>
<tr> <td>afterUseCaseTemplate</td><td>Inclusion of use case context ended</td></tr>
<tr> <td>relatedUseCasesTemplates</td><td>Inclusion of other use cases</td></tr>
<tr><td>useCaseCommentTemplate</td><td>comment.text</td><td>Text of the comment</td></tr>
<tr><td rowspan='3'>beforeUseCaseTemplate</td><td>beforeUseCase.issue</td><td>Issue of the context raise of use case (depending of successClass, failedClass, ignoredClass defined as below)</td></tr>
<tr> <td>contextInstructionTemplates</td><td>Inclusion of instructions call needed for the context raise of use case</td></tr>
<tr> <td>exceptionTemplate</td><td>Inclusion of exception report if needed</td></tr>
<tr><td rowspan='8'>scenarioTemplate</td><td>scenario.issue</td><td>Issue of the scenario (depending of successClass, failedClass, ignoredClass defined as below)</td></tr>
<tr> <td>scenario.name</td><td>Name of the scenario</td></tr>
<tr> <td>scenarioCommentTemplate</td><td>Inclusion of scenario comment</td></tr>
<tr> <td>beforeScenarioTemplate</td><td>Inclusion of scenario context raise</td></tr>
<tr> <td>scenarioInstructionTemplates</td><td>Inclusion of fixtures call</td></tr>
<tr> <td>afterScenarioTemplate</td><td>Inclusion of scenario context ended</td></tr>
<tr> <td>displayedContextsTemplates</td><td>Inclusion of context fact</td></tr>
<tr> <td>exceptionTemplate</td><td>Inclusion of exception if needed</td></tr>
<tr><td>scenarioCommentTemplate</td><td>comment.text</td><td>Text of the comment</td></tr>
<tr><td rowspan='3'>exceptionTemplate</td><td>failure.className</td><td>Class name of the exception</td></tr>
<tr> <td>failure.message</td><td>Message of the exception</td></tr>
<tr> <td>failure.stacktrace</td><td>Stacktrace of the exception</td></tr>
<tr><td>beforeScenarioTemplate</td><td>contextInstructionTemplates</td><td>Inclusion of one instruction call</td></tr>
<tr><td rowspan='2'>scenarioInstructionTemplate</td><td>instruction.issue</td><td>Issue of the fixture call (depending of successClass, failedClass, ignoredClass defined as below)</td></tr>
<tr> <td>instruction.text</td><td>Text of the fixture call</td></tr>
<tr><td>afterScenarioTemplate</td><td>contextInstructionTemplates</td><td>Inclusion of one instruction call</td></tr>
<tr><td>displayedContextsTemplate</td><td>displayedContextTemplates</td><td>Inclusion of one context detail</td></tr>
<tr><td>displayedContextTemplate</td><td>displayedContext.text</td><td>The detail of the context</td></tr>
<tr><td rowspan='3'>afterUseCaseTemplate</td><td>afterUseCase.issue</td><td>Issue of the context ended (depending of successClass, failedClass, ignoredClass defined as below)</td></tr>
<tr> <td>contextInstructionTemplates</td><td>Inclusion of the instructions call</td></tr>
<tr> <td>exceptionTemplate</td><td>Inclusion of exception if needed</td></tr>
<tr><td>contextInstructionTemplate</td><td>instruction.text</td><td>Text of the instruction call</td></tr>
<tr><td>relatedUseCasesTemplate</td><td>relatedUseCaseTemplates</td><td>Inclusion of related use cases</td></tr>
<tr><td rowspan='3'>relatedUseCaseTemplate</td><td>relatedUseCase.link</td><td>Link to the related use case report</td></tr>
<tr> <td>relatedUseCase.issue</td><td>Issue of the related use case (depending of successClass, failedClass, ignoredClass defined as below)</td></tr>
<tr> <td>relatedUseCase.name</td><td>Name of the related use case</td></tr>
<tr><td>parameterTemplate</td><td>parameter.value</td><td>The value of instruction or fixture call</td></tr>
<tr><td>successClass</td><td></td><td>class of issue successful; default value: success</td></tr>
<tr><td>failedClass</td><td></td><td>class of issue failed; default value: failed</td></tr>
<tr><td>ignoredClass</td><td></td><td>class of issue ignored; default value : warning</td></tr>
</table>
*/
@Test
public void customHtml() throws IOException {
byChangingTemplateValues();
weChangeReportGeneration();
}
private void weChangeReportGeneration() {
final String expectedHtmlBeginning = "<!DOCTYPE html>\n" +
"<html>\n" +
" <head>\n" +
" <title>Test: Ink style use case</title>\n" +
" <link rel=\"stylesheet\" href=\"../../../../other-style/css/ink-min.css\" /> \n" +
" </head>\n" +
" <body>\n" +
" <div class=\"ink-grid gutters\">\n" +
" <h1 class=\"ink-label error invert\">Ink style use case</h1>\n" +
" <div>\n" +
" <p class=\"note\"> Test Use Case comment </p>\n" +
" </div>\n" +
" <div class=\"ink-alert block large-80 success\"> \n" +
" <h4>Before Use Case</h4>\n" +
" <p></p>\n" +
" <div class=\"info ink-label invert\">\n" +
" Set up use case\n" +
" </div>\n" +
" <p></p>\n" +
" </div>\n" +
" <div class=\"ink-alert block large-80 success\"> \n" +
" <h4>Successful scenario</h4>\n" +
" <p></p>\n" +
" <p class=\"note\"> Test scenario comment </p>\n" +
" <hr width=\"80%\" align=\"center\" />\n" +
" <div class=\"info ink-label invert\">\n" +
" Set up scenario\n" +
" </div>\n" +
" <div class=\"success ink-label invert\">\n" +
" <span>Successful condition</span>\n" +
" </div>\n" +
" <div class=\"info ink-label invert\">\n" +
" Tear down scenario\n" +
" </div>\n" +
" <p></p>\n" +
" </div>\n" +
" <div class=\"ink-alert block large-80 error\"> \n" +
" <h4>Unsuccessful scenario</h4>\n" +
" <p></p>\n" +
" <div class=\"info ink-label invert\">\n" +
" Set up scenario\n" +
" </div>\n" +
" <div class=\"success ink-label invert\">\n" +
" <span>Successful condition</span>\n" +
" </div>\n" +
" <div class=\"error ink-label invert\">\n" +
" <span>Condition that failed</span>\n" +
" </div>\n" +
" <div class=\"warning ink-label invert\">\n" +
" <span>Successful condition</span>\n" +
" </div>\n" +
" <div class=\"info ink-label invert\">\n" +
" Tear down scenario\n" +
" </div>\n" +
" <div class=\"ink-alert block error\">\n" +
" <h4><span>AssertionError</span>: <span>Condition failed</span></h4>\n" +
" <p class=\"small\">";
final String expectedHtmlEnd = "</p>\n"+
" </div>\n" +
" <p></p>\n" +
" </div>\n" +
" <div class=\"ink-alert block large-80 warning\"> \n" +
" <h4>Ignored scenario</h4>\n" +
" <p></p>\n" +
" <div class=\"info ink-label invert\">\n" +
" Set up scenario\n" +
" </div>\n" +
" <div class=\"warning ink-label invert\">\n" +
" <span>Successful condition</span>\n" +
" </div>\n" +
" <div class=\"warning ink-label invert\">\n" +
" <span>Condition that failed</span>\n" +
" </div>\n" +
" <div class=\"warning ink-label invert\">\n" +
" <span>Successful condition</span>\n" +
" </div>\n" +
" <div class=\"info ink-label invert\">\n" +
" Tear down scenario\n" +
" </div>\n" +
" <p></p>\n" +
" </div>\n" +
" <div class=\"ink-alert block large-80 success\"> \n" +
" <h4>After Use Case</h4>\n" +
" <p></p>\n" +
" <div class=\"info ink-label invert\">\n" +
" Tear down use case\n" +
" </div>\n" +
" <p></p>\n" +
" </div>\n" +
" <div class=\"large-80 \">\n" +
" <ul>\n" +
" <li><a href=\"subUseCase/SubUseCaseFailed.html\" class=\"ink-label error\">Sub use case failed</a></li>\n" +
" <li><a href=\"subUseCase/SubUseCaseIgnored.html\" class=\"ink-label warning\">Sub use case ignored</a></li>\n" +
" <li><a href=\"subUseCase/SubUseCaseSucceeded.html\" class=\"ink-label success\">Sub use case succeeded</a></li>\n" +
" </ul>\n" +
" </div>\n" +
" </div>\n" +
" <div class=\"large-80\">\n" +
" @Copyright nevermind\n" +
" </div>\n" +
" </body>\n" +
"</html>";
final String html = htmlReport.outerHtml();
final String actualHtmlBeginning = html.substring(0, expectedHtmlBeginning.length());
final String actualHtmlEnd = html.substring(html.length() - expectedHtmlEnd.length());
Assert.assertEquals(expectedHtmlBeginning,actualHtmlBeginning);
Assert.assertEquals(expectedHtmlEnd,actualHtmlEnd);
}
private void byChangingTemplateValues() throws IOException {
jUnitHtmlHelper.run(this.getClass(),InkStyleUseCase.class);
htmlReport = jUnitHtmlHelper.html;
JavaResource configurationClass = new JavaResource(InkConfiguration.class);
configurationResource ="<div class=\"resources\">"+ configurationClass.getOpenResourceHtmlLink(this.getClass(), "configuration", "alert-info")+ "</div>" ;
}
}