package fitnesse.responders.testHistory; import java.io.File; import java.text.SimpleDateFormat; import java.util.LinkedList; import java.util.List; import fitnesse.reporting.history.MostRecentPageHistoryReader; import fitnesse.reporting.history.PageHistory; import fitnesse.reporting.history.TestResultRecord; import fitnesse.wiki.WikiPage; import util.GracefulNamer; public class SuiteOverviewTree { private final TreeItem treeRoot = new TreeItem("root", ""); public SuiteOverviewTree(List<WikiPage> wikiPagelist) { makeTree(convertToPageList(wikiPagelist)); } private void makeTree(List<String> pageList) { for (String pageName : pageList) { String[] splits = pageName.split("\\."); treeRoot.addItem(splits, 0); } compactTree(); } public TreeItem getTreeRoot() { return treeRoot; } private static List<String> convertToPageList(List<WikiPage> wikiPagelist) { List<String> allPages = new LinkedList<>(); for (WikiPage aPage : wikiPagelist) { try { allPages.add(aPage.getPageCrawler().getFullPath().toString()); } catch (Exception e) { allPages.add("There was also a probem getting the path of one page."); } } return allPages; } public void countResults() { RecursiveTreeMethod countResults = new RecursiveTreeMethod() { @Override public boolean shouldDoItemBeforeBranches() { return false; } @Override public void doMethod(TreeItem item) { item.calculateResults(); } }; treeRoot.doRecursive(countResults, 0); } public void findLatestResults(final File historyDirectory) { RecursiveTreeMethod findLatestResult = new RecursiveTreeMethod() { @Override public void doMethod(TreeItem item) { if (item.isTest()) { File directory = new File(historyDirectory, item.fullName); MostRecentPageHistoryReader reader = new MostRecentPageHistoryReader(directory); item.result = reader.findMostRecentTestRun(); } } }; treeRoot.doRecursive(findLatestResult, 0); } private void compactTree() { RecursiveTreeMethod compactBranch = new RecursiveTreeMethod() { @Override public void doMethod(TreeItem item) { item.compactWithChildIfOnlyOneChild(); } }; treeRoot.doRecursive(compactBranch, 0); } private SimpleDateFormat dateFormatter = new SimpleDateFormat(PageHistory.TEST_RESULT_FILE_DATE_PATTERN); public class TreeItem { private String name; private String fullName; int testsPassed = 0; int testsUnrun = 0; int testsFailed = 0; List<TreeItem> branches = new LinkedList<>(); TestResultRecord result = null; public int getTestsPassed() { return testsPassed; } public int getTestsUnrun() { return testsUnrun; } public int getTestsFailed() { return testsFailed; } private double calcPercentOfTotalTests(int value) { int totalTests = testsPassed + testsUnrun + testsFailed; return ((double)(Math.round(((1000.0 * value)/totalTests))))/10; } private String makePercentageOfTotalString(int value) { double percentage = calcPercentOfTotalTests(value); if (calcPercentOfTotalTests(value) < 99.95) { return "(" + (int)percentage + "%)"; } return ""; } public String getPassedPercentString() { return makePercentageOfTotalString(testsPassed); } public String getUnrunPercentString() { return makePercentageOfTotalString(testsUnrun); } public String getFailedPercentString() { return makePercentageOfTotalString(testsFailed); } public double getPassedPercent() { return calcPercentOfTotalTests(testsPassed); } public double getUnrunPercent() { return calcPercentOfTotalTests(testsUnrun); } public double getFailedPercent() { return calcPercentOfTotalTests(testsFailed); } public String getName() { return GracefulNamer.regrace(name); } public String getFullName() { return fullName; } public String getHistoryUrl() { String url = getFullName(); if (result != null) { url += "?pageHistory&resultDate="; url += dateFormatter.format(result.getDate()); } return url; } public void compactWithChildIfOnlyOneChild() { if (branches.size() == 1) { TreeItem child = branches.get(0); if (!child.isTest()) { name += "." + child.name; fullName += "." + child.name; branches = child.branches; compactWithChildIfOnlyOneChild(); } } } TreeItem(String branchName, String branchFullName) { name = branchName; fullName = branchFullName; } public List<TreeItem> getBranches() { return branches; } public void calculateResults() { testsPassed = 0; testsUnrun = 0; testsFailed = 0; if (isTest()) { if (result == null) { testsUnrun++; } else if ((result.getExceptions() == 0) && (result.getWrong() == 0)) { testsPassed++; } else { testsFailed++; } } else { for (TreeItem branch : branches) { testsUnrun += branch.testsUnrun; testsPassed += branch.testsPassed; testsFailed += branch.testsFailed; } } } @Override public String toString() { return name; } void addItem(String[] itemPath, int currentIndex) { if (currentIndex < itemPath.length) { //special case for this tree only, that all the titles should be organised before we start. if (nameSameAsLastName(itemPath[currentIndex])) { branches.get(branches.size() - 1).addItem(itemPath, ++currentIndex); } else { String branchName = itemPath[currentIndex]; String branchFullName = fullName; branchFullName += fullName.isEmpty() ? branchName : "." + branchName; TreeItem branch = new TreeItem(branchName, branchFullName); branches.add(branch); branch.addItem(itemPath, ++currentIndex); } } } private boolean nameSameAsLastName(String currentName) { return !branches.isEmpty() && branches.get(branches.size() - 1).name.equals(currentName); } public boolean isTest() { return (branches.isEmpty()); } public String getCssClass() { if (testsFailed != 0) { return "fail"; } else if (testsUnrun != 0) { return "unrun"; } else { return "done"; } } void doRecursive(RecursiveTreeMethod method, int level) { if (method.shouldDoItemBeforeBranches() && (level != 0)) { method.doMethod(this); } for (TreeItem branch : branches) { branch.doRecursive(method, level + 1); } if (!method.shouldDoItemBeforeBranches() && (level != 0)) { method.doMethod(this); } } } abstract class RecursiveTreeMethod { public boolean shouldDoItemBeforeBranches() { return true; } public abstract void doMethod(TreeItem item); } }