package fitnesse.testrunner;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import fitnesse.components.TraversalListener;
import fitnesse.testsystems.ClassPath;
import fitnesse.testsystems.TestPage;
import fitnesse.wiki.BaseWikitextPage;
import fitnesse.wiki.PageData;
import fitnesse.wiki.PathParser;
import fitnesse.wiki.SymbolicPage;
import fitnesse.wiki.WikiPage;
import fitnesse.wiki.WikiPagePath;
import fitnesse.wikitext.parser.HtmlTranslator;
import fitnesse.wikitext.parser.Parser;
import fitnesse.wikitext.parser.ParsingPage;
import fitnesse.wikitext.parser.Symbol;
import fitnesse.wikitext.parser.WikiSourcePage;
// TODO: need 2 implementations, one for wiki text pages (Fit, Slim) and one for non-wiki text pages. See PagesByTestSystem
public class WikiTestPage implements TestPage {
public static final String TEAR_DOWN = "TearDown";
public static final String SET_UP = "SetUp";
private final WikiPage sourcePage;
private List<WikiPage> scenarioLibraries;
private WikiPage setUp;
private WikiPage tearDown;
public WikiTestPage(WikiPage sourcePage) {
this.sourcePage = sourcePage;
}
public PageData getData() {
return sourcePage.getData();
}
@Override
public String getHtml() {
// -AJM- Okay, this is not as clean as I'd like it to be, but for now it does the trick
if (containsWikitext()) {
String content = getDecoratedContent();
ParsingPage parsingPage = BaseWikitextPage.makeParsingPage((BaseWikitextPage) sourcePage);
Symbol syntaxTree = Parser.make(parsingPage, content).parse();
return new HtmlTranslator(new WikiSourcePage(sourcePage), parsingPage).translateTree(syntaxTree);
} else {
return sourcePage.getHtml();
}
}
private boolean containsWikitext() {
return SymbolicPage.containsWikitext(sourcePage);
}
@Override
public String getVariable(String variable) {
return sourcePage.getVariable(variable);
}
@Override
public String getFullPath() {
return PathParser.render(sourcePage.getPageCrawler().getFullPath());
}
@Override
public ClassPath getClassPath() {
return new ClassPath(new ClassPathBuilder().getClassPath(sourcePage), getPathSeparator());
}
@Override
public String getContent() {
if (containsWikitext()) {
return getDecoratedContent();
} else {
return sourcePage.getData().getContent();
}
}
protected String getPathSeparator() {
String separator = sourcePage.getVariable(PageData.PATH_SEPARATOR);
if (separator == null)
separator = File.pathSeparator;
return separator;
}
public WikiPage getSourcePage() {
return sourcePage;
}
protected String getDecoratedContent() {
StringBuilder decoratedContent = new StringBuilder(1024);
includeScenarioLibraries(decoratedContent);
includePage(getSetUp(), "-setup", decoratedContent);
addPageContent(decoratedContent);
includePage(getTearDown(), "-teardown", decoratedContent);
return decoratedContent.toString();
}
protected void addPageContent(StringBuilder decoratedContent) {
String content = getData().getContent();
decoratedContent
.append("\n")
.append(content)
.append(content.endsWith("\n") ? "" : "\n");
}
protected void includeScenarioLibraries(StringBuilder decoratedContent) {
final List<WikiPage> libraries = getScenarioLibraries();
if (!libraries.isEmpty()) {
if (libraries.size() > 1) {
decoratedContent.append("!*> Scenario Libraries\n");
}
for (WikiPage scenarioLibrary : libraries) {
includeScenarioLibrary(scenarioLibrary, decoratedContent);
}
if (libraries.size() > 1) {
decoratedContent.append("*!\n");
}
}
}
protected void includeScenarioLibrary(WikiPage scenarioLibrary, StringBuilder newPageContent) {
newPageContent.append("!include -c .");
newPageContent.append(getPathNameForPage(scenarioLibrary));
newPageContent.append("\n");
}
protected void includePage(WikiPage wikiPage, String arg, StringBuilder newPageContent) {
if (wikiPage == null)
return;
String pagePathName = getPathNameForPage(wikiPage);
newPageContent
.append("!include ")
.append(arg)
.append(" .")
.append(pagePathName)
.append("\n");
}
private String getPathNameForPage(WikiPage page) {
WikiPagePath pagePath = page.getPageCrawler().getFullPath();
return PathParser.render(pagePath);
}
public String getPath() {
return getPathNameForPage(sourcePage);
}
@Override
public String getName() {
return sourcePage.getName();
}
public boolean shouldIncludeScenarioLibraries() {
// Should consider all of the decorated content to resolve those variables.
String testSystem = sourcePage.getVariable(WikiPageIdentity.TEST_SYSTEM);
boolean isSlim = "slim".equalsIgnoreCase(testSystem)
|| "slimCoverage".equalsIgnoreCase(testSystem);
String includeScenarioLibraries = sourcePage.getVariable("INCLUDE_SCENARIO_LIBRARIES");
boolean includeScenarios = "true".equalsIgnoreCase(includeScenarioLibraries);
boolean notIncludeScenarios = "false".equalsIgnoreCase(includeScenarioLibraries);
return includeScenarios || (!notIncludeScenarios && isSlim);
}
public List<WikiPage> getScenarioLibraries() {
if (scenarioLibraries == null) {
scenarioLibraries = findScenarioLibraries();
}
return scenarioLibraries;
}
public WikiPage getSetUp() {
if (setUp == null && !isSuiteSetUpOrTearDownPage()) {
setUp = findInheritedPage(SET_UP);
}
return setUp;
}
public WikiPage getTearDown() {
if (tearDown == null && !isSuiteSetUpOrTearDownPage()) {
tearDown = findInheritedPage(TEAR_DOWN);
}
return tearDown;
}
protected boolean isSuiteSetUpOrTearDownPage() {
return isSuiteSetupOrTearDown(sourcePage);
}
protected WikiPage findInheritedPage(String pageName) {
return sourcePage.getPageCrawler().getClosestInheritedPage(pageName);
}
private List<WikiPage> findScenarioLibraries() {
final LinkedList<WikiPage> uncles = new LinkedList<>();
if (shouldIncludeScenarioLibraries()) {
sourcePage.getPageCrawler().traverseUncles("ScenarioLibrary", new TraversalListener<WikiPage>() {
@Override
public void process(WikiPage page) {
uncles.addFirst(page);
}
});
}
return uncles;
}
public static boolean isSuiteSetupOrTearDown(WikiPage wikiPage) {
String name = wikiPage.getName();
return (PageData.SUITE_SETUP_NAME.equals(name) || PageData.SUITE_TEARDOWN_NAME.equals(name));
}
}