1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.html;
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.IOException;
21 import java.net.MalformedURLException;
22 import java.net.URL;
23 import java.nio.charset.StandardCharsets;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.Iterator;
28 import java.util.LinkedList;
29 import java.util.List;
30 import java.util.Set;
31
32 import javax.xml.parsers.DocumentBuilder;
33 import javax.xml.parsers.DocumentBuilderFactory;
34
35 import org.apache.commons.io.IOUtils;
36 import org.apache.commons.lang3.SerializationUtils;
37 import org.htmlunit.CollectingAlertHandler;
38 import org.htmlunit.ElementNotFoundException;
39 import org.htmlunit.FailingHttpStatusCodeException;
40 import org.htmlunit.HttpMethod;
41 import org.htmlunit.ImmediateRefreshHandler;
42 import org.htmlunit.IncorrectnessListener;
43 import org.htmlunit.MockWebConnection;
44 import org.htmlunit.OnbeforeunloadHandler;
45 import org.htmlunit.Page;
46 import org.htmlunit.SimpleWebTestCase;
47 import org.htmlunit.StringWebResponse;
48 import org.htmlunit.WaitingRefreshHandler;
49 import org.htmlunit.WebClient;
50 import org.htmlunit.WebRequest;
51 import org.htmlunit.WebResponse;
52 import org.htmlunit.html.HtmlElementTest.HtmlAttributeChangeListenerTestImpl;
53 import org.htmlunit.junit.annotation.Alerts;
54 import org.htmlunit.util.Cookie;
55 import org.htmlunit.util.MimeType;
56 import org.htmlunit.util.NameValuePair;
57 import org.htmlunit.util.StringUtils;
58 import org.junit.jupiter.api.Assertions;
59 import org.junit.jupiter.api.Test;
60 import org.w3c.dom.NodeList;
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public class HtmlPageTest extends SimpleWebTestCase {
76
77
78 public static final String STANDARDS_MODE_PREFIX_
79 = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n";
80
81
82
83
84 @Test
85 public void formSubmit() throws Exception {
86 final String htmlContent = DOCTYPE_HTML
87 + "<html>\n"
88 + "<head><title>foo</title></head>\n"
89 + "<body>\n"
90 + "<p>hello world</p>\n"
91 + "<form id='form1' action='/formSubmit' method='PoSt'>\n"
92 + "<input type='text' NAME='textInput1' value='textInput1'/>\n"
93 + "<input type='text' name='textInput2' value='textInput2'/>\n"
94 + "<input type='hidden' name='hidden1' value='hidden1'/>\n"
95 + "<input type='submit' name='submitInput1' value='push me'/>\n"
96 + "</form>\n"
97 + "</body></html>";
98 final HtmlPage page = loadPage(htmlContent);
99 final MockWebConnection webConnection = getMockConnection(page);
100
101 final HtmlForm form = page.getHtmlElementById("form1");
102 final HtmlInput textInput = form.getInputByName("textInput1");
103 textInput.setValue("foo");
104
105 final HtmlSubmitInput button = form.getInputByName("submitInput1");
106 final HtmlPage secondPage = button.click();
107
108 final List<NameValuePair> expectedParameters = new ArrayList<>();
109 expectedParameters.add(new NameValuePair("textInput1", "foo"));
110 expectedParameters.add(new NameValuePair("textInput2", "textInput2"));
111 expectedParameters.add(new NameValuePair("hidden1", "hidden1"));
112 expectedParameters.add(new NameValuePair("submitInput1", "push me"));
113
114 final URL expectedUrl = new URL(URL_FIRST, "formSubmit");
115 final URL actualUrl = secondPage.getUrl();
116 assertEquals("url", expectedUrl, actualUrl);
117 assertSame("method", HttpMethod.POST, webConnection.getLastMethod());
118 assertEquals("parameters", expectedParameters, webConnection.getLastParameters());
119 assertNotNull(secondPage);
120 }
121
122
123
124
125 @Test
126 public void getElementByIdNull() throws Exception {
127 final String htmlContent = DOCTYPE_HTML
128 + "<html>\n"
129 + "<head><title>foo</title></head>\n"
130 + "<body>\n"
131 + "<p>hello world</p>\n"
132 + "</body></html>";
133
134 final HtmlPage page = loadPage(htmlContent);
135
136 assertNull(page.getElementById(null));
137 }
138
139
140
141
142 @Test
143 public void getElementsByIdNull() throws Exception {
144 final String htmlContent = DOCTYPE_HTML
145 + "<html>\n"
146 + "<head><title>foo</title></head>\n"
147 + "<body>\n"
148 + "<p>hello world</p>\n"
149 + "</body></html>";
150
151 final HtmlPage page = loadPage(htmlContent);
152
153 final List<DomElement> elements = page.getElementsById(null);
154 assertNotNull(elements);
155 assertEquals(0, elements.size());
156 }
157
158
159
160
161 @Test
162 public void getElementsByIdOrNameNull() throws Exception {
163 final String htmlContent = DOCTYPE_HTML
164 + "<html>\n"
165 + "<head><title>foo</title></head>\n"
166 + "<body>\n"
167 + "<p>hello world</p>\n"
168 + "</body></html>";
169
170 final HtmlPage page = loadPage(htmlContent);
171
172 final List<DomElement> elements = page.getElementsByIdAndOrName(null);
173 assertNotNull(elements);
174 assertEquals(0, elements.size());
175 }
176
177
178
179
180 @Test
181 public void getElementByNameNull() throws Exception {
182 final String htmlContent = DOCTYPE_HTML
183 + "<html>\n"
184 + "<head><title>foo</title></head>\n"
185 + "<body>\n"
186 + "<p>hello world</p>\n"
187 + "</body></html>";
188
189 final HtmlPage page = loadPage(htmlContent);
190
191 Assertions.assertThrows(ElementNotFoundException.class, () -> page.getElementByName(null));
192 }
193
194
195
196
197 @Test
198 public void getElementsByNameNull() throws Exception {
199 final String htmlContent = DOCTYPE_HTML
200 + "<html>\n"
201 + "<head><title>foo</title></head>\n"
202 + "<body>\n"
203 + "<p>hello world</p>\n"
204 + "</body></html>";
205
206 final HtmlPage page = loadPage(htmlContent);
207
208 final List<DomElement> elements = page.getElementsByName(null);
209 assertNotNull(elements);
210 assertEquals(0, elements.size());
211 }
212
213
214
215
216
217 @Test
218 public void getHtmlElement() throws Exception {
219 final String htmlContent = DOCTYPE_HTML
220 + "<html>\n"
221 + "<head><title>foo</title></head>\n"
222 + "<body>\n"
223 + " <p>hello world</p>\n"
224 + " <form id='form1' id='form1' action='/formSubmit' method='post'>\n"
225 + " <input type='text' NAME='textInput1' value='textInput1'/>\n"
226 + " <button type='submit' name='button1'>foobar</button>\n"
227 + " <select name='select1'>\n"
228 + " <option value='option1'>Option1</option>\n"
229 + " </select>\n"
230 + " <textarea name='textArea1'>foobar</textarea>\n"
231 + " </form>\n"
232 + " <a href='http://www.foo.com' name='anchor1'>foo.com</a>\n"
233 + " <table id='table1'>\n"
234 + " <tr>\n"
235 + " <th id='header1'>Header</th>\n"
236 + " <td id='data1'>Data</td>\n"
237 + " </tr>\n"
238 + " </table>\n"
239 + "</body></html>";
240 final HtmlPage page = loadPage(htmlContent);
241
242 final HtmlForm form = page.getHtmlElementById("form1");
243 assertSame("form1", form, page.getHtmlElementById("form1"));
244
245 final HtmlInput input = form.getInputByName("textInput1");
246 assertSame("input1", input, form.getInputByName("textInput1"));
247
248 final HtmlButton button = form.getButtonByName("button1");
249 assertSame("button1", button, form.getButtonByName("button1"));
250
251 final HtmlSelect select = form.getSelectsByName("select1").get(0);
252 assertSame("select1", select, form.getSelectsByName("select1").get(0));
253
254 final HtmlOption option = select.getOptionByValue("option1");
255 assertSame("option1", option, select.getOptionByValue("option1"));
256
257 final HtmlTable table = page.getHtmlElementById("table1");
258 assertSame("table1", table, page.getHtmlElementById("table1"));
259
260 final HtmlAnchor anchor = page.getAnchorByName("anchor1");
261 assertSame("anchor1", anchor, page.getAnchorByName("anchor1"));
262 assertSame("anchor3", anchor, page.getAnchorByHref("http://www.foo.com"));
263 assertSame("anchor4", anchor, page.getAnchorByText("foo.com"));
264
265 final HtmlTableRow tableRow = table.getRow(0);
266 assertSame("tableRow1", tableRow, table.getRow(0));
267
268 final HtmlTableHeaderCell tableHeaderCell = (HtmlTableHeaderCell) tableRow.getCell(0);
269 assertSame("tableHeaderCell1", tableHeaderCell, tableRow.getCell(0));
270 assertSame("tableHeaderCell2", tableHeaderCell, page.getHtmlElementById("header1"));
271
272 final HtmlTableDataCell tableDataCell = (HtmlTableDataCell) tableRow.getCell(1);
273 assertSame("tableDataCell1", tableDataCell, tableRow.getCell(1));
274 assertSame("tableDataCell2", tableDataCell, page.getHtmlElementById("data1"));
275
276 final HtmlTextArea textArea = form.getTextAreaByName("textArea1");
277 assertSame("textArea1", textArea, form.getTextAreaByName("textArea1"));
278 }
279
280
281
282
283
284 @Test
285 public void getAnchorByText() throws Exception {
286 final String htmlContent = DOCTYPE_HTML
287 + "<html>\n"
288 + "<head></head>\n"
289 + "<body>\n"
290 + " <a href='http://www.foo.com' id='anchor1'>anchor text</a>\n"
291 + " <a href='http://www.foo.com' id='anchor2'><span>anchor text inside span</span></a>\n"
292 + " <a href='http://www.foo.com' id='anchor3'>"
293 + "<svg><rect x='1' y='11' width='8' height='8'/></svg>"
294 + "<span>complex</span>"
295 + "</a>\n"
296 + "</body></html>";
297 final HtmlPage page = loadPage(htmlContent);
298
299 assertSame("anchor1", page.getElementById("anchor1"), page.getAnchorByText("anchor text"));
300 assertSame("anchor2", page.getElementById("anchor2"), page.getAnchorByText("anchor text inside span"));
301 assertSame("anchor3", page.getElementById("anchor3"), page.getAnchorByText("complex"));
302 }
303
304
305
306
307 @Test
308 public void getTabbableElements_None() throws Exception {
309 final String htmlContent = DOCTYPE_HTML
310 + "<html>\n"
311 + "<head><title>foo</title></head>\n"
312 + "<body>\n"
313 + "<p>hello world</p>\n"
314 + "<table><tr><td>foo</td></tr></table>\n"
315 + "</body></html>";
316
317 final HtmlPage page = loadPage(htmlContent);
318
319 assertEquals(Collections.EMPTY_LIST, page.getTabbableElements());
320 }
321
322
323
324
325 @Test
326 public void getTabbableElements_OneEnabled_OneDisabled() throws Exception {
327 final String htmlContent = DOCTYPE_HTML
328 + "<html>\n"
329 + "<head><title>foo</title></head>\n"
330 + "<body>\n"
331 + "<form><p>hello world</p>\n"
332 + "<input name='foo' type='submit' disabled='disabled' id='foo'/>\n"
333 + "<input name='bar' type='submit' id='bar'/>\n"
334 + "</form></body></html>";
335 final HtmlPage page = loadPage(htmlContent);
336
337 final List<HtmlElement> expectedElements = new ArrayList<>();
338 expectedElements.add(page.getHtmlElementById("bar"));
339
340 assertEquals(expectedElements, page.getTabbableElements());
341 }
342
343
344
345
346 @Test
347 public void getTabbableElements() throws Exception {
348 final String htmlContent = DOCTYPE_HTML
349 + "<html>\n"
350 + "<head><title>foo</title></head>\n"
351 + "<body>\n"
352 + "<a id='a' tabindex='1'>foo</a>\n"
353 + "<a id='b'>foo</a>\n"
354 + "<form>\n"
355 + "<a id='c' tabindex='3'>foo</a>\n"
356 + "<a id='d' tabindex='2'>foo</a>\n"
357 + "<a id='e' tabindex='0'>foo</a>\n"
358 + "</form>\n"
359 + "<a id='f' tabindex='3'>foo</a>\n"
360 + "<a id='g' tabindex='1'>foo</a>\n"
361 + "<a id='q' tabindex='-1'>foo</a>\n"
362 + "<form><p>hello world</p>\n"
363 + "<input name='foo' type='submit' disabled='disabled' id='foo'/>\n"
364 + "<input name='bar' type='submit' id='bar'/>\n"
365 + "</form></body></html>";
366 final HtmlPage page = loadPage(htmlContent);
367
368 final List<HtmlElement> expectedElements = Arrays.asList(new HtmlElement[] {page.getHtmlElementById("a"),
369 page.getHtmlElementById("g"), page.getHtmlElementById("d"),
370 page.getHtmlElementById("c"), page.getHtmlElementById("f"),
371 page.getHtmlElementById("e"), page.getHtmlElementById("b"),
372 page.getHtmlElementById("bar")});
373
374 assertEquals(expectedElements, page.getTabbableElements());
375
376 final String[] expectedIds = {"a", "g", "d", "c", "f", "e", "b", "bar"};
377 assertEquals(expectedIds, page.getTabbableElementIds());
378 }
379
380
381
382
383 @Test
384 public void getHtmlElementByAccessKey() throws Exception {
385 final String htmlContent = DOCTYPE_HTML
386 + "<html>\n"
387 + "<head><title>foo</title></head>\n"
388 + "<body>\n"
389 + "<a id='a' accesskey='a'>foo</a>\n"
390 + "<a id='b'>foo</a>\n"
391 + "<form>\n"
392 + "<a id='c' accesskey='c'>foo</a>\n"
393 + "</form>\n"
394 + "<form><p>hello world</p>\n"
395 + "<input name='foo' type='submit' disabled='disabled' id='foo' accesskey='f'/>\n"
396 + "<input name='bar' type='submit' id='bar'/>\n"
397 + "</form></body></html>";
398 final HtmlPage page = loadPage(htmlContent);
399
400 assertEquals(page.getHtmlElementById("a"), page.getHtmlElementByAccessKey('A'));
401 assertEquals(page.getHtmlElementById("c"), page.getHtmlElementByAccessKey('c'));
402 assertNull(page.getHtmlElementByAccessKey('z'));
403 }
404
405
406
407
408 @Test
409 public void getHtmlElementsByAccessKey() throws Exception {
410 final String htmlContent = DOCTYPE_HTML
411 + "<html>\n"
412 + "<head><title>foo</title></head><body>\n"
413 + "<a id='a' accesskey='a'>foo</a>\n"
414 + "<a id='b' accesskey='a'>foo</a>\n"
415 + "<form>\n"
416 + "<a id='c' accesskey='c'>foo</a>\n"
417 + "</form></body></html>";
418 final HtmlPage page = loadPage(htmlContent);
419
420 final List<HtmlElement> expectedElements = Arrays.asList(new HtmlElement[] {page.getHtmlElementById("a"),
421 page.getHtmlElementById("b")});
422 final List<HtmlElement> collectedElements = page.getHtmlElementsByAccessKey('a');
423 assertEquals(expectedElements, collectedElements);
424 }
425
426
427
428
429 @Test
430 public void getFullQualifiedUrl_NoBaseSpecified() throws Exception {
431 final String htmlContent = DOCTYPE_HTML
432 + "<html><head><title>foo</title></head><body>\n"
433 + "<form id='form1'>\n"
434 + "<table><tr><td><input type='text' id='foo'/></td></tr></table>\n"
435 + "</form></body></html>";
436 final WebClient client = getWebClient();
437
438 final MockWebConnection webConnection = new MockWebConnection();
439 webConnection.setDefaultResponse(htmlContent);
440 client.setWebConnection(webConnection);
441
442 final String urlString = URL_FIRST.toExternalForm();
443 final HtmlPage page = client.getPage(URL_FIRST);
444
445 assertEquals(urlString, page.getFullyQualifiedUrl(""));
446 assertEquals(urlString + "foo", page.getFullyQualifiedUrl("foo"));
447 assertEquals("http://foo.com/bar", page.getFullyQualifiedUrl("http://foo.com/bar"));
448 assertEquals("mailto:me@foo.com", page.getFullyQualifiedUrl("mailto:me@foo.com"));
449
450 assertEquals(urlString + "foo", page.getFullyQualifiedUrl("foo"));
451 assertEquals(urlString + "bbb", page.getFullyQualifiedUrl("aaa/../bbb"));
452 assertEquals(urlString + "c/d", page.getFullyQualifiedUrl("c/./d"));
453
454 final HtmlPage secondPage = client.getPage(urlString + "foo/bar?a=b&c=d");
455 assertEquals(urlString + "foo/bar?a=b&c=d", secondPage.getFullyQualifiedUrl(""));
456 assertEquals(urlString + "foo/one", secondPage.getFullyQualifiedUrl("one"));
457 assertEquals(urlString + "two", secondPage.getFullyQualifiedUrl("/two"));
458 assertEquals(urlString + "foo/two?a=b", secondPage.getFullyQualifiedUrl("two?a=b"));
459
460 final HtmlPage thirdPage = client.getPage("http://foo.com/dog/cat/one.html");
461 assertEquals("http://foo.com/dog/cat/one.html", thirdPage.getFullyQualifiedUrl(""));
462 assertEquals("http://foo.com/dog/cat/two.html", thirdPage.getFullyQualifiedUrl("two.html"));
463 }
464
465
466
467
468 @Test
469 public void getFullQualifiedUrl_WithBase() throws Exception {
470 testGetFullQualifiedUrl_WithBase("http", "");
471 testGetFullQualifiedUrl_WithBase("http", ":8080");
472 testGetFullQualifiedUrl_WithBase("https", "");
473 testGetFullQualifiedUrl_WithBase("https", ":2005");
474 }
475
476
477
478
479 private void testGetFullQualifiedUrl_WithBase(final String baseProtocol, final String basePortPart)
480 throws Exception {
481
482 final String baseUrl = baseProtocol + "://second" + basePortPart;
483 final String htmlContent = DOCTYPE_HTML
484 + "<html><head><title>foo</title>\n"
485 + "<base href='" + baseUrl + "'>\n"
486 + "</head><body>\n"
487 + "<form id='form1'>\n"
488 + "<table><tr><td><input type='text' id='foo'/></td></tr></table>\n"
489 + "</form></body></html>";
490 final HtmlPage page = loadPage(htmlContent);
491
492 assertEquals(baseUrl, page.getFullyQualifiedUrl(""));
493 assertEquals(baseUrl + "/foo", page.getFullyQualifiedUrl("foo"));
494 assertEquals(baseUrl + "/foo.js", page.getFullyQualifiedUrl("/foo.js"));
495 assertEquals("http://foo.com/bar", page.getFullyQualifiedUrl("http://foo.com/bar"));
496 assertEquals("mailto:me@foo.com", page.getFullyQualifiedUrl("mailto:me@foo.com"));
497
498 assertEquals(baseUrl + "/bbb", page.getFullyQualifiedUrl("aaa/../bbb"));
499 assertEquals(baseUrl + "/c/d", page.getFullyQualifiedUrl("c/./d"));
500 }
501
502
503
504
505 @Test
506 public void getFullQualifiedUrl_invalid() throws Exception {
507 final String htmlContent = DOCTYPE_HTML + "<html><body></body></html>";
508 final HtmlPage page = loadPage(htmlContent);
509
510 Assertions.assertThrows(MalformedURLException.class, () -> page.getFullyQualifiedUrl("http://"));
511 }
512
513
514
515
516 @Test
517 public void testBase_Multiple() throws Exception {
518 final String html = DOCTYPE_HTML
519 + "<html>\n"
520 + "<head>\n"
521 + "<base href='" + URL_SECOND + "'>\n"
522 + "<base href='" + URL_THIRD + "'>\n"
523 + "</head>\n"
524 + "<body>\n"
525 + " <a href='somepage.html'>\n"
526 + "</body></html>";
527
528 final WebClient webClient = getWebClient();
529 final List<String> collectedIncorrectness = new ArrayList<>();
530 final IncorrectnessListener listener = new IncorrectnessListener() {
531 @Override
532 public void notify(final String message, final Object origin) {
533 collectedIncorrectness.add(message);
534 }
535 };
536 webClient.setIncorrectnessListener(listener);
537
538 final MockWebConnection webConnection = new MockWebConnection();
539 webClient.setWebConnection(webConnection);
540 webConnection.setDefaultResponse(html);
541 final HtmlPage page = webClient.getPage(URL_FIRST);
542 page.getAnchors().get(0).click();
543
544 final String[] expectedIncorrectness = {"Multiple 'base' detected, only the first is used.",
545 "Multiple 'base' detected, only the first is used."};
546 assertEquals(expectedIncorrectness, collectedIncorrectness);
547 }
548
549
550
551
552 @Test
553 public void testBase_InsideBody() throws Exception {
554 final String html = DOCTYPE_HTML
555 + "<html><body>\n"
556 + " <base href='" + URL_SECOND + "'>\n"
557 + " <a href='somepage.html'>link</a>\n"
558 + "</body></html>";
559
560 final WebClient webClient = getWebClient();
561
562 final MockWebConnection webConnection = new MockWebConnection();
563 webClient.setWebConnection(webConnection);
564 webConnection.setDefaultResponse(html);
565 final HtmlPage page = webClient.getPage(URL_FIRST);
566 final HtmlAnchor anchor = page.getAnchors().get(0);
567 final HtmlPage secondPage = anchor.click();
568
569 assertEquals(URL_SECOND + "somepage.html", secondPage.getUrl());
570 }
571
572
573
574
575 @Test
576 public void onLoadHandler_BodyStatement() throws Exception {
577 final String htmlContent = DOCTYPE_HTML
578 + "<html><head><title>foo</title>\n"
579 + "</head><body onLoad='alert(\"foo\")'>\n"
580 + "</body></html>";
581 final List<String> collectedAlerts = new ArrayList<>();
582 final HtmlPage page = loadPage(htmlContent, collectedAlerts);
583 assertEquals("foo", page.getTitleText());
584
585 final String[] expectedAlerts = {"foo"};
586 assertEquals(expectedAlerts, collectedAlerts);
587 }
588
589
590
591
592
593 @Test
594 public void onLoadHandler_TwoBodyStatements() throws Exception {
595 final String htmlContent = DOCTYPE_HTML
596 + "<html><head><title>foo</title>\n"
597 + "</head><body onLoad='alert(\"foo\");alert(\"bar\")'>\n"
598 + "</body></html>";
599 final List<String> collectedAlerts = new ArrayList<>();
600 final HtmlPage page = loadPage(htmlContent, collectedAlerts);
601 assertEquals("foo", page.getTitleText());
602
603 final String[] expectedAlerts = {"foo", "bar"};
604 assertEquals(expectedAlerts, collectedAlerts);
605 }
606
607
608
609
610
611 @Test
612 public void onLoadHandler_BodyName() throws Exception {
613 final String htmlContent = DOCTYPE_HTML
614 + "<html><head><title>foo</title>\n"
615 + "<script type='text/javascript'>\n"
616 + " window.onload = function() {alert('foo')}</script>\n"
617 + "</head><body></body></html>";
618 final List<String> collectedAlerts = new ArrayList<>();
619 final HtmlPage page = loadPage(htmlContent, collectedAlerts);
620 assertEquals("foo", page.getTitleText());
621
622 final String[] expectedAlerts = {"foo"};
623 assertEquals(expectedAlerts, collectedAlerts);
624 }
625
626
627
628
629
630 @Test
631 public void onLoadHandler_BodyName_NotAFunction() throws Exception {
632 final String htmlContent = DOCTYPE_HTML
633 + "<html><head><title>foo</title></head>\n"
634 + "<body onLoad='foo=4711'>\n"
635 + "<a name='alert' href='javascript:alert(foo)'/>\n"
636 + "</body></html>";
637 final List<String> collectedAlerts = new ArrayList<>();
638 final HtmlPage page = loadPage(htmlContent, collectedAlerts);
639 assertEquals("foo", page.getTitleText());
640
641 page.getAnchorByName("alert").click();
642
643 final String[] expectedAlerts = {"4711"};
644 assertEquals(expectedAlerts, collectedAlerts);
645 }
646
647
648
649
650
651 @Test
652 public void onLoadHandler_ScriptName() throws Exception {
653 final String htmlContent = DOCTYPE_HTML
654 + "<html><head><title>foo</title>\n"
655 + "<script type='text/javascript'>\n"
656 + "load=function() {alert('foo')};\n"
657 + "onload=load\n"
658 + "</script></head><body></body></html>";
659 final List<String> collectedAlerts = new ArrayList<>();
660 final HtmlPage page = loadPage(htmlContent, collectedAlerts);
661 assertEquals("foo", page.getTitleText());
662
663 final String[] expectedAlerts = {"foo"};
664 assertEquals(expectedAlerts, collectedAlerts);
665 }
666
667
668
669
670 @Test
671 public void embeddedMetaTag_Regression() throws Exception {
672 final String htmlContent = DOCTYPE_HTML
673 + "<html><head><title>foo</title>\n"
674 + "</head><body>\n"
675 + "<table><tr><td>\n"
676 + "<meta name=vs_targetSchema content=\"http://schemas.microsoft.com/intellisense/ie5\">\n"
677 + "<form name='form1'>\n"
678 + " <input type='text' name='textfield1' id='textfield1' value='foo' />\n"
679 + " <input type='text' name='textfield2' id='textfield2'/>\n"
680 + "</form>\n"
681 + "</td></tr></table>\n"
682 + "</body></html>";
683 final List<String> collectedAlerts = new ArrayList<>();
684
685
686 final HtmlPage page = loadPage(htmlContent, collectedAlerts);
687 assertEquals("foo", page.getTitleText());
688
689 final List<?> expectedAlerts = Collections.EMPTY_LIST;
690 assertEquals(expectedAlerts, collectedAlerts);
691 }
692
693
694
695
696
697 @Test
698 public void getPageEncoding_EmptyCharset() throws Exception {
699 final String html = DOCTYPE_HTML
700 + "<html><head>\n"
701 + "<meta http-equiv='Content-Type' content='text/html; charset='>\n"
702 + "</head><body>abc</body></html>";
703 final HtmlPage page = loadPage(html);
704 assertEquals(ISO_8859_1, page.getCharset());
705 }
706
707
708
709
710
711
712 @Test
713 public void getPageEncoding_HeaderHasPrecedenceOverMetaTag() throws Exception {
714 final String html = DOCTYPE_HTML
715 + "<html><head><meta content='text/html; charset=iso-8859-1' http-equiv='Content-Type'/>\n"
716 + "</head><body></body></html>";
717 final MockWebConnection conn = new MockWebConnection();
718 conn.setResponse(URL_FIRST, html, "text/html; charset=UTF-8");
719 final WebClient client = getWebClient();
720 client.setWebConnection(conn);
721 final HtmlPage page = client.getPage(URL_FIRST);
722 assertSame(UTF_8, page.getCharset());
723 assertEquals(page.getWebResponse().getContentCharset(), page.getCharset());
724 }
725
726
727
728
729 @Test
730 public void getForms() throws Exception {
731 final String htmlContent = DOCTYPE_HTML
732 + "<html>\n"
733 + "<head><title>foo</title></head>\n"
734 + "<body>\n"
735 + "<form name='one'>\n"
736 + "<a id='c' accesskey='c'>foo</a>\n"
737 + "</form>\n"
738 + "<form name='two'>\n"
739 + "<a id='c' accesskey='c'>foo</a>\n"
740 + "</form>\n"
741 + "<input name='foo' type='submit' disabled='disabled' id='foo' accesskey='f'/>\n"
742 + "<input name='bar' type='submit' id='bar'/>\n"
743 + "</form></body></html>";
744
745 final HtmlPage page = loadPage(htmlContent);
746
747 final List<HtmlForm> expectedForms = Arrays.asList(new HtmlForm[] {page.getFormByName("one"),
748 page.getFormByName("two")});
749 assertEquals(expectedForms, page.getForms());
750 }
751
752
753
754
755
756
757
758 @Test
759 public void refresh_ImmediateRefresh_AvoidOOME() throws Exception {
760 final String firstContent = DOCTYPE_HTML
761 + "<html><head><title>first</title>\n"
762 + "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"1\">\n"
763 + "</head><body></body></html>";
764
765 final WebClient client = getWebClient();
766 assertTrue(ImmediateRefreshHandler.class.isInstance(client.getRefreshHandler()));
767 try {
768 loadPage(firstContent);
769 Assertions.fail("should have thrown");
770 }
771 catch (final RuntimeException e) {
772 assertTrue(e.getMessage().indexOf("could have caused an OutOfMemoryError") > -1);
773 }
774 Thread.sleep(1000);
775 }
776
777
778
779
780 @Test
781 @Alerts("Too many redirects (>= 72) for §§URL§§")
782 public void refresh_EndlessLoop() throws Exception {
783 final String firstContent = DOCTYPE_HTML
784 + "<html><head><title>first</title>\n"
785 + "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\">\n"
786 + "</head><body></body></html>";
787
788 expandExpectedAlertsVariables(URL_FIRST);
789
790 final WebClient client = getWebClient();
791 client.setRefreshHandler(new WaitingRefreshHandler());
792 try {
793 loadPage(firstContent);
794 Assertions.fail("should have thrown");
795 }
796 catch (final FailingHttpStatusCodeException e) {
797 assertEquals(getExpectedAlerts()[0], e.getMessage());
798 }
799 }
800
801
802
803
804
805 @Test
806 public void refresh_MetaTagNoScript() throws Exception {
807 final String firstContent = DOCTYPE_HTML
808 + "<html><head><title>first</title>\n"
809 + "<noscript>\n"
810 + "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;URL=" + URL_SECOND + "\">\n"
811 + "</noscript>\n"
812 + "</head><body></body></html>";
813 final String secondContent = DOCTYPE_HTML + "<html><head><title>second</title></head><body></body></html>";
814
815 final WebClient client = getWebClient();
816
817 final MockWebConnection webConnection = new MockWebConnection();
818 webConnection.setResponse(URL_FIRST, firstContent);
819 webConnection.setResponse(URL_SECOND, secondContent);
820 client.setWebConnection(webConnection);
821
822 HtmlPage page = client.getPage(URL_FIRST);
823 assertEquals("first", page.getTitleText());
824
825 client.getOptions().setJavaScriptEnabled(false);
826 page = client.getPage(URL_FIRST);
827 assertEquals("second", page.getTitleText());
828 }
829
830
831
832
833
834 @Test
835 public void refresh_MetaTag_CustomRefreshHandler() throws Exception {
836 final String firstContent = DOCTYPE_HTML
837 + "<html><head><title>first</title>\n"
838 + "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"3;URL=" + URL_SECOND + "\">\n"
839 + "</head><body></body></html>";
840 final String secondContent = DOCTYPE_HTML + "<html><head><title>second</title></head><body></body></html>";
841
842 final WebClient client = getWebClient();
843 final List<Object> collectedItems = new ArrayList<>();
844 client.setRefreshHandler(new LoggingRefreshHandler(collectedItems));
845
846 final MockWebConnection webConnection = new MockWebConnection();
847 webConnection.setResponse(URL_FIRST, firstContent);
848 webConnection.setResponse(URL_SECOND, secondContent);
849 client.setWebConnection(webConnection);
850
851 final HtmlPage page = client.getPage(URL_FIRST);
852
853 assertEquals("first", page.getTitleText());
854
855
856 assertEquals("first", collectedItems.get(0));
857 assertEquals(URL_SECOND, (URL) collectedItems.get(1));
858 assertEquals(Integer.valueOf(3), collectedItems.get(2));
859 }
860
861
862
863
864
865 @Test
866 public void documentParentIsNull() throws Exception {
867 final String htmlContent = DOCTYPE_HTML
868 + "<html>\n"
869 + "<head><title>foo</title></head>\n"
870 + "<body>\n"
871 + "</body></html>";
872 final HtmlPage page = loadPage(htmlContent);
873
874 assertNotNull(page);
875 assertNull(page.getParentNode());
876 }
877
878
879
880
881 @Test
882 public void documentElement() throws Exception {
883 final String htmlContent = DOCTYPE_HTML
884 + "<html>\n"
885 + "<head><title>foo</title></head>\n"
886 + "<body>\n"
887 + "</body></html>";
888 final HtmlPage page = loadPage(htmlContent);
889
890 final DomElement root = page.getDocumentElement();
891
892 assertNotNull(root);
893 assertEquals("html", root.getTagName());
894 assertSame(page, root.getParentNode());
895 }
896
897
898
899
900 @Test
901 public void documentNodeType() throws Exception {
902 final String htmlContent = DOCTYPE_HTML
903 + "<html>\n"
904 + "<head><title>foo</title></head>\n"
905 + "<body>\n"
906 + "</body></html>";
907 final HtmlPage page = loadPage(htmlContent);
908
909 final DomElement root = page.getDocumentElement();
910
911 assertEquals(org.w3c.dom.Node.DOCUMENT_NODE, page.getNodeType());
912 assertEquals(org.w3c.dom.Node.ELEMENT_NODE, root.getNodeType());
913 assertEquals("#document", page.getNodeName());
914 }
915
916
917
918
919 @Test
920 public void deregisterFrameWithoutSrc() throws Exception {
921 final String htmlContent = DOCTYPE_HTML
922 + "<html>\n"
923 + "<head><title>foo</title></head>\n"
924 + "<body>\n"
925 + "<iframe></iframe>\n"
926 + "<a href='about:blank'>link</a>\n"
927 + "</body></html>";
928
929 final HtmlPage page = loadPage(htmlContent);
930 final HtmlAnchor link = page.getAnchors().get(0);
931 link.click();
932 }
933
934
935
936
937
938 @Test
939 public void onLoadReturn() throws Exception {
940 final String htmlContent = DOCTYPE_HTML
941 + "<html><head><title>foo</title></head>\n"
942 + "<body onload='return true'>\n"
943 + "</body></html>";
944
945 loadPage(htmlContent);
946 }
947
948
949
950
951 @Test
952 public void asXml() throws Exception {
953 final String htmlContent =
954 "<html><head><title>foo</title></head>"
955 + "<body><p>helloworld</p></body>"
956 + "</html>";
957
958 final HtmlPage page = loadPage(htmlContent);
959 String xml = page.asXml();
960 final String prefix = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
961 assertTrue(xml.startsWith(prefix));
962 xml = xml.substring(prefix.length());
963 assertEquals(htmlContent, xml.replaceAll("\\s", ""));
964 }
965
966
967
968
969
970 @Test
971 public void asXmlValidHtmlOutput() throws Exception {
972 final String html =
973 "<html><head><title>foo</title>"
974 + "<script src='script.js'></script></head>"
975 + "<body><div></div><iframe src='about:blank'></iframe></body>"
976 + "</html>";
977
978 final WebClient client = getWebClient();
979 final MockWebConnection webConnection = new MockWebConnection();
980 webConnection.setDefaultResponse(html);
981 webConnection.setResponse(new URL(URL_FIRST, "script.js"), "", "text/javascript");
982 client.setWebConnection(webConnection);
983
984 final HtmlPage page = client.getPage(URL_FIRST);
985
986 String xml = page.asXml();
987 final String prefix = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
988 assertTrue(xml.startsWith(prefix));
989 xml = xml.substring(prefix.length());
990 assertEquals(html, xml
991 .replaceAll("[\\n\\r]", "")
992 .replaceAll("\\s\\s+", "")
993 .replaceAll("\"", "'"));
994 }
995
996
997
998
999 @Test
1000 public void asXml2() throws Exception {
1001 final String htmlContent = DOCTYPE_HTML
1002 + "<html><head><title>foo</title>\n"
1003 + "<script>var test = 15 < 16;</script></head>\n"
1004 + "</head>\n"
1005 + "<body onload='test=(1 > 2) && (45 < 78)'><p>helloworld &amp; helloall</p></body>\n"
1006 + "</html>";
1007
1008 final HtmlPage page = loadPage(htmlContent);
1009 assertNotNull("xml document could not be parsed", page.asXml());
1010 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
1011 final DocumentBuilder builder = factory.newDocumentBuilder();
1012 builder.parse(IOUtils.toInputStream(page.asXml(), StandardCharsets.ISO_8859_1));
1013 }
1014
1015
1016
1017
1018 @Test
1019 public void asXml_unicode() throws Exception {
1020 final String unicodeString = "\u064A\u0627 \u0644\u064A\u064A\u0644";
1021 final String html = DOCTYPE_HTML
1022 + "<html>\n"
1023 + "<head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'></head>\n"
1024 + "<body><span id='foo'>" + unicodeString + "</span></body></html>";
1025
1026 final WebClient client = getWebClient();
1027 final MockWebConnection webConnection = new MockWebConnection();
1028
1029 webConnection.setDefaultResponse(StringUtils.toByteArray(html, UTF_8), 200, "OK", MimeType.TEXT_HTML);
1030 client.setWebConnection(webConnection);
1031
1032 final HtmlPage page = client.getPage(URL_FIRST);
1033 final String xml = page.asXml();
1034 assertTrue(xml.contains("<?xml "));
1035 assertTrue(xml.contains(unicodeString));
1036 }
1037
1038
1039
1040
1041 @Test
1042 public void asXml_noscript() throws Exception {
1043 final String html = DOCTYPE_HTML
1044 + "<html>"
1045 + "<body>"
1046 + "<noscript><p><strong>your browser does not support JavaScript</strong></p></noscript>"
1047 + "</body></html>";
1048
1049 final String expected = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\r\n"
1050 + "<html>\r\n"
1051 + " <head/>\r\n"
1052 + " <body>\r\n"
1053 + " <noscript>"
1054 + "<p><strong>your browser does not support JavaScript</strong></p>"
1055 + "</noscript>\r\n"
1056 + " </body>\r\n"
1057 + "</html>";
1058
1059 final HtmlPage page = loadPage(html);
1060 assertEquals(expected, page.asXml());
1061 }
1062
1063
1064
1065
1066 @Test
1067 public void getElementsById() throws Exception {
1068 final String html = DOCTYPE_HTML
1069 + "<html><body>"
1070 + "<div id='a'>foo</div>"
1071 + "<div id='b'/><div id='b'/>"
1072 + "<div id='c'><div id='c'/></div>"
1073 + "</body></html>";
1074 final HtmlPage page = loadPage(html);
1075 assertEquals(1, page.getElementsById("a").size());
1076 assertEquals(2, page.getElementsById("b").size());
1077 assertEquals(2, page.getElementsById("c").size());
1078 assertEquals(0, page.getElementsById("d").size());
1079
1080 final DomElement a = page.getElementsById("a").get(0);
1081 a.remove();
1082 assertEquals(0, page.getElementsById("a").size());
1083
1084 final DomElement b1 = page.getElementsById("b").get(0);
1085 b1.appendChild(a);
1086
1087 assertEquals(1, page.getElementsById("a").size());
1088 }
1089
1090
1091
1092
1093 @Test
1094 public void getElementsByName() throws Exception {
1095 final String html = DOCTYPE_HTML
1096 + "<html><body><div name='a'>foo</div><div name='b'/><div name='b'/></body></html>";
1097 final HtmlPage page = loadPage(html);
1098 assertEquals(1, page.getElementsByName("a").size());
1099 assertEquals(2, page.getElementsByName("b").size());
1100 assertEquals(0, page.getElementsByName("c").size());
1101
1102 final DomElement a = page.getElementsByName("a").get(0);
1103 a.remove();
1104 assertEquals(0, page.getElementsByName("a").size());
1105
1106 final DomElement b1 = page.getElementsByName("b").get(0);
1107 b1.appendChild(a);
1108 assertEquals(1, page.getElementsByName("a").size());
1109 }
1110
1111
1112
1113
1114 @Test
1115 public void getElementByName() throws Exception {
1116 final String html = DOCTYPE_HTML
1117 + "<html><body>\n"
1118 + "<div id='a' name='a'>foo</div>\n"
1119 + "<div id='b1' name='b'>bar</div>\n"
1120 + "<div id='b2' name='b'>baz</div></body></html>";
1121 final HtmlPage page = loadPage(html);
1122 assertEquals(page.getElementById("a"), page.getElementByName("a"));
1123 assertEquals(page.getElementById("b1"), page.getElementByName("b"));
1124
1125 page.getElementByName("b").remove();
1126 assertEquals(page.getElementById("b2"), page.getElementByName("b"));
1127 }
1128
1129
1130
1131
1132 @Test
1133 public void getElementByNameNotfound() throws Exception {
1134 final String html = DOCTYPE_HTML
1135 + "<html><body>\n"
1136 + "<div id='a' name='a'>foo</div>\n"
1137 + "<div id='b1' name='b'>bar</div>\n"
1138 + "<div id='b2' name='b'>baz</div></body></html>";
1139 final HtmlPage page = loadPage(html);
1140
1141 Assertions.assertThrows(ElementNotFoundException.class, () -> page.getElementByName("c"));
1142 }
1143
1144
1145
1146
1147 @Test
1148 public void getHtmlElementsByIdAndOrName() throws Exception {
1149 final String html = DOCTYPE_HTML
1150 + "<html><body><div name='a' id='a'>foo</div><div name='b' id='c'>bar</div>"
1151 + "<div name='b' id='d'>bar</div></body></html>";
1152 final HtmlPage page = loadPage(html);
1153 assertEquals(1, page.getElementsByIdAndOrName("a").size());
1154 assertEquals(2, page.getElementsByIdAndOrName("b").size());
1155 assertEquals(1, page.getElementsByIdAndOrName("c").size());
1156 assertEquals(1, page.getElementsByIdAndOrName("d").size());
1157
1158 final DomElement a = page.getElementsByIdAndOrName("a").get(0);
1159 a.remove();
1160 assertEquals(0, page.getElementsByIdAndOrName("a").size());
1161
1162 final DomElement b1 = page.getElementsByIdAndOrName("b").get(0);
1163 b1.appendChild(a);
1164 assertEquals(1, page.getElementsByIdAndOrName("a").size());
1165 }
1166
1167
1168
1169
1170
1171 @Test
1172 public void getHtmlElementByIdAfterRemove() throws Exception {
1173 final String htmlContent = DOCTYPE_HTML
1174 + "<html><head><title>foo</title></head>\n"
1175 + "<body>\n"
1176 + "<div id='div1'>\n"
1177 + "<div id='div2'>\n"
1178 + "</div>\n"
1179 + "</div>\n"
1180 + "</body>\n"
1181 + "</html>";
1182
1183 final HtmlPage page = loadPage(htmlContent);
1184 final HtmlElement div1 = page.getHtmlElementById("div1");
1185 page.getHtmlElementById("div2");
1186 div1.remove();
1187 try {
1188 page.getHtmlElementById("div1");
1189 Assertions.fail("div1 should have been removed");
1190 }
1191 catch (final ElementNotFoundException e) {
1192
1193 }
1194
1195 try {
1196 page.getHtmlElementById("div2");
1197 Assertions.fail("div2 should have been removed");
1198 }
1199 catch (final ElementNotFoundException e) {
1200
1201 }
1202 }
1203
1204
1205
1206
1207
1208
1209 @Test
1210 public void getHtmlElementById_idTwice() throws Exception {
1211 final String htmlContent = DOCTYPE_HTML
1212 + "<html><head><title>foo</title></head>\n"
1213 + "<body>\n"
1214 + "<div id='id1'>foo</div>\n"
1215 + "<span id='id1'>bla</span>\n"
1216 + "</body>\n"
1217 + "</html>";
1218
1219 final HtmlPage page = loadPage(htmlContent);
1220 final HtmlElement elt1 = page.getHtmlElementById("id1");
1221 assertEquals("div", elt1.getNodeName());
1222 elt1.remove();
1223 assertEquals("span", page.getHtmlElementById("id1").getNodeName());
1224 }
1225
1226
1227
1228
1229
1230 @Test
1231 @Alerts("webm=none")
1232 public void setCookieMetaTag() throws Exception {
1233 final String content = DOCTYPE_HTML
1234 + "<html><head>\n"
1235 + "<meta http-equiv='set-cookie' content='webm=none; path=/;'>\n"
1236 + "</head><body>\n"
1237 + "<script>document.title = document.cookie</script>\n"
1238 + "</body></html>";
1239
1240 final HtmlPage page = loadPage(content);
1241 assertEquals(getExpectedAlerts()[0], page.getTitleText());
1242
1243 final Set<Cookie> cookies = page.getWebClient().getCookieManager().getCookies();
1244 assertEquals(1, cookies.size());
1245 final Cookie cookie = cookies.iterator().next();
1246 assertEquals(page.getUrl().getHost(), cookie.getDomain());
1247 assertEquals("webm", cookie.getName());
1248 assertEquals("none", cookie.getValue());
1249 assertEquals("/", cookie.getPath());
1250 }
1251
1252
1253
1254
1255
1256 @Test
1257 public void noSlashURL() throws Exception {
1258 testNoSlashURL("http:/second");
1259 testNoSlashURL("http:second");
1260 }
1261
1262 private void testNoSlashURL(final String url) throws Exception {
1263 final String firstContent = DOCTYPE_HTML
1264 + "<html><body>\n"
1265 + "<iframe id='myIFrame' src='" + url + "'></iframe>\n"
1266 + "</body></html>";
1267
1268 final String secondContent = DOCTYPE_HTML + "<html><body></body></html>";
1269 final WebClient client = getWebClient();
1270
1271 final URL secondURL = new URL("http://second/");
1272 final MockWebConnection webConnection = new MockWebConnection();
1273 webConnection.setResponse(URL_FIRST, firstContent);
1274 webConnection.setResponse(secondURL, secondContent);
1275
1276 client.setWebConnection(webConnection);
1277
1278 final HtmlPage firstPage = client.getPage(URL_FIRST);
1279 final HtmlInlineFrame iframe = firstPage.getHtmlElementById("myIFrame");
1280
1281 assertEquals(secondURL, iframe.getEnclosedPage().getUrl());
1282 }
1283
1284
1285
1286
1287 @Test
1288 public void metaTagWithEmptyURL() throws Exception {
1289 final WebClient client = getWebClient();
1290 client.setRefreshHandler(new ImmediateRefreshHandler());
1291
1292
1293
1294 final MockWebConnection webConnection = new MockWebConnection() {
1295 private int nbCalls_ = 0;
1296 @Override
1297 public WebResponse getResponse(final WebRequest request) throws IOException {
1298 String content = DOCTYPE_HTML + "<html><head>\n";
1299 if (nbCalls_ == 0) {
1300 content += "<meta http-equiv='refresh' content='1; URL='>\n";
1301 }
1302 content += "</head><body></body></html>";
1303 nbCalls_++;
1304
1305 final StringWebResponse response = new StringWebResponse(content, request.getUrl());
1306 response.getWebRequest().setHttpMethod(request.getHttpMethod());
1307 return response;
1308 }
1309 };
1310 client.setWebConnection(webConnection);
1311
1312 final WebRequest request = new WebRequest(URL_FIRST);
1313 request.setHttpMethod(HttpMethod.POST);
1314 client.getPage(request);
1315 }
1316
1317
1318
1319
1320 @Test
1321 public void serialization() throws Exception {
1322
1323
1324
1325 final String content = DOCTYPE_HTML
1326 + "<html><body>\n"
1327 + "<div id='myId'>Hello there!</div>\n"
1328 + "<script>\n"
1329 + " var x = document.all;\n"
1330 + " window.onload = function() {alert('foo')};\n"
1331
1332
1333
1334 + " var aktiv = window.setInterval('foo()', 1000);\n"
1335 + " var i = 0;\n"
1336 + " function foo() {\n"
1337 + " i = i + 1;\n"
1338 + " if (i >= 10)\n"
1339 + " window.clearInterval(aktiv);\n"
1340 + " }\n"
1341 + "</script>\n"
1342 + "<form name='f' id='f'></form>\n"
1343 + "<script>var y = document.getElementById('f').elements;</script>\n"
1344 + "</body></html>";
1345
1346
1347
1348 final List<String> expectedAlerts = new LinkedList<>();
1349 expectedAlerts.add("foo");
1350
1351 final HtmlPage page1 = loadPage(content, expectedAlerts);
1352 final byte[] bytes = SerializationUtils.serialize(page1);
1353
1354 final HtmlPage page2 = (HtmlPage) SerializationUtils.deserialize(bytes);
1355
1356 final Iterator<HtmlElement> iterator1 = page1.getHtmlElementDescendants().iterator();
1357 final Iterator<HtmlElement> iterator2 = page2.getHtmlElementDescendants().iterator();
1358 while (iterator1.hasNext()) {
1359 assertTrue(iterator2.hasNext());
1360 final HtmlElement element1 = iterator1.next();
1361 final HtmlElement element2 = iterator2.next();
1362 assertEquals(element1.getNodeName(), element2.getNodeName());
1363 }
1364 assertFalse(iterator2.hasNext());
1365 assertEquals("Hello there!", page2.getHtmlElementById("myId").getFirstChild().getNodeValue());
1366 }
1367
1368
1369
1370
1371
1372 @Test
1373 public void serializationLambda() throws Exception {
1374 final String content = DOCTYPE_HTML
1375 + "<html><body>\n"
1376 + "<div id='myId'>Hello there!</div>\n"
1377 + "<form name='f' id='f'></form>\n"
1378 + "<script>var y = document.body.getElementsByTagName('form').elements;</script>\n"
1379 + "</body></html>";
1380
1381 final HtmlPage page1 = loadPage(content);
1382 final byte[] bytes = SerializationUtils.serialize(page1);
1383
1384 final HtmlPage page2 = (HtmlPage) SerializationUtils.deserialize(bytes);
1385
1386 final Iterator<HtmlElement> iterator1 = page1.getHtmlElementDescendants().iterator();
1387 final Iterator<HtmlElement> iterator2 = page2.getHtmlElementDescendants().iterator();
1388 while (iterator1.hasNext()) {
1389 assertTrue(iterator2.hasNext());
1390 final HtmlElement element1 = iterator1.next();
1391 final HtmlElement element2 = iterator2.next();
1392 assertEquals(element1.getNodeName(), element2.getNodeName());
1393 }
1394 assertFalse(iterator2.hasNext());
1395 assertEquals("Hello there!", page2.getHtmlElementById("myId").getFirstChild().getNodeValue());
1396 }
1397
1398
1399
1400
1401 @Test
1402 public void serializationStaticDomNodeList() throws Exception {
1403 final String content = DOCTYPE_HTML
1404 + "<html><body>\n"
1405 + "<div id='myId'>Hello there!</div>\n"
1406 + "<form name='f' id='f'></form>\n"
1407 + "<script>var y = document.querySelectorAll('*');</script>\n"
1408 + "</body></html>";
1409
1410 final HtmlPage page1 = loadPage(content);
1411 final byte[] bytes = SerializationUtils.serialize(page1);
1412
1413 final HtmlPage page2 = (HtmlPage) SerializationUtils.deserialize(bytes);
1414
1415 final Iterator<HtmlElement> iterator1 = page1.getHtmlElementDescendants().iterator();
1416 final Iterator<HtmlElement> iterator2 = page2.getHtmlElementDescendants().iterator();
1417 while (iterator1.hasNext()) {
1418 assertTrue(iterator2.hasNext());
1419 final HtmlElement element1 = iterator1.next();
1420 final HtmlElement element2 = iterator2.next();
1421 assertEquals(element1.getNodeName(), element2.getNodeName());
1422 }
1423 assertFalse(iterator2.hasNext());
1424 assertEquals("Hello there!", page2.getHtmlElementById("myId").getFirstChild().getNodeValue());
1425 }
1426
1427
1428
1429
1430
1431 @Test
1432 public void clonedPageHasOwnIdMap() throws Exception {
1433 final String content = DOCTYPE_HTML
1434 + "<html><head><title>foo</title>"
1435 + "<body>"
1436 + "<div id='id1' class='cl1'><div id='id2' class='cl2'></div></div>"
1437 + "</body></html>";
1438
1439 final HtmlPage page = loadPage(content);
1440 final HtmlElement id1 = (HtmlElement) page.getDocumentElement().getLastChild().getLastChild();
1441 assertEquals("id1", id1.getId());
1442 assertSame(id1, page.getHtmlElementById("id1"));
1443 final HtmlPage clone = page.cloneNode(true);
1444 assertSame(id1, page.getHtmlElementById("id1"));
1445 final HtmlElement id1clone = (HtmlElement) clone.getDocumentElement().getLastChild().getLastChild();
1446 assertNotSame(id1, id1clone);
1447 assertEquals("id1", id1clone.getId());
1448 assertSame(id1clone, clone.getHtmlElementById("id1"));
1449 assertNotSame(id1clone, page.getHtmlElementById("id1"));
1450 assertNotSame(id1, clone.getHtmlElementById("id1"));
1451
1452 page.getHtmlElementById("id2").remove();
1453 try {
1454 page.getHtmlElementById("id2");
1455 Assertions.fail("should have thrown ElementNotFoundException");
1456 }
1457 catch (final ElementNotFoundException expected) {
1458 }
1459 assertNotNull(clone.getHtmlElementById("id2"));
1460 }
1461
1462
1463
1464
1465
1466 @Test
1467 public void clonedPageHasOwnDocumentElement() throws Exception {
1468 final String content = DOCTYPE_HTML
1469 + "<html><head><title>foo</title>\n"
1470 + "<body>\n"
1471 + "<div id='id1' class='cl1'><div id='id2' class='cl2'></div></div>\n"
1472 + "</body></html>";
1473
1474 final HtmlPage page = loadPage(content);
1475 final HtmlPage clone = page.cloneNode(true);
1476 assertTrue(page != clone);
1477 final DomElement doc = page.getDocumentElement();
1478 final DomElement docclone = clone.getDocumentElement();
1479 assertTrue(doc != docclone);
1480 }
1481
1482
1483
1484
1485 @Test
1486 public void htmlAttributeChangeListener_AddAttribute() throws Exception {
1487 final String htmlContent = DOCTYPE_HTML
1488 + "<html><head><title>foo</title>\n"
1489 + "<script>\n"
1490 + " function clickMe() {\n"
1491 + " var p1 = document.getElementById('p1');\n"
1492 + " p1.setAttribute('title', 'myTitle');\n"
1493 + " }\n"
1494 + "</script>\n"
1495 + "</head>\n"
1496 + "<body>\n"
1497 + "<p id='p1'></p>\n"
1498 + "<input id='myButton' type='button' onclick='clickMe()'>\n"
1499 + "</body></html>";
1500
1501 final String[] expectedValues = {"attributeAdded: p,title,myTitle"};
1502 final HtmlPage page = loadPage(htmlContent);
1503 final HtmlAttributeChangeListenerTestImpl listenerImpl = new HtmlAttributeChangeListenerTestImpl();
1504 page.addHtmlAttributeChangeListener(listenerImpl);
1505 final HtmlButtonInput myButton = page.getHtmlElementById("myButton");
1506
1507 myButton.click();
1508 assertEquals(expectedValues, listenerImpl.getCollectedValues());
1509 }
1510
1511
1512
1513
1514 @Test
1515 public void htmlAttributeChangeListener_ReplaceAttribute() throws Exception {
1516 final String htmlContent = DOCTYPE_HTML
1517 + "<html><head><title>foo</title>\n"
1518 + "<script>\n"
1519 + " function clickMe() {\n"
1520 + " var p1 = document.getElementById('p1');\n"
1521 + " p1.setAttribute('title', p1.getAttribute('title') + 'a');\n"
1522 + " }\n"
1523 + "</script>\n"
1524 + "</head>\n"
1525 + "<body>\n"
1526 + "<p id='p1' title='myTitle'></p>\n"
1527 + "<input id='myButton' type='button' onclick='clickMe()'>\n"
1528 + "</body></html>";
1529
1530 final String[] expectedValues = {"attributeReplaced: p,title,myTitle"};
1531 final HtmlPage page = loadPage(htmlContent);
1532 final HtmlAttributeChangeListenerTestImpl listenerImpl = new HtmlAttributeChangeListenerTestImpl();
1533 page.addHtmlAttributeChangeListener(listenerImpl);
1534 final HtmlButtonInput myButton = page.getHtmlElementById("myButton");
1535
1536 myButton.click();
1537 assertEquals(expectedValues, listenerImpl.getCollectedValues());
1538 }
1539
1540
1541
1542
1543 @Test
1544 public void htmlAttributeChangeListener_RemoveAttribute() throws Exception {
1545 final String htmlContent = DOCTYPE_HTML
1546 + "<html><head><title>foo</title>\n"
1547 + "<script>\n"
1548 + " function clickMe() {\n"
1549 + " var p1 = document.getElementById('p1');\n"
1550 + " p1.removeAttribute('title');\n"
1551 + " }\n"
1552 + "</script>\n"
1553 + "</head>\n"
1554 + "<body>\n"
1555 + "<p id='p1' title='myTitle'></p>\n"
1556 + "<input id='myButton' type='button' onclick='clickMe()'>\n"
1557 + "</body></html>";
1558
1559 final String[] expectedValues = {"attributeRemoved: p,title,myTitle"};
1560 final HtmlPage page = loadPage(htmlContent);
1561 final HtmlAttributeChangeListenerTestImpl listenerImpl = new HtmlAttributeChangeListenerTestImpl();
1562 page.addHtmlAttributeChangeListener(listenerImpl);
1563 final HtmlButtonInput myButton = page.getHtmlElementById("myButton");
1564
1565 myButton.click();
1566 assertEquals(expectedValues, listenerImpl.getCollectedValues());
1567 }
1568
1569
1570
1571
1572 @Test
1573 public void htmlAttributeChangeListener_RemoveListener() throws Exception {
1574 final String htmlContent = DOCTYPE_HTML
1575 + "<html><head><title>foo</title>\n"
1576 + "<script>\n"
1577 + " function clickMe() {\n"
1578 + " var p1 = document.getElementById('p1');\n"
1579 + " p1.setAttribute('title', p1.getAttribute('title') + 'a');\n"
1580 + " }\n"
1581 + "</script>\n"
1582 + "</head>\n"
1583 + "<body>\n"
1584 + "<p id='p1' title='myTitle'></p>\n"
1585 + "<input id='myButton' type='button' onclick='clickMe()'>\n"
1586 + "</body></html>";
1587
1588 final String[] expectedValues = {"attributeReplaced: p,title,myTitle"};
1589 final HtmlPage page = loadPage(htmlContent);
1590 final HtmlAttributeChangeListenerTestImpl listenerImpl = new HtmlAttributeChangeListenerTestImpl();
1591 page.addHtmlAttributeChangeListener(listenerImpl);
1592 final HtmlButtonInput myButton = page.getHtmlElementById("myButton");
1593
1594 myButton.click();
1595 page.removeHtmlAttributeChangeListener(listenerImpl);
1596 myButton.click();
1597 assertEquals(expectedValues, listenerImpl.getCollectedValues());
1598 }
1599
1600
1601
1602
1603 @Test
1604 public void htmlAttributeChangeListener_ListenerRegistersNewListener() throws Exception {
1605 final String htmlContent = DOCTYPE_HTML
1606 + "<html><head><title>foo</title>\n"
1607 + "</head>\n"
1608 + "<body>\n"
1609 + "<p id='p1' title='myTitle'></p>\n"
1610 + "</body></html>";
1611
1612 final HtmlPage page = loadPage(htmlContent);
1613
1614 final List<String> collector = new ArrayList<>();
1615 final HtmlAttributeChangeListener listener2 = new HtmlAttributeChangeListenerTestImpl() {
1616 @Override
1617 public void attributeReplaced(final HtmlAttributeChangeEvent event) {
1618 collector.add("in listener 2");
1619 }
1620 };
1621 final HtmlAttributeChangeListener listener1 = new HtmlAttributeChangeListenerTestImpl() {
1622 @Override
1623 public void attributeReplaced(final HtmlAttributeChangeEvent event) {
1624 collector.add("in listener 1");
1625 page.addHtmlAttributeChangeListener(listener2);
1626 }
1627 };
1628
1629 page.addHtmlAttributeChangeListener(listener1);
1630
1631 final HtmlElement p = page.getHtmlElementById("p1");
1632 p.setAttribute("title", "new title");
1633
1634 final String[] expectedValues = {"in listener 1"};
1635 assertEquals(expectedValues, collector);
1636 collector.clear();
1637
1638 p.setAttribute("title", "new new title");
1639 final String[] expectedValues2 = {"in listener 1", "in listener 2"};
1640 assertEquals(expectedValues2, collector);
1641 }
1642
1643
1644
1645
1646 @Test
1647 public void caseInsensitiveRegexReplacement() throws Exception {
1648 final String html = DOCTYPE_HTML
1649 + "<html><body><script>\n"
1650 + "var r = /^([#.]?)([a-z0-9\\*_-]*)/i;\n"
1651 + "var s = '#userAgent';\n"
1652 + "s = s.replace(r, '');\n"
1653 + "alert(s.length);\n"
1654 + "</script></body></html>";
1655 final String[] expectedAlerts = {"0"};
1656 final List<String> actualAlerts = new ArrayList<>();
1657 loadPage(html, actualAlerts);
1658 assertEquals(expectedAlerts, actualAlerts);
1659 }
1660
1661
1662
1663
1664 @Test
1665 public void regexReplacementWithFunction() throws Exception {
1666 final String html = DOCTYPE_HTML
1667 + "<html><body><script>\n"
1668 + "var r = /-([a-z])/ig;\n"
1669 + "var s = 'font-size';\n"
1670 + "s = s.replace(r, function(z,b){return b.toUpperCase();});\n"
1671 + "alert(s);\n"
1672 + "</script></body></html>";
1673 final String[] expectedAlerts = {"fontSize"};
1674 final List<String> collectedAlerts = new ArrayList<>();
1675 loadPage(html, collectedAlerts);
1676 assertEquals(expectedAlerts, collectedAlerts);
1677 }
1678
1679
1680
1681
1682 @Test
1683 public void title_EmptyXmlTagExpanded() throws Exception {
1684 final String content = DOCTYPE_HTML
1685 + "<html><head><title/></head>\n"
1686 + "<body>Hello World!</body></html>";
1687 final HtmlPage page = loadPage(content);
1688 assertTrue(page.asXml().indexOf("</title>") != -1);
1689 }
1690
1691
1692
1693
1694 @Test
1695 public void onunLoadHandler() throws Exception {
1696 final String htmlContent = DOCTYPE_HTML
1697 + "<html><head><title>foo</title>\n"
1698 + "</head><body onunload='alert(\"foo\");alert(\"bar\")'>\n"
1699 + "</body></html>";
1700
1701 final String[] expectedAlerts = {"foo", "bar"};
1702 final List<String> collectedAlerts = new ArrayList<>();
1703 final WebClient client = getWebClient();
1704 client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
1705 final MockWebConnection conn = new MockWebConnection();
1706 conn.setResponse(URL_FIRST, htmlContent);
1707 client.setWebConnection(conn);
1708
1709 client.getPage(URL_FIRST);
1710 client.getPage(URL_FIRST);
1711
1712 assertEquals(expectedAlerts, collectedAlerts);
1713 }
1714
1715
1716
1717
1718 @Test
1719 public void onbeforeunloadHandler_ok() throws Exception {
1720 testOnbeforeunloadHandler(true, "second");
1721 }
1722
1723
1724
1725
1726 @Test
1727 public void onbeforeunloadHandler_cancel() throws Exception {
1728 testOnbeforeunloadHandler(false, "first");
1729 }
1730
1731
1732
1733
1734
1735
1736 private void testOnbeforeunloadHandler(final boolean handlerOk, final String expectedPageTitle) throws Exception {
1737 final WebClient webClient = getWebClient();
1738 final MockWebConnection webConnection = new MockWebConnection();
1739 final List<String> collectedConfirms = new ArrayList<>();
1740
1741 webClient.setOnbeforeunloadHandler(new OnbeforeunloadHandler() {
1742 @Override
1743 public boolean handleEvent(final Page page, final String message) {
1744 collectedConfirms.add(message);
1745 return handlerOk;
1746 }
1747 });
1748
1749 final String expectedMessage = "Any string value here forces a dialog box to appear before closing the window.";
1750 final String firstContent = DOCTYPE_HTML
1751 + "<html><head><title>first</title>\n"
1752 + "<script>\n"
1753 + " function closeIt(event) {\n"
1754 + " event.returnValue = '" + expectedMessage + "';\n"
1755 + " }\n"
1756 + "</script>\n"
1757 + "</head><body onbeforeunload='closeIt(event)'>\n"
1758 + " <a href='" + URL_SECOND + "'>Second page</a>\n"
1759 + "</body></html>";
1760
1761 final String secondContent = DOCTYPE_HTML
1762 + "<html><head><title>second</title>\n"
1763 + "</head><body>\n"
1764 + "</body></html>";
1765
1766 webConnection.setResponse(URL_FIRST, firstContent);
1767 webConnection.setResponse(URL_SECOND, secondContent);
1768 webClient.setWebConnection(webConnection);
1769
1770 final HtmlPage page = webClient.getPage(URL_FIRST);
1771 final HtmlAnchor anchor = page.getAnchors().get(0);
1772 final HtmlPage secondPage = anchor.click();
1773
1774 assertEquals(new String[] {expectedMessage}, collectedConfirms);
1775 assertEquals(expectedPageTitle, secondPage.getTitleText());
1776 }
1777
1778
1779
1780
1781 @Test
1782 public void srcJavaScript() throws Exception {
1783 final String htmlContent = DOCTYPE_HTML
1784 + "<html><head><title>foo</title></head><body>\n"
1785 + "<script id='ie_ready' src='javascript:void(0)'></script>\n"
1786 + "</body></html>";
1787
1788 loadPage(htmlContent);
1789 }
1790
1791
1792
1793
1794
1795
1796 @Test
1797 public void asNormalizedText() throws Exception {
1798 final String htmlContent = DOCTYPE_HTML
1799 + "<html><head><title>test</title></head>\n"
1800 + "<body><table>\n"
1801 + "<tr><form><td>a</td></form></tr>\n"
1802 + "</table></body></html>";
1803
1804 final HtmlPage page = loadPage(htmlContent);
1805 assertEquals("test\na", page.asNormalizedText());
1806 }
1807
1808
1809
1810
1811 @Test
1812 public void getElementsByTagName() throws Exception {
1813 final String firstContent = DOCTYPE_HTML
1814 + "<html><head><title>First</title></head>\n"
1815 + "<body>\n"
1816 + "<form><input type='button' name='button1' value='pushme'></form>\n"
1817 + "<div>a</div> <div>b</div> <div>c</div>\n"
1818 + "</body></html>";
1819
1820 final HtmlPage page = loadPage(firstContent);
1821
1822 NodeList inputs = page.getElementsByTagName("input");
1823 assertEquals(1, inputs.getLength());
1824 assertEquals("button", inputs.item(0).getAttributes().getNamedItem("type").getNodeValue());
1825
1826 final NodeList divs = page.getElementsByTagName("div");
1827 assertEquals(3, divs.getLength());
1828
1829 final HtmlDivision newDiv = new HtmlDivision(HtmlDivision.TAG_NAME, page, null);
1830 page.getBody().appendChild(newDiv);
1831 assertEquals(4, divs.getLength());
1832
1833
1834 inputs = page.getElementsByTagName("inPUT");
1835 assertEquals(1, inputs.getLength());
1836
1837
1838 inputs = page.getElementsByTagName("");
1839 assertEquals(0, inputs.getLength());
1840
1841
1842 inputs = page.getElementsByTagName(null);
1843 assertEquals(0, inputs.getLength());
1844 }
1845
1846
1847
1848
1849
1850
1851 @Test
1852 public void readyState() throws Exception {
1853 final String htmlContent = DOCTYPE_HTML
1854 + "<html><head><title>test</title></head>\n"
1855 + "<body><table>\n"
1856 + "<tr><form><td>a</td></form></tr>\n"
1857 + "</table></body></html>";
1858
1859 final HtmlPage page = loadPage(htmlContent);
1860 assertEquals(DomNode.READY_STATE_COMPLETE, page.getReadyState());
1861 }
1862
1863
1864
1865
1866 @Test
1867 public void cloneNode() throws Exception {
1868 final String html = DOCTYPE_HTML
1869 + "<html>\n"
1870 + "<head><title>foo</title></head>\n"
1871 + "<body>\n"
1872 + "<p>hello world</p>\n"
1873 + "</body></html>";
1874 final HtmlPage page = loadPage(html);
1875 page.getByXPath("//p");
1876 final HtmlPage clonedPage = page.cloneNode(true);
1877 clonedPage.getByXPath("//p");
1878 }
1879
1880
1881
1882
1883 @Test
1884 public void cloneHtmlPageWithFrame() throws Exception {
1885 final String html = DOCTYPE_HTML
1886 + "<html>\n"
1887 + "<head></head><body>\n"
1888 + "<div id='content'>"
1889 + " <iframe name='content' src='frame1.html'></iframe>"
1890 + "</div>"
1891 + "</body></html>";
1892
1893 final String frameContent = DOCTYPE_HTML
1894 + "<html>\n"
1895 + "<head></head>\n"
1896 + "<body>"
1897 + " <p>frame1</p>"
1898 + "</body></html>";
1899
1900 final MockWebConnection webConnection = getMockWebConnection();
1901 webConnection.setResponse(new URL("http://example/index.html"), html);
1902 webConnection.setResponse(new URL("http://example/frame1.html"), frameContent);
1903
1904 final WebClient webClient = getWebClientWithMockWebConnection();
1905
1906 final HtmlPage page = webClient.getPage("http://example/index.html");
1907
1908
1909 final List<FrameWindow> frames = page.getFrames();
1910 assertEquals(1, frames.size());
1911 assertEquals("frame1", ((HtmlPage) frames.get(0).getEnclosedPage()).asNormalizedText());
1912
1913
1914 HtmlPage clonedPage = page.cloneNode(false);
1915
1916 assertEquals(1, page.getFrames().size());
1917 assertEquals(1, clonedPage.getFrames().size());
1918
1919
1920 clonedPage = page.cloneNode(true);
1921
1922
1923 assertEquals(1, page.getFrames().size());
1924 assertEquals(1, clonedPage.getFrames().size());
1925
1926
1927 page.executeJavaScript("document.cloneNode(true)");
1928
1929
1930 assertEquals(1, page.getFrames().size());
1931 assertEquals(1, clonedPage.getFrames().size());
1932 }
1933
1934
1935
1936
1937 @Test
1938 public void addAutoCloseable() throws Exception {
1939 final String html = "";
1940 final HtmlPage page = loadPage(html);
1941 page.addAutoCloseable(new AutoCloseable() {
1942 @Override
1943 public void close() throws Exception {
1944 page.addAutoCloseable(new AutoCloseable() {
1945 @Override
1946 public void close() throws Exception {
1947 throw new NullPointerException("close failed");
1948 }
1949 });
1950 }
1951 });
1952 page.cleanUp();
1953 }
1954
1955
1956
1957
1958 @Test
1959 public void addAutoCloseableNull() throws Exception {
1960 final String html = "";
1961 final HtmlPage page = loadPage(html);
1962 page.addAutoCloseable(null);
1963 page.cleanUp();
1964 }
1965
1966
1967
1968
1969 @Test
1970 public void getBaseUrl() throws Exception {
1971 final String html = DOCTYPE_HTML
1972 + "<html>\n"
1973 + "<head></head>\n"
1974 + "<body>body</body>\n"
1975 + "</html>";
1976
1977 HtmlPage page = loadPage(getBrowserVersion(), html, null, URL_FIRST);
1978 assertEquals(URL_FIRST.toExternalForm(), page.getBaseURL().toExternalForm());
1979
1980
1981 String path = "details/abc";
1982 page = loadPage(getBrowserVersion(), html, null, new URL(URL_FIRST.toString() + path));
1983 assertEquals(URL_FIRST.toExternalForm() + path, page.getBaseURL().toExternalForm());
1984
1985 path = "details/abc?x=y&z=z";
1986 page = loadPage(getBrowserVersion(), html, null, new URL(URL_FIRST.toString() + path));
1987 assertEquals(URL_FIRST.toExternalForm() + path, page.getBaseURL().toExternalForm());
1988
1989 path = "details/abc;jsessionid=42?x=y&z=z";
1990 page = loadPage(getBrowserVersion(), html, null, new URL(URL_FIRST.toString() + path));
1991 assertEquals(URL_FIRST.toExternalForm() + path, page.getBaseURL().toExternalForm());
1992 }
1993 }