View Javadoc

1   /**
2    * Copyright 2005-2012 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   */package edu.samplu.common;
16  
17  import com.thoughtworks.selenium.Selenium;
18  import org.apache.commons.lang.RandomStringUtils;
19  import org.junit.Assert;
20  import org.openqa.selenium.By;
21  import org.openqa.selenium.WebDriver;
22  import org.openqa.selenium.chrome.ChromeDriver;
23  import org.openqa.selenium.firefox.FirefoxDriver;
24  import org.openqa.selenium.firefox.FirefoxProfile;
25  import org.openqa.selenium.remote.DesiredCapabilities;
26  import org.openqa.selenium.remote.RemoteWebDriver;
27  
28  import java.io.PrintWriter;
29  import java.io.StringWriter;
30  import java.net.MalformedURLException;
31  import java.net.URL;
32  import java.util.Calendar;
33  import java.util.HashMap;
34  import java.util.Iterator;
35  import java.util.Map;
36  
37  import static com.thoughtworks.selenium.SeleneseTestBase.fail;
38  import static org.junit.Assert.assertEquals;
39  
40  /**
41   * Common selenium test methods that should be reused rather than recreated for each test.
42   * @author Kuali Rice Team (rice.collab@kuali.org)
43   */
44  
45  public class ITUtil {
46  
47      public static final String KUALI_PORTAL_TITLE = "Kuali Portal Index";
48      public static final String DEFAULT_BASE_URL = "http://localhost:8080/kr-dev";
49      public final static String PORTAL = "/portal.do";
50      public static final String DTS = Calendar.getInstance().getTimeInMillis() + "";
51      public static final String DTS_TWO = Calendar.getInstance().getTimeInMillis() + "" + RandomStringUtils.randomAlphabetic(2).toLowerCase();
52      public static String WAIT_TO_END_TEST = "5000";
53      public static final String DIV_ERROR_LOCATOR = "//div[@class='error']";
54      public static final String DIV_EXCOL_LOCATOR = "//div[@class='msg-excol']";
55      public static final int WAIT_DEFAULT_SECONDS = 60;
56      public static final String DEFAULT_WAIT_FOR_PAGE_TO_LOAD_TIMEOUT = "30000";
57      static Map<String, String> jiraMatches;
58      public static final String REMOTE_PUBLIC_URL_PROPERTY = "remote.public.url";
59      public static final String REMOTE_AUTOLOGIN_PROPERTY = "remote.autologin";
60      public static final String HUB_PROPERTY = "remote.public.hub";
61      public static final String HUB_DRIVER_PROPERTY = "remote.public.driver";
62      public static final String HUB_URL_PROPERTY = "http://localhost:4444/wd/hub";
63      public static final String DONT_TEAR_DOWN_PROPERTY = "remote.driver.dontTearDown";
64  
65      static {
66          jiraMatches = new HashMap<String, String>();
67          jiraMatches.put("Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'refreshWhenChanged' of bean class [org.kuali.rice.krad.uif.element.Action]: Bean property 'refreshWhenChanged' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?",
68                  "KULRICE-8137 Agenda Rule edit Incident report Invalid property 'refreshWhenChanged'");
69  
70          jiraMatches.put("org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase.processAddCollectionLineBusinessRules(MaintenanceDocumentRuleBase.",
71                  "KULRICE-8142 NPE in MaintenanceDocumentRuleBase.processAddCollectionLineBusinessRules");
72  
73          jiraMatches.put("at org.kuali.rice.krad.rules.DocumentRuleBase.isDocumentOverviewValid(DocumentRuleBase.",
74                  "KULRICE-8134 NPE in DocumentRuleBase.isDocumentOverviewValid(DocumentRuleBase");
75  
76          jiraMatches.put("org.kuali.rice.krad.uif.layout.TableLayoutManager.buildLine(TableLayoutManager.",
77                  "KULRICE-8160 NPE at TableLayoutManager.buildLine(TableLayoutManager");
78  
79          jiraMatches.put("Bean property 'configFileLocations' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?",
80                  "KULRICE-8173 Bean property 'configFileLocations' is not writable or has an invalid setter method");
81  
82          jiraMatches.put("Bean property 'componentSecurity' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?",
83                  "KULRICE-8182 JDK7 Bean property 'componentSecurity' is not readable...");
84  
85          jiraMatches.put("java.sql.SQLSyntaxErrorException: ORA-00904: \"ROUTEHEADERID\": invalid identifier",
86                  "KULRICE-8277 Several ITs fail with OJB operation; bad SQL grammar []; nested exception is java.sql.SQLException: ORA-00904: \"ROUTEHEADERID\": invalid identifier");
87  //        jiraMatches.put("",
88  //                "");
89  
90      }
91  
92      /**
93       * "FINAL", selenium.getText("//table[@id='row']/tbody/tr[1]/td[4]"
94       * @param selenium
95       * @param docId
96       */
97      public static void assertDocFinal(Selenium selenium, String docId) {
98          docId= "link=" + docId;
99          if(selenium.isElementPresent(docId)){
100             assertEquals("FINAL", selenium.getText("//table[@id='row']/tbody/tr[1]/td[4]"));
101         }else{
102             assertEquals(docId, selenium.getText("//table[@id='row']/tbody/tr[1]/td[1]"));
103             assertEquals("FINAL", selenium.getText("//table[@id='row']/tbody/tr[1]/td[4]"));
104         }
105     }
106 
107     protected static String blanketApprovalCleanUpErrorText(String errorText) {
108         errorText = errorText.replace("* required field", "").replace("\n", " ").trim(); // bit of extra ui text we don't care about
109         return errorText;
110     }
111 
112     /**
113      * Generic blanket approve behavior
114      * @param selenium
115      * @throws InterruptedException
116      */
117     public static void blanketApprove(Selenium selenium) throws InterruptedException {
118         ITUtil.checkForIncidentReport(selenium, "methodToCall.blanketApprove");
119         ITUtil.waitAndClick(selenium, "methodToCall.blanketApprove");
120         selenium.waitForPageToLoad(DEFAULT_WAIT_FOR_PAGE_TO_LOAD_TIMEOUT);
121         Thread.sleep(2000);
122 
123         if (selenium.isElementPresent(DIV_ERROR_LOCATOR)) {
124             String errorText = selenium.getText(DIV_ERROR_LOCATOR);
125             if (errorText != null && errorText.contains("error(s) found on page.")) {
126                 errorText = blanketApprovalCleanUpErrorText(errorText);
127                 if (selenium.isElementPresent(DIV_EXCOL_LOCATOR)) { // not present if errors are at the bottom of the page (see left-errmsg below)
128                     errorText = blanketApprovalCleanUpErrorText(selenium.getText(DIV_EXCOL_LOCATOR));// + "\n" + selenium.getHtmlSource()); // replacing errorText as DIV_EXCOL_LOCATOR includes the error count
129                 }
130                 if (selenium.isElementPresent("//div[@class='left-errmsg-tab']/div/div")) {
131                     errorText = errorText + blanketApprovalCleanUpErrorText(selenium.getText("//div[@class='left-errmsg-tab']/div/div"));
132                 }
133 
134                 //                if (selenium.isElementPresent("//div[@class='left-errmsg']/div")) {
135                 //                    errorText = errorText + " " + selenium.getText("//div[@class='left-errmsg']/div/div[1]");
136                 //                }
137                 Assert.fail(errorText);
138             }
139         }
140         ITUtil.checkForIncidentReport(selenium, "//img[@alt='doc search']");
141         waitAndClick(selenium, "//img[@alt='doc search']");
142         selenium.waitForPageToLoad(DEFAULT_WAIT_FOR_PAGE_TO_LOAD_TIMEOUT);
143         assertEquals("Kuali Portal Index", selenium.getTitle());
144         selenium.selectFrame("iframeportlet");
145         selenium.click("//input[@name='methodToCall.search' and @value='search']");
146         selenium.waitForPageToLoad(DEFAULT_WAIT_FOR_PAGE_TO_LOAD_TIMEOUT);
147     }
148 
149     /**
150      * "//li[@class='uif-errorMessageItem']"
151      * @param selenium
152      * @param message
153      */
154     public static void checkErrorMessageItem(Selenium selenium, String message) {
155         final String error_locator = "//li[@class='uif-errorMessageItem']";
156         if (selenium.isElementPresent(error_locator)) {
157             String errorText = selenium.getText(error_locator);
158             if (errorText != null && errorText.contains("errors")) {
159                 Assert.fail(errorText + message);
160             }
161         }
162     }
163 
164 
165     /**
166      * In order to run as a smoke test the ability to set the baseUrl via the JVM arg remote.public.url is required.
167      * Trailing slashes are trimmed.  If the remote.public.url does not start with http:// it will be added.
168      * @return http://localhost:8080/kr-dev by default else the value of remote.public.url
169      */
170     public static String getBaseUrlString() {
171         String baseUrl = System.getProperty(REMOTE_PUBLIC_URL_PROPERTY);
172         if (baseUrl == null) {
173             baseUrl = DEFAULT_BASE_URL;
174         }
175         baseUrl = prettyHttp(baseUrl);
176         return baseUrl;
177     }
178 
179     /**
180      * Append http:// if not present.  Remove trailing /
181      * @param baseUrl
182      * @return
183      */
184     public static String prettyHttp(String baseUrl) {
185         if (baseUrl.endsWith("/")) {
186             baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
187         }
188         if (!baseUrl.startsWith("http")) {
189             baseUrl = "http://" + baseUrl;
190         }
191         return baseUrl;
192     }
193 
194     /**
195      * 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.
196      * Trailing slashes are trimmed.  If the remote.public.hub does not start with http:// it will be added.
197      * @return http://localhost:4444/wd/hub by default else the value of remote.public.hub
198      */
199     public static String getHubUrlString() {
200         String hubUrl = System.getProperty(HUB_PROPERTY);
201         if (hubUrl == null) {
202             hubUrl = HUB_URL_PROPERTY;
203         }
204         hubUrl = prettyHttp(hubUrl);
205         if (!hubUrl.endsWith("/wd/hub")) {
206             hubUrl = hubUrl + "/wd/hub";
207         }
208         return hubUrl;
209     }
210 
211     /**
212      * remote.public.driver set to chrome or firefox (null assumes firefox)
213      * if remote.public.hub is set a RemoteWebDriver is created (Selenium Grid)
214      * @return WebDriver or null if unable to create
215      */
216     public static WebDriver getWebDriver() {
217         String driverParam = System.getProperty(HUB_DRIVER_PROPERTY);
218         String hubParam = System.getProperty(HUB_PROPERTY);
219         if (hubParam == null) {
220             if (driverParam == null || "firefox".equalsIgnoreCase(driverParam)) {
221                 FirefoxProfile profile = new FirefoxProfile();
222                 profile.setEnableNativeEvents(false);
223                 return new FirefoxDriver(profile);
224             } else if ("chrome".equalsIgnoreCase(driverParam)) {
225                 return new ChromeDriver();
226             }
227         } else {
228             try {
229                 if (driverParam == null || "firefox".equalsIgnoreCase(driverParam)) {
230                     return new RemoteWebDriver(new URL(ITUtil.getHubUrlString()), DesiredCapabilities.firefox());
231                 } else if ("chrome".equalsIgnoreCase(driverParam)) {
232                     return new RemoteWebDriver(new URL(ITUtil.getHubUrlString()), DesiredCapabilities.chrome());
233                 }
234             } catch (MalformedURLException mue) {
235                 System.out.println(ITUtil.getHubUrlString() + " " + mue.getMessage());
236                 mue.printStackTrace();
237             }
238         }
239         return null;
240     }
241 
242     /**
243      * If the JVM arg remote.autologin is set, auto login as admin will not be done.
244      * @param selenium to login with
245      */
246     public static void loginSe(Selenium selenium) {
247         loginSe(selenium, "admin");
248     }
249 
250     /**
251      * If the JVM arg remote.autologin is set, auto login as admin will not be done.
252      * @param driver
253      * @param userName
254      * @throws InterruptedException
255      */
256     public static void login(WebDriver driver, String userName) throws InterruptedException {
257         if (System.getProperty(REMOTE_AUTOLOGIN_PROPERTY) == null) {
258             driver.findElement(By.name("__login_user")).clear();
259             driver.findElement(By.name("__login_user")).sendKeys(userName);
260             driver.findElement(By.cssSelector("input[type=\"submit\"]")).click();
261             Thread.sleep(1000);
262             String contents = driver.getPageSource();
263             checkForInvalidUserName(userName, contents);
264         }
265     }
266 
267     private static void checkForInvalidUserName(String userName, String contents) {
268         if (contents.indexOf("Invalid username") > -1) {
269             Assert.fail("Invalid username " + userName);
270         }
271     }
272 
273     /**
274      * If the JVM arg remote.autologin is set, auto login as admin will not be done.
275      * @param selenium to login with
276      */
277     public static void loginSe(Selenium selenium, String user) {
278         if (System.getProperty(REMOTE_AUTOLOGIN_PROPERTY) == null) {
279             try {
280                 selenium.waitForPageToLoad(DEFAULT_WAIT_FOR_PAGE_TO_LOAD_TIMEOUT);
281             } catch (Exception e) {
282                 Assert.fail("Login page not loaded app started?");
283             }
284             if (!"Login".equals(selenium.getTitle())) {
285                 fail("Title is not Login as expected, but " + selenium.getTitle());
286             }
287             selenium.type("__login_user", user);
288             selenium.click("//input[@type='submit']"); //using css selector fails
289             selenium.waitForPageToLoad(DEFAULT_WAIT_FOR_PAGE_TO_LOAD_TIMEOUT);
290             String contents = selenium.getHtmlSource();
291             checkForInvalidUserName(user, contents);
292         }
293     }
294 
295     /**
296      * Write the given stack trace into a String
297      * @param throwable whose stack trace to return
298      * @return String of the given throwable's stack trace.
299      */
300     public static String stackTrace(Throwable throwable) {
301         StringWriter wrt=new StringWriter();
302         PrintWriter pw=new PrintWriter(wrt);
303         throwable.printStackTrace(pw);
304         pw.flush();
305         return wrt.toString();
306     }
307 
308     /**
309      * 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.
310      * 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.
311      * {@code }
312      * @return true if the dontTearDownProperty is not set.
313      */
314     public static boolean dontTearDownPropertyNotSet() {
315         return System.getProperty(DONT_TEAR_DOWN_PROPERTY) == null ||
316                 "f".startsWith(System.getProperty(DONT_TEAR_DOWN_PROPERTY).toLowerCase()) ||
317                 "n".startsWith(System.getProperty(DONT_TEAR_DOWN_PROPERTY).toLowerCase());
318     }
319 
320     /**
321      * Wait 60 seconds for the elementLocator to be present or fail.  Click if present
322      * @param selenium
323      * @param elementLocator
324      * @throws InterruptedException
325      */
326     public static void waitAndClick(Selenium selenium, String elementLocator) throws InterruptedException {
327         waitAndClick(selenium, elementLocator, WAIT_DEFAULT_SECONDS);
328     }
329 
330     /**
331      * Wait 60 seconds for the elementLocator to be present or fail.  Click if present
332      * @param selenium
333      * @param elementLocator
334      * @param message
335      * @throws InterruptedException
336      */
337     public static void waitAndClick(Selenium selenium, String elementLocator, String message) throws InterruptedException {
338         waitAndClick(selenium, elementLocator, WAIT_DEFAULT_SECONDS, message);
339     }
340 
341     /**
342      * Wait the given seconds for the elementLocator to be present or fail
343      * @param selenium
344      * @param elementLocator
345      * @param seconds
346      * @throws InterruptedException
347      */
348     public static void waitAndClick(Selenium selenium, String elementLocator, int seconds) throws InterruptedException {
349         waitAndClick(selenium, elementLocator, seconds, "");
350     }
351 
352     /**
353      * Wait the given seconds for the elementLocator to be present or fail
354      * @param selenium
355      * @param elementLocator
356      * @param seconds
357      * @param message
358      * @throws InterruptedException
359      */
360     public static void waitAndClick(Selenium selenium, String elementLocator, int seconds, String message) throws InterruptedException {
361         waitForElement(selenium, elementLocator, seconds, message);
362         selenium.click(elementLocator);
363         Thread.sleep(1000);
364         ITUtil.checkForIncidentReport(selenium, elementLocator, message);
365     }
366 
367     /**
368      * Wait the 60 seconds for the elementLocator to be present or fail, when present type the text.
369      * @param selenium
370      * @param elementLocator
371      * @param text
372      * @throws InterruptedException
373      */
374     public static void waitAndType(Selenium selenium, String elementLocator, String text) throws InterruptedException {
375         waitAndType(selenium, elementLocator, text, "");
376     }
377 
378     /**
379      * Wait the 60 seconds for the elementLocator to be present or fail, when present type the text.  Include failure message on fail.
380      * @param selenium
381      * @param elementLocator
382      * @param text
383      * @param message
384      * @throws InterruptedException
385      */
386     public static void waitAndType(Selenium selenium, String elementLocator, String text, String message) throws InterruptedException {
387         waitAndType(selenium, elementLocator, WAIT_DEFAULT_SECONDS, text, message);
388     }
389 
390     /**
391      * Wait the given seconds for the elementLocator to be present or fail, when present type the text.
392      * @param selenium
393      * @param elementLocator
394      * @param seconds
395      * @param text
396      * @param message
397      * @throws InterruptedException
398      */
399     public static void waitAndType(Selenium selenium, String elementLocator, int seconds, String text, String message) throws InterruptedException {
400         waitForElement(selenium, elementLocator, seconds, message);
401         selenium.type(elementLocator, text);
402         Thread.sleep(1000);
403     }
404 
405     /**
406      * Wait 60 seconds for the elementLocator to be present or fail
407      * @param selenium
408      * @param elementLocator
409      * @throws InterruptedException
410      */
411     public static void waitForElement(Selenium selenium, String elementLocator) throws InterruptedException {
412         waitForElement(selenium, elementLocator, WAIT_DEFAULT_SECONDS);
413     }
414 
415     /**
416      * Wait 60 seconds for the elementLocator to be present or fail
417      * @param selenium
418      * @param elementLocator
419      * @param message
420      * @throws InterruptedException
421      */
422     public static void waitForElement(Selenium selenium, String elementLocator, String message) throws InterruptedException {
423         waitForElement(selenium, elementLocator, WAIT_DEFAULT_SECONDS, message);
424     }
425 
426     /**
427      * Wait the given seconds for the elementLocator to be present or fail
428      * @param selenium
429      * @param elementLocator
430      * @param seconds
431      * @throws InterruptedException
432      */
433     public static void waitForElement(Selenium selenium, String elementLocator, int seconds) throws InterruptedException {
434         waitForElement(selenium, elementLocator, WAIT_DEFAULT_SECONDS, "");
435     }
436 
437     /**
438      * Wait the given seconds for the elementLocator to be present or fail
439      * @param selenium
440      * @param elementLocator
441      * @param seconds
442      * @param message
443      * @throws InterruptedException
444      */
445     public static void waitForElement(Selenium selenium, String elementLocator, int seconds, String message) throws InterruptedException {
446         boolean failed = false;
447         for (int second = 0;; second++) {
448             if (second >= seconds) failed = true;
449             try { if (failed || selenium.isElementPresent(elementLocator)) break; } catch (Exception e) {}
450             Thread.sleep(1000);
451         }
452         ITUtil.checkForIncidentReport(selenium, elementLocator); // after timeout to be sure page is loaded
453         if (failed) fail("timeout of " + seconds + " seconds waiting for " + elementLocator + " " + message);
454     }
455 
456     /**
457      * Wait the given seconds for the elementLocator to be present or fail
458      * @param selenium
459      * @param elementLocator
460      * @throws InterruptedException
461      */
462     public static void waitForElementVisible(Selenium selenium, String elementLocator) throws InterruptedException {
463         waitForElementVisible(selenium, elementLocator, WAIT_DEFAULT_SECONDS, "");
464     }
465 
466     /**
467      * Wait 60 seconds for the elementLocator to be present or fail including the given message
468      * @param selenium
469      * @param elementLocator
470      * @param message
471      * @throws InterruptedException
472      */
473     public static void waitForElementVisible(Selenium selenium, String elementLocator, String message) throws InterruptedException {
474         waitForElementVisible(selenium, elementLocator, WAIT_DEFAULT_SECONDS, message);
475     }
476 
477     /**
478      * Wait the given seconds for the elementLocator to be present or fail
479      * @param selenium
480      * @param elementLocator
481      * @param seconds
482      * @throws InterruptedException
483      */
484     public static void waitForElementVisible(Selenium selenium, String elementLocator, int seconds, String message) throws InterruptedException {
485         for (int second = 0;; second++) {
486             if (second >= seconds) fail("timeout of " + seconds + " seconds waiting for " + elementLocator + " " + message);
487             try { if (selenium.isVisible(elementLocator)) break; } catch (Exception e) {}
488             Thread.sleep(1000);
489         }
490     }
491 
492     /**
493      * Wait for 60 seconds for the selenium.getTitle to match the given title then fail.
494      * @param selenium
495      * @param title
496      * @throws InterruptedException
497      */
498     public static void waitForTitleToEqual(Selenium selenium, String title) throws InterruptedException {
499         waitForTitleToEqual(selenium, title, "");
500     }
501 
502     /**
503      * Wait for 60 seconds for the selenium.getTitle to match the given title then fail including the given message.
504      * @param selenium
505      * @param title
506      * @param message
507      * @throws InterruptedException
508      */
509     public static void waitForTitleToEqual(Selenium selenium, String title, String message) throws InterruptedException {
510         Thread.sleep(2000);
511 //        for (int second = 0;; second++) {
512 //            if (second >= WAIT_DEFAULT_SECONDS) fail(("timeout of " + WAIT_DEFAULT_SECONDS + " seconds waiting for title to equal " + title + " " + message).trim());
513 //            try { if (title.equals(selenium.getTitle())) break; } catch (Exception e) {}
514 //            Thread.sleep(1000);
515 //        }
516     }
517 
518     /**
519      * Check the selenium contents for an Incident Report failure with Incident Report Details
520      * @param selenium
521      * @param linkLocator
522      */
523     public static void checkForIncidentReport(Selenium selenium, String linkLocator) {
524         checkForIncidentReport(selenium, linkLocator, "");
525     }
526 
527     /**
528      * Fails if a Incident Report is detected, extracting and reporting the View Id, Document Id, and StackTrace
529      * @param selenium
530      * @param linkLocator used only in the failure message
531      */
532     public static void checkForIncidentReport(Selenium selenium, String linkLocator, String message) {
533         selenium.waitForPageToLoad(DEFAULT_WAIT_FOR_PAGE_TO_LOAD_TIMEOUT);
534         String contents = selenium.getHtmlSource();
535         checkForIncidentReport(contents, linkLocator, message);
536     }
537 
538     protected static void checkForIncidentReport(String contents, String linkLocator, String message) {
539         if (contents != null &&
540                 contents.contains("Incident Report") &&
541                 !contents.contains("portal.do?channelTitle=Incident%20Report&amp;") && // Incident Report link on sampleapp KRAD tab
542                 !contents.contains("portal.do?channelTitle=Incident Report&amp;") && // Incident Report link on sampleapp KRAD tab IE8
543                 !contents.contains("SeleniumException")) { // selenium timeouts have Incident Report in them
544             try {
545                 if (contents.indexOf("Incident Feedback") > -1) {
546                     Iterator<String> iter = jiraMatches.keySet().iterator();
547                     String key = null;
548                     while (iter.hasNext()) {
549                         key = iter.next();
550                         if (contents.contains(key)) {
551                             Assert.fail("https://jira.kuali.org/browse/" + jiraMatches.get(key));
552                         }
553                     }
554 
555                     String chunk =  contents.substring(contents.indexOf("Incident Feedback"), contents.lastIndexOf("</div>") );
556                     String docId = chunk.substring(chunk.lastIndexOf("Document Id"), chunk.indexOf("View Id"));
557                     docId = docId.substring(0, docId.indexOf("</span>"));
558                     docId = docId.substring(docId.lastIndexOf(">") + 2, docId.length());
559 
560                     String viewId = chunk.substring(chunk.lastIndexOf("View Id"), chunk.indexOf("Error Message"));
561                     viewId = viewId.substring(0, viewId.indexOf("</span>"));
562                     viewId = viewId.substring(viewId.lastIndexOf(">") + 2, viewId.length());
563 
564                     String stackTrace = chunk.substring(chunk.lastIndexOf("(only in dev mode)"), chunk.length());
565                     stackTrace = stackTrace.substring(stackTrace.indexOf("<span id=\"") + 3, stackTrace.length());
566                     stackTrace = stackTrace.substring(stackTrace.indexOf("\">") + 2, stackTrace.indexOf("</span>"));
567 
568                     //            System.out.println(docId);
569                     //            System.out.println(viewId);
570                     //            System.out.println(stackTrace);
571                     Assert.fail("\nIncident report " + message + " navigating to "
572                             + linkLocator
573                             + " : View Id: "
574                             + viewId.trim()
575                             + " Doc Id: "
576                             + docId.trim()
577                             + "\nStackTrace: "
578                             + stackTrace.trim());
579                 } else {
580                     Assert.fail("\nIncident report detected " + message + "\nContents that triggered exception: " + deLinespace(contents));
581                 }
582             } catch (IndexOutOfBoundsException e) {
583                 Assert.fail("\nIncident report detected " + message + " but there was an exception during processing: " + e.getMessage() + "\nStack Trace from processing exception" + stackTrace(e) + "\nContents that triggered exception: " + deLinespace(
584                         contents));
585             }
586         } else {
587             if (contents.contains("HTTP Status 404")) {
588                 Assert.fail("\nHTTP Status 404 " + linkLocator + " " + message + " " + "\ncontents:" + contents);
589             }
590         }
591     }
592 
593     private static String deLinespace(String contents) {
594         while (contents.contains("\n\n")) {
595             contents = contents.replace("\n\n", "\n");
596         }
597         return contents;
598     }
599 }