View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.html;
16  
17  import static org.junit.jupiter.api.Assertions.fail;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.htmlunit.SimpleWebTestCase;
23  import org.htmlunit.WebClient;
24  import org.htmlunit.junit.annotation.Alerts;
25  import org.junit.jupiter.api.Test;
26  import org.w3c.dom.NodeList;
27  
28  /**
29   * Unit tests for {@link HtmlElement}.
30   *
31   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
32   * @author Denis N. Antonioli
33   * @author Daniel Gredler
34   * @author Ahmed Ashour
35   * @author Sudhan Moghe
36   * @author Frank Danek
37   * @author Ronald Brill
38   * @author Lai Quang Duong
39   */
40  public class HtmlElementTest extends SimpleWebTestCase {
41  
42      /**
43       * Test hasAttribute() on an element with the attribute.
44       * @throws Exception if the test fails
45       */
46      @Test
47      public void hasAttributeWith() throws Exception {
48          final String html = DOCTYPE_HTML + "<html><head></head><body id='tag'>text</body></html>";
49          final HtmlPage page = loadPage(html);
50  
51          final HtmlElement node = page.getHtmlElementById("tag");
52          assertTrue("Element should have attribute", node.hasAttribute("id"));
53      }
54  
55      /**
56       * Test hasAttribute() on an element with the attribute but without a value.
57       * @throws Exception if the test fails
58       */
59      @Test
60      public void hasAttributeWithMissingValue() throws Exception {
61          final String html = DOCTYPE_HTML + "<html><head></head><body id='tag' attrib>text</body></html>";
62          final HtmlPage page = loadPage(html);
63  
64          final HtmlElement node = page.getHtmlElementById("tag");
65          assertTrue("Element should have attribute", node.hasAttribute("attrib"));
66      }
67  
68      /**
69       * Test hasAttribute() on an element without the attributes.
70       * @throws Exception if the test fails
71       */
72      @Test
73      public void hasAttributeNone() throws Exception {
74          final String html = DOCTYPE_HTML + "<html><head></head><body id='tag'>text</body></html>";
75          final HtmlPage page = loadPage(html);
76  
77          final HtmlElement node = page.getHtmlElementById("tag");
78          assertFalse("Element should not have attribute", node.hasAttribute("foo"));
79      }
80  
81      /**
82       * Test hasAttribute() on an element with the attribute.
83       * @throws Exception if the test fails
84       */
85      @Test
86      public void hasAttributeNSWith() throws Exception {
87          final String html = DOCTYPE_HTML
88              + "<html><head></head><body xmlns:ns='http://foobar' id='tag' ns:foo='bar'>text</body></html>";
89          final HtmlPage page = loadPage(html);
90  
91          final HtmlElement node = page.getHtmlElementById("tag");
92          assertTrue("Element should have attribute", node.hasAttributeNS("http://foobar", "foo"));
93      }
94  
95      /**
96       * Test hasAttribute() on an element without the attributes.
97       * @throws Exception if the test fails
98       */
99      @Test
100     public void hasAttributeNSNone() throws Exception {
101         final String html = DOCTYPE_HTML + "<html><head></head><body id='tag'>text</body></html>";
102         final HtmlPage page = loadPage(html);
103 
104         final HtmlElement node = page.getHtmlElementById("tag");
105         assertFalse("Element should not have attribute", node.hasAttributeNS("http://foobar", "foo"));
106     }
107 
108     /**
109      * Test getAttribute() on an element with the attribute.
110      * @throws Exception if the test fails
111      */
112     @Test
113     public void getAttributeWith() throws Exception {
114         final String html = DOCTYPE_HTML + "<html><head></head><body id='tag'>text</body></html>";
115         final HtmlPage page = loadPage(html);
116 
117         final HtmlElement node = page.getHtmlElementById("tag");
118         assertEquals("Element should have attribute", "tag", node.getId());
119     }
120 
121     /**
122      * Test getAttribute() on an element with the attribute but without a value.
123      * @throws Exception if the test fails
124      */
125     @Test
126     public void getAttributeWithMissingValue() throws Exception {
127         final String html = DOCTYPE_HTML + "<html><head></head><body id='tag' attrib>text</body></html>";
128         final HtmlPage page = loadPage(html);
129 
130         final HtmlElement node = page.getHtmlElementById("tag");
131         assertEquals("", node.getAttribute("attrib"));
132         assertTrue(DomElement.ATTRIBUTE_VALUE_EMPTY == node.getAttribute("attrib"));
133     }
134 
135     /**
136      * Test getAttribute() on an element with the attribute but without a value.
137      * @throws Exception if the test fails
138      */
139     @Test
140     public void getAttributeWithEmptyValue() throws Exception {
141         final String html = DOCTYPE_HTML + "<html><head></head><body id='tag' attrib=''>text</body></html>";
142         final HtmlPage page = loadPage(html);
143 
144         final HtmlElement node = page.getHtmlElementById("tag");
145         assertEquals("", node.getAttribute("attrib"));
146         assertTrue(DomElement.ATTRIBUTE_VALUE_EMPTY == node.getAttribute("attrib"));
147     }
148 
149     /**
150      * Test getAttribute() on an element without the attributes.
151      * @throws Exception if the test fails
152      */
153     @Test
154     public void getAttributeNone() throws Exception {
155         final String html = DOCTYPE_HTML + "<html><head></head><body id='tag'>text</body></html>";
156         final HtmlPage page = loadPage(html);
157 
158         final HtmlElement node = page.getHtmlElementById("tag");
159         assertEquals("Element should not have attribute", "", node.getAttribute("foo"));
160     }
161 
162     /**
163      * Test getAttribute() on an element with the attribute.
164      * @throws Exception if the test fails
165      */
166     @Test
167     public void getAttributeNSWith() throws Exception {
168         final String html = DOCTYPE_HTML
169             + "<html><head></head><body xmlns:ns='http://foobar' id='tag' ns:foo='bar'>text</body></html>";
170         final HtmlPage page = loadPage(html);
171 
172         final HtmlElement node = page.getHtmlElementById("tag");
173         assertEquals("Element should have attribute", "bar", node.getAttributeNS("http://foobar", "foo"));
174     }
175 
176     /**
177      * Test getAttribute() on an element without the attributes.
178      * @throws Exception if the test fails
179      */
180     @Test
181     public void getAttributeNSNone() throws Exception {
182         final String html = DOCTYPE_HTML + "<html><head></head><body id='tag'>text</body></html>";
183         final HtmlPage page = loadPage(html);
184 
185         final HtmlElement node = page.getHtmlElementById("tag");
186         assertEquals("Element should not have attribute", "", node.getAttributeNS("http://foobar", "foo"));
187     }
188 
189     /**
190      * Test getNamespaceURI on an attribute that has a namespace.
191      * @throws Exception if the test fails
192      */
193     @Test
194     public void getNamespaceURIWith() throws Exception {
195         final String html = DOCTYPE_HTML
196             + "<html><head></head><body xmlns:ns='http://foobar' id='tag' ns:foo='bar'>text</body></html>";
197         final HtmlPage page = loadPage(html);
198 
199         final HtmlElement node = page.getHtmlElementById("tag");
200         for (final DomAttr attr : node.getAttributesMap().values()) {
201             if ("ns:foo".equals(attr.getName())) {
202                 assertEquals("Element should have a namespace URI", "http://foobar", attr.getNamespaceURI());
203                 return;
204             }
205         }
206         fail("Attribute ns:foo not found.");
207     }
208 
209     /**
210      * Test getNamespaceURI on an attribute that has a namespace.
211      * @throws Exception if the test fails
212      */
213     @Test
214     public void getNamespaceURINone() throws Exception {
215         final String html = DOCTYPE_HTML
216             + "<html><head></head><body xmlns:ns='http://foobar' id='tag' ns:foo='bar'>text</body></html>";
217         final HtmlPage page = loadPage(html);
218 
219         final HtmlElement node = page.getHtmlElementById("tag");
220         for (final DomAttr attr : node.getAttributesMap().values()) {
221             if ("id".equals(attr.getName())) {
222                 assertEquals("Element should not have a namespace URI", null, attr.getNamespaceURI());
223                 return;
224             }
225         }
226         fail("Attribute ns:foo not found.");
227     }
228 
229     /**
230      * Test getLocalName on an attribute that has a local name.
231      * @throws Exception if the test fails
232      */
233     @Test
234     public void getLocalNameWith() throws Exception {
235         final String html = DOCTYPE_HTML
236             + "<html><head></head><body xmlns:ns='http://foobar' id='tag' ns:foo='bar'>text</body></html>";
237         final HtmlPage page = loadPage(html);
238 
239         final HtmlElement node = page.getHtmlElementById("tag");
240         for (final DomAttr attr : node.getAttributesMap().values()) {
241             if ("ns:foo".equals(attr.getName())) {
242                 assertEquals("Element should have a local name", "foo", attr.getLocalName());
243                 return;
244             }
245         }
246         fail("Attribute ns:foo not found.");
247     }
248 
249     /**
250      * Test getLocalName on an attribute that has a local name.
251      * @throws Exception if the test fails
252      */
253     @Test
254     public void getLocalNameNone() throws Exception {
255         final String html = DOCTYPE_HTML
256             + "<html><head></head><body xmlns:ns='http://foobar' id='tag' ns:foo='bar'>text</body></html>";
257         final HtmlPage page = loadPage(html);
258 
259         final HtmlElement node = page.getHtmlElementById("tag");
260         for (final DomAttr attr : node.getAttributesMap().values()) {
261             if ("id".equals(attr.getName())) {
262                 // This is not standard, but to change it now would break backwards compatibility.
263                 assertEquals("Element should not have a local name", "id", attr.getLocalName());
264                 return;
265             }
266         }
267         fail("Attribute ns:foo not found.");
268     }
269 
270     /**
271      * Test getPrefix on an attribute that has a prefix.
272      * @throws Exception if the test fails
273      */
274     @Test
275     public void getPrefixWith() throws Exception {
276         final String html = DOCTYPE_HTML
277             + "<html><head></head><body xmlns:ns='http://foobar' id='tag' ns:foo='bar'>text</body></html>";
278         final HtmlPage page = loadPage(html);
279 
280         final HtmlElement node = page.getHtmlElementById("tag");
281         for (final DomAttr attr : node.getAttributesMap().values()) {
282             if ("ns:foo".equals(attr.getName())) {
283                 assertEquals("Element should have a prefix", "ns", attr.getPrefix());
284                 return;
285             }
286         }
287         fail("Attribute ns:foo not found.");
288     }
289 
290     /**
291      * Test getPrefix on an attribute that has a prefix.
292      * @throws Exception if the test fails
293      */
294     @Test
295     public void getPrefixNone() throws Exception {
296         final String html = DOCTYPE_HTML
297             + "<html><head></head><body xmlns:ns='http://foobar' id='tag' ns:foo='bar'>text</body></html>";
298         final HtmlPage page = loadPage(html);
299 
300         final HtmlElement node = page.getHtmlElementById("tag");
301         for (final DomAttr attr : node.getAttributesMap().values()) {
302             if ("id".equals(attr.getName())) {
303                 assertEquals("Element should not have a prefix", null, attr.getPrefix());
304                 return;
305             }
306         }
307         fail("Attribute ns:foo not found.");
308     }
309 
310     /**
311      * Test setPrefix on an attribute that has a prefix.
312      * @throws Exception if the test fails
313      */
314     @Test
315     public void setPrefix() throws Exception {
316         final String html = DOCTYPE_HTML
317             + "<html><head></head><body xmlns:ns='http://foobar' id='tag' ns:foo='bar'>text</body></html>";
318         final HtmlPage page = loadPage(html);
319 
320         final HtmlElement node = page.getHtmlElementById("tag");
321         for (final DomAttr attr : node.getAttributesMap().values()) {
322             if ("ns:foo".equals(attr.getName())) {
323                 attr.setPrefix("other");
324                 assertEquals("Element should have a changed prefix", "other", attr.getPrefix());
325                 assertEquals("setPrefix should change qualified name", "other:foo", attr.getName());
326                 return;
327             }
328         }
329         fail("Attribute ns:foo not found.");
330     }
331 
332     /**
333      * Test setAttribute() on an element with the attribute.
334      * @throws Exception if the test fails
335      */
336     @Test
337     public void setAttributeWith() throws Exception {
338         final String html = DOCTYPE_HTML
339             + "<html><head></head><body id='tag'>text</body></html>";
340         final HtmlPage page = loadPage(html);
341 
342         final HtmlElement node = page.getHtmlElementById("tag");
343         node.setAttribute("id", "other");
344         assertEquals("Element should have attribute", "other", node.getId());
345     }
346 
347     /**
348      * Test setAttribute() on an element without the attributes.
349      * @throws Exception if the test fails
350      */
351     @Test
352     public void setAttributeNone() throws Exception {
353         final String html = DOCTYPE_HTML
354             + "<html><head></head><body id='tag'>text</body></html>";
355         final HtmlPage page = loadPage(html);
356 
357         final HtmlElement node = page.getHtmlElementById("tag");
358         node.setAttribute("foo", "other");
359         assertEquals("Element should have attribute", "other", node.getAttribute("foo"));
360     }
361 
362     /**
363      * Test setAttribute() on an element with the attribute.
364      * @throws Exception if the test fails
365      */
366     @Test
367     public void setAttributeNSWith() throws Exception {
368         final String html = DOCTYPE_HTML
369             + "<html><head></head><body xmlns:ns='http://foobar' id='tag' ns:foo='bar'>text</body></html>";
370         final HtmlPage page = loadPage(html);
371 
372         final HtmlElement node = page.getHtmlElementById("tag");
373         node.setAttributeNS("http://foobar", "ns:foo", "other");
374         assertEquals("Element should have attribute", "other", node.getAttributeNS("http://foobar", "foo"));
375     }
376 
377     /**
378      * Test setAttribute() on an element without the attributes.
379      * @throws Exception if the test fails
380      */
381     @Test
382     public void setAttributeNSNone() throws Exception {
383         final String html = DOCTYPE_HTML
384             + "<html><head></head><body id='tag'>text</body></html>";
385         final HtmlPage page = loadPage(html);
386 
387         final HtmlElement node = page.getHtmlElementById("tag");
388         node.setAttributeNS("http://foobar", "ns:foo", "other");
389         assertEquals("Element should not have attribute", "other", node.getAttributeNS("http://foobar", "foo"));
390     }
391 
392     /**
393      * Test removeAttribute() on an element with the attribute.
394      * @throws Exception if the test fails
395      */
396     @Test
397     public void removeAttributeWith() throws Exception {
398         final String html = DOCTYPE_HTML
399             + "<html><head></head><body id='tag'>text</body></html>";
400         final HtmlPage page = loadPage(html);
401 
402         final HtmlElement node = page.getHtmlElementById("tag");
403         node.removeAttribute("id");
404         assertEquals("Element should not have removed attribute", "", node.getId());
405     }
406 
407     /**
408      * Test removeAttribute() on an element without the attributes.
409      * @throws Exception if the test fails
410      */
411     @Test
412     public void removeAttributeNone() throws Exception {
413         final String html = DOCTYPE_HTML
414             + "<html><head></head><body id='tag'>text</body></html>";
415         final HtmlPage page = loadPage(html);
416 
417         final HtmlElement node = page.getHtmlElementById("tag");
418         node.removeAttribute("foo");
419         assertEquals("Element should not have attribute", "", node.getAttribute("foo"));
420     }
421 
422     /**
423      * Test removeAttribute() on an element with the attribute.
424      * @throws Exception if the test fails
425      */
426     @Test
427     public void removeAttributeNSWith() throws Exception {
428         final String html = DOCTYPE_HTML
429             + "<html><head></head><body xmlns:ns='http://foobar' id='tag' ns:foo='bar'>text</body></html>";
430         final HtmlPage page = loadPage(html);
431 
432         final HtmlElement node = page.getHtmlElementById("tag");
433         node.removeAttributeNS("http://foobar", "foo");
434         assertEquals("Element should not have removed attribute", "",
435             node.getAttributeNS("http://foobar", "foo"));
436     }
437 
438     /**
439      * Test removeAttribute() on an element without the attributes.
440      * @throws Exception if the test fails
441      */
442     @Test
443     public void removeAttributeNSNone() throws Exception {
444         final String html = DOCTYPE_HTML
445             + "<html><head></head><body id='tag'>text</body></html>";
446         final HtmlPage page = loadPage(html);
447 
448         final HtmlElement node = page.getHtmlElementById("tag");
449         node.removeAttributeNS("http://foobar", "foo");
450         assertEquals("Element should not have attribute", "", node.getAttributeNS("http://foobar", "foo"));
451     }
452 
453     /**
454      * @throws Exception if the test fails
455      */
456     @Test
457     public void getEnclosingForm() throws Exception {
458         final String htmlContent = DOCTYPE_HTML
459             + "<html><head><title>foo</title></head><body>\n"
460             + "<form id='form1'>\n"
461             + "<table><tr><td><input type='text' id='foo'/></td></tr></table>\n"
462             + "</form></body></html>";
463         final HtmlPage page = loadPage(htmlContent);
464         final HtmlForm form = page.getHtmlElementById("form1");
465 
466         final HtmlInput input = page.getHtmlElementById("foo");
467         assertSame(form, input.getEnclosingForm());
468     }
469 
470     /**
471      * @throws Exception if the test fails
472      */
473     @Test
474     public void getEnclosing() throws Exception {
475         final String htmlContent = DOCTYPE_HTML
476             + "<html><head><title>foo</title></head><body>\n"
477             + "<form id='form1'>\n"
478             + "<table id='table1'>\n"
479             + "<tr id='tr1'><td id='td1'>foo</td></tr>\n"
480             + "<tr id='tr2'><td id='td2'>foo</td></tr>\n"
481             + "</table>\n"
482             + "</form></body></html>";
483         final HtmlPage page = loadPage(htmlContent);
484 
485         final HtmlElement td1 = page.getHtmlElementById("td1");
486         assertEquals("tr1", td1.getEnclosingElement("tr").getId());
487         assertEquals("tr1", td1.getEnclosingElement("TR").getId());
488         assertEquals("table1", td1.getEnclosingElement("table").getId());
489         assertEquals("form1", td1.getEnclosingElement("form").getId());
490 
491         final HtmlElement td2 = page.getHtmlElementById("td2");
492         assertEquals("tr2", td2.getEnclosingElement("tr").getId());
493         assertEquals("tr2", td2.getEnclosingElement("TR").getId());
494         assertEquals("table1", td2.getEnclosingElement("table").getId());
495         assertEquals("form1", td2.getEnclosingElement("form").getId());
496     }
497 
498     /**
499      * @throws Exception if the test fails
500      */
501     @Test
502     public void asNormalizedTextWithComments() throws Exception {
503         final String htmlContent = DOCTYPE_HTML
504             + "<html><head><title>foo</title></head><body>\n"
505             + "<p id='p1'>foo<!--bar--></p>\n"
506             + "</body></html>";
507         final HtmlPage page = loadPage(htmlContent);
508         final HtmlElement element = page.getHtmlElementById("p1");
509         assertEquals("foo", element.asNormalizedText());
510     }
511 
512     /**
513      * Tests constants.
514      */
515     @Test
516     public void constants() {
517         assertEquals("", DomElement.ATTRIBUTE_NOT_DEFINED);
518         assertEquals("", DomElement.ATTRIBUTE_VALUE_EMPTY);
519         assertTrue("Not the same object",
520                 DomElement.ATTRIBUTE_NOT_DEFINED != DomElement.ATTRIBUTE_VALUE_EMPTY);
521     }
522 
523     static class HtmlAttributeChangeListenerTestImpl implements HtmlAttributeChangeListener {
524         private final List<String> collectedValues_ = new ArrayList<>();
525         @Override
526         @Test
527         public void attributeAdded(final HtmlAttributeChangeEvent event) {
528             collectedValues_.add("attributeAdded: " + event.getHtmlElement().getTagName() + ','
529                     + event.getName() + ',' + event.getValue());
530         }
531         @Override
532         @Test
533         public void attributeRemoved(final HtmlAttributeChangeEvent event) {
534             collectedValues_.add("attributeRemoved: " + event.getHtmlElement().getTagName() + ','
535                     + event.getName() + ',' + event.getValue());
536         }
537 
538         @Override
539         @Test
540         public void attributeReplaced(final HtmlAttributeChangeEvent event) {
541             collectedValues_.add("attributeReplaced: " + event.getHtmlElement().getTagName() + ','
542                     + event.getName() + ',' + event.getValue());
543         }
544         List<String> getCollectedValues() {
545             return collectedValues_;
546         }
547     }
548 
549     /**
550      * @throws Exception if the test fails
551      */
552     @Test
553     public void htmlAttributeChangeListener_AddAttribute() throws Exception {
554         final String htmlContent = DOCTYPE_HTML
555             + "<html><head><title>foo</title>\n"
556             + "<script>\n"
557             + "  function clickMe() {\n"
558             + "    var p1 = document.getElementById('p1');\n"
559             + "    p1.setAttribute('title', 'myTitle');\n"
560             + "  }\n"
561             + "</script>\n"
562             + "</head>\n"
563             + "<body id='myBody'>\n"
564             + "<p id='p1'></p>\n"
565             + "<input id='myButton' type='button' onclick='clickMe()'>\n"
566             + "</body></html>";
567 
568         final String[] expectedValues =
569         {"attributeAdded: p,title,myTitle",
570             "attributeAdded: p,title,myTitle",
571             "attributeAdded: p,title,myTitle"};
572         final HtmlPage page = loadPage(htmlContent);
573         final HtmlBody body = page.getHtmlElementById("myBody");
574         final HtmlElement p1 = page.getHtmlElementById("p1");
575 
576         final HtmlAttributeChangeListenerTestImpl listenerImpl = new HtmlAttributeChangeListenerTestImpl();
577         p1.addHtmlAttributeChangeListener(listenerImpl);
578         body.addHtmlAttributeChangeListener(listenerImpl);
579         page.addHtmlAttributeChangeListener(listenerImpl);
580         final HtmlButtonInput myButton = page.getHtmlElementById("myButton");
581 
582         myButton.click();
583         assertEquals(expectedValues, listenerImpl.getCollectedValues());
584     }
585 
586     /**
587      * @throws Exception if the test fails
588      */
589     @Test
590     public void htmlAttributeChangeListener_ReplaceAttribute() throws Exception {
591         final String htmlContent = DOCTYPE_HTML
592             + "<html><head><title>foo</title>\n"
593             + "<script>\n"
594             + "  function clickMe() {\n"
595             + "    var p1 = document.getElementById('p1');\n"
596             + "    p1.setAttribute('title', p1.getAttribute('title') + 'a');\n"
597             + "  }\n"
598             + "</script>\n"
599             + "</head>\n"
600             + "<body id='myBody'>\n"
601             + "<p id='p1' title='myTitle'></p>\n"
602             + "<input id='myButton' type='button' onclick='clickMe()'>\n"
603             + "</body></html>";
604 
605         final String[] expectedValues =
606         {"attributeReplaced: p,title,myTitle",
607             "attributeReplaced: p,title,myTitle",
608             "attributeReplaced: p,title,myTitle"};
609         final HtmlPage page = loadPage(htmlContent);
610         final HtmlBody body = page.getHtmlElementById("myBody");
611         final HtmlElement p1 = page.getHtmlElementById("p1");
612         final HtmlAttributeChangeListenerTestImpl listenerImpl = new HtmlAttributeChangeListenerTestImpl();
613         page.addHtmlAttributeChangeListener(listenerImpl);
614         body.addHtmlAttributeChangeListener(listenerImpl);
615         p1.addHtmlAttributeChangeListener(listenerImpl);
616         final HtmlButtonInput myButton = page.getHtmlElementById("myButton");
617 
618         myButton.click();
619         assertEquals(expectedValues, listenerImpl.getCollectedValues());
620         assertEquals("myTitle" + 'a', p1.getAttribute("title"));
621     }
622 
623     /**
624      * @throws Exception if the test fails
625      */
626     @Test
627     public void htmlAttributeChangeListener_RemoveAttribute() throws Exception {
628         final String htmlContent = DOCTYPE_HTML
629             + "<html><head><title>foo</title>\n"
630             + "<script>\n"
631             + "  function clickMe() {\n"
632             + "    var p1 = document.getElementById('p1');\n"
633             + "    p1.removeAttribute('title');\n"
634             + "  }\n"
635             + "</script>\n"
636             + "</head>\n"
637             + "<body id='myBody'>\n"
638             + "<p id='p1' title='myTitle'></p>\n"
639             + "<input id='myButton' type='button' onclick='clickMe()'>\n"
640             + "</body></html>";
641 
642         final String[] expectedValues =
643         {"attributeRemoved: p,title,myTitle",
644             "attributeRemoved: p,title,myTitle",
645             "attributeRemoved: p,title,myTitle"};
646         final HtmlPage page = loadPage(htmlContent);
647         final HtmlBody body = page.getHtmlElementById("myBody");
648         final HtmlElement p1 = page.getHtmlElementById("p1");
649         final HtmlAttributeChangeListenerTestImpl listenerImpl = new HtmlAttributeChangeListenerTestImpl();
650         page.addHtmlAttributeChangeListener(listenerImpl);
651         body.addHtmlAttributeChangeListener(listenerImpl);
652         p1.addHtmlAttributeChangeListener(listenerImpl);
653         final HtmlButtonInput myButton = page.getHtmlElementById("myButton");
654 
655         myButton.click();
656         assertEquals(expectedValues, listenerImpl.getCollectedValues());
657         assertSame(DomElement.ATTRIBUTE_NOT_DEFINED, p1.getAttribute("title"));
658     }
659 
660     /**
661      * @throws Exception if the test fails
662      */
663     @Test
664     public void htmlAttributeChangeListener_RemoveListener() throws Exception {
665         final String htmlContent = DOCTYPE_HTML
666             + "<html><head><title>foo</title>\n"
667             + "<script>\n"
668             + "  function clickMe() {\n"
669             + "    var p1 = document.getElementById('p1');\n"
670             + "    p1.setAttribute('title', p1.getAttribute('title') + 'a');\n"
671             + "  }\n"
672             + "</script>\n"
673             + "</head>\n"
674             + "<body>\n"
675             + "<p id='p1' title='myTitle'></p>\n"
676             + "<input id='myButton' type='button' onclick='clickMe()'>\n"
677             + "</body></html>";
678 
679         final String[] expectedValues = {"attributeReplaced: p,title,myTitle"};
680         final HtmlPage page = loadPage(htmlContent);
681         final HtmlElement p1 = page.getHtmlElementById("p1");
682         final HtmlAttributeChangeListenerTestImpl listenerImpl = new HtmlAttributeChangeListenerTestImpl();
683         p1.addHtmlAttributeChangeListener(listenerImpl);
684         final HtmlButtonInput myButton = page.getHtmlElementById("myButton");
685 
686         myButton.click();
687         p1.removeHtmlAttributeChangeListener(listenerImpl);
688         myButton.click();
689         assertEquals(expectedValues, listenerImpl.getCollectedValues());
690         assertEquals("myTitle" + 'a' + 'a', p1.getAttribute("title"));
691     }
692 
693     /**
694      * @throws Exception if the test fails
695      */
696     @Test
697     public void mouseOver() throws Exception {
698         final String html = DOCTYPE_HTML
699             + "<html>\n"
700             + "<head>\n"
701             + "<script>\n"
702             + "  function mouseOverMe() {\n"
703             + "    document.getElementById('myTextarea').value+='mouseover-';\n"
704             + "  }\n"
705             + "</script>\n"
706             + "</head>\n"
707             + "<body id='myBody' onmouseover='mouseOverMe()'>\n"
708             + "<textarea id='myTextarea'></textarea>\n"
709             + "</body></html>";
710         final HtmlPage page = loadPage(html);
711         final HtmlBody body = page.getHtmlElementById("myBody");
712         body.mouseOver();
713         final HtmlTextArea textArea = page.getHtmlElementById("myTextarea");
714         assertEquals("mouseover-", textArea.getText());
715     }
716 
717     /**
718      * @throws Exception if the test fails
719      */
720     @Test
721     public void mouseMove() throws Exception {
722         final String html = DOCTYPE_HTML
723             + "<html>\n"
724             + "<head>\n"
725             + "<script>\n"
726             + "  function mouseMoveMe() {\n"
727             + "    document.getElementById('myTextarea').value+='mousemove-';\n"
728             + "  }\n"
729             + "</script>\n"
730             + "</head>\n"
731             + "<body id='myBody' onmousemove='mouseMoveMe()'>\n"
732             + "<textarea id='myTextarea'></textarea>\n"
733             + "</body></html>";
734         final HtmlPage page = loadPage(html);
735         final HtmlBody body = page.getHtmlElementById("myBody");
736         body.mouseMove();
737         final HtmlTextArea textArea = page.getHtmlElementById("myTextarea");
738         assertEquals("mousemove-", textArea.getText());
739     }
740 
741     /**
742      * @throws Exception if the test fails
743      */
744     @Test
745     public void mouseOut() throws Exception {
746         final String html = DOCTYPE_HTML
747             + "<html>\n"
748             + "<head>\n"
749             + "<script>\n"
750             + "  function mouseOutMe() {\n"
751             + "    document.getElementById('myTextarea').value+='mouseout-';\n"
752             + "  }\n"
753             + "</script>\n"
754             + "</head>\n"
755             + "<body id='myBody' onmouseout='mouseOutMe()'>\n"
756             + "<textarea id='myTextarea'></textarea>\n"
757             + "</body></html>";
758         final HtmlPage page = loadPage(html);
759         final HtmlBody body = page.getHtmlElementById("myBody");
760         body.mouseOut();
761         final HtmlTextArea textArea = page.getHtmlElementById("myTextarea");
762         assertEquals("mouseout-", textArea.getText());
763     }
764 
765     /**
766      * @throws Exception if the test fails
767      */
768     @Test
769     @Alerts("mousedown-0")
770     public void mouseDown() throws Exception {
771         final String html = DOCTYPE_HTML
772             + "<html>\n"
773             + "<head>\n"
774             + "<script>\n"
775             + "  function mouseDownMe(e) {\n"
776             + "    document.getElementById('myTextarea').value+='mousedown-' + e.button;\n"
777             + "  }\n"
778             + "</script>\n"
779             + "</head>\n"
780             + "<body id='myBody' onmousedown='mouseDownMe(event)'>\n"
781             + "<textarea id='myTextarea'></textarea>\n"
782             + "</body></html>";
783 
784         final HtmlPage page = loadPage(html);
785         final HtmlBody body = page.getHtmlElementById("myBody");
786         body.mouseDown();
787         final HtmlTextArea textArea = page.getHtmlElementById("myTextarea");
788         assertEquals(getExpectedAlerts()[0], textArea.getText());
789     }
790 
791     /**
792      * @throws Exception if the test fails
793      */
794     @Test
795     public void mouseUp() throws Exception {
796         final String html = DOCTYPE_HTML
797             + "<html>\n"
798             + "<head>\n"
799             + "<script>\n"
800             + "  function mouseUpMe() {\n"
801             + "    document.getElementById('myTextarea').value+='mouseup-';\n"
802             + "  }\n"
803             + "</script>\n"
804             + "</head>\n"
805             + "<body id='myBody' onmouseup='mouseUpMe()'>\n"
806             + "<textarea id='myTextarea'></textarea>\n"
807             + "</body></html>";
808         final HtmlPage page = loadPage(html);
809         final HtmlBody body = page.getHtmlElementById("myBody");
810         body.mouseUp();
811         final HtmlTextArea textArea = page.getHtmlElementById("myTextarea");
812         assertEquals("mouseup-", textArea.getText());
813     }
814 
815     /**
816      * @throws Exception if the test fails
817      */
818     @Test
819     @Alerts("mousedown-2-mouseup-2-contextmenu-2-")
820     public void rightClick() throws Exception {
821         final String html = DOCTYPE_HTML
822             + "<html>\n"
823             + "<head>\n"
824             + "<script>\n"
825             + "  function divMouseEvent(e) {\n"
826             + "    var textarea = document.getElementById('myTextarea');\n"
827             + "    if (window.event)\n"
828             + "      textarea.value += event.type + '-' + event.button + '-';\n"
829             + "    else\n"
830             + "      textarea.value += e.type + '-' + e.which + '-';\n"
831             + "  }\n"
832             + "  function loadFunction(e) {\n"
833             + "    document.getElementById('myDiv').onmousedown   = divMouseEvent;\n"
834             + "    document.getElementById('myDiv').onmouseup     = divMouseEvent;\n"
835             + "    document.getElementById('myDiv').oncontextmenu = divMouseEvent;\n"
836             + "  }\n"
837             + "</script>\n"
838             + "</head>\n"
839             + "<body onload='loadFunction()'>\n"
840             + "  <div id='myDiv'>Hello</div><br>\n"
841             + "  <textarea id='myTextarea'></textarea>\n"
842             + "</body></html>";
843 
844         final HtmlPage page = loadPage(html);
845         final HtmlDivision div = page.getHtmlElementById("myDiv");
846         div.rightClick();
847         final HtmlTextArea textArea = page.getHtmlElementById("myTextarea");
848         assertEquals(getExpectedAlerts()[0], textArea.getText());
849     }
850 
851     /**
852      * Test the mouse down, then mouse up.
853      *
854      * @throws Exception if the test fails
855      */
856     @Test
857     @Alerts("mousedown-0-mouseup-0-")
858     public void mouse_Down_Up() throws Exception {
859         final String html = DOCTYPE_HTML
860             + "<html>\n"
861             + "<head>\n"
862             + "<script>\n"
863             + "  function divMouseEvent(e) {\n"
864             + "    var textarea = document.getElementById('myTextarea');\n"
865             + "    if (window.event)\n"
866             + "      textarea.value += event.type + '-' + event.button + '-';\n"
867             + "    else\n"
868             + "      textarea.value += e.type + '-' + e.which + '-';\n"
869             + "  }\n"
870             + "  function loadFunction(e) {\n"
871             + "    document.getElementById('myDiv').onmousedown = divMouseEvent;\n"
872             + "    document.getElementById('myDiv').onmouseup   = divMouseEvent;\n"
873             + "  }\n"
874             + "</script>\n"
875             + "</head>\n"
876             + "<body onload='loadFunction()'>\n"
877             + "  <div id='myDiv'>Hello</div><br>\n"
878             + "  <textarea id='myTextarea'></textarea>\n"
879             + "</body></html>";
880 
881         final HtmlPage page = loadPage(html);
882         final HtmlDivision div = page.getHtmlElementById("myDiv");
883         div.mouseDown();
884         div.mouseUp();
885         final HtmlTextArea textArea = page.getHtmlElementById("myTextarea");
886         assertEquals(getExpectedAlerts()[0], textArea.getText());
887     }
888 
889     /**
890      * @throws Exception if the test fails
891      */
892     @Test
893     public void asXml_separateLineforEmptyElements() throws Exception {
894         final String html = DOCTYPE_HTML
895             + "<html><head><title>foo</title></head>\n"
896             + "<body><table><tr><td></tr></table>\n"
897             + "</body></html>";
898         final HtmlPage page = loadPage(html);
899         assertTrue(page.asXml().indexOf("/> ") == -1);
900     }
901 
902     /**
903      * @throws Exception if an error occurs
904      */
905     @Test
906     public void type() throws Exception {
907         final String html = DOCTYPE_HTML
908             + "<html><head><script>\n"
909             + "  function test() {\n"
910             + "    alert(document.getElementById('myInput').value);\n"
911             + "  }\n"
912             + "</script></head>\n"
913             + "<body>\n"
914             + "  <input id='myButton' type='button' onclick='test()'>\n"
915             + "  <input id='myInput' onclick='test()'>\n"
916             + "</body></html>";
917 
918         final List<String> collectedAlerts = new ArrayList<>();
919         final HtmlPage page = loadPage(html, collectedAlerts);
920         final HtmlTextInput input = page.getHtmlElementById("myInput");
921         input.type("Hello Cruel World");
922         assertEquals("", input.getValueAttribute());
923         assertEquals("Hello Cruel World", input.getValue());
924         page.getHtmlElementById("myButton").click();
925 
926         final String[] expectedAlerts = {"Hello Cruel World"};
927         assertEquals(expectedAlerts, collectedAlerts);
928     }
929 
930     /**
931      * @throws Exception if the test fails
932      */
933     @Test
934     public void typeOnFocus() throws Exception {
935         final String html = DOCTYPE_HTML
936             + "<html><head><title>foo</title></head><body>\n"
937             + "<form>\n"
938             + "  <input type='text' id='textfield1' onfocus='alert(1)'>\n"
939             + "</form>\n"
940             + "</body></html>";
941         final String[] expectedAlerts = {"1"};
942         final List<String> collectedAlerts = new ArrayList<>();
943         final HtmlPage page = loadPage(html, collectedAlerts);
944 
945         page.getHtmlElementById("textfield1").type('a');
946         assertEquals(expectedAlerts, collectedAlerts);
947     }
948 
949     /**
950      * @throws Exception on test failure
951      */
952     @Test
953     public void asNormalizedText() throws Exception {
954         final String html = DOCTYPE_HTML
955             + "<html>\n"
956             + "<head>\n"
957             + "  <title>test</title>\n"
958             + "</head>\n"
959             + "<body>Welcome\n"
960             + "<div style='visibility:hidden'>to the big</div>\n"
961             + "<div style='display:none'>\n"
962             + "  <div style='display:block'><span style='visibility:visible'>world</span></div>\n"
963             + "</div>\n"
964             + "</body>\n"
965             + "</html>";
966 
967         final HtmlPage page = loadPage(html);
968         assertEquals("test\nWelcome", page.asNormalizedText());
969     }
970 
971     /**
972      * @throws Exception on test failure
973      */
974     @Test
975     public void asNormalizedTextOverridingVisibility() throws Exception {
976         final String html = DOCTYPE_HTML
977             + "<html>\n"
978             + "<head>\n"
979             + "  <title>test</title>\n"
980             + "</head>\n"
981             + "<body>Welcome\n"
982             + "<p style='visibility:hidden'>hidden text\n"
983             + "<FONT COLOR='#FF0000' style='visibility:visible'>to the world</FONT>\n"
984             + "some more hidden text</p>\n"
985             + "</body>\n"
986             + "</html>";
987 
988         final HtmlPage page = loadPage(html);
989         assertEquals("test\nWelcome\nto the world", page.asNormalizedText());
990     }
991 
992     /**
993      * @throws Exception on test failure
994      */
995     @Test
996     public void asNormalizedTextVisibilityCollapse() throws Exception {
997         final String html = DOCTYPE_HTML
998             + "<html>\n"
999             + "<head>\n"
1000             + "  <title>test</title>\n"
1001             + "</head>\n"
1002             + "<body>Welcome\n"
1003             + "<p style='visibility:collapse'>hidden text\n"
1004             + "<font color='#FF0000' style='visibility:visible'>to the world</font>\n"
1005             + "some more hidden text</p>\n"
1006             + "</body>\n"
1007             + "</html>";
1008         final String expected = "test\nWelcome\nto the world";
1009 
1010         final HtmlPage page = loadPage(html);
1011         assertEquals(expected, page.asNormalizedText());
1012     }
1013 
1014     /**
1015      * @throws Exception if the test fails
1016      */
1017     @Test
1018     public void getNodeName() throws Exception {
1019         final String html
1020             = "<html xmlns='http://www.w3.org/1999/xhtml' xmlns:app='http://www.appcelerator.org'>\n"
1021             + "<head>\n"
1022             + "<script>\n"
1023             + "</script>\n"
1024             + "</head>\n"
1025             + "<body>\n"
1026             + "<dIv id='dIv1'></dIv>\n"
1027             + "<app:dIv id='dIv2'></app:dIv>\n"
1028             + "<another:dIv id='dIv3'></another:dIv>\n"
1029             + "</body></html>";
1030 
1031         final HtmlPage page = loadPage(html);
1032         assertEquals("div", page.getHtmlElementById("dIv1").getNodeName());
1033         assertEquals("app:div", page.getHtmlElementById("dIv2").getNodeName());
1034         assertEquals("another:div", page.getHtmlElementById("dIv3").getNodeName());
1035         assertTrue(page.asXml().contains("<app:div "));
1036     }
1037 
1038     /**
1039      * @throws Exception if the test fails
1040      */
1041     @Test
1042     @Alerts({"1", "2"})
1043     public void getElementsByTagName() throws Exception {
1044         final String html = DOCTYPE_HTML
1045             + "<html>\n"
1046             + "<head>\n"
1047             + "<script>\n"
1048             + "  function test() {\n"
1049             + "    var form = document.getElementById('myForm');\n"
1050             + "    alert(form.getElementsByTagName('input').length);\n"
1051             + "    alert(document.body.getElementsByTagName('input').length);\n"
1052             + "  }\n"
1053             + "</script>\n"
1054             + "</head>\n"
1055             + "<body onload='test()'>\n"
1056             + "<form id='myForm'>\n"
1057             + "  <input type='button' name='button1' value='pushme'>\n"
1058             + "</form>\n"
1059             + "<input type='button' name='button2'>\n"
1060             + "</body></html>";
1061 
1062         final HtmlPage page = loadPageWithAlerts(html);
1063         assertEquals(1, page.getElementById("myForm").getElementsByTagName("input").getLength());
1064         assertEquals(2, page.getBody().getElementsByTagName("input").getLength());
1065     }
1066 
1067     /**
1068      * @throws Exception if an error occurs
1069      */
1070     @Test
1071     public void getElementsByTagName2() throws Exception {
1072         final String html = DOCTYPE_HTML
1073             + "<html><head><title>First</title></head>\n"
1074             + "<body>\n"
1075             + "<form><input type='button' name='button1' value='pushme'></form>\n"
1076             + "<div>a</div> <div>b</div> <div>c</div>\n"
1077             + "</body></html>";
1078 
1079         final HtmlPage page = loadPage(html);
1080         final HtmlElement body = page.getBody();
1081 
1082         NodeList inputs = body.getElementsByTagName("input");
1083         assertEquals(1, inputs.getLength());
1084         assertEquals("button", inputs.item(0).getAttributes().getNamedItem("type").getNodeValue());
1085 
1086         final NodeList divs = body.getElementsByTagName("div");
1087         assertEquals(3, divs.getLength());
1088 
1089         final HtmlDivision newDiv = new HtmlDivision(HtmlDivision.TAG_NAME, page, null);
1090         body.appendChild(newDiv);
1091         assertEquals(4, divs.getLength());
1092 
1093         // case sensitive
1094         inputs = page.getElementsByTagName("inPUT");
1095         assertEquals(1, inputs.getLength());
1096 
1097         // empty
1098         inputs = page.getElementsByTagName("");
1099         assertEquals(0, inputs.getLength());
1100 
1101         // null
1102         inputs = page.getElementsByTagName(null);
1103         assertEquals(0, inputs.getLength());
1104     }
1105 
1106     /**
1107      * @throws Exception if the test fails
1108      */
1109     @Test
1110     public void getElementsByAttribute() throws Exception {
1111         final String html = DOCTYPE_HTML
1112             + "<html>\n"
1113             + "<head></head>\n"
1114             + "<body>\n"
1115             + "<form id='myForm'>\n"
1116             + "  <input type='button' name='buttonName' value='pushme'>\n"
1117             + "  <select id='selectId' multiple>\n"
1118             + "    <option value='option1' id='option1' selected>Option1</option>\n"
1119             + "    <option value='option2' id='option2' selected='selected'>Option2</option>\n"
1120             + "  </select>\n"
1121             + "</form>\n"
1122             + "</body></html>";
1123 
1124         final HtmlPage page = loadPage(html);
1125 
1126         final HtmlElement form = page.getHtmlElementById("myForm");
1127 
1128         List<HtmlElement> elements = form.getElementsByAttribute("input", "value", "pushme");
1129         assertEquals(1, elements.size());
1130         assertEquals("<input type=\"button\" name=\"buttonName\" value=\"pushme\"/>",
1131             elements.get(0).asXml());
1132 
1133         // ignore case
1134         elements = form.getElementsByAttribute("iNPuT", "value", "pushme");
1135         assertEquals(1, elements.size());
1136         assertEquals("<input type=\"button\" name=\"buttonName\" value=\"pushme\"/>",
1137                 elements.get(0).asXml());
1138 
1139         // attribute value is case sensitive
1140         elements = form.getElementsByAttribute("input", "value", "pushMe");
1141         assertTrue(elements.isEmpty());
1142 
1143         // selected='selected'
1144         elements = form.getElementsByAttribute("option", "selected", "selected");
1145         assertEquals(1, elements.size());
1146         assertEquals("<option value=\"option2\" id=\"option2\" selected=\"selected\">Option2</option>",
1147                 elements.get(0).asXml());
1148 
1149         // selected
1150         elements = form.getElementsByAttribute("option", "selected", "");
1151         assertEquals(1, elements.size());
1152         assertEquals("<option value=\"option1\" id=\"option1\" selected=\"\">Option1</option>",
1153                 elements.get(0).asXml());
1154     }
1155 
1156     /**
1157      * @throws Exception if an error occurs
1158      */
1159     @Test
1160     public void serialization() throws Exception {
1161         final String html = DOCTYPE_HTML + "<html><body><div id='d' a='b'></div></body></html>";
1162         HtmlPage page = loadPage(html);
1163         assertEquals("b", page.getElementById("d").getAttribute("a"));
1164         page = clone(page);
1165         assertEquals("b", page.getElementById("d").getAttribute("a"));
1166     }
1167 
1168     /**
1169      * Ensure that we don't escape when not needed.
1170      * @throws Exception on test failure
1171      */
1172     @Test
1173     public void asXml() throws Exception {
1174         final String html = DOCTYPE_HTML
1175             + "<html>\n"
1176             + "<head>\n"
1177             + "  <title>test</title>\n"
1178             + "</head>\n"
1179             + "<body>Welcome\n"
1180             + "<div id='div1' onclick=\"alert('hello')\">click me</div>\n"
1181             + "<div id='div2' onclick='alert(\"hello again\")'>click me again</div>\n"
1182             + "</body>\n"
1183             + "</html>";
1184 
1185         final HtmlPage page = loadPage(html);
1186 
1187         final String htmlDiv1XML = "<div id=\"div1\" onclick=\"alert('hello')\">click me</div>";
1188         assertEquals(htmlDiv1XML, page.getElementById("div1").asXml());
1189 
1190         final String htmlDiv2XML = "<div id=\"div2\" onclick=\"alert(&quot;hello again&quot;)\">click me again"
1191                 + "</div>";
1192         assertEquals(htmlDiv2XML, page.getElementById("div2").asXml());
1193     }
1194 
1195     /**
1196      * @throws Exception if the test fails
1197      */
1198     @Test
1199     @Alerts({"true", "false", "false"})
1200     public void isDisplayedJsDisabled() throws Exception {
1201         final String html = DOCTYPE_HTML
1202             + "<html><head>\n"
1203             + "</head>\n"
1204             + "</body>\n"
1205             + "<div id='d1'>hello</div>\n"
1206             + "<div id='d2' hidden>world</div>\n"
1207             + "<div id='d3' style='display:none;'>world</div>\n"
1208             + "</body></html>";
1209 
1210         getWebClient().getOptions().setJavaScriptEnabled(false);
1211         final HtmlPage page = loadPage(html);
1212         assertEquals(Boolean.parseBoolean(getExpectedAlerts()[0]), page.getElementById("d1").isDisplayed());
1213         assertEquals(Boolean.parseBoolean(getExpectedAlerts()[1]), page.getElementById("d2").isDisplayed());
1214         assertEquals(Boolean.parseBoolean(getExpectedAlerts()[2]), page.getElementById("d3").isDisplayed());
1215     }
1216 
1217     /**
1218      * @throws Exception if the test fails
1219      */
1220     @Test
1221     @Alerts({"true", "false", "false"})
1222     public void isDisplayedJsEngineDisabled() throws Exception {
1223         final String html = DOCTYPE_HTML
1224             + "<html><head>\n"
1225             + "</head>\n"
1226             + "</body>\n"
1227             + "<div id='d1'>hello</div>\n"
1228             + "<div id='d2' hidden>world</div>\n"
1229             + "<div id='d3' style='display:none;'>world</div>\n"
1230             + "</body></html>";
1231 
1232         try (WebClient webClient = new WebClient(getBrowserVersion(), false, null, -1)) {
1233             final HtmlPage page = loadPage(webClient, html, null);
1234 
1235             assertFalse(page.getWebClient().isJavaScriptEngineEnabled());
1236             assertEquals(Boolean.parseBoolean(getExpectedAlerts()[0]), page.getElementById("d1").isDisplayed());
1237             assertEquals(Boolean.parseBoolean(getExpectedAlerts()[1]), page.getElementById("d2").isDisplayed());
1238             assertEquals(Boolean.parseBoolean(getExpectedAlerts()[2]), page.getElementById("d3").isDisplayed());
1239         }
1240     }
1241 
1242     /**
1243      * @throws Exception if the test fails
1244      */
1245     @Test
1246     @Alerts({"true", "false", "false"})
1247     public void clickJsEngineDisabled() throws Exception {
1248         final String html = DOCTYPE_HTML
1249             + "<html><head>\n"
1250             + "</head>\n"
1251             + "</body>\n"
1252             + "<div id='d1'>hello</div>\n"
1253             + "</body></html>";
1254 
1255         try (WebClient webClient = new WebClient(getBrowserVersion(), false, null, -1)) {
1256             final HtmlPage page = loadPage(webClient, html, null);
1257 
1258             assertFalse(page.getWebClient().isJavaScriptEngineEnabled());
1259             assertEquals(page, page.getElementById("d1").click());
1260         }
1261     }
1262 
1263     /**
1264      * @throws Exception if an error occurs
1265      */
1266     @Test
1267     public void acceptChar() throws Exception {
1268         final String html = DOCTYPE_HTML + "<html><body><input></body></html>";
1269         final HtmlPage page = loadPage(html);
1270         final String value = "abc[ ][\t][ ][\u2006]123あいう漢字[!@#$%^&*()-=_+]{}<>?/\\";
1271         final HtmlInput input = page.getFirstByXPath("//input");
1272         input.type(value);
1273         assertEquals(value, input.getValue());
1274     }
1275 }