1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.testtools.selenium;
17
18 import com.thoughtworks.selenium.SeleneseTestBase;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.commons.lang3.exception.ExceptionUtils;
21 import org.openqa.selenium.Alert;
22 import org.openqa.selenium.By;
23 import org.openqa.selenium.Dimension;
24 import org.openqa.selenium.JavascriptExecutor;
25 import org.openqa.selenium.NoSuchFrameException;
26 import org.openqa.selenium.Proxy;
27 import org.openqa.selenium.WebDriver;
28 import org.openqa.selenium.WebElement;
29 import org.openqa.selenium.chrome.ChromeDriver;
30 import org.openqa.selenium.chrome.ChromeDriverService;
31 import org.openqa.selenium.firefox.FirefoxDriver;
32 import org.openqa.selenium.firefox.FirefoxProfile;
33 import org.openqa.selenium.remote.CapabilityType;
34 import org.openqa.selenium.remote.DesiredCapabilities;
35 import org.openqa.selenium.remote.RemoteWebDriver;
36 import org.openqa.selenium.safari.SafariDriver;
37
38 import java.io.BufferedReader;
39 import java.io.File;
40 import java.io.InputStream;
41 import java.io.InputStreamReader;
42 import java.net.MalformedURLException;
43 import java.net.URL;
44 import java.text.SimpleDateFormat;
45 import java.util.Calendar;
46 import java.util.Date;
47 import java.util.LinkedList;
48 import java.util.List;
49 import java.util.concurrent.TimeUnit;
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public class WebDriverUtils {
65
66 protected static SauceLabsWebDriverHelper saucelabs;
67
68 public static boolean jGrowlEnabled = false;
69
70 public static boolean jsHighlightEnabled = false;
71
72
73
74
75 public static final String DEFAULT_BASE_URL = "http://localhost:8080/kr-dev";
76
77
78
79
80 public static final String DEFAULT_BASE_URL_KRAD = "http://localhost:8080/krad-dev";
81
82
83
84
85
86
87
88
89 public static final String DONT_TEAR_DOWN_PROPERTY = "remote.driver.dontTearDown";
90
91
92
93
94
95
96
97
98 public static final String DONT_TEAR_DOWN_ON_FAILURE_PROPERTY = "remote.driver.dontTearDownOnFailure";
99
100
101
102
103 public static final String HUB_DRIVER_PROPERTY = "remote.public.driver";
104
105
106
107
108
109 public static final String HUB_PROPERTY = "remote.public.hub";
110
111
112
113
114 public static final String HUB_URL_PROPERTY = "http://localhost:4444/wd/hub";
115
116
117
118
119
120 public static int IMPLICIT_WAIT_TIME_LOOP_MS = 1000;
121
122
123
124
125
126
127
128
129 public static int IMPLICIT_WAIT_TIME_SECONDS_DEFAULT = 30;
130
131
132
133
134
135 public static final boolean JGROWL_ERROR_FAILURE = false;
136
137
138
139
140 public static final String JS_HIGHLIGHT_BACKGROUND = "#66FF33";
141
142
143
144
145 public static final String JS_HIGHLIGHT_BOARDER = "#66FF33";
146
147
148
149
150 public static final int JS_HIGHLIGHT_MS = 400;
151
152
153
154
155
156
157
158
159 public static final String JS_HIGHLIGHT_MS_PROPERTY = "remote.driver.highlight.ms";
160
161
162
163
164
165
166
167
168 public static final String JS_HIGHLIGHT_PROPERTY = "remote.driver.highlight";
169
170
171
172
173
174
175 public static final String JS_HIGHLIGHT_INPUT_PROPERTY = "remote.driver.highlight.input";
176
177
178
179
180
181
182
183
184
185
186 public static final String PROXY_HOST_PROPERTY = "remote.public.proxy";
187
188
189
190
191
192
193
194
195 public static final String REMOTE_AUTOLOGIN_PROPERTY = "remote.autologin";
196
197
198
199
200
201
202
203
204
205
206 public static final String REMOTE_JGROWL_ENABLED = "remote.jgrowl.enabled";
207
208
209
210
211 public static final String REMOTE_LOGIN_UIF = "remote.login.uif";
212
213
214
215
216 public static final String REMOTE_PROPERTIES_PROPERTY = "remote.property.file";
217
218
219
220
221 public static final String REMOTE_PUBLIC_CHROME = "remote.public.chrome";
222
223
224
225
226 public static final String REMOTE_PUBLIC_URL_PROPERTY = "remote.public.url";
227
228
229
230
231
232
233
234
235 public static final String REMOTE_PUBLIC_WAIT_SECONDS_PROPERTY = "remote.public.wait.seconds";
236
237
238
239
240 public static final String REMOTE_PUBLIC_USER_PROPERTY = "remote.public.user";
241
242
243
244
245 public static final String REMOTE_PUBLIC_USERPOOL_PROPERTY = "remote.public.userpool";
246
247
248
249
250
251
252
253
254
255
256 public static final int SETUP_URL_LOAD_WAIT_SECONDS = 120;
257
258
259
260
261 public static final String WEBDRIVER_CHROME_DRIVER = "webdriver.chrome.driver";
262
263
264
265
266
267
268
269
270
271 public static WebDriver setUp(String className, String testName) throws Exception {
272 if ("true".equals(System.getProperty(REMOTE_JGROWL_ENABLED, "false"))) {
273 jGrowlEnabled = true;
274 }
275
276 if ("true".equals(System.getProperty(JS_HIGHLIGHT_PROPERTY, "false"))) {
277 jsHighlightEnabled = true;
278 if (System.getProperty(JS_HIGHLIGHT_INPUT_PROPERTY) != null) {
279 InputStream in = WebDriverUtils.class.getResourceAsStream(System.getProperty(JS_HIGHLIGHT_INPUT_PROPERTY));
280 BufferedReader reader = new BufferedReader(new InputStreamReader(in));
281 String line = null;
282 List<String> lines = new LinkedList<String>();
283 while ((line = reader.readLine()) != null) {
284 lines.add(line);
285 }
286 }
287 }
288
289 WebDriver driver = null;
290 if (System.getProperty(SauceLabsWebDriverHelper.REMOTE_DRIVER_SAUCELABS_PROPERTY) == null) {
291 driver = getWebDriver();
292 } else {
293 saucelabs = new SauceLabsWebDriverHelper();
294 saucelabs.setUp(className, testName);
295 driver = saucelabs.getDriver();
296 }
297
298 return driver;
299 }
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315 public static void tearDown(boolean passed, String sessionId, String poolParamTest, String poolParamUser, String className, String testName) throws Exception {
316
317 if (passed) {
318 System.out.println("Registering session passed " + sessionId);
319 } else {
320 System.out.println("Registering session failed " + sessionId);
321 }
322
323 if (System.getProperty(SauceLabsWebDriverHelper.REMOTE_DRIVER_SAUCELABS_PROPERTY) != null) {
324 saucelabs.tearDown(passed, sessionId, className, testName);
325 }
326
327 if (System.getProperty(REMOTE_PUBLIC_USERPOOL_PROPERTY) != null) {
328 AutomatedFunctionalTestUtils.getHTML(AutomatedFunctionalTestUtils.prettyHttp(System.getProperty(
329 REMOTE_PUBLIC_USERPOOL_PROPERTY) + "?test=" + poolParamTest + "&user=" + poolParamUser));
330 }
331 }
332
333
334
335
336
337
338
339
340 public static void acceptAlertIfPresent(WebDriver driver) {
341 if (WebDriverUtils.isAlertPresent(driver)) {
342 System.out.println("Alert present " + WebDriverUtils.alertText(driver));
343 try {
344 alertAccept(driver);
345 } catch (Exception e) {
346
347 }
348 }
349 }
350
351
352
353
354
355
356
357
358 public static void alertAccept(WebDriver driver) {
359 Alert alert = driver.switchTo().alert();
360 jGrowl(driver, "AFT Step", false, "AFT Step: Accept Alert " + WebDriverUtils.alertText(driver));
361 alert.accept();
362 }
363
364
365
366
367
368
369
370
371 public static void alertDismiss(WebDriver driver) {
372 Alert alert = driver.switchTo().alert();
373 jGrowl(driver, "AFT Step", false, "AFT Step: Dismiss Alert " + WebDriverUtils.alertText(driver));
374 alert.dismiss();
375 }
376
377
378
379
380
381
382
383
384
385 public static String alertText(WebDriver driver) {
386 return driver.switchTo().alert().getText();
387 }
388
389
390
391
392
393
394
395
396
397 public static ChromeDriverService chromeDriverCreateCheck() {
398 String driverParam = System.getProperty(HUB_DRIVER_PROPERTY);
399
400 if (driverParam != null && "chrome".equals(driverParam.toLowerCase())) {
401 if (System.getProperty(WEBDRIVER_CHROME_DRIVER) == null) {
402 if (System.getProperty(REMOTE_PUBLIC_CHROME) != null) {
403 System.setProperty(WEBDRIVER_CHROME_DRIVER, System.getProperty(REMOTE_PUBLIC_CHROME));
404 }
405 }
406 try {
407 ChromeDriverService chromeDriverService = new ChromeDriverService.Builder()
408 .usingDriverExecutable(new File(System.getProperty(WEBDRIVER_CHROME_DRIVER)))
409 .usingAnyFreePort()
410 .build();
411 return chromeDriverService;
412 } catch (Throwable t) {
413 throw new RuntimeException("Exception starting chrome driver service, is chromedriver ( http://code.google.com/p/chromedriver/downloads/list ) installed? You can include the path to it using -Dremote.public.chrome", t) ;
414 }
415 }
416 return null;
417 }
418
419
420
421
422
423
424
425
426 public static int configuredImplicityWait() {
427 return Integer.parseInt(System.getProperty(REMOTE_PUBLIC_WAIT_SECONDS_PROPERTY, IMPLICIT_WAIT_TIME_SECONDS_DEFAULT + ""));
428 }
429
430
431
432
433
434
435
436
437
438 public static String deLinespace(String contents) {
439 while (contents.contains("\n\n")) {
440 contents = contents.replaceAll("\n\n", "\n");
441 }
442
443 return contents;
444 }
445
446
447
448
449
450
451
452
453
454
455 public static String determineUser(String testParam) {
456 String user = null;
457
458 if (System.getProperty(REMOTE_PUBLIC_USER_PROPERTY) != null) {
459 return System.getProperty(REMOTE_PUBLIC_USER_PROPERTY);
460 } else if (System.getProperty(REMOTE_PUBLIC_USERPOOL_PROPERTY) != null) {
461 String userResponse = AutomatedFunctionalTestUtils.getHTML(AutomatedFunctionalTestUtils.prettyHttp(
462 System.getProperty(REMOTE_PUBLIC_USERPOOL_PROPERTY) + "?test=" + testParam.trim()));
463 return userResponse.substring(userResponse.lastIndexOf(":") + 2, userResponse.lastIndexOf("\""));
464 }
465
466 return user;
467 }
468
469
470
471
472
473
474
475
476
477
478
479
480 public static boolean dontTearDownPropertyNotSet() {
481 return System.getProperty(DONT_TEAR_DOWN_PROPERTY) == null ||
482 "f".startsWith(System.getProperty(DONT_TEAR_DOWN_PROPERTY).toLowerCase()) ||
483 "n".startsWith(System.getProperty(DONT_TEAR_DOWN_PROPERTY).toLowerCase());
484 }
485
486
487
488
489
490
491
492
493 public static boolean dontTearDownOnFailure(boolean passed) {
494 if (!"n".equalsIgnoreCase(System.getProperty(DONT_TEAR_DOWN_ON_FAILURE_PROPERTY, "n"))) {
495 return passed;
496 }
497 return true;
498 }
499
500
501
502
503
504
505
506
507
508
509 public static WebElement findButtonByText(WebDriver driver, String buttonText) {
510 return findElement(driver, By.xpath("//button[contains(text(), '" + buttonText + "')]"));
511 }
512
513
514
515
516
517
518
519
520
521
522 public static WebElement findElement(WebDriver driver, By by) {
523 WebElement found = driver.findElement(by);
524 WebDriverUtils.highlightElement(driver, found);
525 return found;
526 }
527
528
529
530
531
532
533
534
535
536
537 public static String getBaseUrlString() {
538 String baseUrl = System.getProperty(REMOTE_PUBLIC_URL_PROPERTY);
539 if (baseUrl == null) {
540 baseUrl = DEFAULT_BASE_URL;
541 }
542 baseUrl = AutomatedFunctionalTestUtils.prettyHttp(baseUrl);
543 return baseUrl;
544 }
545
546
547
548
549
550
551 public static String getDateTimeStampFormatted() {
552 Date now = Calendar.getInstance().getTime();
553 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
554 return sdf.format(now);
555 }
556
557
558
559
560
561
562
563
564
565
566
567 public static WebElement getElementByAttributeValue(WebDriver driver, String attributeName, String value){
568 return findElement(driver, By.cssSelector("[" + attributeName + "='" + value +"']"));
569 }
570
571
572
573
574
575
576
577
578
579
580 public static String getHubUrlString() {
581 String hubUrl = System.getProperty(HUB_PROPERTY);
582 if (hubUrl == null) {
583 hubUrl = HUB_URL_PROPERTY;
584 }
585 hubUrl = AutomatedFunctionalTestUtils.prettyHttp(hubUrl);
586 if (!hubUrl.endsWith("/wd/hub")) {
587 hubUrl = hubUrl + "/wd/hub";
588 }
589 return hubUrl;
590 }
591
592
593
594
595
596
597
598
599
600
601
602 public static WebDriver getWebDriver() {
603 String driverParam = System.getProperty(HUB_DRIVER_PROPERTY);
604 String hubParam = System.getProperty(HUB_PROPERTY);
605 String proxyParam = System.getProperty(PROXY_HOST_PROPERTY);
606
607
608 DesiredCapabilities capabilities = new DesiredCapabilities();
609 WebDriver webDriver = null;
610 if (StringUtils.isNotEmpty(proxyParam)) {
611 capabilities.setCapability(CapabilityType.PROXY, new Proxy().setHttpProxy(proxyParam));
612 }
613
614 if (hubParam == null) {
615 if (driverParam == null || "firefox".equalsIgnoreCase(driverParam)) {
616 FirefoxProfile profile = new FirefoxProfile();
617 profile.setEnableNativeEvents(false);
618 capabilities.setCapability(FirefoxDriver.PROFILE, profile);
619 return new FirefoxDriver(capabilities);
620 } else if ("chrome".equalsIgnoreCase(driverParam)) {
621 return new ChromeDriver(capabilities);
622 } else if ("safari".equals(driverParam)) {
623 System.out.println("SafariDriver probably won't work, if it does please contact Erik M.");
624 return new SafariDriver(capabilities);
625 }
626 } else {
627 try {
628 if (driverParam == null || "firefox".equalsIgnoreCase(driverParam)) {
629 return new RemoteWebDriver(new URL(getHubUrlString()), DesiredCapabilities.firefox());
630 } else if ("chrome".equalsIgnoreCase(driverParam)) {
631 return new RemoteWebDriver(new URL(getHubUrlString()), DesiredCapabilities.chrome());
632 }
633 } catch (MalformedURLException mue) {
634 System.out.println(getHubUrlString() + " " + mue.getMessage());
635 mue.printStackTrace();
636 }
637 }
638 return null;
639 }
640
641 public static void highlightElement(WebDriver webDriver, By by) {
642 List<WebElement> elements = webDriver.findElements(by);
643 for (WebElement element : elements) {
644 WebDriverUtils.highlightElement(webDriver, element);
645 }
646 }
647
648
649 public static void highlightElements(WebDriver webDriver, List<WebElement> webElements) {
650 for (WebElement webElement: webElements) {
651 highlightElement(webDriver, webElement);
652 }
653 }
654
655
656
657
658
659
660
661
662
663 public static void highlightElement(WebDriver webDriver, WebElement webElement) {
664 if (jsHighlightEnabled && webElement != null) {
665 try {
666
667 JavascriptExecutor js = (JavascriptExecutor) webDriver;
668 String jsHighlight = "element = arguments[0];\n"
669 + "originalStyle = element.getAttribute('style');\n"
670 + "element.setAttribute('style', originalStyle + \"; background: "
671 + JS_HIGHLIGHT_BACKGROUND + "; border: 2px solid " + JS_HIGHLIGHT_BOARDER + ";\");\n"
672 + "setTimeout(function(){\n"
673 + " element.setAttribute('style', originalStyle);\n"
674 + "}, " + System.getProperty(JS_HIGHLIGHT_MS_PROPERTY, JS_HIGHLIGHT_MS + "") + ");";
675 js.executeScript(jsHighlight, webElement);
676 } catch (Throwable t) {
677 System.out.println("Throwable during javascript highlight element");
678 t.printStackTrace();
679 }
680 }
681 }
682
683
684
685
686
687
688
689
690
691 public static boolean isAlertPresent(WebDriver driver) {
692 try {
693 driver.switchTo().alert();
694 return true;
695 } catch (Exception e) {
696 return false;
697 }
698 }
699
700 public static Boolean isTextPresent(WebDriver driver, String pageText, String text) {
701 boolean textPresent = Boolean.FALSE;
702 if (pageText.contains(text)) {
703 WebDriverUtils.highlightElement(driver, By.xpath("//*[contains(text(), '" + text + "')]"));
704 textPresent = Boolean.TRUE;
705 }
706 WebDriverUtils.jGrowl(driver, "Is Text Present?", false, "Is text '" + text + "' present?" + " " + textPresent);
707 return textPresent;
708 }
709
710
711
712
713
714
715
716
717
718
719
720
721 public static void jGrowl(WebDriver driver, String jGrowlHeader, boolean sticky, String message, Throwable throwable) {
722 if (jGrowlEnabled) {
723 jGrowl(driver, jGrowlHeader, sticky, message + " " + throwable.getMessage() + "\n" + ExceptionUtils.getStackTrace(throwable));
724 }
725 }
726
727
728
729
730
731
732
733
734
735
736
737 public static void jGrowl(WebDriver driver, String jGrowlHeader, boolean sticky, String message) {
738 stepMessage(message);
739 if (jGrowlEnabled) {
740 String javascript="jQuery.jGrowl('" + message + "' , {sticky: " + sticky + ", header : '" + jGrowlHeader + "'});";
741 try {
742 ((JavascriptExecutor) driver).executeScript(javascript);
743 } catch (Throwable t) {
744 jGrowlException(t, javascript);
745 }
746 }
747 }
748
749
750
751
752
753
754
755
756 public static void jGrowlException(Throwable throwable, String jGrowlJavascript) {
757 String failMessage = jGrowlJavascript + " failed with " + throwable.getMessage() + "\n"
758 + ExceptionUtils.getStackTrace(throwable);
759 System.out.println("jGrowl failure " + failMessage);
760 if (JGROWL_ERROR_FAILURE) {
761 SeleneseTestBase.fail(failMessage);
762 }
763 }
764
765 public static void openTestUrl(WebDriver driver, String testUrl) {
766 driver.manage().timeouts().implicitlyWait(WebDriverUtils.SETUP_URL_LOAD_WAIT_SECONDS, TimeUnit.SECONDS);
767
768 driver.get(testUrl);
769 if (!System.getProperty(SauceLabsWebDriverHelper.SAUCE_BROWSER_PROPERTY,"ff").equals("opera")) {
770 driver.manage().window().maximize();
771
772 }
773
774 WebDriverUtils.jGrowl(driver, "Open URL", false, "Open " + testUrl);
775
776 driver.manage().timeouts().implicitlyWait(WebDriverUtils.configuredImplicityWait(), TimeUnit.SECONDS);
777 }
778
779
780
781
782
783
784
785
786
787 public static void selectFrameSafe(WebDriver driver, String locator) {
788 try {
789 driver.switchTo().frame(locator);
790 } catch (NoSuchFrameException nsfe) {
791
792 }
793 }
794
795 public static void stepMessage(String message) {
796 System.out.println("AFT Step: " + message);
797 }
798
799
800
801
802
803
804
805
806
807
808
809
810
811 public static WebElement waitAndGetElementByAttributeValue(WebDriver driver, String attribute, String attributeValue, int waitSeconds) throws InterruptedException {
812
813
814
815
816 driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
817
818 boolean failed = false;
819
820 for (int second = 0;; second++) {
821 Thread.sleep(1000);
822 if (second >= waitSeconds) {
823 failed = true;
824 }
825 try {
826 if (failed || (getElementByAttributeValue(driver, attribute, attributeValue) != null)) {
827 break;
828 }
829 } catch (Exception e) {}
830 }
831
832 WebElement element = getElementByAttributeValue(driver, attribute, attributeValue);
833 driver.manage().timeouts().implicitlyWait(WebDriverUtils.configuredImplicityWait(), TimeUnit.SECONDS);
834 return element;
835 }
836
837 public static void waitToAcceptAlert(WebDriver driver, int waitSeconds, String message) throws InterruptedException {
838 driver.manage().timeouts().implicitlyWait(IMPLICIT_WAIT_TIME_LOOP_MS, TimeUnit.MILLISECONDS);
839
840 boolean failed = false;
841
842 for (int second = 0;; second++) {
843 Thread.sleep(1000);
844 if (second >= waitSeconds) {
845 failed = true;
846 }
847 try {
848 if (failed) {
849 break;
850 } else if (isAlertPresent(driver)) {
851 acceptAlertIfPresent(driver);
852 break;
853 }
854 } catch (Exception e) {}
855 }
856
857 driver.manage().timeouts().implicitlyWait(configuredImplicityWait(), TimeUnit.SECONDS);
858 }
859
860
861
862
863
864
865
866
867
868
869
870
871
872 public static WebElement waitFor(WebDriver driver, int waitSeconds, By by, String message) throws InterruptedException {
873
874
875
876
877 driver.manage().timeouts().implicitlyWait(IMPLICIT_WAIT_TIME_LOOP_MS, TimeUnit.MILLISECONDS);
878
879 boolean failed = false;
880 WebElement element = null;
881
882 for (int second = 0;; second++) {
883 Thread.sleep(1000);
884 if (second >= waitSeconds) {
885 failed = true;
886 }
887 try {
888 if (failed) {
889 break;
890 } else if ((driver.findElements(by)).size() > 0) {
891 element = findElement(driver, by);
892 highlightElement(driver, element);
893 break;
894 }
895 } catch (Exception e) {}
896 }
897
898 driver.manage().timeouts().implicitlyWait(configuredImplicityWait(), TimeUnit.SECONDS);
899 return element;
900 }
901
902
903
904
905
906
907
908
909
910
911
912 public static List<WebElement> waitFors(WebDriver driver, By by) throws InterruptedException {
913 return waitFors(driver, configuredImplicityWait(), by, "");
914 }
915
916
917
918
919
920
921
922
923
924
925
926
927 public static List<WebElement> waitFors(WebDriver driver, By by, String message) throws InterruptedException {
928 return waitFors(driver, configuredImplicityWait(), by, message);
929 }
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944 public static List<WebElement> waitFors(WebDriver driver, int waitSeconds, By by, String message) throws InterruptedException {
945
946
947
948
949 driver.manage().timeouts().implicitlyWait(IMPLICIT_WAIT_TIME_LOOP_MS, TimeUnit.MILLISECONDS);
950
951 boolean failed = false;
952
953 for (int second = 0;; second++) {
954 Thread.sleep(1000);
955 if (second >= waitSeconds) {
956 failed = true;
957 }
958 try {
959 if (failed || (driver.findElements(by)).size() > 0) {
960 break;
961 }
962 } catch (Exception e) {}
963 }
964
965 driver.manage().timeouts().implicitlyWait(configuredImplicityWait(), TimeUnit.SECONDS);
966 return driver.findElements(by);
967 }
968 }