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