1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.dom;
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
22
23
24
25
26
27
28
29 public class SelectionTest extends WebDriverTestCase {
30
31
32
33
34 @Test
35 @Alerts("true")
36 public void equality_selection() throws Exception {
37 final String html = DOCTYPE_HTML
38 + "<html>\n"
39 + "<body>\n"
40 + "<script>"
41 + LOG_TITLE_FUNCTION
42 + "log(document.selection==document.selection);\n"
43 + "</script>\n"
44 + "</body></html>";
45 loadPageVerifyTitle2(html);
46 }
47
48
49
50
51 @Test
52 @Alerts("true")
53 public void equality_getSelection() throws Exception {
54 final String html = DOCTYPE_HTML
55 + "<html><body>\n"
56 + "<script>\n"
57 + LOG_TITLE_FUNCTION
58 + "try {\n"
59 + " log(window.getSelection()==window.getSelection());\n"
60 + "} catch(e) { logEx(e) }\n"
61 + "</script>\n"
62 + "</body></html>";
63 loadPageVerifyTitle2(html);
64 }
65
66
67
68
69 @Test
70 @Alerts({"0", "0", "0", "cdefg"})
71 public void inputSelectionsAreIndependent() throws Exception {
72 final String html = DOCTYPE_HTML
73 + "<html><body onload='test()'>\n"
74 + "<input id='i' value='abcdefghi'/>\n"
75 + "<script>\n"
76 + LOG_TITLE_FUNCTION
77 + " function test() {\n"
78 + " var i = document.getElementById('i');\n"
79 + " var s = window.getSelection();\n"
80 + " log(s.rangeCount);\n"
81 + " i.selectionStart = 2;\n"
82 + " log(s.rangeCount);\n"
83 + " i.selectionEnd = 7;\n"
84 + " log(s.rangeCount);\n"
85 + " log(i.value.substring(i.selectionStart, i.selectionEnd));\n"
86 + " }\n"
87 + "</script>\n"
88 + "</body></html>";
89 loadPageVerifyTitle2(html);
90 }
91
92
93
94
95 @Test
96 @Alerts({"1:null/0/null/0/true/None/0/",
97 "2:s2/0/s2/1/false/Range/1/xyz[xyz"})
98 public void selectAllChildren() throws Exception {
99 final String jsSnippet = ""
100 + " alertSelection(selection);\n"
101 + " selection.selectAllChildren(s2);\n"
102 + " alertSelection(selection);\n";
103
104 tester(jsSnippet);
105 }
106
107
108
109
110 @Test
111 @Alerts({"1:s2/0/s2/1/false/Range/1/xyz[xyz",
112 "2:s2/0/s3/1/false/Range/1/xyzfoo[xyzfoo",
113 "3:s2/0/s3/2/false/Range/1/xyzfoo---[xyzfoo---",
114 "4:s2/0/s3/3/false/Range/1/xyzfoo---foo[xyzfoo---foo"})
115 public void extend() throws Exception {
116 final String jsSnippet = ""
117 + " selection.selectAllChildren(s2);\n"
118 + " alertSelection(selection);\n"
119 + " if (selection.extend) {\n"
120 + " selection.extend(s3, 1);\n"
121 + " alertSelection(selection);\n"
122 + " selection.extend(s3, 2);\n"
123 + " alertSelection(selection);\n"
124 + " selection.extend(s3, 3);\n"
125 + " alertSelection(selection);\n"
126 + " } else { log('selection.extend not available'); }\n";
127
128 tester(jsSnippet);
129 }
130
131
132
133
134 @Test
135 @Alerts({"1:s2/0/s2/1/false/Range/1/xyz[xyz",
136 "2:s2/0/s2/0/true/Caret/1/["})
137 public void collapseToStart() throws Exception {
138 final String jsSnippet = ""
139 + " selection.selectAllChildren(s2);\n"
140 + " alertSelection(selection);\n"
141 + " selection.collapseToStart();\n"
142 + " alertSelection(selection);\n";
143
144 tester(jsSnippet);
145 }
146
147
148
149
150 @Test
151 @Alerts({"1:s2/0/s2/1/false/Range/1/xyz[xyz",
152 "2:s2/1/s2/1/true/Caret/1/["})
153 public void collapseToEnd() throws Exception {
154 final String jsSnippet = ""
155 + " selection.selectAllChildren(s2);\n"
156 + " alertSelection(selection);\n"
157 + " selection.collapseToEnd();\n"
158 + " alertSelection(selection);\n";
159
160 tester(jsSnippet);
161 }
162
163
164
165
166 @Test
167 @Alerts({"1:s2/0/s2/1/false/Range/1/xyz[xyz",
168 "2:null/0/null/0/true/None/0/"})
169 public void empty() throws Exception {
170 final String jsSnippet = ""
171 + " selection.selectAllChildren(s2);\n"
172 + " alertSelection(selection);\n"
173 + " selection.empty();\n"
174 + " alertSelection(selection);\n";
175
176 tester(jsSnippet);
177 }
178
179
180
181
182 @Test
183 @Alerts({"1:null/0/null/0/true/None/0/",
184 "2:null/0/null/0/true/None/0/",
185 "3:s2/1/s3/1/false/Range/1/foo[foo"})
186 public void addRange() throws Exception {
187 final String jsSnippet = ""
188 + " alertSelection(selection);\n"
189
190 + " var range = document.createRange();\n"
191 + " range.setStart(s2, 1);\n"
192 + " range.setEnd(s3, 1);\n"
193 + " alertSelection(selection);\n"
194
195 + " selection.addRange(range);\n"
196 + " alertSelection(selection);\n";
197
198 tester(jsSnippet);
199 }
200
201
202
203
204 @Test
205 @Alerts({"1:null/0/null/0/true/None/0/",
206 "2:s1/1/s3/1/false/Range/1/xyzfoo[xyzfoo",
207 "3:null/0/null/0/true/None/0/"})
208 public void removeAllRanges() throws Exception {
209 final String jsSnippet = ""
210 + " alertSelection(selection);\n"
211
212 + " var range = document.createRange();\n"
213 + " range.setStart(s1, 1);\n"
214 + " range.setEnd(s3, 1);\n"
215 + " selection.addRange(range);\n"
216 + " alertSelection(selection);\n"
217
218 + " selection.removeAllRanges();\n"
219 + " alertSelection(selection);\n";
220
221 tester(jsSnippet);
222 }
223
224
225
226
227 @Test
228 @Alerts({"1:s1/1/s3/1/false/Range/1/xyzfoo[xyzfoo",
229 "2:null/0/null/0/true/None/0/"})
230 public void removeAllRanges2() throws Exception {
231 final String jsSnippet = ""
232 + " var range = document.createRange();\n"
233 + " range.setStart(s1, 1);\n"
234 + " range.setEnd(s3, 1);\n"
235 + " selection.addRange(range);\n"
236 + " alertSelection(selection);\n"
237
238 + " selection.removeAllRanges();\n"
239 + " alertSelection(selection);\n";
240
241 tester(jsSnippet);
242 }
243
244
245
246
247 @Test
248 @Alerts(DEFAULT = {"1:null/0/null/0/true/None/0/",
249 "2:s1/0/s1/1/false/Range/1/abc[abc",
250 "3:null/0/null/0/true/None/0/"},
251 FF = {"1:null/0/null/0/true/None/0/",
252 "2:s1/1/s3/1/false/Range/2/abcxyzfoo[abc[xyzfoo",
253 "3:null/0/null/0/true/None/0/"},
254 FF_ESR = {"1:null/0/null/0/true/None/0/",
255 "2:s1/1/s3/1/false/Range/2/abcxyzfoo[abc[xyzfoo",
256 "3:null/0/null/0/true/None/0/"})
257 @HtmlUnitNYI(CHROME = {"1:null/0/null/0/true/None/0/",
258 "2:s1/0/s1/1/false/Range/2/abcxyzfoo[abc[xyzfoo",
259 "3:null/0/null/0/true/None/0/"},
260 EDGE = {"1:null/0/null/0/true/None/0/",
261 "2:s1/0/s1/1/false/Range/2/abcxyzfoo[abc[xyzfoo",
262 "3:null/0/null/0/true/None/0/"},
263 FF = {"1:null/0/null/0/true/None/0/",
264 "2:s1/0/s1/1/false/Range/2/abcxyzfoo[abc[xyzfoo",
265 "3:null/0/null/0/true/None/0/"},
266 FF_ESR = {"1:null/0/null/0/true/None/0/",
267 "2:s1/0/s1/1/false/Range/2/abcxyzfoo[abc[xyzfoo",
268 "3:null/0/null/0/true/None/0/"})
269 public void selectAllChildrenAddRange() throws Exception {
270 final String jsSnippet = ""
271 + " alertSelection(selection);\n"
272
273 + " selection.selectAllChildren(s1);\n"
274 + " var range = document.createRange();\n"
275 + " range.setStart(s1, 1);\n"
276 + " range.setEnd(s3, 1);\n"
277 + " selection.addRange(range);\n"
278 + " alertSelection(selection);\n"
279
280 + " selection.removeAllRanges();\n"
281 + " alertSelection(selection);\n";
282
283 tester(jsSnippet);
284 }
285
286
287
288
289 @Test
290 @Alerts({"1:null/0/null/0/true/None/0/",
291 "2:s1/0/s1/1/false/Range/1/abc[abc",
292 "3:null/0/null/0/true/None/0/"})
293 public void addRangeSelectAllChildren() throws Exception {
294 final String jsSnippet = ""
295 + " alertSelection(selection);\n"
296
297 + " var range = document.createRange();\n"
298 + " range.setStart(s1, 1);\n"
299 + " range.setEnd(s3, 1);\n"
300 + " selection.addRange(range);\n"
301 + " selection.selectAllChildren(s1);\n"
302 + " alertSelection(selection);\n"
303
304 + " selection.removeAllRanges();\n"
305 + " alertSelection(selection);\n";
306
307 tester(jsSnippet);
308 }
309
310
311
312
313 @Test
314 @Alerts(DEFAULT = {"1:null/0/null/0/true/None/0/",
315 "2:s1/0/s1/1/false/Range/1/abc[abc",
316 "3:s1/0/s1/1/false/Range/1/abc[abc",
317 "4:null/0/null/0/true/None/0/"},
318 FF = {"1:null/0/null/0/true/None/0/",
319 "2:s1/1/s2/1/false/Range/2/abcxyz[abc[xyz",
320 "3:s2/1/s3/3/false/Range/3/abcxyzfoo---foo[abc[xyz[foo---foo",
321 "4:null/0/null/0/true/None/0/"},
322 FF_ESR = {"1:null/0/null/0/true/None/0/",
323 "2:s1/1/s2/1/false/Range/2/abcxyz[abc[xyz",
324 "3:s2/1/s3/3/false/Range/3/abcxyzfoo---foo[abc[xyz[foo---foo",
325 "4:null/0/null/0/true/None/0/"})
326 @HtmlUnitNYI(CHROME = {"1:null/0/null/0/true/None/0/",
327 "2:s1/0/s1/1/false/Range/2/abcxyz[abc[xyz",
328 "3:s2/1/s3/3/false/Range/3/abcxyzfoo---foo[abc[xyz[foo---foo",
329 "4:null/0/null/0/true/None/0/"},
330 EDGE = {"1:null/0/null/0/true/None/0/",
331 "2:s1/0/s1/1/false/Range/2/abcxyz[abc[xyz",
332 "3:s2/1/s3/3/false/Range/3/abcxyzfoo---foo[abc[xyz[foo---foo",
333 "4:null/0/null/0/true/None/0/"},
334 FF = {"1:null/0/null/0/true/None/0/",
335 "2:s1/0/s1/1/false/Range/2/abcxyz[abc[xyz",
336 "3:s2/1/s3/3/false/Range/3/abcxyzfoo---foo[abc[xyz[foo---foo",
337 "4:null/0/null/0/true/None/0/"},
338 FF_ESR = {"1:null/0/null/0/true/None/0/",
339 "2:s1/0/s1/1/false/Range/2/abcxyz[abc[xyz",
340 "3:s2/1/s3/3/false/Range/3/abcxyzfoo---foo[abc[xyz[foo---foo",
341 "4:null/0/null/0/true/None/0/"})
342 public void addRangeAddRange() throws Exception {
343 final String jsSnippet = ""
344 + " alertSelection(selection);\n"
345
346 + " selection.selectAllChildren(s1);\n"
347 + " var range = document.createRange();\n"
348 + " range.setStart(s1, 1);\n"
349 + " range.setEnd(s2, 1);\n"
350 + " selection.addRange(range);\n"
351 + " alertSelection(selection);\n"
352
353 + " var range = document.createRange();\n"
354 + " range.setStart(s2, 1);\n"
355 + " range.setEnd(s3, 3);\n"
356 + " selection.addRange(range);\n"
357 + " alertSelection(selection);\n"
358
359 + " selection.removeAllRanges();\n"
360 + " alertSelection(selection);\n";
361
362 tester(jsSnippet);
363 }
364
365
366
367
368
369
370 @Test
371 @Alerts({"1:[object Text]/1/[object Text]/2/false/Range/1/yzfo[yzfo",
372 "2:null/0/null/0/true/None/0/",
373 "false", "true"})
374 public void aLittleBitOfEverything_removeRange() throws Exception {
375 final String jsSnippet = ""
376 + " var range = document.createRange();\n"
377 + " range.setStart(s2.firstChild, 1);\n"
378 + " range.setEnd(s3.firstChild, 2);\n"
379 + " selection.addRange(range);\n"
380 + " alertSelection(selection);\n"
381 + " selection.removeRange(range);\n"
382 + " alertSelection(selection);\n"
383 + " log(range.collapsed);\n"
384 + " selection.addRange(range);\n"
385 + " log(selection.getRangeAt(0) == selection.getRangeAt(0));\n";
386
387 tester(jsSnippet);
388 }
389
390 private void tester(final String jsSnippet) throws Exception {
391 final String html = DOCTYPE_HTML
392 + "<html>\n"
393 + "<body onload='test()'>\n"
394 + " <span id='s1'>abc</span><span id='s2'>xyz</span><span id='s3'>foo<span>---</span>foo</span>\n"
395
396 + "<script>\n"
397 + LOG_TITLE_FUNCTION
398 + " var x = 1;\n"
399 + " function test() {\n"
400 + " var selection = window.getSelection();\n"
401 + " var s1 = document.getElementById('s1');\n"
402 + " var s2 = document.getElementById('s2');\n"
403 + " var s3 = document.getElementById('s3');\n"
404 + " try {\n"
405 + jsSnippet
406 + " } catch(e) { logEx(e); }\n"
407 + " }\n"
408
409 + " function alertSelection(s) {\n"
410 + " var anchorNode = (s.anchorNode && s.anchorNode.id ? s.anchorNode.id : s.anchorNode);\n"
411 + " var focusNode = (s.focusNode && s.focusNode.id ? s.focusNode.id : s.focusNode);\n"
412 + " var msg = (x++) + ':' + anchorNode + '/' + s.anchorOffset + '/' + focusNode + '/' +\n"
413 + " s.focusOffset + '/' + s.isCollapsed + '/' + s.type + '/' + s.rangeCount + '/' + s;\n"
414 + " for(var i = 0; i < s.rangeCount; i++) {\n"
415 + " msg += '[' + s.getRangeAt(i);\n"
416 + " }\n"
417 + " log(msg);\n"
418 + " }\n"
419 + "</script>\n"
420 + "</body></html>";
421 loadPageVerifyTitle2(html);
422 }
423
424
425
426
427 @Test
428 @Alerts(DEFAULT = {"", "null-0", "", "null-0", "", "null-0", "", "null-0"},
429 FF = {"", "null-0", "", "null-0", "null", "null"},
430 FF_ESR = {"", "null-0", "", "null-0", "null", "null"})
431 public void getSelection_display() throws Exception {
432 final String html = DOCTYPE_HTML
433 + "<html>\n"
434 + "<body onload='test()'>\n"
435 + " <iframe id='frame1' src='about:blank'></iframe>\n"
436 + " <iframe id='frame2' src='about:blank' style='display: none'></iframe>\n"
437 + " <div style='display: none'>\n"
438 + " <iframe id='frame3' src='about:blank'></iframe>\n"
439 + " </div>\n"
440
441 + " <script>\n"
442 + LOG_TITLE_FUNCTION
443 + " function sel(win) {\n"
444 + " if (win.getSelection) {\n"
445 + " var range = win.getSelection();\n"
446 + " log(range);\n"
447 + " if (range) {\n"
448 + " log(range.anchorNode + '-' + range.rangeCount);\n"
449 + " }\n"
450 + " }\n"
451 + " }\n"
452
453 + " function test() {\n"
454 + " sel(window);\n"
455 + " sel(document.getElementById('frame1').contentWindow);\n"
456 + " sel(document.getElementById('frame2').contentWindow);\n"
457 + " sel(document.getElementById('frame3').contentWindow);\n"
458 + " }\n"
459 + " </script>\n"
460 + "</body></html>";
461 loadPageVerifyTitle2(html);
462 }
463
464
465
466
467 @Test
468 @Alerts({"", "", ""})
469 public void testToString() throws Exception {
470 final String html = DOCTYPE_HTML
471 + "<html>\n"
472 + "<body onload='test()'>\n"
473 + "<input id='i' value='abcdefghi'/>\n"
474 + "<script>\n"
475 + LOG_TITLE_FUNCTION
476 + " function test() {\n"
477 + " var i = document.getElementById('i');\n"
478 + " var s = window.getSelection();\n"
479 + " log(s);\n"
480 + " log('' + s);\n"
481 + " log(s.toString());\n"
482 + " }\n"
483 + "</script>\n"
484 + "</body></html>";
485 loadPageVerifyTitle2(html);
486 }
487 }