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