1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit;
16
17 import static java.nio.charset.StandardCharsets.ISO_8859_1;
18 import static java.nio.charset.StandardCharsets.UTF_8;
19
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.IOException;
23 import java.net.URISyntaxException;
24 import java.net.URL;
25 import java.nio.charset.Charset;
26 import java.time.Duration;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.EnumSet;
31 import java.util.Enumeration;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.Map;
37 import java.util.Properties;
38 import java.util.Set;
39 import java.util.concurrent.Executor;
40 import java.util.concurrent.Executors;
41
42 import javax.servlet.DispatcherType;
43 import javax.servlet.Filter;
44 import javax.servlet.FilterChain;
45 import javax.servlet.FilterConfig;
46 import javax.servlet.Servlet;
47 import javax.servlet.ServletException;
48 import javax.servlet.ServletRequest;
49 import javax.servlet.ServletResponse;
50 import javax.servlet.http.HttpServlet;
51 import javax.servlet.http.HttpServletRequest;
52 import javax.servlet.http.HttpServletResponse;
53
54 import org.apache.commons.io.FileUtils;
55 import org.apache.commons.io.IOUtils;
56 import org.apache.commons.lang3.StringUtils;
57 import org.apache.commons.lang3.exception.ExceptionUtils;
58 import org.apache.commons.logging.Log;
59 import org.apache.commons.logging.LogFactory;
60 import org.eclipse.jetty.security.ConstraintMapping;
61 import org.eclipse.jetty.security.ConstraintSecurityHandler;
62 import org.eclipse.jetty.security.HashLoginService;
63 import org.eclipse.jetty.server.Request;
64 import org.eclipse.jetty.server.Server;
65 import org.eclipse.jetty.server.handler.HandlerWrapper;
66 import org.eclipse.jetty.util.security.Constraint;
67 import org.eclipse.jetty.webapp.WebAppContext;
68 import org.htmlunit.MockWebConnection.RawResponseData;
69 import org.htmlunit.html.HtmlElement;
70 import org.htmlunit.javascript.JavaScriptEngine;
71 import org.htmlunit.junit.TestCaseCorrector;
72 import org.htmlunit.util.NameValuePair;
73 import org.junit.jupiter.api.AfterAll;
74 import org.junit.jupiter.api.AfterEach;
75 import org.junit.jupiter.api.Assertions;
76 import org.junit.jupiter.api.BeforeEach;
77 import org.junit.jupiter.api.extension.ExtendWith;
78 import org.openqa.selenium.Alert;
79 import org.openqa.selenium.By;
80 import org.openqa.selenium.Dimension;
81 import org.openqa.selenium.JavascriptExecutor;
82 import org.openqa.selenium.NoAlertPresentException;
83 import org.openqa.selenium.NoSuchSessionException;
84 import org.openqa.selenium.NoSuchWindowException;
85 import org.openqa.selenium.UnhandledAlertException;
86 import org.openqa.selenium.WebDriver;
87 import org.openqa.selenium.WebDriverException;
88 import org.openqa.selenium.WebElement;
89 import org.openqa.selenium.chrome.ChromeDriver;
90 import org.openqa.selenium.chrome.ChromeDriverService;
91 import org.openqa.selenium.chrome.ChromeOptions;
92 import org.openqa.selenium.devtools.DevTools;
93 import org.openqa.selenium.devtools.v141.emulation.Emulation;
94 import org.openqa.selenium.edge.EdgeDriver;
95 import org.openqa.selenium.edge.EdgeDriverService;
96 import org.openqa.selenium.edge.EdgeOptions;
97 import org.openqa.selenium.firefox.FirefoxDriver;
98 import org.openqa.selenium.firefox.FirefoxDriverService;
99 import org.openqa.selenium.firefox.FirefoxOptions;
100 import org.openqa.selenium.firefox.FirefoxProfile;
101 import org.openqa.selenium.firefox.GeckoDriverService;
102 import org.openqa.selenium.htmlunit.HtmlUnitDriver;
103 import org.openqa.selenium.htmlunit.HtmlUnitWebElement;
104 import org.openqa.selenium.htmlunit.options.HtmlUnitDriverOptions;
105 import org.openqa.selenium.htmlunit.options.HtmlUnitOption;
106 import org.openqa.selenium.remote.UnreachableBrowserException;
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 @ExtendWith(TestCaseCorrector.class)
166 public abstract class WebDriverTestCase extends WebTestCase {
167
168 private static final String LOG_EX_FUNCTION =
169 " function logEx(e) {\n"
170 + " let toStr = null;\n"
171 + " if (toStr === null && e instanceof EvalError) { toStr = ''; }\n"
172 + " if (toStr === null && e instanceof RangeError) { toStr = ''; }\n"
173 + " if (toStr === null && e instanceof ReferenceError) { toStr = ''; }\n"
174 + " if (toStr === null && e instanceof SyntaxError) { toStr = ''; }\n"
175 + " if (toStr === null && e instanceof TypeError) { toStr = ''; }\n"
176 + " if (toStr === null && e instanceof URIError) { toStr = ''; }\n"
177 + " if (toStr === null && e instanceof AggregateError) { toStr = '/AggregateError'; }\n"
178 + " if (toStr === null && typeof InternalError == 'function' "
179 + "&& e instanceof InternalError) { toStr = '/InternalError'; }\n"
180 + " if (toStr === null) {\n"
181 + " let rx = /\\[object (.*)\\]/;\n"
182 + " toStr = Object.prototype.toString.call(e);\n"
183 + " let match = rx.exec(toStr);\n"
184 + " if (match != null) { toStr = '/' + match[1]; }\n"
185 + " }"
186 + " log(e.name + toStr);\n"
187 + "}\n";
188
189
190
191
192 public static final String LOG_TITLE_FUNCTION =
193 " function log(msg) { window.document.title += msg + '\\u00a7'; }\n"
194 + LOG_EX_FUNCTION;
195
196
197
198
199 public static final String LOG_TITLE_FUNCTION_NORMALIZE =
200 " function log(msg) { "
201 + "msg = '' + msg; "
202 + "msg = msg.replace(/ /g, '\\\\s'); "
203 + "msg = msg.replace(/\\n/g, '\\\\n'); "
204 + "msg = msg.replace(/\\r/g, '\\\\r'); "
205 + "msg = msg.replace(/\\t/g, '\\\\t'); "
206 + "msg = msg.replace(/\\u001e/g, '\\\\u001e'); "
207 + "window.document.title += msg + '\u00A7';}\n"
208
209 + LOG_EX_FUNCTION;
210
211
212
213
214 public static final String LOG_WINDOW_NAME_FUNCTION =
215 " function log(msg) { window.top.name += msg + '\\u00a7'; }\n"
216 + " window.top.name = '';"
217 + LOG_EX_FUNCTION;
218
219
220
221
222 public static final String LOG_SESSION_STORAGE_FUNCTION =
223 " function log(msg) { "
224 + "var l = sessionStorage.getItem('Log');"
225 + "sessionStorage.setItem('Log', (null === l?'':l) + msg + '\\u00a7'); }\n";
226
227
228
229
230 public static final String LOG_TEXTAREA_FUNCTION = " function log(msg) { "
231 + "document.getElementById('myLog').value += msg + '\u00A7';}\n"
232 + LOG_EX_FUNCTION;
233
234
235
236
237 public static final String LOG_TEXTAREA = " <textarea id='myLog' cols='80' rows='22'></textarea>\n";
238
239
240
241
242 public static final String AUTOFIX_ = "htmlunit.autofix";
243
244
245
246
247 private static List<BrowserVersion> ALL_BROWSERS_ = Collections.unmodifiableList(
248 Arrays.asList(BrowserVersion.CHROME,
249 BrowserVersion.EDGE,
250 BrowserVersion.FIREFOX,
251 BrowserVersion.FIREFOX_ESR));
252
253
254
255
256 private static BrowserVersion[] DEFAULT_RUNNING_BROWSERS_ =
257 {BrowserVersion.CHROME,
258 BrowserVersion.EDGE,
259 BrowserVersion.FIREFOX,
260 BrowserVersion.FIREFOX_ESR};
261
262 private static final Log LOG = LogFactory.getLog(WebDriverTestCase.class);
263
264 private static Set<String> BROWSERS_PROPERTIES_;
265 private static String CHROME_BIN_;
266 private static String EDGE_BIN_;
267 private static String GECKO_BIN_;
268 private static String FF_BIN_;
269 private static String FF_ESR_BIN_;
270
271
272 protected static final Map<BrowserVersion, WebDriver> WEB_DRIVERS_ = new HashMap<>();
273
274
275 protected static final Map<BrowserVersion, WebDriver> WEB_DRIVERS_REAL_BROWSERS = new HashMap<>();
276 private static final Map<BrowserVersion, Integer> WEB_DRIVERS_REAL_BROWSERS_USAGE_COUNT = new HashMap<>();
277
278 private static Server STATIC_SERVER_;
279 private static String STATIC_SERVER_STARTER_;
280
281 private static Server STATIC_SERVER2_;
282 private static String STATIC_SERVER2_STARTER_;
283
284 private static Server STATIC_SERVER3_;
285 private static String STATIC_SERVER3_STARTER_;
286
287 private static Boolean LAST_TEST_UsesMockWebConnection_;
288 private static final Executor EXECUTOR_POOL = Executors.newFixedThreadPool(4);
289
290 private boolean useRealBrowser_;
291
292
293
294
295 private HtmlUnitDriver webDriver_;
296
297
298
299
300
301 protected boolean needThreeConnections() {
302 return false;
303 }
304
305
306
307
308 public static Set<String> getBrowsersProperties() {
309 if (BROWSERS_PROPERTIES_ == null) {
310 try {
311 final Properties properties = new Properties();
312 final File file = new File("test.properties");
313 if (file.exists()) {
314 try (FileInputStream in = new FileInputStream(file)) {
315 properties.load(in);
316 }
317
318 String browsersValue = properties.getProperty("browsers");
319 if (browsersValue == null || browsersValue.isEmpty()) {
320 browsersValue = "hu";
321 }
322 BROWSERS_PROPERTIES_ = new HashSet<>(Arrays.asList(browsersValue.replaceAll(" ", "")
323 .toLowerCase(Locale.ROOT).split(",")));
324 CHROME_BIN_ = properties.getProperty("chrome.bin");
325 EDGE_BIN_ = properties.getProperty("edge.bin");
326
327 GECKO_BIN_ = properties.getProperty("geckodriver.bin");
328 FF_BIN_ = properties.getProperty("ff.bin");
329 FF_ESR_BIN_ = properties.getProperty("ff-esr.bin");
330
331 final boolean autofix = Boolean.parseBoolean(properties.getProperty("autofix"));
332 System.setProperty(AUTOFIX_, Boolean.toString(autofix));
333 }
334 }
335 catch (final Exception e) {
336 LOG.error("Error reading htmlunit.properties. Ignoring!", e);
337 }
338 if (BROWSERS_PROPERTIES_ == null) {
339 BROWSERS_PROPERTIES_ = new HashSet<>(Arrays.asList("hu"));
340 }
341 if (BROWSERS_PROPERTIES_.contains("hu")) {
342 for (final BrowserVersion browserVersion : DEFAULT_RUNNING_BROWSERS_) {
343 BROWSERS_PROPERTIES_.add("hu-" + browserVersion.getNickname().toLowerCase());
344 }
345 }
346 }
347 return BROWSERS_PROPERTIES_;
348 }
349
350
351
352
353 public static List<BrowserVersion> allBrowsers() {
354 return ALL_BROWSERS_;
355 }
356
357
358
359
360
361 protected WebDriver getWebDriver() {
362 final BrowserVersion browserVersion = getBrowserVersion();
363 WebDriver driver;
364 if (useRealBrowser()) {
365 synchronized (WEB_DRIVERS_REAL_BROWSERS) {
366 driver = WEB_DRIVERS_REAL_BROWSERS.get(browserVersion);
367 if (driver != null) {
368
369
370 Integer count = WEB_DRIVERS_REAL_BROWSERS_USAGE_COUNT.get(browserVersion);
371 if (null == count) {
372 count = -1;
373 }
374 count += 1;
375 if (count >= 1000) {
376 shutDownReal(browserVersion);
377 driver = null;
378 }
379 else {
380 WEB_DRIVERS_REAL_BROWSERS_USAGE_COUNT.put(browserVersion, count);
381 }
382 }
383
384 if (driver == null) {
385 try {
386 driver = buildWebDriver();
387 }
388 catch (final IOException e) {
389 throw new RuntimeException(e);
390 }
391
392 WEB_DRIVERS_REAL_BROWSERS.put(browserVersion, driver);
393 WEB_DRIVERS_REAL_BROWSERS_USAGE_COUNT.put(browserVersion, 0);
394 }
395 }
396 }
397 else {
398 driver = WEB_DRIVERS_.get(browserVersion);
399 if (driver == null) {
400 try {
401 driver = buildWebDriver();
402 }
403 catch (final IOException e) {
404 throw new RuntimeException(e);
405 }
406
407 if (isWebClientCached()) {
408 WEB_DRIVERS_.put(browserVersion, driver);
409 }
410 }
411 }
412 return driver;
413 }
414
415
416
417
418
419 @AfterAll
420 public static void shutDownAll() throws Exception {
421 for (final WebDriver driver : WEB_DRIVERS_.values()) {
422 driver.quit();
423 }
424 WEB_DRIVERS_.clear();
425
426 shutDownRealBrowsers();
427
428 stopWebServers();
429 }
430
431
432
433
434 private static void shutDownRealBrowsers() {
435 synchronized (WEB_DRIVERS_REAL_BROWSERS) {
436 for (final WebDriver driver : WEB_DRIVERS_REAL_BROWSERS.values()) {
437 quit(driver);
438 }
439 WEB_DRIVERS_REAL_BROWSERS.clear();
440 WEB_DRIVERS_REAL_BROWSERS_USAGE_COUNT.clear();
441 }
442 }
443
444
445
446
447
448 private static void shutDownReal(final BrowserVersion browser) {
449 synchronized (WEB_DRIVERS_REAL_BROWSERS) {
450 final WebDriver driver = WEB_DRIVERS_REAL_BROWSERS.get(browser);
451 if (driver != null) {
452 quit(driver);
453 WEB_DRIVERS_REAL_BROWSERS.remove(browser);
454 WEB_DRIVERS_REAL_BROWSERS_USAGE_COUNT.remove(browser);
455 }
456 }
457 }
458
459 private static void quit(final WebDriver driver) {
460 if (driver != null) {
461 try {
462 driver.quit();
463 }
464 catch (final UnreachableBrowserException e) {
465 LOG.error("Can't quit browser", e);
466
467 }
468 catch (final NoClassDefFoundError e) {
469 LOG.error("Can't quit browser", e);
470
471 }
472 catch (final UnsatisfiedLinkError e) {
473 LOG.error("Can't quit browser", e);
474
475 }
476 }
477 }
478
479
480
481
482
483 protected static void assertWebServersStopped() throws Exception {
484 Assertions.assertNull(STATIC_SERVER_, STATIC_SERVER_STARTER_);
485 Assertions.assertNull(STATIC_SERVER2_, STATIC_SERVER2_STARTER_);
486 Assertions.assertNull(STATIC_SERVER3_, STATIC_SERVER3_STARTER_);
487 }
488
489
490
491
492
493 protected static void stopWebServers() throws Exception {
494 if (STATIC_SERVER_ != null) {
495 STATIC_SERVER_.stop();
496 STATIC_SERVER_.destroy();
497 STATIC_SERVER_ = null;
498 }
499
500 if (STATIC_SERVER2_ != null) {
501 STATIC_SERVER2_.stop();
502 STATIC_SERVER2_.destroy();
503 STATIC_SERVER2_ = null;
504 }
505
506 if (STATIC_SERVER3_ != null) {
507 STATIC_SERVER3_.stop();
508 STATIC_SERVER3_.destroy();
509 STATIC_SERVER3_ = null;
510 }
511 LAST_TEST_UsesMockWebConnection_ = null;
512 }
513
514
515
516
517 public boolean useRealBrowser() {
518 return useRealBrowser_;
519 }
520
521
522
523
524
525 public void setUseRealBrowser(final boolean useRealBrowser) {
526 useRealBrowser_ = useRealBrowser;
527 }
528
529
530
531
532
533
534 protected WebDriver buildWebDriver() throws IOException {
535 if (useRealBrowser()) {
536 if (BrowserVersion.EDGE.isSameBrowser(getBrowserVersion())) {
537 final EdgeDriverService service = new EdgeDriverService.Builder()
538 .withLogOutput(System.out)
539 .usingDriverExecutable(new File(EDGE_BIN_))
540
541 .withAppendLog(true)
542 .withReadableTimestamp(true)
543
544 .build();
545
546 final String locale = getBrowserVersion().getBrowserLocale().toLanguageTag();
547
548 final EdgeOptions options = new EdgeOptions();
549
550
551
552 options.addArguments("--lang=" + locale);
553
554 options.setExperimentalOption("prefs", Map.of("intl.accept_languages", locale));
555 options.addArguments("--remote-allow-origins=*");
556
557
558
559
560
561
562
563 final EdgeDriver edge = new EdgeDriver(service, options);
564
565 final DevTools devTools = edge.getDevTools();
566 devTools.createSession();
567
568 final String tz = getBrowserVersion().getSystemTimezone().getID();
569 devTools.send(Emulation.setTimezoneOverride(tz));
570
571 return edge;
572 }
573
574 if (BrowserVersion.CHROME.isSameBrowser(getBrowserVersion())) {
575 final ChromeDriverService service = new ChromeDriverService.Builder()
576 .withLogOutput(System.out)
577 .usingDriverExecutable(new File(CHROME_BIN_))
578
579 .withAppendLog(true)
580 .withReadableTimestamp(true)
581
582 .build();
583
584 final String locale = getBrowserVersion().getBrowserLocale().toLanguageTag();
585
586 final ChromeOptions options = new ChromeOptions();
587
588
589
590 options.addArguments("--lang=" + locale);
591
592 options.setExperimentalOption("prefs", Map.of("intl.accept_languages", locale));
593 options.addArguments("--remote-allow-origins=*");
594 options.addArguments("--disable-search-engine-choice-screen");
595
596 options.addArguments("--disable-features=OptimizationGuideModelDownloading,"
597 + "OptimizationHintsFetching,OptimizationTargetPrediction,OptimizationHints");
598
599 final ChromeDriver chrome = new ChromeDriver(service, options);
600
601 final DevTools devTools = chrome.getDevTools();
602 devTools.createSession();
603
604 final String tz = getBrowserVersion().getSystemTimezone().getID();
605 devTools.send(Emulation.setTimezoneOverride(tz));
606
607 return chrome;
608 }
609
610 if (BrowserVersion.FIREFOX.isSameBrowser(getBrowserVersion())) {
611 return createFirefoxDriver(GECKO_BIN_, FF_BIN_);
612 }
613
614 if (BrowserVersion.FIREFOX_ESR.isSameBrowser(getBrowserVersion())) {
615 return createFirefoxDriver(GECKO_BIN_, FF_ESR_BIN_);
616 }
617
618 throw new RuntimeException("Unexpected BrowserVersion: " + getBrowserVersion());
619 }
620
621 if (webDriver_ == null) {
622 final HtmlUnitDriverOptions driverOptions = new HtmlUnitDriverOptions(getBrowserVersion());
623
624 if (isWebClientCached()) {
625 driverOptions.setCapability(HtmlUnitOption.optHistorySizeLimit, 0);
626 }
627
628 if (getWebClientTimeout() != null) {
629 driverOptions.setCapability(HtmlUnitOption.optTimeout, getWebClientTimeout());
630 }
631 webDriver_ = new HtmlUnitDriver(driverOptions);
632 webDriver_.setExecutor(EXECUTOR_POOL);
633 }
634 return webDriver_;
635 }
636
637 private FirefoxDriver createFirefoxDriver(final String geckodriverBinary, final String binary) {
638 final FirefoxDriverService service = new GeckoDriverService.Builder()
639 .withLogOutput(System.out)
640 .usingDriverExecutable(new File(geckodriverBinary))
641 .build();
642
643 final FirefoxOptions options = new FirefoxOptions();
644
645
646
647 options.setBinary(binary);
648
649 String locale = getBrowserVersion().getBrowserLocale().toLanguageTag();
650 locale = locale + "," + getBrowserVersion().getBrowserLocale().getLanguage();
651
652 final FirefoxProfile profile = new FirefoxProfile();
653 profile.setPreference("intl.accept_languages", locale);
654
655
656
657 options.setProfile(profile);
658
659 return new FirefoxDriver(service, options);
660 }
661
662
663
664
665
666
667
668 protected void startWebServer(final MockWebConnection mockConnection, final Charset serverCharset)
669 throws Exception {
670 if (Boolean.FALSE.equals(LAST_TEST_UsesMockWebConnection_)) {
671 stopWebServers();
672 }
673
674 LAST_TEST_UsesMockWebConnection_ = Boolean.TRUE;
675 if (STATIC_SERVER_ == null) {
676 final Server server = new Server(PORT);
677
678 final WebAppContext context = new WebAppContext();
679 context.setContextPath("/");
680 context.setResourceBase("./");
681
682 if (isBasicAuthentication()) {
683 final Constraint constraint = new Constraint();
684 constraint.setName(Constraint.__BASIC_AUTH);
685 constraint.setRoles(new String[]{"user"});
686 constraint.setAuthenticate(true);
687
688 final ConstraintMapping constraintMapping = new ConstraintMapping();
689 constraintMapping.setConstraint(constraint);
690 constraintMapping.setPathSpec("/*");
691
692 final ConstraintSecurityHandler handler = (ConstraintSecurityHandler) context.getSecurityHandler();
693 handler.setLoginService(new HashLoginService("MyRealm", "./src/test/resources/realm.properties"));
694 handler.setConstraintMappings(new ConstraintMapping[]{constraintMapping});
695 }
696
697 context.addServlet(MockWebConnectionServlet.class, "/*");
698 if (serverCharset != null) {
699 AsciiEncodingFilter.CHARSET_ = serverCharset;
700 context.addFilter(AsciiEncodingFilter.class, "/*",
701 EnumSet.of(DispatcherType.INCLUDE, DispatcherType.REQUEST));
702 }
703 server.setHandler(context);
704 WebServerTestCase.tryStart(PORT, server);
705
706 STATIC_SERVER_STARTER_ = ExceptionUtils.getStackTrace(new Throwable("StaticServerStarter"));
707 STATIC_SERVER_ = server;
708 }
709 MockWebConnectionServlet.MockConnection_ = mockConnection;
710
711 if (STATIC_SERVER2_ == null && needThreeConnections()) {
712 final Server server2 = new Server(PORT2);
713 final WebAppContext context2 = new WebAppContext();
714 context2.setContextPath("/");
715 context2.setResourceBase("./");
716 context2.addServlet(MockWebConnectionServlet.class, "/*");
717 server2.setHandler(context2);
718 WebServerTestCase.tryStart(PORT2, server2);
719
720 STATIC_SERVER2_STARTER_ = ExceptionUtils.getStackTrace(new Throwable("StaticServer2Starter"));
721 STATIC_SERVER2_ = server2;
722
723 final Server server3 = new Server(PORT3);
724 final WebAppContext context3 = new WebAppContext();
725 context3.setContextPath("/");
726 context3.setResourceBase("./");
727 context3.addServlet(MockWebConnectionServlet.class, "/*");
728 server3.setHandler(context3);
729 WebServerTestCase.tryStart(PORT3, server3);
730
731 STATIC_SERVER3_STARTER_ = ExceptionUtils.getStackTrace(new Throwable("StaticServer3Starter"));
732 STATIC_SERVER3_ = server3;
733
734
735
736
737 }
738 }
739
740
741
742
743
744
745 protected boolean isBasicAuthentication() {
746 return false;
747 }
748
749
750
751
752
753
754
755
756
757
758
759 protected static void startWebServer(final String resourceBase, final String[] classpath,
760 final Map<String, Class<? extends Servlet>> servlets) throws Exception {
761 startWebServer(resourceBase, classpath, servlets, null);
762 }
763
764
765
766
767
768
769
770
771
772
773
774 protected static void startWebServer2(final String resourceBase, final String[] classpath,
775 final Map<String, Class<? extends Servlet>> servlets) throws Exception {
776
777 if (STATIC_SERVER2_ != null) {
778 STATIC_SERVER2_.stop();
779 }
780 STATIC_SERVER2_STARTER_ = ExceptionUtils.getStackTrace(new Throwable("StaticServer2Starter"));
781 STATIC_SERVER2_ = WebServerTestCase.createWebServer(PORT2, resourceBase, classpath, servlets, null);
782 }
783
784
785
786
787
788
789
790
791
792
793
794
795 protected static void startWebServer(final String resourceBase, final String[] classpath,
796 final Map<String, Class<? extends Servlet>> servlets, final HandlerWrapper handler) throws Exception {
797 stopWebServers();
798 LAST_TEST_UsesMockWebConnection_ = Boolean.FALSE;
799
800 STATIC_SERVER_STARTER_ = ExceptionUtils.getStackTrace(new Throwable("StaticServerStarter"));
801 STATIC_SERVER_ = WebServerTestCase.createWebServer(PORT, resourceBase, classpath, servlets, handler);
802 }
803
804
805
806
807 public static class MockWebConnectionServlet extends HttpServlet {
808 private static MockWebConnection MockConnection_;
809
810 static void setMockconnection(final MockWebConnection connection) {
811 MockConnection_ = connection;
812 }
813
814
815
816
817 @Override
818 protected void service(final HttpServletRequest request, final HttpServletResponse response)
819 throws ServletException, IOException {
820
821 try {
822 doService(request, response);
823 }
824 catch (final ServletException e) {
825 throw e;
826 }
827 catch (final IOException e) {
828 throw e;
829 }
830 catch (final Exception e) {
831 throw new ServletException(e);
832 }
833 }
834
835 private static void doService(final HttpServletRequest request, final HttpServletResponse response)
836 throws Exception {
837 String url = request.getRequestURL().toString();
838 if (LOG.isDebugEnabled()) {
839 LOG.debug(request.getMethod() + " " + url);
840 }
841
842 if (url.endsWith("/favicon.ico")) {
843 response.setStatus(HttpServletResponse.SC_NOT_FOUND);
844 return;
845 }
846
847 if (url.contains("/delay")) {
848 final String delay = StringUtils.substringBetween(url, "/delay", "/");
849 final int ms = Integer.parseInt(delay);
850 if (LOG.isDebugEnabled()) {
851 LOG.debug("Sleeping for " + ms + " before to deliver " + url);
852 }
853 Thread.sleep(ms);
854 }
855
856
857 final List<NameValuePair> requestParameters = new ArrayList<>();
858 try {
859 for (final Enumeration<String> paramNames = request.getParameterNames();
860 paramNames.hasMoreElements();) {
861 final String name = paramNames.nextElement();
862 final String[] values = request.getParameterValues(name);
863 for (final String value : values) {
864 requestParameters.add(new NameValuePair(name, value));
865 }
866 }
867 }
868 catch (final IllegalArgumentException e) {
869
870
871 requestParameters.clear();
872 final String query = request.getQueryString();
873 if (query != null) {
874 url += "?" + query;
875 }
876 }
877
878 final String queryString = request.getQueryString();
879 if (StringUtils.isNotBlank(queryString)) {
880 url = url + "?" + queryString;
881 }
882 final URL requestedUrl = new URL(url);
883 final WebRequest webRequest = new WebRequest(requestedUrl);
884 webRequest.setHttpMethod(HttpMethod.valueOf(request.getMethod()));
885
886
887 for (final Enumeration<String> en = request.getHeaderNames(); en.hasMoreElements();) {
888 final String headerName = en.nextElement();
889 final String headerValue = request.getHeader(headerName);
890 webRequest.setAdditionalHeader(headerName, headerValue);
891 }
892
893 if (requestParameters.isEmpty() && request.getContentLength() > 0) {
894 final byte[] buffer = new byte[request.getContentLength()];
895 IOUtils.read(request.getInputStream(), buffer, 0, buffer.length);
896
897 final String encoding = request.getCharacterEncoding();
898 if (encoding == null) {
899 webRequest.setRequestBody(new String(buffer, ISO_8859_1));
900 webRequest.setCharset(null);
901 }
902 else {
903 webRequest.setRequestBody(new String(buffer, encoding));
904 webRequest.setCharset(Charset.forName(encoding));
905 }
906 }
907 else {
908 webRequest.setRequestParameters(requestParameters);
909 }
910
911
912 if (request.getContentType() != null
913 && request.getContentType().startsWith(FormEncodingType.MULTIPART.getName())) {
914 webRequest.setEncodingType(FormEncodingType.MULTIPART);
915 }
916
917 final RawResponseData resp = MockConnection_.getRawResponse(webRequest);
918
919
920 response.setStatus(resp.getStatusCode());
921
922 boolean charsetInContentType = false;
923 for (final NameValuePair responseHeader : resp.getHeaders()) {
924 final String headerName = responseHeader.getName();
925 if (HttpHeader.CONTENT_TYPE.equals(headerName) && responseHeader.getValue().contains("charset=")) {
926 charsetInContentType = true;
927 }
928 response.addHeader(headerName, responseHeader.getValue());
929 }
930
931 if (resp.getByteContent() != null) {
932 response.getOutputStream().write(resp.getByteContent());
933 }
934 else {
935 if (!charsetInContentType) {
936 response.setCharacterEncoding(resp.getCharset().name());
937 }
938 response.getWriter().print(resp.getStringContent());
939 }
940 response.flushBuffer();
941 }
942 }
943
944
945
946
947
948
949
950 protected final WebDriver loadPage2(final String html) throws Exception {
951 return loadPage2(html, URL_FIRST);
952 }
953
954
955
956
957
958
959
960
961 protected final WebDriver loadPage2(final String html, final URL url) throws Exception {
962 return loadPage2(html, url, "text/html;charset=ISO-8859-1", ISO_8859_1, null);
963 }
964
965
966
967
968
969
970
971
972
973
974 protected final WebDriver loadPage2(final String html, final URL url,
975 final String contentType, final Charset charset) throws Exception {
976 return loadPage2(html, url, contentType, charset, null);
977 }
978
979
980
981
982
983
984
985
986
987
988
989 protected final WebDriver loadPage2(final String html, final URL url,
990 final String contentType, final Charset charset, final Charset serverCharset) throws Exception {
991 getMockWebConnection().setResponse(url, html, contentType, charset);
992 return loadPage2(url, serverCharset);
993 }
994
995
996
997
998
999
1000
1001
1002 protected final WebDriver loadPage2(final URL url, final Charset serverCharset) throws Exception {
1003 startWebServer(getMockWebConnection(), serverCharset);
1004
1005 WebDriver driver = getWebDriver();
1006 if (!(driver instanceof HtmlUnitDriver)) {
1007 try {
1008 resizeIfNeeded(driver);
1009 }
1010 catch (final NoSuchSessionException e) {
1011
1012 shutDownRealBrowsers();
1013
1014 driver = getWebDriver();
1015 resizeIfNeeded(driver);
1016 }
1017 }
1018 driver.get(url.toExternalForm());
1019
1020 return driver;
1021 }
1022
1023
1024
1025
1026
1027
1028
1029
1030 protected final WebDriver loadPage2(final String html,
1031 final Map<String, Class<? extends Servlet>> servlets) throws Exception {
1032 return loadPage2(html, URL_FIRST, servlets, null);
1033 }
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043 protected final WebDriver loadPage2(final String html, final URL url,
1044 final Map<String, Class<? extends Servlet>> servlets) throws Exception {
1045 return loadPage2(html, url, servlets, null);
1046 }
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057 protected final WebDriver loadPage2(final String html, final URL url,
1058 final Map<String, Class<? extends Servlet>> servlets,
1059 final Map<String, Class<? extends Servlet>> servlets2) throws Exception {
1060 servlets.put("/*", MockWebConnectionServlet.class);
1061 getMockWebConnection().setResponse(url, html);
1062 MockWebConnectionServlet.MockConnection_ = getMockWebConnection();
1063
1064 startWebServer("./", null, servlets);
1065 if (servlets2 != null) {
1066 startWebServer2("./", null, servlets2);
1067 }
1068
1069 WebDriver driver = getWebDriver();
1070 if (!(driver instanceof HtmlUnitDriver)) {
1071 try {
1072 resizeIfNeeded(driver);
1073 }
1074 catch (final NoSuchSessionException e) {
1075
1076 shutDownRealBrowsers();
1077
1078 driver = getWebDriver();
1079 resizeIfNeeded(driver);
1080 }
1081 }
1082 driver.get(url.toExternalForm());
1083
1084 return driver;
1085 }
1086
1087 protected void resizeIfNeeded(final WebDriver driver) {
1088 final Dimension size = driver.manage().window().getSize();
1089 if (size.getWidth() != 1272 || size.getHeight() != 768) {
1090
1091 driver.manage().window().setSize(new Dimension(1272, 768));
1092 }
1093 }
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103 protected final WebDriver loadPageWithAlerts2(final String html) throws Exception {
1104 return loadPageWithAlerts2(html, URL_FIRST, DEFAULT_WAIT_TIME);
1105 }
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115 protected final WebDriver loadPageVerifyTitle2(final String html) throws Exception {
1116 return loadPageVerifyTitle2(html, getExpectedAlerts());
1117 }
1118
1119 protected final WebDriver loadPageVerifyTitle2(final String html, final String... expectedAlerts) throws Exception {
1120 final WebDriver driver = loadPage2(html);
1121 return verifyTitle2(driver, expectedAlerts);
1122 }
1123
1124 protected final WebDriver verifyTitle2(final Duration maxWaitTime, final WebDriver driver,
1125 final String... expectedAlerts) throws Exception {
1126
1127 final StringBuilder expected = new StringBuilder();
1128 for (int i = 0; i < expectedAlerts.length; i++) {
1129 expected.append(expectedAlerts[i]).append('\u00A7');
1130 }
1131 final String expectedTitle = expected.toString();
1132
1133 final long maxWait = System.currentTimeMillis() + maxWaitTime.toMillis();
1134
1135 while (System.currentTimeMillis() < maxWait) {
1136 try {
1137 final String title = driver.getTitle();
1138 assertEquals(expectedTitle, title);
1139 return driver;
1140 }
1141 catch (final AssertionError e) {
1142
1143 }
1144 }
1145
1146 assertEquals(expectedTitle, driver.getTitle());
1147 return driver;
1148 }
1149
1150 protected final WebDriver verifyTitle2(final WebDriver driver,
1151 final String... expectedAlerts) throws Exception {
1152 if (expectedAlerts.length == 0) {
1153 assertEquals("", driver.getTitle());
1154 return driver;
1155 }
1156
1157 final StringBuilder expected = new StringBuilder();
1158 for (int i = 0; i < expectedAlerts.length; i++) {
1159 expected.append(expectedAlerts[i]).append('\u00A7');
1160 }
1161
1162 final String title = driver.getTitle();
1163 try {
1164 assertEquals(expected.toString(), title);
1165 }
1166 catch (final AssertionError e) {
1167 if (useRealBrowser() && StringUtils.isEmpty(title)) {
1168 Thread.sleep(42);
1169 assertEquals(expected.toString(), driver.getTitle());
1170 return driver;
1171 }
1172 throw e;
1173 }
1174 return driver;
1175 }
1176
1177 protected final WebDriver loadPageVerifyTextArea2(final String html) throws Exception {
1178 return loadPageTextArea2(html, getExpectedAlerts());
1179 }
1180
1181 protected final WebDriver loadPageTextArea2(final String html, final String... expectedAlerts) throws Exception {
1182 final WebDriver driver = loadPage2(html);
1183 return verifyTextArea2(driver, expectedAlerts);
1184 }
1185
1186 protected final WebDriver verifyTextArea2(final WebDriver driver,
1187 final String... expectedAlerts) throws Exception {
1188 final WebElement textArea = driver.findElement(By.id("myLog"));
1189
1190 if (expectedAlerts.length == 0) {
1191 assertEquals("", textArea.getDomProperty("value"));
1192 return driver;
1193 }
1194
1195 if (!useRealBrowser()
1196 && expectedAlerts.length == 1
1197 && expectedAlerts[0].startsWith("data:image/png;base64,")) {
1198 String value = textArea.getDomProperty("value");
1199 if (value.endsWith("\u00A7")) {
1200 value = value.substring(0, value.length() - 1);
1201 }
1202 compareImages(expectedAlerts[0], value);
1203 return driver;
1204 }
1205
1206 final StringBuilder expected = new StringBuilder();
1207 for (int i = 0; i < expectedAlerts.length; i++) {
1208 expected.append(expectedAlerts[i]).append('\u00A7');
1209 }
1210 verify(() -> textArea.getDomProperty("value"), expected.toString());
1211
1212 return driver;
1213 }
1214
1215 protected final String getJsVariableValue(final WebDriver driver, final String varName) throws Exception {
1216 final String script = "return String(" + varName + ")";
1217 final String result = (String) ((JavascriptExecutor) driver).executeScript(script);
1218
1219 return result;
1220 }
1221
1222 protected final WebDriver verifyJsVariable(final WebDriver driver, final String varName,
1223 final String expected) throws Exception {
1224 final String result = getJsVariableValue(driver, varName);
1225 assertEquals(expected, result);
1226
1227 return driver;
1228 }
1229
1230 protected final WebDriver verifyWindowName2(final Duration maxWaitTime, final WebDriver driver,
1231 final String... expectedAlerts) throws Exception {
1232 final long maxWait = System.currentTimeMillis() + maxWaitTime.toMillis();
1233
1234 while (System.currentTimeMillis() < maxWait) {
1235 try {
1236 return verifyWindowName2(driver, expectedAlerts);
1237 }
1238 catch (final AssertionError e) {
1239
1240 }
1241 }
1242
1243 return verifyWindowName2(driver, expectedAlerts);
1244 }
1245
1246 protected final WebDriver verifyWindowName2(final WebDriver driver,
1247 final String... expectedAlerts) throws Exception {
1248 final StringBuilder expected = new StringBuilder();
1249 for (int i = 0; i < expectedAlerts.length; i++) {
1250 expected.append(expectedAlerts[i]).append('\u00A7');
1251 }
1252
1253 return verifyJsVariable(driver, "window.top.name", expected.toString());
1254 }
1255
1256 protected final WebDriver verifySessionStorage2(final WebDriver driver,
1257 final String... expectedAlerts) throws Exception {
1258 final StringBuilder expected = new StringBuilder();
1259 for (int i = 0; i < expectedAlerts.length; i++) {
1260 expected.append(expectedAlerts[i]).append('\u00A7');
1261 }
1262
1263 return verifyJsVariable(driver, "sessionStorage.getItem('Log')", expected.toString());
1264 }
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275 protected final WebDriver loadPageWithAlerts2(final String html, final Duration maxWaitTime) throws Exception {
1276 return loadPageWithAlerts2(html, URL_FIRST, maxWaitTime);
1277 }
1278
1279
1280
1281
1282
1283
1284
1285
1286 protected final WebDriver loadPageWithAlerts2(final String html, final URL url) throws Exception {
1287 return loadPageWithAlerts2(html, url, DEFAULT_WAIT_TIME);
1288 }
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298 protected final WebDriver loadPageWithAlerts2(final String html, final URL url, final Duration maxWaitTime)
1299 throws Exception {
1300 final WebDriver driver = loadPage2(html, url);
1301
1302 verifyAlerts(maxWaitTime, driver, getExpectedAlerts());
1303 return driver;
1304 }
1305
1306
1307
1308
1309
1310
1311
1312 protected void verifyAlerts(final WebDriver driver, final String... expectedAlerts) throws Exception {
1313 verifyAlerts(DEFAULT_WAIT_TIME, driver, expectedAlerts);
1314 }
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324 protected void verifyAlerts(final Duration maxWaitTime, final WebDriver driver, final String... expected)
1325 throws Exception {
1326 final List<String> actualAlerts = getCollectedAlerts(maxWaitTime, driver, expected.length);
1327
1328 assertEquals(expected.length, actualAlerts.size());
1329
1330 if (!useRealBrowser()) {
1331
1332 for (int i = 0; i < expected.length; i++) {
1333 if (expected[i].startsWith("data:image/png;base64,")) {
1334
1335 for (int j = 0; j < expected.length; j++) {
1336 if (expected[j].startsWith("data:image/png;base64,")) {
1337 compareImages(expected[j], actualAlerts.get(j));
1338 }
1339 else {
1340 assertEquals(expected[j], actualAlerts.get(j));
1341 }
1342 }
1343 return;
1344 }
1345 }
1346 }
1347
1348 assertEquals(expected, actualAlerts);
1349 }
1350
1351
1352
1353
1354
1355
1356
1357
1358 protected final WebDriver loadPageWithAlerts2(final String html,
1359 final Map<String, Class<? extends Servlet>> servlets) throws Exception {
1360 return loadPageWithAlerts2(html, URL_FIRST, DEFAULT_WAIT_TIME, servlets);
1361 }
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372 protected final WebDriver loadPageWithAlerts2(final String html, final URL url, final Duration maxWaitTime,
1373 final Map<String, Class<? extends Servlet>> servlets) throws Exception {
1374
1375 expandExpectedAlertsVariables(URL_FIRST);
1376
1377 final WebDriver driver = loadPage2(html, url, servlets);
1378 verifyAlerts(maxWaitTime, driver, getExpectedAlerts());
1379
1380 return driver;
1381 }
1382
1383
1384
1385
1386
1387
1388
1389
1390 protected final WebDriver loadPageWithAlerts2(final URL url) throws Exception {
1391 return loadPageWithAlerts2(url, DEFAULT_WAIT_TIME);
1392 }
1393
1394
1395
1396
1397
1398
1399
1400
1401 protected final WebDriver loadPageWithAlerts2(final URL url, final Duration maxWaitTime) throws Exception {
1402 startWebServer(getMockWebConnection(), null);
1403
1404 final WebDriver driver = getWebDriver();
1405 driver.get(url.toExternalForm());
1406
1407 verifyAlerts(maxWaitTime, driver, getExpectedAlerts());
1408 return driver;
1409 }
1410
1411
1412
1413
1414
1415
1416
1417
1418 protected List<String> getCollectedAlerts(final WebDriver driver) throws Exception {
1419 return getCollectedAlerts(driver, getExpectedAlerts().length);
1420 }
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430 protected List<String> getCollectedAlerts(final WebDriver driver, final int alertsLength) throws Exception {
1431 return getCollectedAlerts(DEFAULT_WAIT_TIME, driver, alertsLength);
1432 }
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443 protected List<String> getCollectedAlerts(final Duration maxWaitTime,
1444 final WebDriver driver, final int alertsLength) throws Exception {
1445 final List<String> collectedAlerts = new ArrayList<>();
1446
1447 long maxWait = System.currentTimeMillis() + maxWaitTime.toMillis();
1448
1449 while (collectedAlerts.size() < alertsLength && System.currentTimeMillis() < maxWait) {
1450 try {
1451 final Alert alert = driver.switchTo().alert();
1452 final String text = alert.getText();
1453
1454 collectedAlerts.add(text);
1455 alert.accept();
1456
1457
1458
1459 maxWait += 100;
1460 }
1461 catch (final NoAlertPresentException e) {
1462 Thread.sleep(10);
1463 }
1464 }
1465
1466 return collectedAlerts;
1467 }
1468
1469
1470
1471
1472
1473
1474
1475 protected HtmlElement toHtmlElement(final WebElement webElement) throws Exception {
1476 return (HtmlElement) ((HtmlUnitWebElement) webElement).getElement();
1477 }
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487 protected String loadExpectation(final String resourcePrefix, final String resourceSuffix) throws Exception {
1488 final Class<?> referenceClass = getClass();
1489 final BrowserVersion browserVersion = getBrowserVersion();
1490
1491 String realBrowserNyiExpectation = null;
1492 String realNyiExpectation = null;
1493 final String browserExpectation;
1494 final String expectation;
1495 if (!useRealBrowser()) {
1496
1497 final String browserSpecificNyiResource
1498 = resourcePrefix + "." + browserVersion.getNickname() + "_NYI" + resourceSuffix;
1499 realBrowserNyiExpectation = loadContent(referenceClass.getResource(browserSpecificNyiResource));
1500
1501
1502 final String nyiResource = resourcePrefix + ".NYI" + resourceSuffix;
1503 realNyiExpectation = loadContent(referenceClass.getResource(nyiResource));
1504 }
1505
1506
1507 final String browserSpecificResource = resourcePrefix + "." + browserVersion.getNickname() + resourceSuffix;
1508 browserExpectation = loadContent(referenceClass.getResource(browserSpecificResource));
1509
1510
1511 final String resource = resourcePrefix + resourceSuffix;
1512 expectation = loadContent(referenceClass.getResource(resource));
1513
1514
1515 if (realBrowserNyiExpectation != null) {
1516 if (realNyiExpectation != null) {
1517 Assertions.assertNotEquals(realBrowserNyiExpectation, realNyiExpectation,
1518 "Duplicate NYI Expectation for Browser " + browserVersion.getNickname());
1519 }
1520
1521 if (browserExpectation == null) {
1522 if (expectation != null) {
1523 Assertions.assertNotEquals(realBrowserNyiExpectation, expectation,
1524 "NYI Expectation matches the expected "
1525 + "result for Browser " + browserVersion.getNickname());
1526 }
1527 }
1528 else {
1529 Assertions.assertNotEquals(realBrowserNyiExpectation, browserExpectation,
1530 "NYI Expectation matches the expected "
1531 + "browser specific result for Browser "
1532 + browserVersion.getNickname());
1533 }
1534
1535 return realBrowserNyiExpectation;
1536 }
1537
1538 if (realNyiExpectation != null) {
1539 if (browserExpectation == null) {
1540 if (expectation != null) {
1541 Assertions.assertNotEquals(realNyiExpectation, expectation,
1542 "NYI Expectation matches the expected "
1543 + "result for Browser " + browserVersion.getNickname());
1544 }
1545 }
1546 else {
1547 Assertions.assertNotEquals(realNyiExpectation, browserExpectation,
1548 "NYI Expectation matches the expected "
1549 + "browser specific result for Browser "
1550 + browserVersion.getNickname());
1551 }
1552 return realNyiExpectation;
1553 }
1554
1555 if (browserExpectation != null) {
1556 if (expectation != null) {
1557 Assertions.assertNotEquals(browserExpectation, expectation,
1558 "Browser specific NYI Expectation matches the expected "
1559 + "result for Browser " + browserVersion.getNickname());
1560 }
1561 return browserExpectation;
1562 }
1563 return expectation;
1564 }
1565
1566 private static String loadContent(final URL url) throws URISyntaxException, IOException {
1567 if (url == null) {
1568 return null;
1569 }
1570
1571 final File file = new File(url.toURI());
1572 String content = FileUtils.readFileToString(file, UTF_8);
1573 content = StringUtils.replace(content, "\r\n", "\n");
1574 return content;
1575 }
1576
1577
1578
1579
1580
1581
1582 @BeforeEach
1583 public void beforeTest() throws InterruptedException {
1584 if (!isWebClientCached()) {
1585 if (!getJavaScriptThreads().isEmpty()) {
1586 Thread.sleep(200);
1587 }
1588 assertTrue("There are already JS threads running before the test", getJavaScriptThreads().isEmpty());
1589 }
1590 }
1591
1592
1593
1594
1595
1596
1597
1598 protected void assertTitle(final WebDriver webdriver, final String expected) throws Exception {
1599 final long maxWait = System.currentTimeMillis() + DEFAULT_WAIT_TIME.toMillis();
1600
1601 while (true) {
1602 final String title = webdriver.getTitle();
1603 try {
1604 assertEquals(expected, title);
1605 return;
1606 }
1607 catch (final org.opentest4j.AssertionFailedError e) {
1608 if (expected.length() <= title.length()
1609 || System.currentTimeMillis() > maxWait) {
1610 throw e;
1611 }
1612 Thread.sleep(10);
1613 }
1614 }
1615 }
1616
1617
1618
1619
1620
1621 @AfterEach
1622 @Override
1623 public void releaseResources() {
1624 final List<String> unhandledAlerts = new ArrayList<>();
1625 if (webDriver_ != null) {
1626 UnhandledAlertException ex = null;
1627 do {
1628 ex = null;
1629 try {
1630
1631 webDriver_.getTitle();
1632 }
1633 catch (final NoSuchWindowException e) {
1634
1635 }
1636 catch (final UnhandledAlertException e) {
1637 ex = e;
1638 unhandledAlerts.add(e.getMessage());
1639 }
1640 }
1641 while (ex != null);
1642 }
1643
1644 super.releaseResources();
1645
1646 if (!isWebClientCached()) {
1647 boolean rhino = false;
1648 if (webDriver_ != null) {
1649 try {
1650 rhino = getWebClient().getJavaScriptEngine() instanceof JavaScriptEngine;
1651 }
1652 catch (final Exception e) {
1653 throw new RuntimeException(e);
1654 }
1655 webDriver_.quit();
1656 webDriver_ = null;
1657 }
1658 if (rhino) {
1659 assertTrue("There are still JS threads running after the test", getJavaScriptThreads().isEmpty());
1660 }
1661 }
1662
1663 if (useRealBrowser()) {
1664 synchronized (WEB_DRIVERS_REAL_BROWSERS) {
1665 final WebDriver driver = WEB_DRIVERS_REAL_BROWSERS.get(getBrowserVersion());
1666 if (driver != null) {
1667 try {
1668 final String currentWindow = driver.getWindowHandle();
1669
1670 final Set<String> handles = driver.getWindowHandles();
1671
1672 handles.remove(currentWindow);
1673
1674 if (handles.size() > 0) {
1675 for (final String handle : handles) {
1676 try {
1677 driver.switchTo().window(handle);
1678 driver.close();
1679 }
1680 catch (final NoSuchWindowException e) {
1681 LOG.error("Error switching to browser window; quit browser.", e);
1682 WEB_DRIVERS_REAL_BROWSERS.remove(getBrowserVersion());
1683 WEB_DRIVERS_REAL_BROWSERS_USAGE_COUNT.remove(getBrowserVersion());
1684 driver.quit();
1685 return;
1686 }
1687 }
1688
1689
1690
1691
1692 driver.switchTo().window(currentWindow);
1693 }
1694
1695 driver.manage().deleteAllCookies();
1696
1697
1698 driver.get("about:blank");
1699 }
1700 catch (final NoSuchSessionException e) {
1701 LOG.error("Error browser session no longer available.", e);
1702 WEB_DRIVERS_REAL_BROWSERS.remove(getBrowserVersion());
1703 WEB_DRIVERS_REAL_BROWSERS_USAGE_COUNT.remove(getBrowserVersion());
1704 return;
1705 }
1706 catch (final WebDriverException e) {
1707 shutDownRealBrowsers();
1708 }
1709 }
1710 }
1711 }
1712 assertTrue("There are still unhandled alerts: " + String.join("; ", unhandledAlerts),
1713 unhandledAlerts.isEmpty());
1714 }
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724 protected WebWindow getWebWindow() {
1725 return webDriver_.getCurrentWindow().getWebWindow();
1726 }
1727
1728
1729
1730
1731
1732
1733
1734
1735 protected boolean isWebClientCached() {
1736 return false;
1737 }
1738
1739
1740
1741
1742
1743
1744 protected Integer getWebClientTimeout() {
1745 return null;
1746 }
1747
1748 protected Page getEnclosedPage() {
1749 return getWebWindow().getEnclosedPage();
1750 }
1751
1752 protected WebClient getWebClient() {
1753 return webDriver_.getWebClient();
1754 }
1755
1756
1757
1758
1759 public static class AsciiEncodingFilter implements Filter {
1760
1761 private static Charset CHARSET_;
1762
1763
1764
1765
1766 @Override
1767 public void init(final FilterConfig filterConfig) throws ServletException {
1768 }
1769
1770
1771
1772
1773 @Override
1774 public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
1775 throws IOException, ServletException {
1776 if (request instanceof Request) {
1777 ((Request) request).setQueryEncoding(CHARSET_.name());
1778 }
1779 chain.doFilter(request, response);
1780 }
1781
1782
1783
1784
1785 @Override
1786 public void destroy() {
1787 }
1788 }
1789 }