]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
6d13151892a96dfaadd044b50990442f5ff57ffa
[tmp/jakarta-migration.git] /
1 package org.collectionspace.services.IntegrationTests.xmlreplay;
2
3 import org.collectionspace.services.client.XmlTools;
4 import org.collectionspace.services.common.api.FileTools;
5 import org.collectionspace.services.common.api.Tools;
6 import org.dom4j.Document;
7 import org.dom4j.DocumentHelper;
8
9 import javax.swing.text.Style;
10
11 import java.io.File;
12 import java.util.ArrayList;
13 import java.util.List;
14
15 /**  Format a report based on XmlReplay ServiceResult object from a test group.
16  * @author  laramie
17  */
18 public class XmlReplayReport {
19     public static final String INCLUDES_DIR =  "_includes";
20
21     protected static final String HTML_PAGE_END = "</body></html>";
22     protected static final String TOPLINKS = "<a class='TOPLINKS' href='javascript:openAll();'>Show All Payloads</a>" + "<a class='TOPLINKS' href='javascript:closeAll();'>Hide All Payloads</a>";
23
24     protected static final String HTML_TEST_START = "<div class='TESTCASE'>";
25     protected static final String HTML_TEST_END = "</div>";
26
27     protected static final String GROUP_START = "<div class='TESTGROUP'>";
28     protected static final String GROUP_END = "</div>";
29
30     protected static final String RUNINFO_START = "<div class='RUNINFO'>";
31     protected static final String RUNINFO_END = "</div>";
32
33
34     protected static final String DIV_END = "</div>";
35
36     protected static final String PRE_START = "<pre class='SUMMARY'>";
37     protected static final String PRE_END = "</pre>";
38     protected static final String BR = "<br />\r\n";
39
40     protected static final String DETAIL_START = "<table border='1' class='DETAIL_TABLE'><tr><td>\r\n";
41     protected static final String DETAIL_LINESEP = "</td></tr>\r\n<tr><td>";
42     protected static final String DETAIL_END = "</td></tr></table>";
43
44     private static final String SP = "&nbsp;&nbsp;&nbsp;";
45
46     public XmlReplayReport(String reportsDir){
47         this.reportsDir = reportsDir;
48     }
49
50     private String reportsDir = "";
51     public String getReportsDir(){
52         return reportsDir;
53     }
54
55     protected static String formatCollapse(String myDivID, String linkText){
56         return  "<a href='javascript:;' onmousedown=\"toggleDiv('"+myDivID+"');\">"+linkText+"</a>"
57                  + BR
58                  + "<div ID='"+myDivID+"' class='PAYLOAD' style='display:none'>";
59     }
60
61
62     private StringBuffer header = new StringBuffer();
63     private StringBuffer buffer = new StringBuffer();
64     private String runInfo = "";
65
66     public String getPage(String basedir){
67         return    formatPageStart(basedir)
68                     +"<div class='REPORTTIME'>XmlReplay run  "+Tools.nowLocale()+"</div>"
69                     +header.toString()
70                     +this.runInfo
71                     +BR
72                     +getTOC("").toString()
73                     +BR
74                     +buffer.toString()
75                     +HTML_PAGE_END;
76     }
77
78     public String getTOC(String reportName){
79         StringBuffer tocBuffer = new StringBuffer();
80
81         if (Tools.notBlank(reportName)){
82             // We are generating a TOC for an index.html file that references other report files.
83             tocBuffer.append(this.header.toString());
84         } else {
85             // We are generating a single report file, so all links are relative to this file, and we should have the TOPLINKS which allow things like showAllPayloads..
86             tocBuffer.append(BR).append(TOPLINKS).append(BR);
87         }
88         for (TOC toc: tocList){
89               tocBuffer.append(BR+"<a href='"+reportName+"#TOC"+toc.tocID+"'>"+toc.testID+"</a> "+ toc.detail);
90         }
91         tocBuffer.append(BR+BR);
92         return tocBuffer.toString();
93     }
94
95     public void addRunInfo(String text){
96          this.runInfo = RUNINFO_START+text+RUNINFO_END;
97          //addText(this.runInfo);
98     }
99
100     /** Call this method to insert arbitrary HTML in your report file, at the point after the last call to addTestResult() or addTestGroup().    */
101     public void addText(String text){
102          buffer.append(text);
103     }
104
105     public void addTestGroup(String groupID, String controlFile){
106         header.append(GROUP_START);
107         header.append(lbl("Test Group")).append(groupID).append(SP).append(lbl("Control File")).append(controlFile);
108         header.append(GROUP_END);
109     }
110
111     private int divID = 0;
112
113     public void addTestResult(ServiceResult serviceResult){
114         buffer.append(HTML_TEST_START);
115         int tocID = ++divID;
116         buffer.append(formatSummary(serviceResult, tocID));
117         buffer.append(formatPayloads(serviceResult, tocID));
118         buffer.append(HTML_TEST_END);
119     }
120
121     public static class TOC {
122         public int tocID;
123         public String testID;
124         public String detail;
125     }
126     private List<TOC> tocList = new ArrayList<TOC>();
127
128     public static String formatPageStart(String xmlReplayBaseDir){
129             String script = FileTools.readFile(xmlReplayBaseDir, INCLUDES_DIR+"/reports-include.js");
130             String style =  FileTools.readFile(xmlReplayBaseDir, INCLUDES_DIR+"/reports-include.css");
131             return "<html><head><script type='text/javascript'>\r\n"
132                      +script
133                      +"\r\n</script>\r\n<style>\r\n"
134                      +style
135                      +"\r\n</style></head><body>";
136     }
137
138     public File saveReport(String xmlReplayBaseDir, String reportsDir, String reportName)  {
139         try {
140             File resultFile = FileTools.saveFile(reportsDir, reportName, this.getPage(xmlReplayBaseDir), true);
141             if (resultFile!=null) {
142                 String resultFileName =  resultFile.getCanonicalPath();
143                 //System.out.println("XmlReplay summary reports saved to directory: "+resultFile.getParent());
144                 System.out.println("XmlReplay summary report: "+resultFileName);
145                 return resultFile;
146             }
147         } catch (Exception e){
148             System.out.println("ERROR saving XmlReplay report in basedir: "+reportsDir+" reportName: "+reportName+" error: "+e);
149         }
150         return null;
151     }
152
153     //public static String getReportsDir(String basename){
154     //    return Tools.glue(basename,"/","TEST-REPORTS");
155     //}
156
157     /** @param localMasterFilename should be a local filename for the index of each xmlReplay master control file, e.g. objectexit.xml
158      *               so what gets written to disk will be something like index.objectexit.xml.html . The actual filename will be available from
159      *               the returned File object if successful.
160      *   @return File if successful, else returns null.
161      */
162     public static File saveIndexForMaster(String xmlReplayBaseDir, String reportsDir, String localMasterFilename, List<String> reportsList){
163         String masterFilename =  "index."+localMasterFilename+".html";
164         try{
165             StringBuffer sb = new StringBuffer(formatPageStart(xmlReplayBaseDir));
166             String dateStr = Tools.nowLocale();
167             sb.append("<div class='REPORTTIME'>XmlReplay run  "+dateStr+" master: "+localMasterFilename+"</div>");
168             for (String oneToc: reportsList){
169                 sb.append(oneToc);
170                 sb.append("<hr />");
171             }
172             sb.append(HTML_PAGE_END);
173
174             return FileTools.saveFile(reportsDir,masterFilename, sb.toString(), false);
175         } catch (Exception e){
176             System.out.println("ERROR saving XmlReplay report index: in  xmlReplayBaseDir: "+reportsDir+"localMasterFilename: "+localMasterFilename+" masterFilename: "+masterFilename+" list: "+reportsList+" error: "+e);
177             return null;
178         }
179     }
180
181     protected String formatSummary(ServiceResult serviceResult, int tocID){
182         TOC toc = new TOC();
183         toc.tocID = tocID;
184         toc.testID = serviceResult.testID;
185         toc.detail =  (serviceResult.gotExpectedResult() ? ok("SUCCESS") : red("FAILURE") );
186         tocList.add(toc);
187
188         StringBuffer fb = new StringBuffer();
189         fb.append("<a name='TOC"+tocID+"'></a>");
190         fb.append(detail(serviceResult, false, false, DETAIL_START, DETAIL_LINESEP, DETAIL_END, tocID));
191         return fb.toString();
192     }
193
194     protected String formatPayloads(ServiceResult serviceResult, int tocID){
195         StringBuffer fb = new StringBuffer();
196         fb.append(BR);
197         appendPayload(fb, serviceResult.requestPayload, "REQUEST", "REQUEST" + tocID);
198         appendPayload(fb, serviceResult.requestPayloadsRaw, "REQUEST (RAW)", "REQUESTRAW" + tocID);
199         appendPayload(fb, serviceResult.result, "RESPONSE", "RESPONSE" + tocID);
200         appendPayload(fb, serviceResult.expectedContentExpanded, "EXPECTED", "EXPECTED" + tocID);
201         fb.append(BR);
202
203         return fb.toString();
204     }
205
206     protected void appendPayload( StringBuffer fb , String payload, String title, String theDivID){
207         if (Tools.notBlank(payload)){
208             //fb.append(BR+title+":"+BR);
209             try {
210                 String pretty = prettyPrint(payload);
211
212
213                 fb.append(formatCollapse(theDivID, title));  //starts a div.
214                 fb.append(PRE_START);
215                 fb.append(escape(pretty));
216                 fb.append(PRE_END);
217                 fb.append(DIV_END);                        //ends that div.
218             } catch (Exception e){
219                 String error = "<font color='red'>ERROR:</font> "+payload;
220                 fb.append(error);
221                 fb.append(BR).append(BR);
222             }
223         }
224     }
225
226     private String escape(String source){
227         try {
228             return Tools.searchAndReplace(source, "<", "&lt;");
229         } catch (Exception e){
230             return "ERROR escaping requestPayload"+e;
231         }
232     }
233
234     private String prettyPrint(String rawXml) throws Exception {
235         Document document = DocumentHelper.parseText(rawXml);
236         return XmlTools.prettyPrint(document, "    ");
237     }
238
239     private static final String LINE = "<hr />\r\n";
240     private static final String CRLF = "<br />\r\n";
241
242     protected String red(String label){
243         return "<span class='ERROR'>"+label+"</span> ";
244     }
245     protected String ok(String label){
246         return "<span class='OK'>"+label+"</span> ";
247     }
248     protected String lbl(String label){
249         return "<span class='LABEL'>"+label+":</span> ";
250     }
251     public String detail(ServiceResult s, boolean includePayloads, boolean includePartSummary, String start, String linesep, String end, int tocID){
252         String partSummary = s.partsSummary(includePartSummary);
253         String res =  start
254                 + ( s.gotExpectedResult() ? lbl("SUCCESS") : "<font color='red'><b>FAILURE</b></font>"  )
255                   + SP + ( Tools.notEmpty(s.testID) ? s.testID : "" )
256                   + SP +linesep
257                 +s.method+ SP +"<a href='"+s.fullURL+"'>"+s.fullURL+"</a>"                                     +linesep
258                 + s.responseCode+ SP +lbl("gotExpected")+s.gotExpectedResult()                                                       +linesep
259                 + (Tools.notBlank(s.failureReason) ? s.failureReason +linesep : "" )
260                 + ( (s.expectedCodes.size()>0) ? lbl("expectedCodes")+s.expectedCodes+linesep : "" )
261                 //+ ( Tools.notEmpty(s.testGroupID) ? "testGroupID:"+s.testGroupID+linesep : "" )
262                 //THIS WORKS, BUT IS VERBOSE: + ( Tools.notEmpty(s.fromTestID) ? "fromTestID:"+s.fromTestID+linesep : "" )
263                 + ( Tools.notEmpty(s.responseMessage) ? lbl("msg")+s.responseMessage+linesep : "" )
264                 +lbl("auth")+s.auth                                                                                        +linesep
265                 + ( Tools.notEmpty(s.deleteURL) ? lbl("deleteURL")+s.deleteURL+linesep : "" )
266                 + ( Tools.notEmpty(s.location) ? lbl("location.CSID")+s.location+linesep : "" )
267                 + ( Tools.notEmpty(s.error) ? "ERROR:"+s.error +linesep : "" )
268                 + ((includePartSummary && Tools.notBlank(partSummary)) ? lbl("part summary")+partSummary +linesep : "")
269                 + ( includePayloads && Tools.notBlank(s.requestPayload) ? LINE+lbl("requestPayload")+LINE+CRLF+s.requestPayload+LINE : "" )
270                 + ( includePayloads && Tools.notBlank(s.result) ? LINE+lbl("result")+LINE+CRLF+s.result : "" )
271                 +end;
272         return res;
273     }
274
275 }