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       * //div[@class='error']"
48       */
49      public static final String DIV_ERROR_LOCATOR = "//div[@class='error']";
50  
51      /**
52       * //div[@class='msg-excol']
53       */
54      public static final String DIV_EXCOL_LOCATOR = "//div[@class='msg-excol']";
55  
56      /**
57       * remote.driver.dontTearDown
58       */
59      public static final String DONT_TEAR_DOWN_PROPERTY = "remote.driver.dontTearDown";
60  
61      /**
62       * Calendar.getInstance().getTimeInMillis() + ""
63       */
64      public static final String DTS = Calendar.getInstance().getTimeInMillis() + "";
65  
66      /**
67       * Calendar.getInstance().getTimeInMillis() + "" + RandomStringUtils.randomAlphabetic(2).toLowerCase()
68       */
69      public static final String DTS_TWO = Calendar.getInstance().getTimeInMillis() + "" + RandomStringUtils.randomAlphabetic(2).toLowerCase();
70  
71      /**
72       *  &hideReturnLink=true
73       */
74      public static final String HIDE_RETURN_LINK =  "&hideReturnLink=true";
75  
76      /**
77       * remote.public.hub
78       */
79      public static final String HUB_PROPERTY = "remote.public.hub";
80  
81      /**
82       * remote.public.driver
83       */
84      public static final String HUB_DRIVER_PROPERTY = "remote.public.driver";
85  
86      /**
87       * http://localhost:4444/wd/hub
88       */
89      public static final String HUB_URL_PROPERTY = "http://localhost:4444/wd/hub";
90  
91      /**
92       * /kr-krad/lookup?methodToCall=start&dataObjectClassName=
93       */
94      public static final String KRAD_LOOKUP_METHOD =  "/kr-krad/lookup?methodToCall=start&dataObjectClassName=";
95  
96      /**
97       * /kr/lookup.do?methodToCall=start&businessObjectClassName=
98       */
99      public static final String KNS_LOOKUP_METHOD =  "/kr/lookup.do?methodToCall=start&businessObjectClassName=";
100 
101     /**
102      * /portal.do
103      */
104     public static final  String PORTAL = "/portal.do";
105 
106     /**
107      * ITUtil.getBaseUrlString() + ITUtil.PORTAL
108      */
109     public static final String PORTAL_URL =  ITUtil.getBaseUrlString() + ITUtil.PORTAL;
110 
111     /**
112      * URLEncoder.encode(PORTAL_URL)
113      */
114     public static final String PORTAL_URL_ENCODED = URLEncoder.encode(PORTAL_URL);
115 
116     /**
117      *  &showMaintenanceLinks=true
118      */
119     public static final String SHOW_MAINTENANCE_LINKS =  "&showMaintenanceLinks=true";
120 
121     /**
122      * remote.public.url
123      */
124     public static final String REMOTE_PUBLIC_URL_PROPERTY = "remote.public.url";
125 
126     /**
127      * remote.autologin
128      */
129     public static final String REMOTE_AUTOLOGIN_PROPERTY = "remote.autologin";
130     
131     /**
132      * &docFormKey=
133      */
134     public static final String DOC_FORM_KEY = "&docFormKey=";
135     
136 
137     public static String blanketApprovalCleanUpErrorText(String errorText) {
138         errorText = errorText.replace("* required field", "").replace("\n", " ").trim(); // bit of extra ui text we don't care about
139         return errorText;
140     }
141 
142     protected static void checkForIncidentReport(String contents, String linkLocator, Failable failable, String message) {
143         if (contents == null) { //guard clause
144             return;
145         }
146 
147         if (incidentReported(contents)) {
148             try {
149                 processIncidentReport(contents, linkLocator, failable, message);
150             } catch (IndexOutOfBoundsException e) {
151                 failable.fail(
152                         "\nIncident report detected "
153                                 + message
154                                 + " but there was an exception during processing: "
155                                 + e.getMessage()
156                                 + "\nStack Trace from processing exception"
157                                 + stackTrace(e)
158                                 + "\nContents that triggered exception: "
159                                 + deLinespace(contents));
160             }
161         }
162 
163         if (contents.contains("HTTP Status 404")) {
164             failable.fail("\nHTTP Status 404 " + linkLocator + " " + message + " " + "\ncontents:" + contents);
165         }
166 
167         if (contents.contains("Java backtrace for programmers:")) { // freemarker exception
168             try {
169                 processFreemarkerException(contents, linkLocator, failable, message);
170             } catch (IndexOutOfBoundsException e) {
171                 failable.fail("\nFreemarker exception detected "
172                         + message
173                         + " but there was an exception during processing: "
174                         + e.getMessage()
175                         + "\nStack Trace from processing exception"
176                         + stackTrace(e)
177                         + "\nContents that triggered exception: "
178                         + deLinespace(contents));
179             }
180 
181         }
182     }
183 
184     public static String deLinespace(String contents) {
185         while (contents.contains("\n\n")) {
186             contents = contents.replaceAll("\n\n", "\n");
187         }
188         return contents;
189     }
190 
191     /**
192      * 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.
193      * 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.
194      * {@code }
195      * @return true if the dontTearDownProperty is not set.
196      */
197     public static boolean dontTearDownPropertyNotSet() {
198         return System.getProperty(DONT_TEAR_DOWN_PROPERTY) == null ||
199                 "f".startsWith(System.getProperty(DONT_TEAR_DOWN_PROPERTY).toLowerCase()) ||
200                 "n".startsWith(System.getProperty(DONT_TEAR_DOWN_PROPERTY).toLowerCase());
201     }
202 
203     private static String extractIncidentReportInfo(String contents, String linkLocator, String message) {
204         String chunk =  contents.substring(contents.indexOf("Incident Feedback"), contents.lastIndexOf("</div>") );
205         String docId = chunk.substring(chunk.lastIndexOf("Document Id"), chunk.indexOf("View Id"));
206         docId = docId.substring(0, docId.indexOf("</span>"));
207         docId = docId.substring(docId.lastIndexOf(">") + 2, docId.length());
208 
209         String viewId = chunk.substring(chunk.lastIndexOf("View Id"), chunk.indexOf("Error Message"));
210         viewId = viewId.substring(0, viewId.indexOf("</span>"));
211         viewId = viewId.substring(viewId.lastIndexOf(">") + 2, viewId.length());
212 
213         String stackTrace = chunk.substring(chunk.lastIndexOf("(only in dev mode)"), chunk.length());
214         stackTrace = stackTrace.substring(stackTrace.indexOf("<span id=\"") + 3, stackTrace.length());
215         stackTrace = stackTrace.substring(stackTrace.indexOf("\">") + 2, stackTrace.indexOf("</span>"));
216 
217         //            System.out.println(docId);
218         //            System.out.println(viewId);
219         //            System.out.println(stackTrace);
220         return "\nIncident report "
221                 + message
222                 + " navigating to "
223                 + linkLocator
224                 + " : View Id: "
225                 + viewId.trim()
226                 + " Doc Id: "
227                 + docId.trim()
228                 + "\nStackTrace: "
229                 + stackTrace.trim();
230     }
231 
232     private static String extractIncidentReportKim(String contents, String linkLocator, String message) {
233         String chunk =  contents.substring(contents.indexOf("id=\"headerarea\""), contents.lastIndexOf("</div>") );
234         String docIdPre = "type=\"hidden\" value=\"";
235         String docId = chunk.substring(chunk.indexOf(docIdPre) + docIdPre.length(), chunk.indexOf("\" name=\"documentId\""));
236 
237         String stackTrace = chunk.substring(chunk.lastIndexOf("name=\"displayMessage\""), chunk.length());
238         String stackTracePre = "value=\"";
239         stackTrace = stackTrace.substring(stackTrace.indexOf(stackTracePre) + stackTracePre.length(), stackTrace.indexOf("name=\"stackTrace\"") - 2);
240 
241         return "\nIncident report "
242                 + message
243                 + " navigating to "
244                 + linkLocator
245                 + " Doc Id: "
246                 + docId.trim()
247                 + "\nStackTrace: "
248                 + stackTrace.trim();
249     }
250 
251     public static void failOnInvalidUserName(String userName, String contents, Failable failable) {
252         if (contents.indexOf("Invalid username") > -1) {
253             failable.fail("Invalid username " + userName);
254         }
255     }
256 /*
257     public static void failOnMatchedJira(String contents) {
258         Iterator<String> iter = jiraMatches.keySet().iterator();
259         String key = null;
260 
261         while (iter.hasNext()) {
262             key = iter.next();
263             if (contents.contains(key)) {
264                 SeleneseTestBase.fail(JIRA_BROWSE_URL + jiraMatches.get(key));
265             }
266         }
267     }
268 */
269 
270     private static void failWithReportInfo(String contents, String linkLocator, Failable failable, String message) {
271         final String incidentReportInformation = extractIncidentReportInfo(contents, linkLocator, message);
272         failable.fail(incidentReportInformation);
273     }
274 
275 /*
276     private static void failWithReportInfoForKim(String contents, String linkLocator, String message) {
277         final String kimIncidentReport = extractIncidentReportKim(contents, linkLocator, message);
278         SeleneseTestBase.fail(kimIncidentReport);
279     }
280 */
281     private static void failWithReportInfoForKim(String contents, String linkLocator, Failable failable, String message) {
282         final String kimIncidentReport = extractIncidentReportKim(contents, linkLocator, message);
283         failable.fail(kimIncidentReport);
284     }
285 
286     /**
287      * In order to run as a smoke test the ability to set the baseUrl via the JVM arg remote.public.url is required.
288      * Trailing slashes are trimmed.  If the remote.public.url does not start with http:// it will be added.
289      * @return http://localhost:8080/kr-dev by default else the value of remote.public.url
290      */
291     public static String getBaseUrlString() {
292         String baseUrl = System.getProperty(REMOTE_PUBLIC_URL_PROPERTY);
293         if (baseUrl == null) {
294             baseUrl = DEFAULT_BASE_URL;
295         }
296         baseUrl = prettyHttp(baseUrl);
297         return baseUrl;
298     }
299 
300     public static String getHTML(String urlToRead) {
301         URL url;
302         HttpURLConnection conn;
303         BufferedReader rd;
304         String line;
305         String result = "";
306 
307         try {
308             url = new URL(urlToRead);
309             conn = (HttpURLConnection) url.openConnection();
310             conn.setRequestMethod("GET");
311             rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
312             while ((line = rd.readLine()) != null) {
313                 result += line;
314             }
315             rd.close();
316         } catch (Exception e) {
317             e.printStackTrace();
318         }
319 
320         return result;
321     }
322 
323     /**
324      * 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.
325      * Trailing slashes are trimmed.  If the remote.public.hub does not start with http:// it will be added.
326      * @return http://localhost:4444/wd/hub by default else the value of remote.public.hub
327      */
328     public static String getHubUrlString() {
329         String hubUrl = System.getProperty(HUB_PROPERTY);
330         if (hubUrl == null) {
331             hubUrl = HUB_URL_PROPERTY;
332         }
333         hubUrl = prettyHttp(hubUrl);
334         if (!hubUrl.endsWith("/wd/hub")) {
335             hubUrl = hubUrl + "/wd/hub";
336         }
337         return hubUrl;
338     }
339 
340     private static boolean incidentReported(String contents) {
341         return contents != null &&
342                 contents.contains("Incident Report") &&
343                 !contents.contains("portal.do?channelTitle=Incident%20Report") && // Incident Report link on sampleapp KRAD tab
344                 !contents.contains("portal.do?channelTitle=Incident Report") &&   // Incident Report link on sampleapp KRAD tab IE8
345                 !contents.contains("uitest?viewId=Travel-testView2") &&
346                 !contents.contains("SeleniumException"); // selenium timeouts have Incident Report in them
347     }
348 
349     /**
350      * Append http:// if not present.  Remove trailing /
351      * @param baseUrl
352      * @return
353      */
354     public static String prettyHttp(String baseUrl) {
355 
356         if (baseUrl.endsWith("/")) {
357             baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
358         }
359 
360         if (!baseUrl.startsWith("http")) {
361             baseUrl = "http://" + baseUrl;
362         }
363 
364         return baseUrl;
365     }
366 
367     private static void processFreemarkerException(String contents, String linkLocator, Failable failable, String message) {
368         JiraAwareFailureUtil.failOnMatchedJira(contents, failable);
369         String stackTrace = contents.substring(contents.indexOf("Error: on line"), contents.indexOf("more<") - 1);
370         failable.fail(
371                 "\nFreemarker Exception " + message + " navigating to " + linkLocator + "\nStackTrace: " + stackTrace
372                         .trim());
373     }
374 
375 /*
376     private static void processIncidentReport(String contents, String linkLocator, String message) {
377         failOnMatchedJira(contents);
378 
379         if (contents.indexOf("Incident Feedback") > -1) {
380             failWithReportInfo(contents, linkLocator, message);
381         }
382 
383         if (contents.indexOf("Incident Report") > -1) { // KIM incident report
384             failWithReportInfoForKim(contents, linkLocator, message);
385         }
386 
387         SeleneseTestBase.fail("\nIncident report detected " + message + "\n Unable to parse out details for the contents that triggered exception: " + deLinespace(
388                 contents));
389     }
390 
391     private static void failWithReportInfo(String contents, String linkLocator, String message) {
392         final String incidentReportInformation = extractIncidentReportInfo(contents, linkLocator, message);
393         SeleneseTestBase.fail(incidentReportInformation);
394     }
395 */
396 
397     protected static void processIncidentReport(String contents, String linkLocator, Failable failable, String message) {
398         JiraAwareFailureUtil.failOnMatchedJira(contents, failable);
399 
400         if (contents.indexOf("Incident Feedback") > -1) {
401             failWithReportInfo(contents, linkLocator, failable, message);
402         }
403 
404         if (contents.indexOf("Incident Report") > -1) { // KIM incident report
405             failWithReportInfoForKim(contents, linkLocator, failable, message);
406         }
407 
408         failable.fail("\nIncident report detected "
409                 + message
410                 + "\n Unable to parse out details for the contents that triggered exception: "
411                 + deLinespace(contents));
412     }
413 
414     /**
415      * Write the given stack trace into a String
416      * @param throwable whose stack trace to return
417      * @return String of the given throwable's stack trace.
418      */
419     public static String stackTrace(Throwable throwable) {
420         StringWriter wrt = new StringWriter();
421         PrintWriter pw = new PrintWriter(wrt);
422         throwable.printStackTrace(pw);
423         pw.flush();
424         return wrt.toString();
425     }
426 
427 }