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