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.javascript.host.html;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.html.HtmlHtml;
19  import org.htmlunit.junit.annotation.Alerts;
20  import org.htmlunit.junit.annotation.HtmlUnitNYI;
21  import org.junit.jupiter.api.Test;
22  import org.openqa.selenium.By;
23  import org.openqa.selenium.JavascriptExecutor;
24  import org.openqa.selenium.WebDriver;
25  import org.openqa.selenium.WebElement;
26  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
27  
28  /**
29   * Unit tests for {@link HTMLHtmlElement}.
30   *
31   * @author Daniel Gredler
32   * @author Marc Guillemot
33   * @author Frank Danek
34   * @author Ronald Brill
35   */
36  public class HTMLHtmlElementTest extends WebDriverTestCase {
37  
38      /**
39       * @throws Exception if the test fails
40       */
41      @Test
42      @Alerts("[object HTMLHtmlElement]")
43      public void simpleScriptable() throws Exception {
44          final String html = DOCTYPE_HTML
45              + "<html id='myId'><head><title>foo</title><script>\n"
46              + "  function test() {\n"
47              + "    alert(document.getElementById('myId'));\n"
48              + "  }\n"
49              + "</script></head><body onload='test()'>\n"
50              + "</body></html>";
51  
52          final WebDriver driver = loadPageWithAlerts2(html);
53          if (driver instanceof HtmlUnitDriver) {
54              final WebElement element = driver.findElement(By.id("myId"));
55              assertTrue(toHtmlElement(element) instanceof HtmlHtml);
56          }
57      }
58  
59      /**
60       * @throws Exception if the test fails
61       */
62      @Test
63      @Alerts({"[object HTMLHtmlElement]", "function HTMLHtmlElement() { [native code] }"})
64      public void HTMLHtmlElement_toString() throws Exception {
65          final String html = DOCTYPE_HTML
66              + "<html id='myId'><head><script>\n"
67              + LOG_TITLE_FUNCTION
68              + "  function test() {\n"
69              + "    try {\n"
70              + "      log(document.getElementById('myId'));\n"
71              + "      log(HTMLHtmlElement);\n"
72              + "    } catch(e) {\n"
73              + "      logEx(e);\n"
74              + "    }\n"
75              + "  }\n"
76              + "</script></head><body onload='test()'>\n"
77              + "</body></html>";
78  
79          loadPageVerifyTitle2(html);
80      }
81  
82      /**
83       * @throws Exception if an error occurs
84       */
85      @Test
86      @Alerts({"2", "HEAD", "BODY", "null", "null"})
87      public void childNodes_1() throws Exception {
88          // The whitespace in this HTML is very important, because we're verifying
89          // that it doesn't get included in the childNodes collection.
90          final String html = DOCTYPE_HTML
91              + "<html> \n <body> \n <script>\n"
92              + LOG_TITLE_FUNCTION
93              + "var nodes = document.documentElement.childNodes;\n"
94              + "log(nodes.length);\n"
95              + "log(nodes[0].nodeName);\n"
96              + "log(nodes[1].nodeName);\n"
97              + "log(nodes[0].previousSibling);\n"
98              + "log(nodes[1].nextSibling);\n"
99              + "</script> \n </body> \n </html>";
100 
101         loadPageVerifyTitle2(html);
102     }
103 
104     /**
105      * @throws Exception if an error occurs
106      */
107     @Test
108     @Alerts({"1", "HEAD"})
109     public void childNodes_2() throws Exception {
110         // The whitespace in this HTML is very important, because we're verifying
111         // that it doesn't get included in the childNodes collection.
112         final String html = DOCTYPE_HTML
113             + "<html> \n <head> \n <script>\n"
114             + LOG_TITLE_FUNCTION
115             + "var nodes = document.documentElement.childNodes;\n"
116             + "log(nodes.length);\n"
117             + "log(nodes[0].nodeName);\n"
118             + "</script> \n </head> \n </html>";
119 
120         loadPageVerifyTitle2(html);
121     }
122 
123     /**
124      * @throws Exception if an error occurs
125      */
126     @Test
127     @Alerts({"true", "true", "true", "true"})
128     public void clientWidth() throws Exception {
129         final String html = "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'"
130             + " 'http://www.w3.org/TR/html4/loose.dtd'>"
131             + "<html><head>\n"
132             + "<script>\n"
133             + LOG_TITLE_FUNCTION
134             + "function test() {\n"
135             + "  var elt = document.body.parentNode;\n"
136             + "  log(elt.clientWidth > 0);\n"
137             + "  log(elt.clientWidth == window.innerWidth);\n"
138             + "  log(elt.clientHeight > 0);\n"
139             + "  log(elt.clientHeight == window.innerHeight);\n"
140             + "}\n"
141             + "</script></head><body onload='test()'>\n"
142             + "</body></html>";
143 
144         loadPageVerifyTitle2(html);
145     }
146 
147     /**
148      * @throws Exception if the test fails
149      */
150     @Test
151     @Alerts("Hello World")
152     public void innerText() throws Exception {
153         final String html = DOCTYPE_HTML
154             + "<html><head>\n"
155             + "<script>\n"
156             + LOG_TITLE_FUNCTION
157             + "  function test() {\n"
158             + "    document.documentElement.innerText = 'Hello World';\n"
159             + "  }\n"
160             + "</script>\n"
161             + "</head>\n"
162             + "<body onload='test()'>\n"
163             + "</body></html>";
164 
165         final String js =
166                 "if (document.documentElement.childNodes.length == 0) { return '0'; }"
167                 + " return document.documentElement.childNodes.item(0).data;";
168 
169         final WebDriver driver = loadPage2(html);
170         final String text = (String) ((JavascriptExecutor) driver).executeScript(js);
171         assertEquals(getExpectedAlerts()[0], text);
172     }
173 
174     /**
175      * Test offsets (real values don't matter currently).
176      * But we have to make sure this works without an exception
177      * because parent is null.
178      *
179      * @throws Exception if the test fails
180      */
181     @Test
182     @Alerts(DEFAULT = {"8", "16", "13", "0"},
183             FF = {"8", "16", "0", "0"},
184             FF_ESR = {"8", "16", "0", "0"})
185     @HtmlUnitNYI(CHROME = {"8", "1256", "13", "0"},
186             EDGE = {"8", "1256", "13", "0"},
187             FF = {"8", "1256", "13", "0"},
188             FF_ESR = {"8", "1256", "13", "0"})
189     public void offsetsHtmlAbsoluteLeft() throws Exception {
190         offsetsHtml("position: absolute; left: 13px;");
191     }
192 
193     /**
194      * Test offsets (real values don't matter currently).
195      * But we have to make sure this works without an exception
196      * because parent is null.
197      *
198      * @throws Exception if the test fails
199      */
200     @Test
201     @Alerts(CHROME = {"8", "16", "1227", "0"},
202             EDGE = {"8", "16", "1219", "0"},
203             FF = {"8", "16", "0", "0"},
204             FF_ESR = {"8", "16", "0", "0"})
205     @HtmlUnitNYI(CHROME = {"8", "1256", "1243", "0"},
206             EDGE = {"8", "1256", "1243", "0"},
207             FF = {"8", "1256", "1243", "0"},
208             FF_ESR = {"8", "1256", "1243", "0"})
209     public void offsetsHtmlAbsoluteRight() throws Exception {
210         offsetsHtml("position: absolute; right: 13px;");
211     }
212 
213     /**
214      * Test offsets (real values don't matter currently).
215      * But we have to make sure this works without an exception
216      * because parent is null.
217      *
218      * @throws Exception if the test fails
219      */
220     @Test
221     @Alerts({"8", "16", "0", "0"})
222     @HtmlUnitNYI(CHROME = {"8", "1256", "0", "0"},
223             EDGE = {"8", "1256", "0", "0"},
224             FF = {"8", "1256", "0", "0"},
225             FF_ESR = {"8", "1256", "0", "0"})
226     public void offsetsHtmlFixed() throws Exception {
227         offsetsHtml("position: fixed;");
228     }
229 
230     /**
231      * Test offsets (real values don't matter currently).
232      * But we have to make sure this works without an exception
233      * because parent is null.
234      *
235      * @throws Exception if the test fails
236      */
237     @Test
238     @Alerts(CHROME = {"8", "16", "1227", "0"},
239             EDGE = {"8", "16", "1219", "0"},
240             FF = {"8", "16", "0", "0"},
241             FF_ESR = {"8", "16", "0", "0"})
242     @HtmlUnitNYI(CHROME = {"8", "1256", "1243", "0"},
243             EDGE = {"8", "1256", "1243", "0"},
244             FF = {"8", "1256", "1243", "0"},
245             FF_ESR = {"8", "1256", "1243", "0"})
246     public void offsetsHtmlFixedRight() throws Exception {
247         offsetsHtml("position: fixed; right: 13px;");
248     }
249 
250     private void offsetsHtml(final String style) throws Exception {
251         final String html = DOCTYPE_HTML
252               + "<html id='my' style='" + style + "'>\n"
253               + "<head></head>\n"
254               + "<body>\n"
255               + "</div></body>\n"
256               + "<script>\n"
257               + LOG_TITLE_FUNCTION
258               + "function alertOffsets(elt) {\n"
259               + "  log(elt.offsetHeight);\n"
260               + "  log(elt.offsetWidth);\n"
261               + "  log(elt.offsetLeft);\n"
262               + "  log(elt.offsetTop);\n"
263               + "}\n"
264 
265               + "alertOffsets(document.getElementById('my'));\n"
266               + "</script></body></html>";
267         loadPageVerifyTitle2(html);
268     }
269 }