View Javadoc
1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package edu.samplu.common;
17  
18  import org.apache.commons.lang.RandomStringUtils;
19  
20  import java.io.BufferedReader;
21  import java.io.InputStreamReader;
22  import java.io.PrintWriter;
23  import java.io.StringWriter;
24  import java.net.HttpURLConnection;
25  import java.net.URL;
26  import java.net.URLEncoder;
27  import java.util.Calendar;
28  
29  /**
30   * TODO:
31   * <ol>
32   *   <li>Keep WebDriver dependencies out of this class, those should be in {@link WebDriverUtil}</li>
33   *   <li>Keep JUnit or TestNG dependencies out of in this class.</li>
34   *   <li>Extract Hub specific logic?/li>
35   *   <li>Rename to SmokeTestUtil or such</li>
36   * </ol>
37   * @author Kuali Rice Team (rice.collab@kuali.org)
38   */
39  public class ITUtil {
40  
41      /**
42       * http://localhost:8080/kr-dev
43       */
44      public static final String DEFAULT_BASE_URL = "http://localhost:8080/kr-dev";
45  
46      /**
47       * http://localhost:8080/krad-dev
48       */
49      public static final String DEFAULT_BASE_URL_KRAD = "http://localhost:8080/krad-dev";
50  
51      /**
52       * //div[@class='error']"
53       */
54      public static final String DIV_ERROR_LOCATOR = "//div[@class='error']";
55  
56      /**
57       * //div[@class='msg-excol']
58       */
59      public static final String DIV_EXCOL_LOCATOR = "//div[@class='msg-excol']";
60  
61      /**
62       * remote.driver.dontTearDown
63       */
64      public static final String DONT_TEAR_DOWN_PROPERTY = "remote.driver.dontTearDown";
65  
66      /**
67       * Calendar.getInstance().getTimeInMillis() + ""
68       */
69      public static final String DTS = Calendar.getInstance().getTimeInMillis() + "";
70  
71      /**
72       * Calendar.getInstance().getTimeInMillis() + "" + RandomStringUtils.randomAlphabetic(2).toLowerCase()
73       * @Deprecated {@link ITUtil#createUniqueDtsPlusTwoRandomChars()}
74       */
75      public static final String DTS_TWO = Calendar.getInstance().getTimeInMillis() + "" + RandomStringUtils.randomAlphabetic(2).toLowerCase();
76  
77      /**
78       *  &hideReturnLink=true
79       */
80      public static final String HIDE_RETURN_LINK =  "&hideReturnLink=true";
81  
82      /**
83       *  &hideReturnLink=false
84       */
85      public static final String HIDE_RETURN_LINK_FALSE =  "&hideReturnLink=false";
86  
87      /**
88       * remote.public.hub
89       */
90      public static final String HUB_PROPERTY = "remote.public.hub";
91  
92      /**
93       * remote.public.driver
94       */
95      public static final String HUB_DRIVER_PROPERTY = "remote.public.driver";
96  
97      /**
98       * http://localhost:4444/wd/hub
99       */
100     public static final String HUB_URL_PROPERTY = "http://localhost:4444/wd/hub";
101 
102     /**
103      * /kr-krad/lookup?methodToCall=start&dataObjectClassName=
104      */
105     public static final String KRAD_LOOKUP_METHOD =  "/kr-krad/lookup?methodToCall=start&dataObjectClassName=";
106 
107     /**
108      * /kr/lookup.do?methodToCall=start&businessObjectClassName=
109      */
110     public static final String KNS_LOOKUP_METHOD =  "/kr/lookup.do?methodToCall=start&businessObjectClassName=";
111 
112     /**
113      * /kr-krad/kradsampleapp?viewId=KradSampleAppHome
114      */
115     public static final String KRAD_PORTAL = "/kr-krad/kradsampleapp?viewId=KradSampleAppHome";
116 
117     /**
118      * /kr-krad/kradsampleapp?viewId=KradSampleAppHome
119      */
120     public static final String KRAD_PORTAL_URL = ITUtil.getBaseUrlString() + KRAD_PORTAL;
121 
122     /**
123      * /kr-krad/labs?viewId=LabsMenuView
124      */
125     public static final  String LABS = "/kr-krad/labs?viewId=LabsMenuView";
126 
127     /**
128      * ITUtil.getBaseUrlString() + LABS
129      */
130     public static final String LABS_URL = ITUtil.getBaseUrlString() + LABS;
131 
132     /**
133      * /portal.do
134      */
135     public static final String PORTAL = "/portal.do";
136 
137     /**
138      * ITUtil.getBaseUrlString() + ITUtil.PORTAL
139      */
140     public static final String PORTAL_URL =  ITUtil.getBaseUrlString() + ITUtil.PORTAL;
141 
142     /**
143      * URLEncoder.encode(PORTAL_URL)
144      */
145     public static final String PORTAL_URL_ENCODED = URLEncoder.encode(PORTAL_URL);
146 
147     /**
148      *  &showMaintenanceLinks=true
149      */
150     public static final String SHOW_MAINTENANCE_LINKS =  "&showMaintenanceLinks=true";
151 
152     /**
153      * remote.public.url
154      */
155     public static final String REMOTE_PUBLIC_URL_PROPERTY = "remote.public.url";
156 
157     /**
158      * remote.autologin
159      */
160     public static final String REMOTE_AUTOLOGIN_PROPERTY = "remote.autologin";
161 
162     /**
163      * KRAD
164      */
165     public static final String REMOTE_UIF_KRAD = "KRAD";
166 
167     /**
168      * KNS
169      */
170     public static final String REMOTE_UIF_KNS  = "KNS";
171 
172     /**
173      * &docFormKey=
174      */
175     public static final String DOC_FORM_KEY = "&docFormKey=";
176     
177 
178     public static String blanketApprovalCleanUpErrorText(String errorText) {
179         errorText = errorText.replace("* required field", "").replace("\n", " ").trim(); // bit of extra ui text we don't care about
180         return errorText;
181     }
182 
183     public static String createUniqueDtsPlusTwoRandomChars() {
184         return Calendar.getInstance().getTimeInMillis() + "" + RandomStringUtils.randomAlphabetic(2).toLowerCase();
185     }
186 
187     // The Document Description contains 9 continuous digits or 9 digits grouped in the following pattern: ###-##-####, which may represent a Tax Number.
188     // The Document Description is not secure and its contents may be viewed by other application users. Please revise the Document Description to not contain digits in those patterns.
189     public static String createUniqueDtsPlusTwoRandomCharsNot9Digits() {
190         String dtsTwo = ITUtil.createUniqueDtsPlusTwoRandomChars();
191         dtsTwo = dtsTwo.substring(0, 5) + dtsTwo.substring(13, 14) + dtsTwo.substring(6, 12);
192         return dtsTwo;
193     }
194 
195     protected static void checkForIncidentReport(String contents, String linkLocator, Failable failable, String message) {
196         if (contents == null) { //guard clause
197             return;
198         }
199 
200         if (incidentReported(contents)) {
201             try {
202                 processIncidentReport(contents, linkLocator, failable, message);
203             } catch (IndexOutOfBoundsException e) {
204                 failable.fail(
205                         "\nIncident report detected "
206                                 + message
207                                 + " but there was an exception during processing: "
208                                 + e.getMessage()
209                                 + "\nStack Trace from processing exception"
210                                 + stackTrace(e)
211                                 + "\nContents that triggered exception: "
212                                 + deLinespace(contents));
213             }
214         }
215 
216         if (contents.contains("HTTP Status 404")) {
217             failable.fail("\nHTTP Status 404 " + linkLocator + " " + message + " " + "\ncontents:" + contents);
218         }
219 
220         if (contents.contains("Java backtrace for programmers:") || contents.contains("Java stack trace (for programmers):")) { // freemarker exception
221             try {
222                 processFreemarkerException(contents, linkLocator, failable, message);
223             } catch (IndexOutOfBoundsException e) {
224                 failable.fail("\nFreemarker exception detected "
225                         + message
226                         + " but there was an exception during processing: "
227                         + e.getMessage()
228                         + "\nStack Trace from processing exception"
229                         + stackTrace(e)
230                         + "\nContents that triggered exception: "
231                         + deLinespace(contents));
232             }
233         }
234 
235         if (contents.contains("Document Expired")) { // maybe Firefox specific
236             failable.fail("Document Expired message.");
237         }
238     }
239 
240     public static String deLinespace(String contents) {
241         while (contents.contains("\n\n")) {
242             contents = contents.replaceAll("\n\n", "\n");
243         }
244         return contents;
245     }
246 
247     /**
248      * Setting the JVM arg remote.driver.dontTearDown to y or t leaves the browser window open when the test has completed.  Valuable when debugging, updating, or creating new tests.
249      * When implementing your own tearDown method rather than an inherited one, it is a common courtesy to include this check and not stop and shutdown the browser window to make it easy debug or update your test.
250      * {@code }
251      * @return true if the dontTearDownProperty is not set.
252      */
253     public static boolean dontTearDownPropertyNotSet() {
254         return System.getProperty(DONT_TEAR_DOWN_PROPERTY) == null ||
255                 "f".startsWith(System.getProperty(DONT_TEAR_DOWN_PROPERTY).toLowerCase()) ||
256                 "n".startsWith(System.getProperty(DONT_TEAR_DOWN_PROPERTY).toLowerCase());
257     }
258 
259     private static String extractIncidentReportInfo(String contents, String linkLocator, String message) {
260         String chunk =  contents.substring(contents.indexOf("Incident Feedback"), contents.lastIndexOf("</div>") );
261         String docId = chunk.substring(chunk.lastIndexOf("Document Id"), chunk.indexOf("View Id"));
262         docId = docId.substring(0, docId.indexOf("</span>"));
263         docId = docId.substring(docId.lastIndexOf(">") + 2, docId.length());
264 
265         String viewId = chunk.substring(chunk.lastIndexOf("View Id"), chunk.indexOf("Error Message"));
266         viewId = viewId.substring(0, viewId.indexOf("</span>"));
267         viewId = viewId.substring(viewId.lastIndexOf(">") + 2, viewId.length());
268 
269         String stackTrace = chunk.substring(chunk.lastIndexOf("(only in dev mode)"), chunk.length());
270         stackTrace = stackTrace.substring(stackTrace.indexOf("<pre>") + 5, stackTrace.length());
271         stackTrace = stackTrace.substring(0, stackTrace.indexOf("</"));
272 
273         //            System.out.println(docId);
274         //            System.out.println(viewId);
275         //            System.out.println(stackTrace);
276         return "\nIncident report "
277                 + message
278                 + " navigating to "
279                 + linkLocator
280                 + " : View Id: "
281                 + viewId.trim()
282                 + " Doc Id: "
283                 + docId.trim()
284                 + "\nStackTrace: "
285                 + stackTrace.trim().replace(" at ", "");
286     }
287 
288     private static String extractIncidentReportKim(String contents, String linkLocator, String message) {
289         String chunk =  contents.substring(contents.indexOf("id=\"headerarea\""), contents.lastIndexOf("</div>") );
290         String docIdPre = "type=\"hidden\" value=\"";
291         String docId = chunk.substring(chunk.indexOf(docIdPre) + docIdPre.length(), chunk.indexOf("\" name=\"documentId\""));
292 
293         String stackTrace = chunk.substring(chunk.lastIndexOf("name=\"displayMessage\""), chunk.length());
294         String stackTracePre = "value=\"";
295         stackTrace = stackTrace.substring(stackTrace.indexOf(stackTracePre) + stackTracePre.length(), stackTrace.indexOf("name=\"stackTrace\"") - 2);
296 
297         return "\nIncident report "
298                 + message
299                 + " navigating to "
300                 + linkLocator
301                 + " Doc Id: "
302                 + docId.trim()
303                 + "\nStackTrace: "
304                 + stackTrace.trim().replace(" at ", "");
305     }
306 
307     public static void failOnInvalidUserName(String userName, String contents, Failable failable) {
308         if (contents.indexOf("Invalid") > -1) {
309             failable.fail("Invalid Login " + userName);
310         }
311     }
312 /*
313     public static void failOnMatchedJira(String contents) {
314         Iterator<String> iter = jiraMatches.keySet().iterator();
315         String key = null;
316 
317         while (iter.hasNext()) {
318             key = iter.next();
319             if (contents.contains(key)) {
320                 SeleneseTestBase.fail(JIRA_BROWSE_URL + jiraMatches.get(key));
321             }
322         }
323     }
324 */
325 
326     private static void failWithReportInfo(String contents, String linkLocator, Failable failable, String message) {
327         final String incidentReportInformation = extractIncidentReportInfo(contents, linkLocator, message);
328         failable.fail(incidentReportInformation);
329     }
330 
331 /*
332     private static void failWithReportInfoForKim(String contents, String linkLocator, String message) {
333         final String kimIncidentReport = extractIncidentReportKim(contents, linkLocator, message);
334         SeleneseTestBase.fail(kimIncidentReport);
335     }
336 */
337     private static void failWithReportInfoForKim(String contents, String linkLocator, Failable failable, String message) {
338         final String kimIncidentReport = extractIncidentReportKim(contents, linkLocator, message);
339         failable.fail(kimIncidentReport);
340     }
341 
342     /**
343      * In order to run as a smoke test the ability to set the baseUrl via the JVM arg remote.public.url is required.
344      * Trailing slashes are trimmed.  If the remote.public.url does not start with http:// it will be added.
345      * @return http://localhost:8080/kr-dev by default else the value of remote.public.url
346      */
347     public static String getBaseUrlString() {
348         String baseUrl = System.getProperty(REMOTE_PUBLIC_URL_PROPERTY);
349         if (baseUrl == null) {
350             baseUrl = DEFAULT_BASE_URL;
351         }
352         baseUrl = prettyHttp(baseUrl);
353         return baseUrl;
354     }
355 
356     public static String getHTML(String urlToRead) {
357         URL url;
358         HttpURLConnection conn;
359         BufferedReader rd;
360         String line;
361         String result = "";
362 
363         try {
364             url = new URL(urlToRead);
365             conn = (HttpURLConnection) url.openConnection();
366             conn.setRequestMethod("GET");
367             rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
368             while ((line = rd.readLine()) != null) {
369                 result += line;
370             }
371             rd.close();
372         } catch (Exception e) {
373             e.printStackTrace();
374         }
375 
376         return result;
377     }
378 
379     /**
380      * In order to run as a smoke test under selenium grid the ability to set the hubUrl via the JVM arg remote.public.hub is required.
381      * Trailing slashes are trimmed.  If the remote.public.hub does not start with http:// it will be added.
382      * @return http://localhost:4444/wd/hub by default else the value of remote.public.hub
383      */
384     public static String getHubUrlString() {
385         String hubUrl = System.getProperty(HUB_PROPERTY);
386         if (hubUrl == null) {
387             hubUrl = HUB_URL_PROPERTY;
388         }
389         hubUrl = prettyHttp(hubUrl);
390         if (!hubUrl.endsWith("/wd/hub")) {
391             hubUrl = hubUrl + "/wd/hub";
392         }
393         return hubUrl;
394     }
395 
396     private static boolean incidentReported(String contents) {
397         return contents != null &&
398                 contents.contains("Incident Report") &&
399                 !contents.contains("portal.do?channelTitle=Incident%20Report") && // Incident Report link on sampleapp KRAD tab
400                 !contents.contains("portal.do?channelTitle=Incident Report") &&   // Incident Report link on sampleapp KRAD tab IE8
401                 !contents.contains("uitest?viewId=Travel-testView2") &&
402                 !contents.contains("SeleniumException"); // selenium timeouts have Incident Report in them
403     }
404 
405     /**
406      * Append http:// if not present.  Remove trailing /
407      * @param baseUrl
408      * @return
409      */
410     public static String prettyHttp(String baseUrl) {
411 
412         if (baseUrl.endsWith("/")) {
413             baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
414         }
415 
416         if (!baseUrl.startsWith("http")) {
417             baseUrl = "http://" + baseUrl;
418         }
419 
420         return baseUrl;
421     }
422 
423     private static void processFreemarkerException(String contents, String linkLocator, Failable failable, String message) {
424         JiraAwareFailureUtil.failOnMatchedJira(contents, failable);
425         String stackTrace = contents.substring(contents.indexOf("Error: on line"), contents.indexOf("more<") - 1);
426         failable.fail(
427                 "\nFreemarker Exception " + message + " navigating to " + linkLocator + "\nStackTrace: " + stackTrace
428                         .trim().replace(" at ", ""));
429     }
430 
431 /*
432     private static void processIncidentReport(String contents, String linkLocator, String message) {
433         failOnMatchedJira(contents);
434 
435         if (contents.indexOf("Incident Feedback") > -1) {
436             failWithReportInfo(contents, linkLocator, message);
437         }
438 
439         if (contents.indexOf("Incident Report") > -1) { // KIM incident report
440             failWithReportInfoForKim(contents, linkLocator, message);
441         }
442 
443         SeleneseTestBase.fail("\nIncident report detected " + message + "\n Unable to parse out details for the contents that triggered exception: " + deLinespace(
444                 contents));
445     }
446 
447     private static void failWithReportInfo(String contents, String linkLocator, String message) {
448         final String incidentReportInformation = extractIncidentReportInfo(contents, linkLocator, message);
449         SeleneseTestBase.fail(incidentReportInformation);
450     }
451 */
452 
453     protected static void processIncidentReport(String contents, String linkLocator, Failable failable, String message) {
454         JiraAwareFailureUtil.failOnMatchedJira(contents, failable);
455 
456         if (contents.indexOf("Incident Feedback") > -1) {
457             failWithReportInfo(contents, linkLocator, failable, message);
458         }
459 
460         if (contents.indexOf("Incident Report") > -1) { // KIM incident report
461             failWithReportInfoForKim(contents, linkLocator, failable, message);
462         }
463 
464         failable.fail("\nIncident report detected "
465                 + message
466                 + "\n Unable to parse out details for the contents that triggered exception: "
467                 + deLinespace(contents));
468     }
469 
470     /**
471      * Write the given stack trace into a String remove the ats in an attempt to not cause Jenkins problems.
472      * @param throwable whose stack trace to return
473      * @return String of the given throwable's stack trace.
474      */
475     public static String stackTrace(Throwable throwable) {
476         StringWriter wrt = new StringWriter();
477         PrintWriter pw = new PrintWriter(wrt);
478         throwable.printStackTrace(pw);
479         pw.flush();
480         return wrt.toString().replace(" at " ,"");
481     }
482 }