1package org.testng.reporters.jq;
2
3import org.testng.ISuite;
4import org.testng.ISuiteResult;
5import org.testng.ITestContext;
6import org.testng.ITestResult;
7import org.testng.collections.Lists;
8import org.testng.reporters.XMLStringBuffer;
9
10import java.util.Collections;
11import java.util.List;
12import java.util.Map;
13
14public class NavigatorPanel extends BasePanel {
15
16  private List<INavigatorPanel> m_panels;
17
18  public NavigatorPanel(Model model, List<INavigatorPanel> panels) {
19    super(model);
20    m_panels = panels;
21  }
22
23  @Override
24  public void generate(XMLStringBuffer main) {
25    main.push(D, C, "navigator-root");
26    main.push(D, C, "navigator-suite-header");
27    main.addRequired(S, "All suites");
28    main.push("a", C, "collapse-all-link", "href", "#", "title", "Collapse/expand all the suites");
29    main.push("img", "src", "collapseall.gif", C, "collapse-all-icon");
30    main.pop("img");
31    main.pop("a");
32    main.pop(D);
33    for (ISuite suite : getSuites()) {
34      if (suite.getResults().size() == 0) {
35        continue;
36      }
37
38      String suiteName = "suite-" + suiteToTag(suite);
39
40      XMLStringBuffer header = new XMLStringBuffer(main.getCurrentIndent());
41
42      Map<String, ISuiteResult> results = suite.getResults();
43      int failed = 0;
44      int skipped = 0;
45      int passed = 0;
46      for (ISuiteResult result : results.values()) {
47        ITestContext context = result.getTestContext();
48        failed += context.getFailedTests().size();
49        skipped += context.getSkippedTests().size();
50        passed += context.getPassedTests().size();
51      }
52
53      // Suite name in big font
54      header.push(D, C, "suite");
55      header.push(D, C, "rounded-window");
56      // Extra div so the highlighting logic will only highlight this line and not
57      // the entire container
58      header.push(D, C, "suite-header light-rounded-window-top");
59      header.push("a", "href", "#",
60          "panel-name", suiteName,
61          C, "navigator-link");
62      header.addOptional(S, suite.getName(),
63          C, "suite-name border-" + getModel().getStatusForSuite(suite.getName()));
64      header.pop("a");
65      header.pop(D);
66
67      header.push(D, C, "navigator-suite-content");
68
69      generateInfo(header, suite);
70      generateResult(header, failed, skipped, passed, suite, suiteName);
71
72      header.pop("ul");
73
74      header.pop(D); // suite-section-content
75      header.pop(D); // suite-header
76      header.pop(D); // suite
77
78      header.pop(D); // result-section
79
80      header.pop(D); // navigator-suite-content
81
82      main.addString(header.toXML());
83    }
84    main.pop(D);
85  }
86
87  private void generateResult(XMLStringBuffer header, int failed, int skipped, int passed,
88      ISuite suite, String suiteName) {
89    //
90    // Results
91    //
92    header.push(D, C, "result-section");
93
94    header.push(D, C, "suite-section-title");
95    header.addRequired(S, "Results");
96    header.pop(D);
97
98    // Method stats
99    int total = failed + skipped + passed;
100    String stats = String.format("%s, %s %s %s",
101        pluralize(total, "method"),
102        maybe(failed, "failed", ", "),
103        maybe(skipped, "skipped", ", "),
104        maybe(passed, "passed", ""));
105    header.push(D, C, "suite-section-content");
106    header.push("ul");
107    header.push("li");
108    header.addOptional(S, stats, C, "method-stats");
109    header.pop("li");
110
111    generateMethodList("Failed methods", new ResultsByStatus(suite, "failed", ITestResult.FAILURE),
112        suiteName, header);
113    generateMethodList("Skipped methods", new ResultsByStatus(suite, "skipped", ITestResult.SKIP),
114        suiteName, header);
115    generateMethodList("Passed methods", new ResultsByStatus(suite, "passed", ITestResult.SUCCESS),
116        suiteName, header);
117    }
118
119  private void generateInfo(XMLStringBuffer header, ISuite suite) {
120    //
121    // Info
122    //
123    header.push(D, C, "suite-section-title");
124    header.addRequired(S, "Info");
125    header.pop(D);
126
127    header.push(D, C, "suite-section-content");
128
129    header.push("ul");
130
131    // All the panels
132    for (INavigatorPanel panel : m_panels) {
133      addLinkTo(header, panel, suite);
134    }
135
136    header.pop("ul");
137    header.pop(D); // suite-section-content
138  }
139
140  private void addLinkTo(XMLStringBuffer header, INavigatorPanel panel, ISuite suite) {
141    String text = panel.getNavigatorLink(suite);
142    header.push("li");
143    header.push("a", "href", "#",
144        "panel-name", panel.getPanelName(suite),
145        C, "navigator-link ");
146    String className = panel.getClassName();
147    if (className != null) {
148      header.addOptional(S, text, C, className);
149    } else {
150      header.addOptional(S, text);
151    }
152    header.pop("a");
153    header.pop("li");
154  }
155
156  private static String maybe(int count, String s, String sep) {
157    return count > 0 ? count + " " + s + sep: "";
158  }
159
160  private List<ITestResult> getMethodsByStatus(ISuite suite, int status) {
161    List<ITestResult> result = Lists.newArrayList();
162    List<ITestResult> testResults = getModel().getTestResults(suite);
163    for (ITestResult tr : testResults) {
164      if (tr.getStatus() == status) {
165        result.add(tr);
166      }
167    }
168    Collections.sort(result, ResultsByClass.METHOD_NAME_COMPARATOR);
169
170    return result;
171  }
172
173  private static interface IResultProvider {
174    List<ITestResult> getResults();
175    String getType();
176  }
177
178  private abstract static class BaseResultProvider implements IResultProvider {
179    protected ISuite m_suite;
180    protected String m_type;
181    public BaseResultProvider(ISuite suite, String type) {
182      m_suite = suite;
183      m_type = type;
184    }
185
186    @Override
187    public String getType() {
188      return m_type;
189    }
190  }
191
192  private class ResultsByStatus extends BaseResultProvider {
193    private final int m_status;
194
195    public ResultsByStatus(ISuite suite, String type, int status) {
196      super(suite, type);
197      m_status = status;
198    }
199
200    @Override
201    public List<ITestResult> getResults() {
202      return getMethodsByStatus(m_suite, m_status);
203    }
204  }
205
206  private void generateMethodList(String name, IResultProvider provider,
207      String suiteName, XMLStringBuffer main) {
208    XMLStringBuffer xsb = new XMLStringBuffer(main.getCurrentIndent());
209    String type = provider.getType();
210    String image = Model.getImage(type);
211
212    xsb.push("li");
213
214    // The methods themselves
215    xsb.addRequired(S, name, C, "method-list-title " + type);
216
217    // The mark up to show the (hide)/(show) links
218    xsb.push(S, C, "show-or-hide-methods " + type);
219    xsb.addRequired("a", " (hide)", "href", "#", C, "hide-methods " + type + " " + suiteName,
220        "panel-name", suiteName);
221    xsb.addRequired("a", " (show)", "href", "#",C, "show-methods " + type + " " + suiteName,
222        "panel-name", suiteName);
223    xsb.pop(S);
224
225    // List of methods
226    xsb.push(D, C, "method-list-content " + type + " " + suiteName);
227    int count = 0;
228    List<ITestResult> testResults = provider.getResults();
229    if (testResults != null) {
230      Collections.sort(testResults, ResultsByClass.METHOD_NAME_COMPARATOR);
231      for (ITestResult tr : testResults) {
232        String testName = Model.getTestResultName(tr);
233        xsb.push(S);
234        xsb.addEmptyElement("img", "src", image, "width", "3%");
235        xsb.addRequired("a", testName, "href", "#",
236            "hash-for-method", getModel().getTag(tr),
237            "panel-name", suiteName,
238            "title", tr.getTestClass().getName(),
239            C, "method navigator-link");
240        xsb.pop(S);
241        xsb.addEmptyElement("br");
242        count++;
243      }
244    }
245    xsb.pop(D);
246    xsb.pop("li");
247
248    if (count > 0) {
249      main.addString(xsb.toXML());
250    }
251  }
252
253}
254