NavigatorPanel.java revision 0fe6cf657bd3740e8c877506169146565e37a557
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 TestNgXmlPanel m_testNgPanel;
17  private TestPanel m_testPanel;
18  private GroupPanel m_groupPanel;
19  private TimesPanel m_timePanel;
20  private ReporterPanel m_reporterPanel;
21  private IgnoredMethodsPanel m_ignoredMethodsPanel;
22
23  public NavigatorPanel(Model model, TestNgXmlPanel testNgPanel, TestPanel testPanel,
24      GroupPanel groupPanel, TimesPanel timePanel, ReporterPanel reporterPanel,
25      IgnoredMethodsPanel ignoredMethodsPanel) {
26    super(model);
27    m_testNgPanel = testNgPanel;
28    m_testPanel = testPanel;
29    m_groupPanel = groupPanel;
30    m_timePanel = timePanel;
31    m_reporterPanel = reporterPanel;
32    m_ignoredMethodsPanel = ignoredMethodsPanel;
33  }
34
35  @Override
36  public void generate(XMLStringBuffer main) {
37    main.push(D, C, "navigator-root");
38    int suiteCount = 0;
39    for (ISuite suite : getSuites()) {
40      if (suite.getResults().size() == 0) {
41        continue;
42      }
43
44      String suiteName = "suite-" + suiteCount;
45
46      XMLStringBuffer header = new XMLStringBuffer(main.getCurrentIndent());
47
48      Map<String, ISuiteResult> results = suite.getResults();
49      int failed = 0;
50      int skipped = 0;
51      int passed = 0;
52      for (ISuiteResult result : results.values()) {
53        ITestContext context = result.getTestContext();
54        failed += context.getFailedTests().size();
55        skipped += context.getSkippedTests().size();
56        passed += context.getPassedTests().size();
57      }
58
59      // Suite name in big font
60      header.push(D, C, "suite");
61      header.push(D, C, "rounded-window");
62      // Extra div so the highlighting logic will only highlight this line and not
63      // the entire container
64      header.push(D, C, "suite-header light-rounded-window-top");
65      header.push("a", "href", "#",
66          "panel-name", suiteName,
67          C, "navigator-link");
68      header.addOptional(S, suite.getName(),
69          C, "suite-name border-" + getModel().getStatusForSuite(suite.getName()));
70      header.pop("a");
71      header.pop(D);
72
73      header.push(D, C, "navigator-suite-content");
74
75      generateInfo(header, suite, results);
76      generateResult(header, failed, skipped, passed, suite, suiteName);
77
78      header.pop("ul");
79
80      header.pop(D); // suite-section-content
81      header.pop(D); // suite-header
82      header.pop(D); // suite
83
84      header.pop(D); // result-section
85
86      header.pop(D); // navigator-suite-content
87
88      main.addString(header.toXML());
89
90      suiteCount++;
91    }
92    main.pop(D);
93  }
94
95  private void generateResult(XMLStringBuffer header, int failed, int skipped, int passed,
96      ISuite suite, String suiteName) {
97    //
98    // Results
99    //
100    header.push(D, C, "result-section");
101
102    header.push(D, C, "suite-section-title");
103    header.addRequired(S, "Results");
104    header.pop(D);
105
106    // Method stats
107    int total = failed + skipped + passed;
108    String stats = String.format("%s, %s %s %s",
109        pluralize(total, "method"),
110        maybe(failed, "failed", ", "),
111        maybe(skipped, "skipped", ", "),
112        maybe(passed, "passed", ""));
113    header.push(D, C, "suite-section-content");
114    header.push("ul");
115    header.push("li");
116    header.addOptional(S, stats, C, "method-stats");
117    header.pop("li");
118
119    generateMethodList("Failed methods", new ResultsByStatus(suite, "failed", ITestResult.FAILURE),
120        suiteName, header);
121    generateMethodList("Skipped methods", new ResultsByStatus(suite, "skipped", ITestResult.SKIP),
122        suiteName, header);
123    generateMethodList("Passed methods", new ResultsByStatus(suite, "passed", ITestResult.SUCCESS),
124        suiteName, header);
125    }
126
127  private void generateInfo(XMLStringBuffer header, ISuite suite,
128      Map<String, ISuiteResult> results) {
129    //
130    // Info
131    //
132    header.push(D, C, "suite-section-title");
133    header.addRequired(S, "Info");
134    header.pop(D);
135
136    //
137    // Info
138    //
139    header.push(D, C, "suite-section-content");
140
141    header.push("ul");
142
143    // "59 Tests"
144    addLinkTo(header, m_testPanel, suite,
145        pluralize(results.values().size(), "test"),
146        "test-stats");
147
148    // "12 groups"
149    addLinkTo(header, m_groupPanel, suite,
150        pluralize(getModel().getGroups(suite.getName()).size(), "group"),
151        null /* no class */);
152
153    // Times
154    addLinkTo(header, m_timePanel, suite, "Times", null);
155
156    // Reporter
157    addLinkTo(header, m_reporterPanel, suite, "Reporter output", null);
158
159    // Ignored methods
160    addLinkTo(header, m_ignoredMethodsPanel, suite, "Ignored methods", null);
161
162    // "testng.xml"
163    String fqName = suite.getXmlSuite().getFileName();
164    if (fqName == null) fqName = "/[unset file name]";
165    addLinkTo(header, m_testNgPanel, suite, fqName.substring(fqName.lastIndexOf("/") + 1), null);
166
167    header.pop("ul");
168    header.pop(D); // suite-section-content
169  }
170
171  private void addLinkTo(XMLStringBuffer header, INavigatorPanel panel, ISuite suite,
172      String text, String className) {
173    header.push("li");
174    header.push("a", "href", "#",
175        "panel-name", panel.getPanelName(suite),
176        C, "navigator-link ");
177    if (className != null) {
178      header.addOptional(S, text, C, className);
179    } else {
180      header.addOptional(S, text);
181    }
182    header.pop("a");
183    header.pop("li");
184  }
185
186  private static String maybe(int count, String s, String sep) {
187    return count > 0 ? count + " " + s + sep: "";
188  }
189
190  private List<ITestResult> getMethodsByStatus(ISuite suite, int status) {
191    List<ITestResult> result = Lists.newArrayList();
192    List<ITestResult> testResults = getModel().getTestResults(suite);
193    for (ITestResult tr : testResults) {
194      if (tr.getStatus() == status) {
195        result.add(tr);
196      }
197    }
198    Collections.sort(result, ResultsByClass.METHOD_NAME_COMPARATOR);
199
200    return result;
201  }
202
203  private static interface IResultProvider {
204    List<ITestResult> getResults();
205    String getType();
206  }
207
208  private abstract static class BaseResultProvider implements IResultProvider {
209    protected ISuite m_suite;
210    protected String m_type;
211    public BaseResultProvider(ISuite suite, String type) {
212      m_suite = suite;
213      m_type = type;
214    }
215
216    @Override
217    public String getType() {
218      return m_type;
219    }
220  }
221
222  private class ResultsByStatus extends BaseResultProvider {
223    private final int m_status;
224
225    public ResultsByStatus(ISuite suite, String type, int status) {
226      super(suite, type);
227      m_status = status;
228    }
229
230    @Override
231    public List<ITestResult> getResults() {
232      return getMethodsByStatus(m_suite, m_status);
233    }
234  }
235
236  private void generateMethodList(String name, IResultProvider provider,
237      String suiteName, XMLStringBuffer main) {
238    XMLStringBuffer xsb = new XMLStringBuffer(main.getCurrentIndent());
239    String type = provider.getType();
240    String image = Model.getImage(type);
241
242    xsb.push("li");
243
244    // The methods themselves
245    xsb.addRequired(S, name, C, "method-list-title " + type);
246
247    // The mark up to show the (hide)/(show) links
248    xsb.push(S, C, "show-or-hide-methods " + type);
249    xsb.addRequired("a", " (hide)", "href", "#", C, "hide-methods " + type + " " + suiteName,
250        "panel-name", suiteName);
251    xsb.addRequired("a", " (show)", "href", "#",C, "show-methods " + type + " " + suiteName,
252        "panel-name", suiteName);
253    xsb.pop(S);
254
255    // List of methods
256    xsb.push(D, C, "method-list-content " + type + " " + suiteName);
257    int count = 0;
258    List<ITestResult> testResults = provider.getResults();
259    if (testResults != null) {
260      Collections.sort(testResults, ResultsByClass.METHOD_NAME_COMPARATOR);
261      for (ITestResult tr : testResults) {
262        String testName = Model.getTestResultName(tr);
263        xsb.push(S);
264        xsb.addEmptyElement("img", "src", image, "width", "3%");
265        xsb.addRequired("a", testName, "href", "#",
266            "hash-for-method", getModel().getTag(tr),
267            "panel-name", suiteName,
268            "title", tr.getTestClass().getName(),
269            C, "method navigator-link");
270        xsb.pop(S);
271        xsb.addEmptyElement("br");
272        count++;
273      }
274    }
275    xsb.pop(D);
276    xsb.pop("li");
277
278    if (count > 0) {
279      main.addString(xsb.toXML());
280    }
281  }
282
283}
284