1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.html;
16
17 import java.io.InputStream;
18 import java.net.URL;
19 import java.util.Collections;
20
21 import org.apache.commons.io.IOUtils;
22 import org.htmlunit.WebDriverTestCase;
23 import org.htmlunit.junit.annotation.Alerts;
24 import org.htmlunit.junit.annotation.BuggyWebDriver;
25 import org.htmlunit.junit.annotation.HtmlUnitNYI;
26 import org.htmlunit.util.MimeType;
27 import org.junit.jupiter.api.Test;
28 import org.openqa.selenium.By;
29 import org.openqa.selenium.WebDriver;
30 import org.openqa.selenium.WebElement;
31 import org.openqa.selenium.htmlunit.HtmlUnitDriver;
32
33
34
35
36
37
38
39
40
41
42
43
44 public class HtmlElement2Test extends WebDriverTestCase {
45
46
47
48
49 @Test
50 public void onpropertychange() throws Exception {
51 final String html = DOCTYPE_HTML
52 + "<html><head><script>\n"
53 + LOG_TITLE_FUNCTION
54 + " function test() {\n"
55 + " document.getElementById('input1').value = 'New Value';\n"
56 + " }\n"
57 + " function handler() {\n"
58 + " log(event.propertyName);\n"
59 + " }\n"
60 + "</script></head>\n"
61 + "<body onload='test()'>\n"
62 + " <input id='input1' onpropertychange='handler()'>\n"
63 + "</body></html>";
64
65 loadPageVerifyTitle2(html);
66 }
67
68
69
70
71 @Test
72 @Alerts({"true", "true"})
73 public void duplicateId() throws Exception {
74 final String html = DOCTYPE_HTML
75 + "<html>\n"
76 + "<script>\n"
77 + LOG_TITLE_FUNCTION
78 + " function test() {\n"
79 + " var value = document.getElementById('duplicateID').innerHTML;\n"
80 + " log(value.length > 10);\n"
81 + " document.getElementById('duplicateID').style.display = 'block';\n"
82 + " log(value === document.getElementById('duplicateID').innerHTML);\n"
83 + " }\n"
84 + "</script>\n"
85 + "</head>\n"
86 + "<body onload='test()'>\n"
87 + " <fieldset id='duplicateID'><span id='duplicateID'></span></fieldset>\n"
88 + "</body></html>";
89
90 loadPageVerifyTitle2(html);
91 }
92
93
94
95
96 @Test
97 public void onpropertychange2() throws Exception {
98 final String html = DOCTYPE_HTML
99 + "<html><head><script>\n"
100 + LOG_TITLE_FUNCTION
101 + " function test() {\n"
102 + " document.getElementById('input1').value = 'New Value';\n"
103 + " }\n"
104 + " function handler() {\n"
105 + " log(1);\n"
106 + " document.getElementById('input1').dir='rtl';\n"
107 + " }\n"
108 + "</script></head>\n"
109 + "<body onload='test()'>\n"
110 + " <input id='input1' onpropertychange='handler()'>\n"
111 + "</body></html>";
112
113 loadPageVerifyTitle2(html);
114 }
115
116
117
118
119
120
121
122 @Test
123 @Alerts({"false", "true", "a", "a", "b", "b", "b", "c"})
124 public void clonedNodeAttributes() throws Exception {
125 final String html = DOCTYPE_HTML
126 + "<html><body id='a' title='b'><script>\n"
127 + LOG_TITLE_FUNCTION
128 + "var x = document.body.cloneNode(true);\n"
129 + "log(document.body == x);\n"
130 + "log(document.getElementById('a') == document.body);\n"
131 + "log(document.body.id);\n"
132 + "log(x.id);\n"
133 + "log(document.body.title);\n"
134 + "log(x.title);\n"
135 + "x.title = 'c';\n"
136 + "log(document.body.title);\n"
137 + "log(x.title);\n"
138 + "</script></body></html>";
139
140 loadPageVerifyTitle2(html);
141 }
142
143
144
145
146
147
148 @Test
149 @Alerts({"true", "undefined", "undefined"})
150 public void textAndXmlUndefined() throws Exception {
151 final String html = DOCTYPE_HTML
152 + "<html><head></head>\n"
153 + "<body>\n"
154 + " <input type='text' id='textfield1' onfocus='log(1)'>\n"
155 + " <script>\n"
156 + LOG_TITLE_FUNCTION
157 + " var node = document.getElementById('textfield1');\n"
158 + " log(node.attributes[0].nodeName.length > 0);\n"
159 + " log(node.attributes[0].text);\n"
160 + " log(node.attributes[0].xml);\n"
161 + " </script>\n"
162 + "</body></html>";
163
164 loadPageVerifyTitle2(html);
165 }
166
167
168
169
170 @Test
171 @Alerts("something")
172 @BuggyWebDriver(FF = "",
173 FF_ESR = "")
174 @HtmlUnitNYI(CHROME = "initialsomething",
175 EDGE = "initialsomething",
176 FF = "initialsomething",
177 FF_ESR = "initialsomething")
178
179
180 public void contentEditable() throws Exception {
181 final String html = DOCTYPE_HTML
182 + "<html>\n"
183 + "<body contentEditable><p>initial</p></body>\n"
184 + "</html>";
185
186 final WebDriver driver = loadPage2(html);
187 final WebElement body = driver.findElement(By.xpath("//body"));
188 body.clear();
189 body.sendKeys("something");
190 assertEquals(getExpectedAlerts()[0], body.getText());
191 }
192
193
194
195
196 @Test
197
198 @Alerts("down: 16,0 down: 49,0 press: 33,33 up: 49,0 up: 16,0"
199 + " down: 16,0 down: 220,0 press: 124,124 up: 220,0 up: 16,0")
200
201 @BuggyWebDriver(FF_ESR = "down: 49,0 press: 33,33 up: 49,0 down: 220,0 press: 124,124 up: 220,0",
202 FF = "down: 49,0 press: 33,33 up: 49,0 down: 220,0 press: 124,124 up: 220,0")
203 public void shiftKeys() throws Exception {
204 final String html = DOCTYPE_HTML
205 + "<html><head><script>\n"
206 + " function appendMessage(message) {\n"
207 + " document.getElementById('result').innerHTML += message + ' ';\n"
208 + " }\n"
209 + "</script></head>\n"
210 + "<body >\n"
211 + " <input id='input1' onkeyup=\"appendMessage('up: ' + event.keyCode + ',' + event.charCode)\" "
212 + "onkeypress=\"appendMessage('press: ' + event.keyCode + ',' + event.charCode)\" "
213 + "onkeydown=\"appendMessage('down: ' + event.keyCode + ',' + event.charCode)\"><br>\n"
214 + "<p id='result'></p>\n"
215 + "</body></html>";
216
217 final WebDriver driver = loadPage2(html);
218 final WebElement input = driver.findElement(By.id("input1"));
219 final WebElement result = driver.findElement(By.id("result"));
220 input.sendKeys("!|");
221 assertEquals(getExpectedAlerts()[0], result.getText());
222 }
223
224
225
226
227 @Test
228 @Alerts(DEFAULT = "[object HTMLInputElement] [object HTMLBodyElement]",
229 CHROME = "[object HTMLInputElement] onblur onfocusout [object HTMLBodyElement]",
230 EDGE = "[object HTMLInputElement] onblur onfocusout [object HTMLBodyElement]")
231 public void removeActiveElement() throws Exception {
232 final String html = DOCTYPE_HTML
233 + "<html>\n"
234 + "<head>\n"
235 + "<script>\n"
236 + "function test() {\n"
237 + " var elem = document.getElementById('text1');\n"
238 + " elem.focus();\n"
239 + " document.title += ' ' + document.activeElement;\n"
240 + " elem.parentNode.removeChild(elem);\n"
241 + " document.title += ' ' + document.activeElement;\n"
242 + "}\n"
243 + "</script>\n"
244 + "</head>\n"
245 + "<body onload='test()'>\n"
246 + "<form name='form1'>\n"
247 + " <input id='text1' onblur='document.title += \" onblur\"' "
248 + "onfocusout='document.title += \" onfocusout\"'>\n"
249 + "</form>\n"
250 + "</body></html>";
251
252 final WebDriver driver = loadPage2(html);
253 assertTitle(driver, getExpectedAlerts()[0]);
254 }
255
256
257
258
259 @Test
260 @Alerts(DEFAULT = "[object HTMLInputElement] [object HTMLBodyElement]",
261 CHROME = "[object HTMLInputElement] onblur1 onfocusout1 [object HTMLBodyElement]",
262 EDGE = "[object HTMLInputElement] onblur1 onfocusout1 [object HTMLBodyElement]")
263 public void removeParentOfActiveElement() throws Exception {
264 final String html = DOCTYPE_HTML
265 + "<html>\n"
266 + "<head>\n"
267 + "<script>\n"
268 + "function test() {\n"
269 + " var elem = document.getElementById('text1');\n"
270 + " elem.focus();\n"
271 + " document.title += ' ' + document.activeElement;\n"
272
273 + " var elem = document.getElementById('parent');\n"
274 + " elem.parentNode.removeChild(elem);\n"
275 + " document.title += ' ' + document.activeElement;\n"
276 + "}\n"
277 + "</script>\n"
278 + "</head>\n"
279 + "<body onload='test()'>\n"
280 + "<form name='form1'>\n"
281 + " <div id='parent'>\n"
282 + " <input id='text1' onblur='document.title += \" onblur1\"' "
283 + "onfocusout='document.title += \" onfocusout1\"'>\n"
284 + " <input id='text2' onblur='document.title += \" onblur2\"' "
285 + "onfocusout='document.title += \" onfocusout2\"'>\n"
286 + " </div>\n"
287 + "</form>\n"
288 + "</body></html>";
289
290 final WebDriver driver = loadPage2(html);
291 assertTitle(driver, getExpectedAlerts()[0]);
292 }
293
294
295
296
297
298
299 @Test
300 @Alerts({"before appendChild;after appendChild;image onload;after removeChild;", "2"})
301 public void addRemove() throws Exception {
302 try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
303 final byte[] directBytes = IOUtils.toByteArray(is);
304 final URL urlImage = new URL(URL_FIRST, "img.jpg");
305 getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
306 }
307
308 final String html = DOCTYPE_HTML
309 + "<html>\n"
310 + "<head>\n"
311 + "<script>\n"
312 + "function test() {\n"
313 + " var elem = document.createElement('img');\n"
314 + " elem.setAttribute('alt', '');\n"
315 + " elem.setAttribute('src', 'img.jpg');\n"
316 + " elem.style.display = 'none';\n"
317 + " elem.onload = function() {\n"
318 + " document.title += 'image onload;';"
319 + " document.body.removeChild(elem);\n"
320 + " document.title += 'after removeChild;';"
321 + " }\n"
322 + " document.title += 'before appendChild;';"
323 + " document.body.appendChild(elem);\n"
324 + " document.title += 'after appendChild;';"
325 + "}\n"
326 + "</script>\n"
327 + "</head>\n"
328 + "<body onload='test()'>\n"
329 + "</body></html>";
330
331 final int count = getMockWebConnection().getRequestCount();
332 final WebDriver driver = getWebDriver();
333 if (driver instanceof HtmlUnitDriver) {
334 ((HtmlUnitDriver) driver).setDownloadImages(true);
335 }
336 loadPage2(html);
337
338 assertTitle(driver, getExpectedAlerts()[0]);
339 assertEquals(Integer.parseInt(getExpectedAlerts()[1]), getMockWebConnection().getRequestCount() - count);
340 }
341
342
343
344
345 @Test
346 public void keyPressEventWhenPreventsDefault() throws Exception {
347 final String html = DOCTYPE_HTML
348 + "<html>\n"
349 + "<body>\n"
350 + " <input id='suppress' onkeydown='event.preventDefault()' onkeypress='alert(\"press\")'>\n"
351 + "</body></html>";
352
353 final WebDriver driver = loadPage2(html);
354 driver.findElement(By.id("suppress")).sendKeys("s");
355 verifyAlerts(driver, getExpectedAlerts());
356 }
357
358
359
360
361 @Test
362 @Alerts("press")
363 public void keyUpEventWhenPreventsDefault() throws Exception {
364 final String html = DOCTYPE_HTML
365 + "<html>\n"
366 + "<body>\n"
367 + " <input id='suppress' onkeydown='event.preventDefault()' onkeyup='alert(\"press\")'>\n"
368 + "</body></html>";
369
370 final WebDriver driver = loadPage2(html);
371 driver.findElement(By.id("suppress")).sendKeys("s");
372 verifyAlerts(driver, getExpectedAlerts());
373 }
374
375
376
377
378 @Test
379 @Alerts({"[object HTMLHtmlElement]", "null"})
380 public void detach() throws Exception {
381 final String html = DOCTYPE_HTML
382 + "<html><head><script>\n"
383 + LOG_TITLE_FUNCTION
384 + " function test() {\n"
385 + " var xhr = new XMLHttpRequest();\n"
386 + " xhr.onload = function () {\n"
387 + " var xml = xhr.responseXML;\n"
388 + " log(xml.documentElement);\n"
389 + " xml.removeChild(xml.firstChild);\n"
390 + " log(xml.documentElement);\n"
391 + " }\n"
392 + " xhr.open('GET', '" + URL_SECOND + "');\n"
393 + " xhr.send();\n"
394 + " }\n"
395 + "</script></head><body onload='test()'>\n"
396 + "</body></html>\n";
397
398 final String xml = "<html xmlns=\"http://www.w3.org/1999/xhtml\"></html>";
399 getMockWebConnection().setResponse(URL_SECOND, xml, MimeType.APPLICATION_XML);
400 loadPage2(html);
401 verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
402 }
403
404
405
406
407 @Test
408 @Alerts("Hello-world")
409 public void typeAtEndOfEditableDiv() throws Exception {
410 final String html = DOCTYPE_HTML
411 + "<html><head><script>\n"
412 + " function test() {\n"
413 + " alert(document.getElementById('myInput').value);\n"
414 + " }\n"
415 + "</script></head>\n"
416 + "<body>\n"
417 + " <input id='myButton' type='button' onclick='test()'>\n"
418 + " <div id='myInput' contenteditable='true'>Hello</div>\n"
419 + "</body></html>";
420
421 final WebDriver driver = loadPage2(html);
422 final WebElement div = driver.findElement(By.id("myInput"));
423 div.sendKeys("-world");
424
425 assertEquals(getExpectedAlerts()[0], div.getText());
426 }
427
428
429
430
431 @Test
432 @Alerts("Hello-world")
433 @BuggyWebDriver(FF = "Hello\n-world",
434 FF_ESR = "Hello\n-world")
435 public void typeAtEndOfEditableDivWithParagraphInside() throws Exception {
436 final String html = DOCTYPE_HTML
437 + "<html><head><script>\n"
438 + " function test() {\n"
439 + " alert(document.getElementById('myInput').value);\n"
440 + " }\n"
441 + "</script></head>\n"
442 + "<body>\n"
443 + " <input id='myButton' type='button' onclick='test()'>\n"
444 + " <div id='myInput' contenteditable='true'><p>Hello</p></div>\n"
445 + "</body></html>";
446
447 final WebDriver driver = loadPage2(html);
448 final WebElement div = driver.findElement(By.id("myInput"));
449 div.sendKeys("-world");
450
451 assertEquals(getExpectedAlerts()[0], div.getText());
452 }
453
454
455
456
457
458 @Test
459 @Alerts({"bottom", "bottom", "bottom", "", "bottom", "bottom"})
460 public void setGetStyle() throws Exception {
461 final String html = DOCTYPE_HTML
462 + "<html>\n"
463 + "<head>\n"
464 + "<script>\n"
465 + LOG_TITLE_FUNCTION
466 + " function test() {\n"
467 + " var d = document.createElement('div');\n"
468 + " d.style.verticalAlign = 'bottom';\n"
469 + " log(d.style.getPropertyValue('vertical-align'));\n"
470
471 + " d = document.getElementById('style-already-set');\n"
472 + " log(d.style.getPropertyValue('vertical-align'));\n"
473 + " document.body.removeChild(d);\n"
474 + " log(d.style.getPropertyValue('vertical-align'));\n"
475
476 + " d = document.getElementById('style-unset');\n"
477 + " log(d.style.getPropertyValue('vertical-align'));\n"
478 + " d.style.verticalAlign = 'bottom';\n"
479 + " log(d.style.getPropertyValue('vertical-align'));\n"
480 + " document.body.removeChild(d);\n"
481 + " log(d.style.getPropertyValue('vertical-align'));\n"
482
483 + " }\n"
484 + "</script>\n"
485 + "</head>\n"
486 + "<body onload='test()'>\n"
487 + " <div id='style-already-set' style='vertical-align: bottom'></div>\n"
488 + " <div id='style-unset'></div>"
489 + "</body>\n"
490 + "</html>";
491
492 loadPageVerifyTitle2(html);
493 }
494 }