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.dom;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.junit.BrowserRunner;
19  import org.htmlunit.junit.annotation.Alerts;
20  import org.junit.Test;
21  import org.junit.runner.RunWith;
22  
23  /**
24   * Tests for {@link NodeList}.
25   *
26   * @author Ahmed Ashour
27   * @author Ronald Brill
28   * @author Lai Quang Duong
29   */
30  @RunWith(BrowserRunner.class)
31  public class NodeListTest extends WebDriverTestCase {
32  
33      /**
34       * @throws Exception on test failure
35       */
36      @Test
37      @Alerts("[object NodeList]")
38      public void defaultValue() throws Exception {
39          final String html = DOCTYPE_HTML
40                  + "<html><head>\n"
41                  + "<script>\n"
42                  + LOG_TITLE_FUNCTION
43                  + "  function test() {\n"
44                  + "    log(document.getElementById('myId').firstChild.childNodes);\n"
45                  + "  }\n"
46                  + "</script>\n"
47                  + "</head><body onload='test()'>\n"
48                  + "  <div id='myId'>abcd</div>\n"
49                  + "</body></html>";
50  
51          loadPageVerifyTitle2(html);
52      }
53  
54      /**
55       * @throws Exception on test failure
56       */
57      @Test
58      @Alerts({"true", "true", "false", "true", "true", "true", "true", "true", "true"})
59      public void has() throws Exception {
60          final String html = DOCTYPE_HTML
61                  + "<html><head>\n"
62                  + "<script>\n"
63                  + LOG_TITLE_FUNCTION
64                  + "  function test() {\n"
65                  + "    var nodeList = document.querySelectorAll('*');\n"
66                  + "    log(0 in nodeList);\n"
67                  + "    log(3 in nodeList);\n"
68                  + "    log(4 in nodeList);\n"
69  
70                  + "    log('entries' in nodeList);\n"
71                  + "    log('forEach' in nodeList);\n"
72                  + "    log('item' in nodeList);\n"
73                  + "    log('keys' in nodeList);\n"
74                  + "    log('length' in nodeList);\n"
75                  + "    log('values' in nodeList);\n"
76                  + "  }\n"
77                  + "</script>\n"
78                  + "</head><body onload='test()'>\n"
79                  + "</body></html>";
80  
81          loadPageVerifyTitle2(html);
82      }
83  
84      /**
85       * @throws Exception on test failure
86       */
87      @Test
88      @Alerts({"4", "true", "undefined"})
89      public void length() throws Exception {
90          final String html = DOCTYPE_HTML
91                  + "<html><head>\n"
92                  + "<script>\n"
93                  + LOG_TITLE_FUNCTION
94                  + "  function test() {\n"
95                  + "    var nodeList = document.querySelectorAll('*');\n"
96                  + "    log(nodeList.length);\n"
97  
98                  + "    log('length' in nodeList);\n"
99                  + "    log(Object.getOwnPropertyDescriptor(nodeList, 'length'));\n"
100                 + "  }\n"
101                 + "</script>\n"
102                 + "</head><body onload='test()'>\n"
103                 + "</body></html>";
104 
105         loadPageVerifyTitle2(html);
106     }
107 
108     /**
109      * @throws Exception on test failure
110      */
111     @Test
112     @Alerts({"[object HTMLHtmlElement]", "[object HTMLScriptElement]", "null", "null"})
113     public void item() throws Exception {
114         final String html = DOCTYPE_HTML
115                 + "<html><head>\n"
116                 + "<script>\n"
117                 + LOG_TITLE_FUNCTION
118                 + "  function test() {\n"
119                 + "    var nodeList = document.querySelectorAll('*');\n"
120                 + "    log(nodeList.item(0));\n"
121                 + "    log(nodeList.item(2));\n"
122                 + "    log(nodeList.item(17));\n"
123                 + "    log(nodeList.item(-1));\n"
124                 + "  }\n"
125                 + "</script>\n"
126                 + "</head><body onload='test()'>\n"
127                 + "  <div></div>\n"
128                 + "</body></html>";
129 
130         loadPageVerifyTitle2(html);
131     }
132 
133     /**
134      * @throws Exception on test failure
135      */
136     @Test
137     @Alerts({"[object HTMLHtmlElement]", "[object HTMLScriptElement]", "undefined", "undefined"})
138     public void itemBracketed() throws Exception {
139         final String html = DOCTYPE_HTML
140                 + "<html><head>\n"
141                 + "<script>\n"
142                 + LOG_TITLE_FUNCTION
143                 + "  function test() {\n"
144                 + "    var nodeList = document.querySelectorAll('*');\n"
145                 + "    log(nodeList[0]);\n"
146                 + "    log(nodeList[2]);\n"
147                 + "    log(nodeList[17]);\n"
148                 + "    log(nodeList[-1]);\n"
149                 + "  }\n"
150                 + "</script>\n"
151                 + "</head><body onload='test()'>\n"
152                 + "  <div></div>\n"
153                 + "</body></html>";
154 
155         loadPageVerifyTitle2(html);
156     }
157 
158     /**
159      * @throws Exception on test failure
160      */
161     @Test
162     @Alerts("0,1,2,3,4,entries,forEach,item,keys,length,values")
163     public void forIn() throws Exception {
164         final String html = DOCTYPE_HTML
165                 + "<html><head>\n"
166                 + "<script>\n"
167                 + LOG_TITLE_FUNCTION
168                 + "  function test() {\n"
169                 + "    var all = [];\n"
170                 + "    for (var i in document.querySelectorAll('*')) {\n"
171                 + "      all.push(i);\n"
172                 + "    }\n"
173                 + "    all.sort(sortFunction);\n"
174                 + "    log(all);\n"
175                 + "  }\n"
176                 + "  function sortFunction(s1, s2) {\n"
177                 + "    return s1.toLowerCase() > s2.toLowerCase() ? 1 : -1;\n"
178                 + "  }\n"
179                 + "</script>\n"
180                 + "</head><body onload='test()'>\n"
181                 + "  <div></div>\n"
182                 + "</body></html>";
183 
184         loadPageVerifyTitle2(html);
185     }
186 
187     /**
188      * @throws Exception on test failure
189      */
190     @Test
191     @Alerts("entries,forEach,item,keys,length,values")
192     public void forInEmptyList() throws Exception {
193         final String html = DOCTYPE_HTML
194                 + "<html><head>\n"
195                 + "<script>\n"
196                 + LOG_TITLE_FUNCTION
197                 + "  function test() {\n"
198                 + "    var all = [];\n"
199                 + "    for (var i in document.querySelectorAll('.notThere')) {\n"
200                 + "      all.push(i);\n"
201                 + "    }\n"
202                 + "    all.sort(sortFunction);\n"
203                 + "    log(all);\n"
204                 + "  }\n"
205                 + "  function sortFunction(s1, s2) {\n"
206                 + "    return s1.toLowerCase() > s2.toLowerCase() ? 1 : -1;\n"
207                 + "  }\n"
208                 + "</script>\n"
209                 + "</head><body onload='test()'>\n"
210                 + "  <div></div>\n"
211                 + "</body></html>";
212 
213         loadPageVerifyTitle2(html);
214     }
215 
216     /**
217      * @throws Exception on test failure
218      */
219     @Test
220     @Alerts({"true", "[object HTMLHtmlElement]", "[object HTMLHeadElement]",
221              "[object HTMLScriptElement]", "[object HTMLBodyElement]",
222              "[object HTMLDivElement]"})
223     public void iterator() throws Exception {
224         final String html = DOCTYPE_HTML
225                 + "<html><head>\n"
226                 + "<script>\n"
227                 + LOG_TITLE_FUNCTION
228                 + "  function test() {\n"
229                 + "    var nodeList = document.querySelectorAll('*');\n"
230 
231                 + "    if (typeof Symbol != 'undefined') {\n"
232                 + "      log(nodeList[Symbol.iterator] === nodeList.values);\n"
233                 + "    }\n"
234 
235                 + "    if (!nodeList.forEach) {\n"
236                 + "      log('no for..of');\n"
237                 + "      return;\n"
238                 + "    }\n"
239 
240                 + "    for (var i of nodeList) {\n"
241                 + "      log(i);\n"
242                 + "    }\n"
243                 + "  }\n"
244                 + "</script>\n"
245                 + "</head><body onload='test()'>\n"
246                 + "  <div></div>\n"
247                 + "</body></html>";
248 
249         loadPageVerifyTitle2(html);
250     }
251 
252     /**
253      * @throws Exception if an error occurs
254      */
255     @Test
256     @Alerts({"[object HTMLHtmlElement] 0 [object NodeList] undefined",
257              "[object HTMLHeadElement] 1 [object NodeList] undefined",
258              "[object HTMLScriptElement] 2 [object NodeList] undefined",
259              "[object HTMLBodyElement] 3 [object NodeList] undefined",
260              "[object HTMLDivElement] 4 [object NodeList] undefined"})
261     public void forEach() throws Exception {
262         final String html = DOCTYPE_HTML
263             + "<html><head>\n"
264             + "<script>\n"
265             + LOG_TITLE_FUNCTION
266             + "  function test() {\n"
267             + "    var nodeList = document.querySelectorAll('*');\n"
268             + "    if (nodeList.forEach) {\n"
269             + "      nodeList.forEach(myFunction, 'something');\n"
270             + "    } else {\n"
271             + "      log('no forEach');\n"
272             + "    }\n"
273             + "  }\n"
274             + "  function myFunction(value, index, list, arg) {\n"
275             + "    log(value + ' ' + index + ' ' + list + ' ' + arg);\n"
276             + "  }\n"
277             + "</script>\n"
278             + "</head><body onload='test()'>\n"
279             + "  <div></div>\n"
280             + "</body></html>";
281 
282         loadPageVerifyTitle2(html);
283     }
284 
285     /**
286      * @throws Exception if an error occurs
287      */
288     @Test
289     @Alerts({"4", "4",
290              "[object HTMLElement]/0", "3", "3",
291              "[object HTMLElement]/1", "2", "2",
292              "2", "2"})
293     public void forEachRemove() throws Exception {
294         final String html = DOCTYPE_HTML
295                 + "<html><head>\n"
296                 + "<script>\n"
297                 + LOG_TITLE_FUNCTION
298                 + "  function test() {\n"
299                 + "    var nodeList = document.getElementById('myId').childNodes;\n"
300                 + "    if (nodeList.forEach) {\n"
301                 + "      log(document.getElementById('myId').childNodes.length);\n"
302                 + "      log(nodeList.length);\n"
303 
304                 + "      nodeList.forEach(myFunction);\n"
305 
306                 + "      log(document.getElementById('myId').childNodes.length);\n"
307                 + "      log(nodeList.length);\n"
308                 + "    } else {\n"
309                 + "      log('no forEach');\n"
310                 + "    }\n"
311                 + "  }\n"
312 
313                 + "  function myFunction(value, index, list, arg) {\n"
314                 + "    log(value + '/' + index);\n"
315                 + "    document.getElementById('myId').removeChild(value);\n"
316                 + "    log(document.getElementById('myId').childNodes.length);\n"
317                 + "    log(list.length);\n"
318                 + "  }\n"
319                 + "</script>\n"
320                 + "</head><body onload='test()'>\n"
321                 + "  <div id='myId'><strong>a</strong>b<b>d</b>e</div>\n"
322                 + "</body></html>";
323 
324         loadPageVerifyTitle2(html);
325     }
326 
327     /**
328      * @throws Exception if an error occurs
329      */
330     @Test
331     @Alerts({"4", "4",
332              "[object HTMLElement]/0", "5", "5",
333              "[object Text]/1", "6", "6",
334              "[object HTMLElement]/2", "7", "7",
335              "[object Text]/3", "8", "8",
336              "8", "8"})
337     public void forEachAppend() throws Exception {
338         final String html = DOCTYPE_HTML
339                 + "<html><head>\n"
340                 + "<script>\n"
341                 + LOG_TITLE_FUNCTION
342                 + "  function test() {\n"
343                 + "    var nodeList = document.getElementById('myId').childNodes;\n"
344                 + "    if (nodeList.forEach) {\n"
345                 + "      log(document.getElementById('myId').childNodes.length);\n"
346                 + "      log(nodeList.length);\n"
347 
348                 + "      nodeList.forEach(myFunction);\n"
349 
350                 + "      log(document.getElementById('myId').childNodes.length);\n"
351                 + "      log(nodeList.length);\n"
352                 + "    } else {\n"
353                 + "      log('no forEach');\n"
354                 + "    }\n"
355                 + "  }\n"
356 
357                 + "  function myFunction(value, index, list, arg) {\n"
358                 + "    log(value + '/' + index);\n"
359                 + "    if (index < 4) {\n"
360                 + "      document.getElementById('myId').appendChild(document.createElement('p'));\n"
361                 + "    }\n"
362                 + "    log(document.getElementById('myId').childNodes.length);\n"
363                 + "    log(list.length);\n"
364                 + "  }\n"
365                 + "</script>\n"
366                 + "</head><body onload='test()'>\n"
367                 + "  <div id='myId'><strong>a</strong>b<b>d</b>e</div>\n"
368                 + "</body></html>";
369 
370         loadPageVerifyTitle2(html);
371     }
372 
373     /**
374      * @throws Exception if an error occurs
375      */
376     @Test
377     @Alerts({"4", "4",
378              "[object HTMLElement]/0", "5", "5",
379              "[object HTMLElement]/1", "6", "6",
380              "[object HTMLElement]/2", "7", "7",
381              "[object HTMLElement]/3", "8", "8",
382              "8", "8"})
383     public void forEachInsert() throws Exception {
384         final String html = DOCTYPE_HTML
385                 + "<html><head>\n"
386                 + "<script>\n"
387                 + LOG_TITLE_FUNCTION
388                 + "  function test() {\n"
389                 + "    var nodeList = document.getElementById('myId').childNodes;\n"
390                 + "    if (nodeList.forEach) {\n"
391                 + "      log(document.getElementById('myId').childNodes.length);\n"
392                 + "      log(nodeList.length);\n"
393 
394                 + "      nodeList.forEach(myFunction);\n"
395 
396                 + "      log(document.getElementById('myId').childNodes.length);\n"
397                 + "      log(nodeList.length);\n"
398                 + "    } else {\n"
399                 + "      log('no forEach');\n"
400                 + "    }\n"
401                 + "  }\n"
402 
403                 + "  function myFunction(value, index, list, arg) {\n"
404                 + "    log(value + '/' + index);\n"
405                 + "    if (index < 4) {\n"
406                 + "      document.getElementById('myId').insertBefore(document.createElement('p'), value);\n"
407                 + "    }\n"
408                 + "    log(document.getElementById('myId').childNodes.length);\n"
409                 + "    log(list.length);\n"
410                 + "  }\n"
411                 + "</script>\n"
412                 + "</head><body onload='test()'>\n"
413                 + "  <div id='myId'><strong>a</strong>b<b>d</b>e</div>\n"
414                 + "</body></html>";
415 
416         loadPageVerifyTitle2(html);
417     }
418 
419     /**
420      * @throws Exception if the test fails
421      */
422     @Test
423     @Alerts({"TypeError", "TypeError"})
424     public void forEachWrongParam() throws Exception {
425         final String html = DOCTYPE_HTML
426                 + "<html><head><script>\n"
427                 + LOG_TITLE_FUNCTION
428                 + "function test() {\n"
429                 + "  var nodeList = document.querySelectorAll('*');\n"
430                 + "  try {\n"
431                 + "    nodeList.forEach();\n"
432                 + "  } catch(e) { logEx(e); }\n"
433                 + "  try {\n"
434                 + "    nodeList.forEach('wrong');\n"
435                 + "  } catch(e) { logEx(e); }\n"
436                 + "}\n"
437                 + "</script></head><body onload='test()'>\n"
438                 + "  <div id='d1' class=' a b \t c \n d \u000B e \u000C f \r g'></div>\n"
439                 + "</body></html>";
440 
441         loadPageVerifyTitle2(html);
442     }
443 
444     /**
445      * @throws Exception if an error occurs
446      */
447     @Test
448     @Alerts({"value", "done", "object", "0", "[object HTMLHtmlElement]"})
449     public void entries() throws Exception {
450         final String html = DOCTYPE_HTML
451             + "<html><head>\n"
452             + "<script>\n"
453             + LOG_TITLE_FUNCTION
454             + "  function test() {\n"
455             + "    var nodeList = document.querySelectorAll('*');\n"
456             + "    if (!nodeList.entries) {\n"
457             + "      log('not defined');\n"
458             + "      return;\n"
459             + "    }\n"
460             + "    var i = nodeList.entries().next();\n"
461             + "    for (var x in i) {\n"
462             + "      log(x);\n"
463             + "    }\n"
464             + "    var v = i.value;\n"
465             + "    log(typeof v);\n"
466             + "    log(v[0]);\n"
467             + "    log(v[1]);\n"
468             + "  }\n"
469             + "</script>\n"
470             + "</head><body onload='test()'>\n"
471             + "</body></html>\n";
472 
473         loadPageVerifyTitle2(html);
474     }
475 
476     /**
477      * @throws Exception if an error occurs
478      */
479     @Test
480     @Alerts({"true", "undefined", "function", "undefined", "undefined", "true", "true", "true"})
481     public void entriesPropertyDescriptor() throws Exception {
482         final String html = DOCTYPE_HTML
483             + "<html><head>\n"
484             + "<script>\n"
485             + LOG_TITLE_FUNCTION
486             + "  function test() {\n"
487             + "    var nodeList = document.querySelectorAll('*');\n"
488 
489             + "    log('entries' in nodeList);\n"
490             + "    log(Object.getOwnPropertyDescriptor(nodeList, 'entries'));\n"
491 
492             + "    var desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(nodeList), 'entries');\n"
493             + "    if (desc === undefined) { log('no entries'); return; }\n"
494             + "    log(typeof desc.value);\n"
495             + "    log(desc.get);\n"
496             + "    log(desc.set);\n"
497             + "    log(desc.writable);\n"
498             + "    log(desc.enumerable);\n"
499             + "    log(desc.configurable);\n"
500             + "  }\n"
501             + "</script>\n"
502             + "</head><body onload='test()'>\n"
503             + "</body></html>\n";
504 
505         loadPageVerifyTitle2(html);
506     }
507 
508     /**
509      * @throws Exception if an error occurs
510      */
511     @Test
512     @Alerts({"0,[object HTMLHtmlElement]", "1,[object HTMLHeadElement]",
513              "2,[object HTMLScriptElement]", "3,[object HTMLBodyElement]"})
514     public void entriesForOf() throws Exception {
515         final String html = DOCTYPE_HTML
516             + "<html><head>\n"
517             + "<script>\n"
518             + LOG_TITLE_FUNCTION
519             + "  function test() {\n"
520             + "    var nodeList = document.querySelectorAll('*');\n"
521             + "    if (!nodeList.entries) {\n"
522             + "      log('not defined');\n"
523             + "      return;\n"
524             + "    }\n"
525             + "    for (var i of nodeList.entries()) {\n"
526             + "      log(i);\n"
527             + "    }\n"
528             + "  }\n"
529             + "</script>\n"
530             + "</head><body onload='test()'>\n"
531             + "</body></html>\n";
532 
533         loadPageVerifyTitle2(html);
534     }
535 
536     /**
537      * @throws Exception if an error occurs
538      */
539     @Test
540     @Alerts({"value", "done", "number", "0"})
541     public void keys() throws Exception {
542         final String html = DOCTYPE_HTML
543             + "<html><head>\n"
544             + "<script>\n"
545             + LOG_TITLE_FUNCTION
546             + "  function test() {\n"
547             + "    var nodeList = document.querySelectorAll('*');\n"
548             + "    if (!nodeList.keys) {\n"
549             + "      log('not defined');\n"
550             + "      return;\n"
551             + "    }\n"
552             + "    var i = nodeList.keys().next();\n"
553             + "    for (var x in i) {\n"
554             + "      log(x);\n"
555             + "    }\n"
556             + "    var v = i.value;\n"
557             + "    log(typeof v);\n"
558             + "    log(v);\n"
559             + "  }\n"
560             + "</script>\n"
561             + "</head><body onload='test()'>\n"
562             + "</body></html>\n";
563 
564         loadPageVerifyTitle2(html);
565     }
566 
567     /**
568      * @throws Exception if an error occurs
569      */
570     @Test
571     @Alerts({"true", "undefined", "function", "undefined", "undefined", "true", "true", "true"})
572     public void keysPropertyDescriptor() throws Exception {
573         final String html = DOCTYPE_HTML
574             + "<html><head>\n"
575             + "<script>\n"
576             + LOG_TITLE_FUNCTION
577             + "  function test() {\n"
578             + "    var nodeList = document.querySelectorAll('*');\n"
579 
580             + "    log('keys' in nodeList);\n"
581             + "    log(Object.getOwnPropertyDescriptor(nodeList, 'keys'));\n"
582 
583             + "    var desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(nodeList), 'keys');\n"
584             + "    if (desc === undefined) { log('no keys'); return; }\n"
585             + "    log(typeof desc.value);\n"
586             + "    log(desc.get);\n"
587             + "    log(desc.set);\n"
588             + "    log(desc.writable);\n"
589             + "    log(desc.enumerable);\n"
590             + "    log(desc.configurable);\n"
591             + "  }\n"
592             + "</script>\n"
593             + "</head><body onload='test()'>\n"
594             + "</body></html>\n";
595 
596         loadPageVerifyTitle2(html);
597     }
598 
599     /**
600      * @throws Exception if an error occurs
601      */
602     @Test
603     @Alerts({"0", "1", "2", "3"})
604     public void keysForOf() throws Exception {
605         final String html = DOCTYPE_HTML
606             + "<html><head>\n"
607             + "<script>\n"
608             + LOG_TITLE_FUNCTION
609             + "  function test() {\n"
610             + "    var nodeList = document.querySelectorAll('*');\n"
611             + "    if (!nodeList.keys) {\n"
612             + "      log('not defined');\n"
613             + "      return;\n"
614             + "    }\n"
615             + "    for (var i of nodeList.keys()) {\n"
616             + "      log(i);\n"
617             + "    }\n"
618             + "  }\n"
619             + "</script>\n"
620             + "</head><body onload='test()'>\n"
621             + "</body></html>\n";
622 
623         loadPageVerifyTitle2(html);
624     }
625 
626     /**
627      * @throws Exception if an error occurs
628      */
629     @Test
630     @Alerts({"0,1,2,3", ""})
631     public void objectKeys() throws Exception {
632         final String html = DOCTYPE_HTML
633             + "<html><head>\n"
634             + "<script>\n"
635             + LOG_TITLE_FUNCTION
636             + "  function test() {\n"
637             + "    var nodeList = document.querySelectorAll('*');\n"
638             + "    log(Object.keys(nodeList));\n"
639 
640             + "    nodeList = document.querySelectorAll('.notThere');\n"
641             + "    log(Object.keys(nodeList));\n"
642             + "  }\n"
643             + "</script>\n"
644             + "</head><body onload='test()'>\n"
645             + "</body></html>\n";
646 
647         loadPageVerifyTitle2(html);
648     }
649 
650     /**
651      * @throws Exception if an error occurs
652      */
653     @Test
654     @Alerts({"value", "done", "object", "[object HTMLHtmlElement]"})
655     public void values() throws Exception {
656         final String html = DOCTYPE_HTML
657             + "<html><head>\n"
658             + "<script>\n"
659             + LOG_TITLE_FUNCTION
660             + "  function test() {\n"
661             + "    var nodeList = document.querySelectorAll('*');\n"
662             + "    if (!nodeList.values) {\n"
663             + "      log('not defined');\n"
664             + "      return;\n"
665             + "    }\n"
666             + "    var i = nodeList.values().next();\n"
667             + "    for (var x in i) {\n"
668             + "      log(x);\n"
669             + "    }\n"
670             + "    var v = i.value;\n"
671             + "    log(typeof v);\n"
672             + "    log(v);\n"
673             + "  }\n"
674             + "</script>\n"
675             + "</head><body onload='test()'>\n"
676             + "</body></html>\n";
677 
678         loadPageVerifyTitle2(html);
679     }
680 
681     /**
682      * @throws Exception if an error occurs
683      */
684     @Test
685     @Alerts({"true", "undefined", "function", "undefined", "undefined", "true", "true", "true"})
686     public void valuesPropertyDescriptor() throws Exception {
687         final String html = DOCTYPE_HTML
688             + "<html><head>\n"
689             + "<script>\n"
690             + LOG_TITLE_FUNCTION
691             + "  function test() {\n"
692             + "    var nodeList = document.querySelectorAll('*');\n"
693 
694             + "    log('values' in nodeList);\n"
695             + "    log(Object.getOwnPropertyDescriptor(nodeList, 'values'));\n"
696 
697             + "    var desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(nodeList), 'values');\n"
698             + "    if (desc === undefined) { log('no values'); return; }\n"
699             + "    log(typeof desc.value);\n"
700             + "    log(desc.get);\n"
701             + "    log(desc.set);\n"
702             + "    log(desc.writable);\n"
703             + "    log(desc.enumerable);\n"
704             + "    log(desc.configurable);\n"
705             + "  }\n"
706             + "</script>\n"
707             + "</head><body onload='test()'>\n"
708             + "</body></html>\n";
709 
710         loadPageVerifyTitle2(html);
711     }
712 
713     /**
714      * @throws Exception if an error occurs
715      */
716     @Test
717     @Alerts({"[object HTMLHtmlElement]", "[object HTMLHeadElement]",
718              "[object HTMLScriptElement]", "[object HTMLBodyElement]"})
719     public void valuesForOf() throws Exception {
720         final String html = DOCTYPE_HTML
721             + "<html><head>\n"
722             + "<script>\n"
723             + LOG_TITLE_FUNCTION
724             + "  function test() {\n"
725             + "    var nodeList = document.querySelectorAll('*');\n"
726             + "    if (!nodeList.values) {\n"
727             + "      log('not defined');\n"
728             + "      return;\n"
729             + "    }\n"
730             + "    for (var i of nodeList.values()) {\n"
731             + "      log(i);\n"
732             + "    }\n"
733             + "  }\n"
734             + "</script>\n"
735             + "</head><body onload='test()'>\n"
736             + "</body></html>\n";
737 
738         loadPageVerifyTitle2(html);
739     }
740 
741     /**
742      * @throws Exception on failure
743      */
744     @Test
745     @Alerts({"0", "4", "0", "1", "2", "3"})
746     public void getOwnPropertySymbols() throws Exception {
747         final String html = DOCTYPE_HTML
748                 + "<html><body>\n"
749                 + "<script>\n"
750                 + LOG_TITLE_FUNCTION
751                 + "  if (Object.getOwnPropertySymbols) {\n"
752 
753                 + "    var nodeList = document.querySelectorAll('*');\n"
754 
755                 + "    var objectSymbols = Object.getOwnPropertySymbols(nodeList);\n"
756                 + "    log(objectSymbols.length);\n"
757 
758                 + "    var objectNames = Object.getOwnPropertyNames(nodeList);\n"
759                 + "    log(objectNames.length);\n"
760                 + "    log(objectNames[0]);\n"
761                 + "    log(objectNames[1]);\n"
762                 + "    log(objectNames[2]);\n"
763                 + "    log(objectNames[3]);\n"
764 
765                 + "  } else { log('not defined'); }\n"
766                 + "</script>\n"
767                 + "</body>\n"
768                 + "</html>\n";
769 
770         loadPageVerifyTitle2(html);
771     }
772 
773     /**
774      * @throws Exception on failure
775      */
776     @Test
777     @Alerts({"0", "0"})
778     public void getOwnPropertySymbolsEmptyList() throws Exception {
779         final String html = DOCTYPE_HTML
780                 + "<html><body>\n"
781                 + "<script>\n"
782                 + LOG_TITLE_FUNCTION
783                 + "  if (Object.getOwnPropertySymbols) {\n"
784 
785                 + "    var nodeList = document.querySelectorAll('.notThere');\n"
786 
787                 + "    var objectSymbols = Object.getOwnPropertySymbols(nodeList);\n"
788                 + "    log(objectSymbols.length);\n"
789 
790                 + "    var objectNames = Object.getOwnPropertyNames(nodeList);\n"
791                 + "    log(objectNames.length);\n"
792 
793                 + "  } else { log('not defined'); }\n"
794                 + "</script>\n"
795                 + "</body>\n"
796                 + "</html>\n";
797 
798         loadPageVerifyTitle2(html);
799     }
800 
801     /**
802      * @throws Exception if an error occurs
803      */
804     @Test
805     @Alerts({"[object HTMLHeadElement]", "[object HTMLHeadElement]"})
806     public void setItem() throws Exception {
807         final String html = DOCTYPE_HTML
808             + "<html><head>\n"
809             + "<script>\n"
810             + LOG_TITLE_FUNCTION
811             + "  function test() {\n"
812             + "    var nodeList = document.querySelectorAll('*');\n"
813             + "    log(nodeList.item(1));\n"
814             + "    nodeList[1] = nodeList.item(0);\n"
815             + "    log(nodeList.item(1));\n"
816             + "  }\n"
817             + "</script>\n"
818             + "</head><body onload='test()'>\n"
819             + "</body></html>\n";
820 
821         loadPageVerifyTitle2(html);
822     }
823 }