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.css.property;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.junit.annotation.Alerts;
19  import org.htmlunit.junit.annotation.HtmlUnitNYI;
20  import org.junit.jupiter.api.Test;
21  import org.openqa.selenium.By;
22  import org.openqa.selenium.WebDriver;
23  
24  /**
25   * Tests for ComputedHeight.
26   *
27   * @author Ahmed Ashour
28   * @author Ronald Brill
29   */
30  public class ElementOffsetHeight2Test extends WebDriverTestCase {
31  
32      /**
33       * Tests the relation between {@code fontSize} and {@code offsetHeight}.
34       *
35       * @throws Exception if the test fails
36       */
37      @Test
38      public void offsetHeight() throws Exception {
39          final String html = DOCTYPE_HTML
40              + "<html><head><body>\n"
41              + "  <div id='myDiv'>a</div>\n"
42              + "  <textarea id='myTextarea' cols='120' rows='20'></textarea>\n"
43              + "<script>\n"
44              + "var e = document.getElementById('myDiv');\n"
45              + "var array = [];\n"
46              + "for (var i = 0; i <= 128; i++) {\n"
47              + "  e.style.fontSize = i + 'px';\n"
48              + "  array.push(e.offsetHeight);\n"
49              + "}\n"
50              + "document.getElementById('myTextarea').value = array.join(', ');\n"
51              + "</script></body></html>";
52  
53          final WebDriver driver = loadPage2(html);
54          final String expected = loadExpectation("ElementOffsetHeightTest.properties", ".txt");
55          final String actual = driver.findElement(By.id("myTextarea")).getDomProperty("value");
56          assertEquals(expected, actual);
57      }
58  
59      /**
60       * Try to do a line break if width is fixed.
61       *
62       * @throws Exception if the test fails
63       */
64      @Test
65      @Alerts(DEFAULT = "12, 27, 44, 60, 80, 108, 126, 161, 208, 216, 270, 288, 340, 407",
66              FF = "14, 30, 48, 60, 80, 108, 126, 161, 208, 224, 279, 297, 350, 418",
67              FF_ESR = "14, 30, 48, 60, 80, 108, 126, 161, 208, 224, 279, 297, 350, 418")
68      // Windows
69      //    @HtmlUnitNYI(CHROME = "12, 27, 44, 60, 80, 108, 126, 161, 208, 216, 270, 320, 374, 407",
70      //            EDGE = "12, 27, 44, 60, 80, 108, 126, 161, 208, 216, 270, 320, 374, 407",
71      //            FF = "14, 30, 48, 60, 80, 108, 126, 161, 208, 224, 279, 330, 385, 418",
72      //            FF_ESR = "14, 30, 48, 60, 80, 108, 126, 161, 208, 224, 279, 330, 385, 418")
73      // Jenkins
74      @HtmlUnitNYI(CHROME = "18, 27, 44, 75, 96, 108, 147, 184, 234, 243, 300, 352, 374, 481",
75              EDGE = "18, 27, 44, 75, 96, 108, 147, 184, 234, 243, 300, 352, 374, 481",
76              FF = "21, 30, 48, 75, 96, 108, 147, 184, 234, 252, 310, 363, 385, 494",
77              FF_ESR = "21, 30, 48, 75, 96, 108, 147, 184, 234, 252, 310, 363, 385, 494")
78      public void offsetHeightLineBreaks() throws Exception {
79          final String html = DOCTYPE_HTML
80              + "<html><head><body>\n"
81              + "  <div id='myDiv' style='width: 400px'>"
82              + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt "
83              + "ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo "
84              + "dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor "
85              + "sit amet.</div>\n"
86              + "  <textarea id='myTextarea' cols='120' rows='20'></textarea>\n"
87              + "<script>\n"
88              + "  var div = document.getElementById('myDiv');\n"
89              + "  var array = [];\n"
90              + "  for (var i = 6; i <= 32; i+=2) {\n"
91              + "    div.style.fontSize = i + 'px';\n"
92              + "    array.push(div.offsetHeight);\n"
93              + "  }\n"
94              + "  document.getElementById('myTextarea').value = array.join(', ');\n"
95              + "</script>\n"
96              + "</body></html>";
97  
98          final WebDriver driver = loadPage2(html);
99          final String actual = driver.findElement(By.id("myTextarea")).getDomProperty("value");
100         assertEquals(getExpectedAlerts()[0], actual);
101     }
102 
103     /**
104      * @throws Exception if the test fails
105      */
106     @Test
107     @Alerts("true, true, true, true, true, true, true, true, true, true, true, true, true, true")
108     public void offsetHeightLineBreaks2() throws Exception {
109         final String html = DOCTYPE_HTML
110             + "<html><head><body>\n"
111             + "  <div id='myLine'>Lorem ipsum</div>\n"
112             + "  <div id='myDiv' style='width: 400px'>"
113             + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt "
114             + "ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo "
115             + "dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor "
116             + "sit amet.</div>\n"
117             + "  <textarea id='myTextarea' cols='120' rows='20'></textarea>\n"
118             + "<script>\n"
119             + "  var div = document.getElementById('myDiv');\n"
120             + "  var array = [];\n"
121             + "  var lastHeight = 0;\n"
122 
123             + "  for (var i = 6; i <= 32; i+=2) {\n"
124             + "    div.style.fontSize = i + 'px';\n"
125             + "    var height = div.offsetHeight;"
126             + "    array.push(height >= lastHeight);\n"
127             + "    lastHeight = height;\n"
128             + "  }\n"
129             + "  document.getElementById('myTextarea').value = array.join(', ');\n"
130             + "</script>\n"
131             + "</body></html>";
132 
133         final WebDriver driver = loadPage2(html);
134         final String actual = driver.findElement(By.id("myTextarea")).getDomProperty("value");
135         assertEquals(getExpectedAlerts()[0], actual);
136     }
137 
138     /**
139      * Try to do a line break if width is fixed.
140      *
141      * @throws Exception if the test fails
142      */
143     @Test
144     @Alerts("true")
145     public void offsetHeightManualLineBreaks() throws Exception {
146         final String html = DOCTYPE_HTML
147             + "<html><head><body>\n"
148 
149             + "  <div id='myDiv' style='width: 400px;font-size: 12px;'>"
150             + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, "
151             + "sed diam nonumy eirmod tempor invidunt "
152             + "ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo "
153             + "dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor "
154             + "sit amet.</div>\n"
155 
156             + "  <div id='myDivBr' style='width: 400px;font-size: 12px;'>"
157             + "Lorem<br>ipsum<br>dolor<br>sit<br>amet, consetetur sadipscing elitr, "
158             + "sed diam nonumy eirmod tempor invidunt "
159             + "ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo "
160             + "dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor "
161             + "sit amet.</div>\n"
162 
163             + "  <textarea id='myTextarea' cols='120' rows='20'></textarea>\n"
164             + "<script>\n"
165             + "  var div = document.getElementById('myDiv');\n"
166             + "  var divBr = document.getElementById('myDivBr');\n"
167 
168             + "  document.getElementById('myTextarea').value = div.offsetHeight < divBr.offsetHeight;\n"
169             + "</script>\n"
170             + "</body></html>";
171 
172         final WebDriver driver = loadPage2(html);
173         final String actual = driver.findElement(By.id("myTextarea")).getDomProperty("value");
174         assertEquals(getExpectedAlerts()[0], actual);
175     }
176 
177     /**
178      * Tests the relation between {@code fontSize} and {@code offsetHeight}.
179      *
180      * @throws Exception if the test fails
181      */
182     @Test
183     @Alerts(DEFAULT = "10, 11, 16, 18, 21, 27, 37, 55",
184             FF = "11, 12, 16, 18, 21, 28, 38, 56",
185             FF_ESR = "11, 12, 16, 18, 21, 28, 38, 56")
186     public void offsetHeightSmallLarge() throws Exception {
187         final String html = DOCTYPE_HTML
188             + "<html><head><body>\n"
189             + "  <div id='myDiv'>a</div>\n"
190             + "  <textarea id='myTextarea' cols='120' rows='20'></textarea>\n"
191             + "<script>\n"
192             + "var e = document.getElementById('myDiv');\n"
193             + "var array = [];\n"
194 
195             + "e.style.fontSize = 'xx-small';\n"
196             + "array.push(e.offsetHeight);\n"
197 
198             + "e.style.fontSize = 'x-small';\n"
199             + "array.push(e.offsetHeight);\n"
200 
201             + "e.style.fontSize = 'small';\n"
202             + "array.push(e.offsetHeight);\n"
203 
204             + "e.style.fontSize = 'medium';\n"
205             + "array.push(e.offsetHeight);\n"
206 
207             + "e.style.fontSize = 'large';\n"
208             + "array.push(e.offsetHeight);\n"
209 
210             + "e.style.fontSize = 'x-large';\n"
211             + "array.push(e.offsetHeight);\n"
212 
213             + "e.style.fontSize = 'xx-large';\n"
214             + "array.push(e.offsetHeight);\n"
215 
216             + "e.style.fontSize = 'xxx-large';\n"
217             + "array.push(e.offsetHeight);\n"
218 
219             + "document.getElementById('myTextarea').value = array.join(', ');\n"
220             + "</script></body></html>";
221 
222         final WebDriver driver = loadPage2(html);
223         final String actual = driver.findElement(By.id("myTextarea")).getDomProperty("value");
224         assertEquals(getExpectedAlerts()[0], actual);
225     }
226 
227     /**
228      * Tests the relation between {@code fontSize} and {@code offsetHeight}.
229      *
230      * @throws Exception if the test fails
231      */
232     @Test
233     @Alerts("16, 22")
234     public void offsetHeightSmallerLarger() throws Exception {
235         final String html = DOCTYPE_HTML
236             + "<html><head><body>\n"
237             + "  <div id='myDiv'>a</div>\n"
238             + "  <textarea id='myTextarea' cols='120' rows='20'></textarea>\n"
239             + "<script>\n"
240             + "var e = document.getElementById('myDiv');\n"
241             + "var array = [];\n"
242 
243             + "e.style.fontSize = 'smaller';\n"
244             + "array.push(e.offsetHeight);\n"
245 
246             + "e.style.fontSize = 'larger';\n"
247             + "array.push(e.offsetHeight);\n"
248 
249             + "document.getElementById('myTextarea').value = array.join(', ');\n"
250             + "</script></body></html>";
251 
252         final WebDriver driver = loadPage2(html);
253         final String actual = driver.findElement(By.id("myTextarea")).getDomProperty("value");
254         assertEquals(getExpectedAlerts()[0], actual);
255     }
256 
257     /**
258      * Tests the relation between {@code fontSize} and {@code offsetHeight}.
259      *
260      * @throws Exception if the test fails
261      */
262     @Test
263     @Alerts(DEFAULT = "11, 49, 6",
264             FF = "12, 49, 3",
265             FF_ESR = "12, 49, 3")
266     @HtmlUnitNYI(CHROME = "11, 49, 2",
267             EDGE = "11, 49, 2")
268     public void offsetHeightUnits() throws Exception {
269         final String html = DOCTYPE_HTML
270             + "<html><head><body>\n"
271             + "  <div id='myDivPX' style='font-size: 10px;'>a</div>\n"
272             + "  <div id='myDivEM' style='font-size: 2.7em;'>a</div>\n"
273             + "  <div id='myDivP' style='font-size: 10%;'>a</div>\n"
274             + "  <textarea id='myTextarea' cols='120' rows='20'></textarea>\n"
275             + "<script>\n"
276             + "var array = [];\n"
277 
278             + "var e = document.getElementById('myDivPX');\n"
279             + "array.push(e.offsetHeight);\n"
280 
281             + "e = document.getElementById('myDivEM');\n"
282             + "array.push(e.offsetHeight);\n"
283 
284             + "e = document.getElementById('myDivP');\n"
285             + "array.push(e.offsetHeight);\n"
286 
287             + "document.getElementById('myTextarea').value = array.join(', ');\n"
288             + "</script></body></html>";
289 
290         final WebDriver driver = loadPage2(html);
291         final String actual = driver.findElement(By.id("myTextarea")).getDomProperty("value");
292         assertEquals(getExpectedAlerts()[0], actual);
293     }
294 
295     /**
296      * Tests the relation between {@code fontSize} and {@code offsetHeight}.
297      *
298      * @throws Exception if the test fails
299      */
300     @Test
301     @Alerts(DEFAULT = "12, 49, 6",
302             FF = "13, 49, 4",
303             FF_ESR = "13, 49, 4")
304     @HtmlUnitNYI(CHROME = "12, 49, 4",
305             EDGE = "12, 49, 4",
306             FF = "13, 49, 5",
307             FF_ESR = "13, 49, 5")
308     public void offsetHeightUnitsWidth() throws Exception {
309         final String html = DOCTYPE_HTML
310             + "<html><head><body>\n"
311             + "  <div id='myDivPX' style='font-size: 11.4px; width: 40px;'>a</div>\n"
312             + "  <div id='myDivEM' style='font-size: 2.7em; width: 40px;'>a</div>\n"
313             + "  <div id='myDivP' style='font-size: 17%; width: 40px;'>a</div>\n"
314             + "  <textarea id='myTextarea' cols='120' rows='20'></textarea>\n"
315             + "<script>\n"
316             + "var array = [];\n"
317 
318             + "var e = document.getElementById('myDivPX');\n"
319             + "array.push(e.offsetHeight);\n"
320 
321             + "e = document.getElementById('myDivEM');\n"
322             + "array.push(e.offsetHeight);\n"
323 
324             + "e = document.getElementById('myDivP');\n"
325             + "array.push(e.offsetHeight);\n"
326 
327             + "document.getElementById('myTextarea').value = array.join(', ');\n"
328             + "</script></body></html>";
329 
330         final WebDriver driver = loadPage2(html);
331         final String actual = driver.findElement(By.id("myTextarea")).getDomProperty("value");
332         assertEquals(getExpectedAlerts()[0], actual);
333     }
334 
335     /**
336      * Test case for #124.
337      *
338      * @throws Exception if the test fails
339      */
340     @Test
341     @Alerts({"300", "549", "945", "60", "273", "938", "35"})
342     @HtmlUnitNYI(CHROME = {"300", "552", "9690", "60", "294", "6885", "43"},
343             EDGE = {"300", "552", "9690", "60", "294", "6885", "43"},
344             FF = {"300", "552", "9690", "60", "294", "6885", "43"},
345             FF_ESR = {"300", "552", "9690", "60", "294", "6885", "43"})
346     public void issue124() throws Exception {
347         final String html = DOCTYPE_HTML
348             + "<html>\n"
349             + "  <head>\n"
350             + "    <style>\n"
351             + "      .title-box {width: 960px; font-size: 60px;}\n"
352             + "      .title-sizer {height: 300px;}\n"
353             + "    </style>\n"
354             + "  </head>\n"
355             + "  <body>\n"
356             + "    <div class='title-box'>\n"
357             + "      <span class='title-sizer'>\n"
358             + "        <span class='title'>\n"
359             + "          8oz steak from Good and Gather. 8oz steak from Good and Gather. 8oz"
360             + "          steak from Good and Gather. 8oz steak from Good and Gather. 8oz steak"
361             + "          from Good and Gather. 8oz steak from Good and Gather. 8oz steak from"
362             + "          Good and Gather. 8oz steak from Good and Gather."
363             + "        </span>\n"
364             + "      </span>\n"
365             + "    </div>\n"
366             + "  </body>\n"
367 
368             + "  <script>\n"
369             + LOG_TITLE_FUNCTION
370             + "    function getAttributeValue(element, attribute) {\n"
371             + "      if (element) {\n"
372             + "        return window.getComputedStyle(element)[attribute].split('px')[0];\n"
373             + "      }\n"
374             + "      return 0;\n"
375             + "    }\n"
376 
377             + "    var titleSizer = document.querySelector('.title-sizer');\n"
378             + "    var title = document.querySelector('.title');\n"
379             + "    var titleHeight = titleSizer.offsetHeight;\n"
380             + "    var titleHeightGoal = getAttributeValue(titleSizer, 'height');\n"
381             + "    var titleFontSize = getAttributeValue(titleSizer, 'fontSize');\n"
382 
383             + "    log(titleHeightGoal);\n"
384 
385             + "    log(titleHeight);\n"
386             + "    log(titleSizer.offsetWidth);\n"
387             + "    log(titleFontSize);\n"
388 
389             + "    while (titleHeight > titleHeightGoal) {\n"
390             + "      titleFontSize -= 1;\n"
391             + "      title.style.fontSize = titleFontSize + 'px';\n"
392             + "      titleHeight = titleSizer.offsetHeight;\n"
393             + "    }\n"
394 
395             + "    log(titleHeight);\n"
396             + "    log(titleSizer.offsetWidth);\n"
397             + "    log(titleFontSize);\n"
398             + "  </script>\n"
399             + "</html>";
400 
401         loadPageVerifyTitle2(html);
402     }
403 }