View Javadoc
1   /**
2    * Copyright 2005-2015 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 org.kuali.rice.testtools.selenium;
17  
18  import org.apache.commons.lang.RandomStringUtils;
19  import org.kuali.rice.testtools.common.JiraAwareFailable;
20  import org.kuali.rice.testtools.common.JiraAwareFailureUtils;
21  
22  import java.io.BufferedReader;
23  import java.io.InputStreamReader;
24  import java.io.PrintWriter;
25  import java.io.StringWriter;
26  import java.net.HttpURLConnection;
27  import java.net.URL;
28  import java.net.URLEncoder;
29  import java.util.Calendar;
30  
31  /**
32   * For Rice specific sampleapp testing code.
33   * <ol>
34   *   <li>Keep test framework methods (WebDriver, Assert) dependencies out of this class, those should be in
35   *   {@link WebDriverUtils}</li>
36   *   <li>Move JiraAware calls out of this class, those should be in {@see JiraAwareFailureUtils} or modified to be failed
37   *   in another class</li>
38   * </ol>
39   * @author Kuali Rice Team (rice.collab@kuali.org)
40   */
41  public class AutomatedFunctionalTestUtils {
42  
43      /**
44       * Calendar.getInstance().getTimeInMillis() + ""
45       */
46      public static final String DTS = Calendar.getInstance().getTimeInMillis() + "";
47  
48      /**
49       * Calendar.getInstance().getTimeInMillis() + "" + RandomStringUtils.randomAlphabetic(2).toLowerCase()
50       * @Deprecated {@link AutomatedFunctionalTestUtils#createUniqueDtsPlusTwoRandomChars()}
51       */
52      public static final String DTS_TWO = Calendar.getInstance().getTimeInMillis() + "" + RandomStringUtils.randomAlphabetic(2).toLowerCase();
53  
54      /**
55       *  &hideReturnLink=true
56       */
57      public static final String HIDE_RETURN_LINK =  "&hideReturnLink=true";
58  
59      /**
60       *  &hideReturnLink=false
61       */
62      public static final String HIDE_RETURN_LINK_FALSE =  "&hideReturnLink=false";
63  
64      /**
65       * /kr-krad/lookup?methodToCall=start&dataObjectClassName=
66       */
67      public static final String KRAD_LOOKUP_METHOD =  "/kr-krad/lookup?methodToCall=start&dataObjectClassName=";
68  
69      /**
70       * /kr/lookup.do?methodToCall=start&businessObjectClassName=
71       */
72      public static final String KNS_LOOKUP_METHOD =  "/kr/lookup.do?methodToCall=start&businessObjectClassName=";
73  
74      /**
75       * /kr-krad/kradsampleapp?viewId=KradSampleAppHome
76       */
77      public static final String KRAD_PORTAL = "/kr-krad/kradsampleapp?viewId=KradSampleAppHome";
78  
79      /**
80       * /kr-krad/kradsampleapp?viewId=KradSampleAppHome
81       */
82      public static final String KRAD_PORTAL_URL = WebDriverUtils.getBaseUrlString() + KRAD_PORTAL;
83  
84      /**
85       * /kr-krad/labs?viewId=LabsMenuView
86       */
87      public static final  String LABS = "/kr-krad/labs?viewId=LabsMenuView";
88  
89      /**
90       * WebDriverUtils.getBaseUrlString() + LABS
91       */
92      public static final String LABS_URL = WebDriverUtils.getBaseUrlString() + LABS;
93  
94      /**
95       * /portal.do
96       */
97      public static final String PORTAL = "/portal.do";
98  
99      /**
100      * WebDriverUtils.getBaseUrlString() + ITUtil.PORTAL
101      */
102     public static final String PORTAL_URL =  WebDriverUtils.getBaseUrlString() + AutomatedFunctionalTestUtils.PORTAL;
103 
104     /**
105      * URLEncoder.encode(PORTAL_URL)
106      */
107     public static final String PORTAL_URL_ENCODED = URLEncoder.encode(PORTAL_URL);
108 
109     /**
110      *  &showMaintenanceLinks=true
111      */
112     public static final String SHOW_MAINTENANCE_LINKS =  "&showMaintenanceLinks=true";
113 
114     /**
115      * KRAD
116      */
117     public static final String REMOTE_UIF_KRAD = "KRAD";
118 
119     /**
120      * KNS
121      */
122     public static final String REMOTE_UIF_KNS  = "KNS";
123 
124     /**
125      * &docFormKey=
126      */
127     public static final String DOC_FORM_KEY = "&docFormKey=";
128     
129     /**
130      * Creates a 13 digit time stamp with two random characters appended for use with fields that require unique values.
131      *
132      * Some fields have built in validation to not allow 9 continuous digits for those cases {@see #createUniqueDtsPlusTwoRandomCharsNot9Digits}
133      * @return
134      */
135     public static String createUniqueDtsPlusTwoRandomChars() {
136         return Calendar.getInstance().getTimeInMillis() + "" + RandomStringUtils.randomAlphabetic(2).toLowerCase();
137     }
138 
139     /**
140      * Creates a 13 digit time stamp with two random characters inserted into it to avoid the 9 continuous digit verification some fields use.
141      *
142      * @return
143      */
144     public static String createUniqueDtsPlusTwoRandomCharsNot9Digits() {
145         String dtsTwo = AutomatedFunctionalTestUtils.createUniqueDtsPlusTwoRandomChars();
146         dtsTwo = dtsTwo.substring(0, 5) + dtsTwo.substring(13, 15) + dtsTwo.substring(6, 12);
147         return dtsTwo;
148     }
149 
150     protected static void checkForIncidentReport(String contents, String linkLocator, String message, JiraAwareFailable failable) {
151         if (contents == null) { //guard clause
152             return;
153         }
154 
155         String errorMessage = incidentReportMessage(contents, linkLocator, message);
156 
157         if (errorMessage != null) {
158             if (message != null && !message.isEmpty()) {
159                 failable.jiraAwareFail(errorMessage, message);
160             } else {
161                 failable.jiraAwareFail(errorMessage, contents);
162             }
163         }
164     }
165 
166     protected static String incidentReportMessage(String contents, String linkLocator, String message) {
167         if (incidentReported(contents)) {
168             try {
169                 return processIncidentReport(contents, linkLocator, message);
170             } catch (IndexOutOfBoundsException e) {
171                 return "\nIncident report 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         if (contents.contains("HTTP Status 404")) {
183             return "HTTP Status 404 contents: " + contents;
184         }
185 
186         if (contents.contains("HTTP Status 500")) {
187             return "\nHTTP Status 500 stacktrace: " + extract500Exception(contents);
188         }
189 
190         // freemarker exception
191         if (contents.contains("Java backtrace for programmers:")
192                 || contents.contains("Java stack trace (for programmers):")
193                 || contents.contains("FreeMarker template error:")) {
194             try {
195                 return freemarkerExceptionMessage(contents, linkLocator, message);
196             } catch (IndexOutOfBoundsException e) {
197                 return "\nFreemarker exception detected "
198                         + message
199                         + " but there was an exception during processing: "
200                         + e.getMessage()
201                         + "\nStack Trace from processing exception"
202                         + stackTrace(e)
203                         + "\nContents that triggered exception: "
204                         + deLinespace(contents);
205             }
206         }
207 
208         if (contents.contains("Document Expired")) { // maybe Firefox specific
209             return "Document Expired message.";
210         }
211 
212         return null;
213     }
214 
215     public static String deLinespace(String contents) {
216         while (contents.contains("\n\n")) {
217             contents = contents.replaceAll("\n\n", "\n");
218         }
219         return contents;
220     }
221 
222     private static String extractIncidentReportInfo(String contents, String linkLocator, String message) {
223         String chunk =  contents.substring(contents.indexOf("Incident Feedback"), contents.lastIndexOf("</div>") );
224         String docId = chunk.substring(chunk.lastIndexOf("Document Id"), chunk.indexOf("View Id"));
225         docId = docId.substring(0, docId.indexOf("</div>"));
226         docId = docId.substring(docId.lastIndexOf(">") + 2, docId.length()).trim();
227 
228         String viewId = chunk.substring(chunk.lastIndexOf("View Id"), chunk.indexOf("Error Message"));
229         viewId = viewId.substring(0, viewId.indexOf("</div>"));
230         viewId = viewId.substring(viewId.lastIndexOf(">") + 2, viewId.length()).trim();
231 
232         String stackTrace = chunk.substring(chunk.lastIndexOf("(only in dev mode)"), chunk.length());
233         stackTrace = stackTrace.substring(stackTrace.indexOf("<pre") + 4, stackTrace.length());
234         stackTrace = stackTrace.substring(stackTrace.indexOf(">") + 1, stackTrace.indexOf("</"));
235 
236         return "\nIncident report "
237                 + message
238                 + " navigating to "
239                 + linkLocator
240                 + " : View Id: "
241                 + viewId.trim()
242                 + " Doc Id: "
243                 + docId.trim()
244                 + "\nStackTrace: "
245                 + stackTrace.trim();
246     }
247 
248     private static String extractIncidentReportKim(String contents, String linkLocator, String message) {
249         if (contents.indexOf("id=\"headerarea\"") > -1) {
250             String chunk =  contents.substring(contents.indexOf("id=\"headerarea\""), contents.lastIndexOf("</div>") );
251             String docIdPre = "type=\"hidden\" value=\"";
252             String docId = chunk.substring(chunk.indexOf(docIdPre) + docIdPre.length(), chunk.indexOf("\" name=\"documentId\""));
253 
254             String stackTrace = chunk.substring(chunk.lastIndexOf("name=\"displayMessage\""), chunk.length());
255             String stackTracePre = "value=\"";
256             stackTrace = stackTrace.substring(stackTrace.indexOf(stackTracePre) + stackTracePre.length(), stackTrace.indexOf("name=\"stackTrace\"") - 2);
257 
258             return "\nIncident report "
259                     + message
260                     + " navigating to "
261                     + linkLocator
262                     + " Doc Id: "
263                     + docId.trim()
264                     + "\nStackTrace: "
265                     + stackTrace.trim();
266         }
267         return "\nIncident report detected for " + linkLocator + " but not able to parse.  " + message;
268     }
269 
270     public static void failOnInvalidUserName(String userName, String contents, JiraAwareFailable failable) {
271         if (contents.indexOf("Invalid") > -1) {
272             failable.fail("Invalid Login " + userName);
273         }
274     }
275 /*
276     public static void failOnMatchedJira(String contents) {
277         Iterator<String> iter = jiraMatches.keySet().iterator();
278         String key = null;
279 
280         while (iter.hasNext()) {
281             key = iter.next();
282             if (contents.contains(key)) {
283                 SeleneseTestBase.fail(JIRA_BROWSE_URL + jiraMatches.get(key));
284             }
285         }
286     }
287 */
288 
289     private static void failWithInfo(String contents, String linkLocator, JiraAwareFailable failable, String message) {
290         JiraAwareFailureUtils.failOnMatchedJira(contents, linkLocator, failable);
291         failable.fail(contents);
292     }
293 
294     private static void failWithReportInfo(String contents, String linkLocator, JiraAwareFailable failable, String message) {
295         final String incidentReportInformation = extractIncidentReportInfo(contents, linkLocator, message);
296         JiraAwareFailureUtils.failOnMatchedJira(incidentReportInformation, failable);
297         failWithInfo(incidentReportInformation, linkLocator, failable, message);
298     }
299 
300     /*
301     private static void failWithReportInfoForKim(String contents, String linkLocator, String message) {
302         final String kimIncidentReport = extractIncidentReportKim(contents, linkLocator, message);
303         SeleneseTestBase.fail(kimIncidentReport);
304     }
305 */
306     private static void failWithReportInfoForKim(String contents, String linkLocator, JiraAwareFailable failable, String message) {
307         final String kimIncidentReport = extractIncidentReportKim(contents, linkLocator, message);
308         JiraAwareFailureUtils.failOnMatchedJira(kimIncidentReport, failable);
309         failable.fail(kimIncidentReport);
310     }
311 
312     public static String getHTML(String urlToRead) {
313         URL url;
314         HttpURLConnection conn;
315         BufferedReader rd;
316         String line;
317         String result = "";
318 
319         try {
320             url = new URL(urlToRead);
321             conn = (HttpURLConnection) url.openConnection();
322             conn.setRequestMethod("GET");
323             rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
324             while ((line = rd.readLine()) != null) {
325                 result += line;
326             }
327             rd.close();
328         } catch (Exception e) {
329             e.printStackTrace();
330         }
331 
332         return result;
333     }
334 
335     private static boolean incidentReported(String contents) {
336         return contents != null &&
337                 contents.contains("Incident Report") &&
338                 !contents.contains("portal.do?channelTitle=Incident%20Report") && // Incident Report link on sampleapp KRAD tab
339                 !contents.contains("portal.do?channelTitle=Incident Report") &&   // Incident Report link on sampleapp KRAD tab IE8
340                 !contents.contains("uitest?viewId=Travel-testView2") &&
341                 !contents.contains("SeleniumException"); // selenium timeouts have Incident Report in them
342     }
343 
344     /**
345      * Append http:// if not present, remove trailing /.
346      *
347      * @param baseUrl
348      * @return
349      */
350     public static String prettyHttp(String baseUrl) {
351 
352         if (baseUrl.endsWith("/")) {
353             baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
354         }
355 
356         if (!baseUrl.startsWith("http")) {
357             baseUrl = "http://" + baseUrl;
358         }
359 
360         return baseUrl;
361     }
362 
363     private static String extract500Exception(String contents) {
364         return contents.substring(contents.indexOf("<b>exception</b> </p><pre>") +26,
365                                   contents.indexOf("</pre><p></p><p><b>note</b>"));
366     }
367 
368     private static void processFreemarkerException(String contents, String linkLocator, JiraAwareFailable failable, String message) {
369         JiraAwareFailureUtils.failOnMatchedJira(contents, failable);
370         String errorMessage = freemarkerExceptionMessage(contents, linkLocator, message);
371 
372         JiraAwareFailureUtils.failOnMatchedJira(errorMessage, linkLocator, failable);
373         failable.fail(errorMessage);
374     }
375 
376     protected static String freemarkerExceptionMessage(String contents, String linkLocator, String message) {
377         String ftlStackTrace = null;
378         if (contents.contains("more<")) {
379             ftlStackTrace = contents.substring(contents.indexOf("----------"), contents.indexOf("more<") - 1);
380         } else if (contents.contains("at java.lang.Thread.run(Thread.java:")) {
381             if (contents.indexOf("Error: on line") > -1) {
382                 ftlStackTrace = contents.substring(contents.indexOf("Error: on line"), contents.indexOf("at java.lang.Thread.run(Thread.java:") + 39 );
383             } else {
384                 ftlStackTrace = contents.substring(contents.indexOf("FreeMarker template error:"), contents.indexOf("at java.lang.Thread.run(Thread.java:") + 39 );
385             }
386         }
387         return "\nFreemarker Exception " + message + " navigating to " + linkLocator + "\nStackTrace: " + ftlStackTrace.trim();
388     }
389 
390 /*
391     private static void processIncidentReport(String contents, String linkLocator, String message) {
392         failOnMatchedJira(contents);
393 
394         if (contents.indexOf("Incident Feedback") > -1) {
395             failWithReportInfo(contents, linkLocator, message);
396         }
397 
398         if (contents.indexOf("Incident Report") > -1) { // KIM incident report
399             failWithReportInfoForKim(contents, linkLocator, message);
400         }
401 
402         SeleneseTestBase.fail("\nIncident report detected " + message + "\n Unable to parse out details for the contents that triggered exception: " + deLinespace(
403                 contents));
404     }
405 
406     private static void failWithReportInfo(String contents, String linkLocator, String message) {
407         final String incidentReportInformation = extractIncidentReportInfo(contents, linkLocator, message);
408         SeleneseTestBase.fail(incidentReportInformation);
409     }
410 */
411 
412     protected static void processIncidentReport(String contents, String linkLocator, JiraAwareFailable failable, String message) {
413 
414         if (contents.indexOf("Incident Feedback") > -1) {
415             failWithReportInfo(contents, linkLocator, failable, message);
416         }
417 
418         if (contents.indexOf("Incident Report") > -1) { // KIM incident report
419             failWithReportInfoForKim(contents, linkLocator, failable, message);
420         }
421 
422         JiraAwareFailureUtils.failOnMatchedJira(contents, failable);
423         failable.fail("\nIncident report detected "
424                 + message
425                 + "\n Unable to parse out details for the contents that triggered exception: "
426                 + deLinespace(contents));
427     }
428 
429     protected static String processIncidentReport(String contents, String linkLocator, String message) {
430 
431         if (contents.indexOf("Incident Feedback") > -1) {
432             return extractIncidentReportInfo(contents, linkLocator, message);
433         }
434 
435         if (contents.indexOf("Incident Report") > -1) { // KIM incident report
436             return extractIncidentReportKim(contents, linkLocator, message);
437         }
438 
439         return "\nIncident report detected "
440                 + message
441                 + "\n Unable to parse out details for the contents that triggered exception: "
442                 + deLinespace(contents);
443     }
444 
445     /**
446      * Write the given stack trace into a String remove the ats in an attempt to not cause Jenkins problems.
447      * @param throwable whose stack trace to return
448      * @return String of the given throwable's stack trace.
449      */
450     public static String stackTrace(Throwable throwable) {
451         StringWriter wrt = new StringWriter();
452         PrintWriter pw = new PrintWriter(wrt);
453         throwable.printStackTrace(pw);
454         pw.flush();
455         return wrt.toString();
456     }
457 
458     /**
459      * <p>
460      * Use the KRAD Login Screen or the old KNS Login Screen
461      * </p>
462      *
463      * @return true if Krad login
464      */
465     public static boolean isKradLogin(){
466         // check system property, default to KRAD
467         String loginUif = System.getProperty(WebDriverUtils.REMOTE_LOGIN_UIF);
468         if (loginUif == null) {
469             loginUif = REMOTE_UIF_KRAD;
470         }
471 
472         return (REMOTE_UIF_KRAD.equalsIgnoreCase(loginUif));
473     }
474 }