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.junit.annotation.Alerts;
19  import org.junit.jupiter.api.Test;
20  
21  /**
22   * Tests for {@link HTMLTableElement}.
23   *
24   * @author David D. Kilzer
25   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
26   * @author Daniel Gredler
27   * @author Marc Guillemot
28   * @author Ahmed Ashour
29   * @author Ronald Brill
30   * @author Frank Danek
31   */
32  public class HTMLTableElementTest extends WebDriverTestCase {
33  
34      /**
35       * @throws Exception if the test fails
36       */
37      @Test
38      @Alerts({"caption1", "caption2", "null", "caption3", "TypeError",
39               "[object HTMLTableCaptionElement]", "caption3", "caption4"})
40      public void tableCaptions() throws Exception {
41          final String html = DOCTYPE_HTML
42              + "<html><head></head>\n"
43              + "<body>\n"
44              + "  <table id='table_1'><caption>caption1</caption><caption>caption2</caption>\n"
45              + "    <tr><td>cell1</td><td>cell2</td><td rowspan='2'>cell4</td></tr>\n"
46              + "    <tr><td colspan='2'>cell3</td></tr>\n"
47              + "  </table>\n"
48              + "  <script type='text/javascript' language='JavaScript'>\n"
49              + LOG_TITLE_FUNCTION
50              + "    var table = document.getElementById('table_1');\n"
51              + "    log(table.caption.innerHTML);\n"
52  
53              + "    table.deleteCaption();\n"
54              + "    log(table.caption.innerHTML);\n"
55  
56              + "    table.deleteCaption();\n"
57              + "    log(table.caption);\n"
58  
59              + "    var newCaption = table.createCaption();\n"
60              + "    newCaption.innerHTML = 'caption3';\n"
61              + "    log(table.caption.innerHTML);\n"
62  
63              + "    try { table.caption = 123; } catch(e) { logEx(e) }\n"
64              + "    log(table.caption);\n"
65              + "    if (table.caption) { log(table.caption.innerHTML) }\n"
66  
67              + "    var caption4 = document.createElement('caption');\n"
68              + "    caption4.innerHTML = 'caption4';\n"
69              + "    try { table.caption = caption4; } catch(e) { logEx(e) }\n"
70              + "    log(table.caption.innerHTML);\n"
71              + "  </script>\n"
72              + "</body></html>";
73  
74          loadPageVerifyTitle2(html);
75      }
76  
77      /**
78       * @throws Exception if the test fails
79       */
80      @Test
81      @Alerts({"thead1", "thead2", "null", "thead3", "TypeError",
82               "[object HTMLTableSectionElement]", "thead3", "thead4"})
83      public void tableHeaders() throws Exception {
84          final String html = DOCTYPE_HTML
85              + "<html><head></head>\n"
86              + "<body>\n"
87              + "  <table id='table_1'>\n"
88              + "    <thead id='thead1'><tr><td>cell1</td><td>cell2</td><td>cell3</td></tr></thead>\n"
89              + "    <thead id='thead2'><tr><td>cell7</td><td>cell8</td><td>cell9</td></tr></thead>\n"
90              + "    <tr><td>cell1</td><td>cell2</td><td rowspan='2'>cell4</td></tr>\n"
91              + "    <tr><td colspan='2'>cell3</td></tr>\n"
92              + "  </table>\n"
93              + "  <script type='text/javascript' language='JavaScript'>\n"
94              + LOG_TITLE_FUNCTION
95              + "    var table = document.getElementById('table_1');\n"
96              + "    log(table.tHead.id);\n"
97  
98              + "    table.deleteTHead();\n"
99              + "    log(table.tHead.id);\n"
100 
101             + "    table.deleteTHead();\n"
102             + "    log(table.tHead);\n"
103 
104             + "    var newTHead = table.createTHead();\n"
105             + "    newTHead.id = 'thead3';\n"
106             + "    log(table.tHead.id);\n"
107 
108             + "    try { table.tHead = 123; } catch(e) { logEx(e) }\n"
109             + "    log(table.tHead);\n"
110             + "    if (table.tHead) { log(table.tHead.id) }\n"
111 
112             + "    var tHead4 = document.createElement('tHead');\n"
113             + "    tHead4.id = 'thead4';\n"
114             + "    try { table.tHead = tHead4; } catch(e) { logEx(e) }\n"
115             + "    log(table.tHead.id);\n"
116             + "  </script>\n"
117             + "</body></html>";
118 
119         loadPageVerifyTitle2(html);
120     }
121 
122     /**
123      * @throws Exception if the test fails
124      */
125     @Test
126     @Alerts({"2", "true", "4 2 2", "6 3 3"})
127     public void tableBodies() throws Exception {
128         final String html = DOCTYPE_HTML
129             + "<html><head></head>\n"
130             + "<body>\n"
131             + "  <table id='table_1'>\n"
132             + "    <tbody id='tbody1'>\n"
133             + "      <tr><td>cell1</td><td>cell2</td></tr>\n"
134             + "      <tr><td>cell3</td><td>cell4</td></tr>\n"
135             + "    </tbody>\n"
136             + "    <tbody id='tbody2'>\n"
137             + "      <tr><td>cell1</td><td>cell2</td></tr>\n"
138             + "      <tr><td>cell3</td><td>cell4</td></tr>\n"
139             + "    </tbody>\n"
140             + "  </table>\n"
141             + "  <script type='text/javascript' language='JavaScript'>\n"
142             + LOG_TITLE_FUNCTION
143             + "    var table = document.getElementById('table_1');\n"
144             + "    var bodies = table.tBodies;\n"
145             + "    log(bodies.length);\n"
146             + "    log(bodies == table.tBodies);\n"
147             + "    var body1 = table.tBodies[0];\n"
148             + "    var body2 = table.tBodies[1];\n"
149             + "    log(table.rows.length + ' ' + body1.rows.length + ' ' + body2.rows.length);\n"
150             + "    table.insertRow(-1); // Should add at end, to body2.\n"
151             + "    body1.insertRow(-1); // Add one to body1, as well.\n"
152             + "    log(table.rows.length + ' ' + body1.rows.length + ' ' + body2.rows.length);\n"
153             + "  </script>\n"
154             + "</body></html>";
155 
156         loadPageVerifyTitle2(html);
157     }
158 
159     /**
160      * @throws Exception if the test fails
161      */
162     @Test
163     @Alerts({"2", "true", "3", "2", "3", "2"})
164     public void tableRows() throws Exception {
165         final String html = DOCTYPE_HTML
166             + "<html><head></head>\n"
167             + "<body>\n"
168             + "  <table id='table_1'>\n"
169             + "    <tr><td>cell1</td><td>cell2</td><td rowspan='2'>cell4</td></tr>\n"
170             + "    <tr><td colspan='2'>cell3</td></tr>\n"
171             + "  </table>\n"
172             + "  <script type='text/javascript' language='JavaScript'>\n"
173             + LOG_TITLE_FUNCTION
174             + "    var table = document.getElementById('table_1');\n"
175             + "    var rows = table.rows;\n"
176             + "    log(rows.length);\n"
177             + "    log(rows == table.rows);\n"
178             + "    table.insertRow(1);\n"
179             + "    log(rows.length);\n"
180             + "    table.deleteRow(1);\n"
181             + "    log(rows.length);\n"
182             + "    table.insertRow(rows.length);\n"
183             + "    log(rows.length);\n"
184             + "    table.deleteRow(-1);\n"
185             + "    log(rows.length);\n"
186             + "  </script>\n"
187             + "</body></html>";
188 
189         loadPageVerifyTitle2(html);
190     }
191 
192     /**
193      * Regression test for bug 1528024.
194      * @see <a href="https://sourceforge.net/tracker/?func=detail&atid=448266&aid=1528024&group_id=47038">bug</a>
195      * @throws Exception if the test fails
196      */
197     @Test
198     @Alerts({"1", "1"})
199     public void tableHeadRows() throws Exception {
200         final String html = DOCTYPE_HTML
201             + "<html><head>\n"
202             + "<script>\n"
203             + LOG_TITLE_FUNCTION
204             + "function test() {\n"
205             + "  var t = document.getElementById('myTable');\n"
206             + "  log(t.rows[0].cells.length);\n"
207             + "  log(t.rows[1].cells.length);\n"
208             + "}\n"
209             + "</script>\n"
210             + "</head>\n"
211             + "<body onload='test()'>\n"
212             + "<table id='myTable'>\n"
213             + "<tr><th>Some Heading</th></tr>\n"
214             + "<tr><td>some desc</td></tr>\n"
215             + "</table>\n"
216             + "</body>\n"
217             + "</html>";
218 
219         loadPageVerifyTitle2(html);
220     }
221 
222     /**
223      * @throws Exception if the test fails
224      */
225     @Test
226     @Alerts({"2", "true", "8 2 2 2 2",
227              "9 2 2 2 3", "8 2 2 1 3", "9 2 3 1 3", "8 1 3 1 3"})
228     public void tableRowsWithManySections() throws Exception {
229         final String html = DOCTYPE_HTML
230             + "<html><head></head>\n"
231             + "<body>\n"
232             + "  <table id='table_1'>\n"
233             + "    <thead>\n"
234             + "      <tr><td>cell1</td><td>cell2</td></tr>\n"
235             + "      <tr><td>cell3</td><td>cell4</td></tr>\n"
236             + "    </thead>\n"
237             + "    <tbody id='tbody1'>\n"
238             + "      <tr><td>cell1</td><td>cell2</td></tr>\n"
239             + "      <tr><td>cell3</td><td>cell4</td></tr>\n"
240             + "    </tbody>\n"
241             + "    <tbody id='tbody2'>\n"
242             + "      <tr><td>cell1</td><td>cell2</td></tr>\n"
243             + "      <tr><td>cell3</td><td>cell4</td></tr>\n"
244             + "    </tbody>\n"
245             + "    <tfoot>\n"
246             + "      <tr><td>cell1</td><td>cell2</td></tr>\n"
247             + "      <tr><td>cell3</td><td>cell4</td></tr>\n"
248             + "    </tfoot>\n"
249             + "  </table>\n"
250             + "  <script type='text/javascript' language='JavaScript'>\n"
251             + LOG_TITLE_FUNCTION
252             + "  <!--\n"
253             + "    var table = document.getElementById('table_1');\n"
254             + "    var bodies = table.tBodies;\n"
255             + "    log(bodies.length);\n"
256             + "    log(bodies == table.tBodies);\n"
257             + "    var head = table.tHead;\n"
258             + "    var body1 = table.tBodies.item(0);\n"
259             + "    var body2 = table.tBodies.item(1);\n"
260             + "    var foot = table.tFoot;\n"
261             + "    log(table.rows.length + ' ' + head.rows.length + ' ' + body1.rows.length "
262             + "        + ' ' + body2.rows.length + ' ' + foot.rows.length);\n"
263             + "    table.insertRow(6); // Insert a row in the footer.\n"
264             + "    log(table.rows.length + ' ' + head.rows.length + ' ' + body1.rows.length "
265             + "        + ' ' + body2.rows.length + ' ' + foot.rows.length);\n"
266             + "    table.deleteRow(5); // Delete a row from the second body.\n"
267             + "    log(table.rows.length + ' ' + head.rows.length + ' ' + body1.rows.length "
268             + "        + ' ' + body2.rows.length + ' ' + foot.rows.length);\n"
269             + "    table.insertRow(2); // Insert a row in the first body.\n"
270             + "    log(table.rows.length + ' ' + head.rows.length + ' ' + body1.rows.length "
271             + "        + ' ' + body2.rows.length + ' ' + foot.rows.length);\n"
272             + "    table.deleteRow(1); // Delete a row from the header.\n"
273             + "    log(table.rows.length + ' ' + head.rows.length + ' ' + body1.rows.length "
274             + "        + ' ' + body2.rows.length + ' ' + foot.rows.length);\n"
275             + "  // -->\n"
276             + "  </script>\n"
277             + "</body></html>";
278 
279         loadPageVerifyTitle2(html);
280     }
281 
282     /**
283      * @throws Exception if the test fails
284      */
285     @Test
286     @Alerts({"tfoot1", "tfoot2", "null", "tfoot3", "TypeError",
287              "[object HTMLTableSectionElement]", "tfoot3", "tfoot4"})
288     public void tableFooters() throws Exception {
289         final String html = DOCTYPE_HTML
290             + "<html><head></head>\n"
291             + "<body>\n"
292             + "  <table id='table_1'>\n"
293             + "    <tr><td>cell1</td><td>cell2</td><td rowspan='2'>cell4</td></tr>\n"
294             + "    <tr><td colspan='2'>cell3</td></tr>\n"
295             + "    <tfoot id='tfoot1'><tr><td>cell1</td><td>cell2</td><td>cell3</td></tr></tfoot>\n"
296             + "    <tfoot id='tfoot2'><tr><td>cell7</td><td>cell8</td><td>cell9</td></tr></tfoot>\n"
297             + "  </table>\n"
298             + "  <script>\n"
299             + LOG_TITLE_FUNCTION
300             + "    var table = document.getElementById('table_1');\n"
301             + "    log(table.tFoot.id);\n"
302 
303             + "    table.deleteTFoot();\n"
304             + "    log(table.tFoot.id);\n"
305 
306             + "    table.deleteTFoot();\n"
307             + "    log(table.tFoot);\n"
308 
309             + "    var newTFoot = table.createTFoot();\n"
310             + "    newTFoot.id = 'tfoot3';\n"
311             + "    log(table.tFoot.id);\n"
312 
313             + "    try { table.tFoot = 123; } catch(e) { logEx(e) }\n"
314             + "    log(table.tFoot);\n"
315             + "    if (table.tFoot) { log(table.tFoot.id) }\n"
316 
317             + "    var tFoot4 = document.createElement('tFoot');\n"
318             + "    tFoot4.id = 'tfoot4';\n"
319             + "    try { table.tFoot = tFoot4; } catch(e) { logEx(e) }\n"
320             + "    log(table.tFoot.id);\n"
321             + "  </script>\n"
322             + "</body></html>";
323 
324         loadPageVerifyTitle2(html);
325     }
326 
327     /**
328      * @throws Exception if the test fails
329      */
330     @Test
331     @Alerts({"0", "1", "0", "1", "-1"})
332     public void cellIndex() throws Exception {
333         final String html = DOCTYPE_HTML
334             + "<html><head>\n"
335             + "<script>\n"
336             + LOG_TITLE_FUNCTION
337             + "  function test() {\n"
338             + "    log(document.getElementById('th1').cellIndex);\n"
339             + "    log(document.getElementById('th2').cellIndex);\n"
340             + "    log(document.getElementById('td1').cellIndex);\n"
341             + "    log(document.getElementById('td2').cellIndex);\n"
342             + "    log(document.createElement('td').cellIndex);\n"
343             + "  }\n"
344             + "</script>\n"
345             + "</head><body onload='test()'><table>\n"
346             + "<tr><th id='th1'>a</th><th id='th2'>b</th></tr>\n"
347             + "<tr><td id='td1'>c</td><td id='td2'>d</td></tr>\n"
348             + "</table></body></html>";
349 
350         loadPageVerifyTitle2(html);
351     }
352 
353     private void insertRow(final String rowIndex) throws Exception {
354         final String html = DOCTYPE_HTML
355             + "<html><head></head>\n"
356             + "<body>\n"
357             + "  <table id='table_1'>\n"
358             + "    <tr><td>first</td></tr>\n"
359             + "    <tr><td>second</td></tr>\n"
360             + "  </table>\n"
361             + "  <script>\n"
362             + LOG_TITLE_FUNCTION
363             + "    var table = document.getElementById('table_1');\n"
364             + "    log(table.rows.length);\n"
365             + "    try {\n"
366             + "      var newRow = table.insertRow(" + rowIndex + ");\n"
367             + "      log(table.rows.length);\n"
368             + "      log(newRow.rowIndex);\n"
369             + "    } catch(e) { logEx(e); }\n"
370             + "  </script>\n"
371             + "</body></html>";
372 
373         loadPageVerifyTitle2(html);
374     }
375 
376     /**
377      * @throws Exception if the test fails
378      */
379     @Test
380     @Alerts({"2", "3", "2"})
381     public void insertRowEmpty() throws Exception {
382         insertRow("");
383     }
384 
385     /**
386      * @throws Exception if the test fails
387      */
388     @Test
389     @Alerts({"2", "IndexSizeError/DOMException"})
390     public void insertRow_MinusTwo() throws Exception {
391         insertRow("-2");
392     }
393 
394     /**
395      * @throws Exception if the test fails
396      */
397     @Test
398     @Alerts({"2", "3", "2"})
399     public void insertRow_MinusOne() throws Exception {
400         insertRow("-1");
401     }
402 
403     /**
404      * @throws Exception if the test fails
405      */
406     @Test
407     @Alerts({"2", "3", "0"})
408     public void insertRow_Zero() throws Exception {
409         insertRow("0");
410     }
411 
412     /**
413      * @throws Exception if the test fails
414      */
415     @Test
416     @Alerts({"2", "3", "1"})
417     public void insertRow_One() throws Exception {
418         insertRow("1");
419     }
420 
421     /**
422      * @throws Exception if the test fails
423      */
424     @Test
425     @Alerts({"2", "3", "2"})
426     public void insertRow_Two() throws Exception {
427         insertRow("2");
428     }
429 
430     /**
431      * @throws Exception if the test fails
432      */
433     @Test
434     @Alerts({"2", "IndexSizeError/DOMException"})
435     public void insertRow_Three() throws Exception {
436         insertRow("3");
437     }
438 
439     /**
440      * Regression test for bug 1244839.
441      * @throws Exception if the test fails
442      */
443     @Test
444     @Alerts({"mytable", "mytable"})
445     public void insertRowNested() throws Exception {
446         final String html = DOCTYPE_HTML
447             + "<html><head>\n"
448             + "<script>\n"
449             + LOG_TITLE_FUNCTION
450             + "function test() {\n"
451             + "  var container = document.getElementById('mytable');\n"
452             + "  log(container.id);\n"
453             + "  var tableRow = container.insertRow(1);\n"
454             + "  log(tableRow.parentNode.parentNode.id);\n"
455             + "}\n"
456             + "</script>\n"
457             + "</head>\n"
458             + "<body onload='test()'>\n"
459             + "<table id='mytable'>\n"
460             + "<tr>\n"
461             + "<td>\n"
462             + "  <table id='nested'><tr><td></td></tr></table>\n"
463             + "</td></tr>\n"
464             + "</table>\n"
465             + "</body>\n"
466             + "</html>";
467 
468         loadPageVerifyTitle2(html);
469     }
470 
471     /**
472      * Tests that a <tt>tbody</tt> is automatically created.
473      * @throws Exception if the test fails
474      */
475     @Test
476     @Alerts({"TBODY", "TABLE"})
477     public void insertRowInEmptyTable() throws Exception {
478         final String html = DOCTYPE_HTML
479             + "<html><head>\n"
480             + "<script>\n"
481             + LOG_TITLE_FUNCTION
482             + "function test() {\n"
483             + "  var oTable = document.getElementById('mytable');\n"
484             + "  var tableRow = oTable.insertRow(0);\n"
485             + "  log(tableRow.parentNode.tagName);\n"
486             + "  log(tableRow.parentNode.parentNode.tagName);\n"
487             + "}\n"
488             + "</script>\n"
489             + "</head>\n"
490             + "<body onload='test()'>\n"
491             + "<table id='mytable'>\n"
492             + "</table>\n"
493             + "</body>\n"
494             + "</html>";
495 
496         loadPageVerifyTitle2(html);
497     }
498 
499     /**
500      * Tests that a <tt>tbody</tt> is automatically created.
501      * @throws Exception if the test fails
502      */
503     @Test
504     @Alerts({"TBODY", "TBODY", "TBODY"})
505     public void insertRowInTableWithEmptyTbody() throws Exception {
506         final String html = DOCTYPE_HTML
507             + "<html><head>\n"
508             + "<script>\n"
509             + LOG_TITLE_FUNCTION
510             + "function test() {\n"
511             + "  var oTable = document.getElementById('mytable');\n"
512             + "  log(oTable.lastChild.tagName);\n"
513             + "  var tableRow = oTable.insertRow(0);\n"
514             + "  log(oTable.lastChild.tagName);\n"
515             + "  log(tableRow.parentNode.tagName);\n"
516             + "}\n"
517             + "</script>\n"
518             + "</head>\n"
519             + "<body onload='test()'>\n"
520             + "<table id='mytable'><tbody></tbody></table>\n"
521             + "</body>\n"
522             + "</html>";
523 
524         loadPageVerifyTitle2(html);
525     }
526 
527     /**
528      * Tests length, tBodies on nested rows.
529      * @throws Exception if the test fails
530      */
531     @Test
532     @Alerts({"1", "1"})
533     public void nestedTables() throws Exception {
534         final String html = DOCTYPE_HTML
535             + "<html><head>\n"
536             + "<script>\n"
537             + LOG_TITLE_FUNCTION
538             + "function test() {\n"
539             + "  var myTable = document.getElementById('mytable');\n"
540             + "  log(myTable.rows.length);\n"
541             + "  log(myTable.tBodies.length);\n"
542             + "}\n"
543             + "</script>\n"
544             + "</head>\n"
545             + "<body onload='test()'>\n"
546             + "<table id='mytable'>\n"
547             + "<tr>\n"
548             + "<td>\n"
549             + "  <table id='nested'><tr><td></td></tr></table>\n"
550             + "</td></tr>\n"
551             + "</table>\n"
552             + "</body>\n"
553             + "</html>";
554 
555         loadPageVerifyTitle2(html);
556     }
557 
558     /**
559      * Tests string default values.
560      * See <a href="https://sourceforge.net/tracker/?func=detail&atid=448266&aid=1538136&group_id=47038">issue 370</a>.
561      * Currently not working for FF as HtmlUnit's object names don't map to FF ones.
562      * @throws Exception if the test fails
563      */
564     @Test
565     @Alerts({"table: [object HTMLTableElement]",
566              "row: [object HTMLTableRowElement]",
567              "headcell: [object HTMLTableCellElement]",
568              "datacell: [object HTMLTableCellElement]"})
569     public void stringValues() throws Exception {
570         final String html = DOCTYPE_HTML
571             + "<html><head>\n"
572             + "  <script>\n"
573             + LOG_TITLE_FUNCTION
574             + "    function test() {\n"
575             + "      log('table: ' + document.getElementById('myTable'));\n"
576             + "      log('row: ' + document.getElementById('myRow'));\n"
577             + "      log('headcell: ' + document.getElementById('myHeadCell'));\n"
578             + "      log('datacell: ' + document.getElementById('myDataCell'));\n"
579             + "    }\n"
580             + "  </script>\n"
581             + "  </head>\n"
582             + "  <body onload='test()'>\n"
583             + "    <table id='myTable'>\n"
584             + "      <tr id='myRow'>\n"
585             + "        <th id='myHeadCell'>Foo</th>\n"
586             + "      </tr>\n"
587             + "      <tr>\n"
588             + "        <td id='myDataCell'>Foo</th>\n"
589             + "      </tr>\n"
590             + "    </table>\n"
591             + "  </body>\n"
592             + "</html>";
593 
594         loadPageVerifyTitle2(html);
595     }
596 
597     /**
598      * @throws Exception if the test fails
599      */
600     @Test
601     @Alerts("21")
602     public void cellSpacing() throws Exception {
603         final String html = DOCTYPE_HTML
604                 + "<html><head></head>\n"
605                 + "<body>\n"
606                 + "<table id='tableID' cellspacing='2'><tr><td></td></tr></table>\n"
607                 + "<script language='javascript'>\n"
608                 + LOG_TITLE_FUNCTION
609                 + "    var table = document.getElementById('tableID');\n"
610                 + "    table.cellSpacing += 1;\n"
611                 + "    log(table.cellSpacing);\n"
612                 + "</script></body></html>";
613 
614         loadPageVerifyTitle2(html);
615     }
616 
617     /**
618      * @throws Exception if the test fails
619      */
620     @Test
621     @Alerts("21")
622     public void cellPadding() throws Exception {
623         final String html = DOCTYPE_HTML
624                 + "<html><head></head>\n"
625                 + "<body>\n"
626                 + "<table id='tableID' cellpadding='2'><tr><td></td></tr></table>\n"
627                 + "<script language='javascript'>\n"
628                 + LOG_TITLE_FUNCTION
629                 + "    var table = document.getElementById('tableID');\n"
630                 + "    table.cellPadding += 1;\n"
631                 + "    log(table.cellPadding);\n"
632                 + "</script></body></html>";
633 
634         loadPageVerifyTitle2(html);
635     }
636 
637     /**
638      * @throws Exception if the test fails
639      */
640     @Test
641     @Alerts("no refresh function")
642     public void refresh() throws Exception {
643         final String html = DOCTYPE_HTML
644             + "<html><head>\n"
645             + "<script>\n"
646             + LOG_TITLE_FUNCTION
647             + "  function test() {\n"
648             + "    try {\n"
649             + "      if (document.getElementById('myTable').refresh) {\n"
650             + "        document.getElementById('myTable').refresh();\n"
651             + "        log('refreshed');\n"
652             + "      } else {\n"
653             + "        log('no refresh function');\n"
654             + "      }\n"
655             + "    } catch(e) { logEx(e); }\n"
656             + "  }\n"
657             + "</script></head><body onload='test()'>\n"
658             + "<table id='myTable'></table>\n"
659             + "</body></html>";
660         loadPageVerifyTitle2(html);
661     }
662 
663     /**
664      * @throws Exception if an error occurs
665      */
666     @Test
667     @Alerts({"", "hello", "left", "hi", "right"})
668     public void align() throws Exception {
669         final String html = DOCTYPE_HTML
670             + "<html>\n"
671             + "  <head>\n"
672             + "    <script>\n"
673             + LOG_TITLE_FUNCTION
674             + "      function test() {\n"
675             + "        var t = document.getElementById('t');\n"
676             + "        log(t.align);\n"
677             + "        set(t, 'hello');\n"
678             + "        log(t.align);\n"
679             + "        set(t, 'left');\n"
680             + "        log(t.align);\n"
681             + "        set(t, 'hi');\n"
682             + "        log(t.align);\n"
683             + "        set(t, 'right');\n"
684             + "        log(t.align);\n"
685             + "      }\n"
686             + "      function set(e, value) {\n"
687             + "        try {\n"
688             + "          e.align = value;\n"
689             + "        } catch(e) { logEx(e); }\n"
690             + "      }\n"
691             + "    </script>\n"
692             + "  </head>\n"
693             + "  <body onload='test()'>\n"
694             + "    <table id='t'>\n"
695             + "      <thead id='th'/>\n"
696             + "      <tbody id='tb'/>\n"
697             + "      <tfoot id='tf'/>\n"
698             + "    </table>\n"
699             + "  </body>\n"
700             + "</html>";
701 
702         loadPageVerifyTitle2(html);
703     }
704 
705     /**
706      * @throws Exception if an error occurs
707      */
708     @Test
709     @Alerts({"", "#0000aa", "x"})
710     public void bgColor() throws Exception {
711         final String html = DOCTYPE_HTML
712             + "<html>\n"
713             + "  <head>\n"
714             + "    <script>\n"
715             + LOG_TITLE_FUNCTION
716             + "      function test() {\n"
717             + "        var table = document.getElementById('table');\n"
718             + "        log(table.bgColor);\n"
719             + "        table.bgColor = '#0000aa';\n"
720             + "        log(table.bgColor);\n"
721             + "        table.bgColor = 'x';\n"
722             + "        log(table.bgColor);\n"
723             + "      }\n"
724             + "    </script>\n"
725             + "  </head>\n"
726             + "  <body onload='test()'>\n"
727             + "  <table id='table'><tr><td>a</td></tr></table>\n"
728             + "  </body>\n"
729             + "</html>";
730 
731         loadPageVerifyTitle2(html);
732     }
733 
734     /**
735      * @throws Exception if the test fails
736      */
737     @Test
738     @Alerts({"cell1", "[object Text]", "abc", "[object Text]", ""})
739     public void innerText() throws Exception {
740         final String html = DOCTYPE_HTML
741             + "<html><body>\n"
742             + "  <table id='tab'>\n"
743             + "    <tr><td>cell1</td></tr>\n"
744             + "  </table>\n"
745             + "<script>\n"
746             + LOG_TITLE_FUNCTION
747             + "  var node = document.getElementById('tab');\n"
748             + "  log(node.innerText);\n"
749             + "  log(node.firstChild);\n"
750 
751             + "  try { node.innerText = 'abc'; } catch(e) { logEx(e); }\n"
752             + "  log(node.innerText);\n"
753             + "  log(node.firstChild);\n"
754 
755             + "  try { node.innerText = ''; } catch(e) { logEx(e); }\n"
756             + "  log(node.innerText);\n"
757             + "</script></body></html>";
758 
759         loadPageVerifyTitle2(html);
760     }
761 
762     /**
763      * @throws Exception if the test fails
764      */
765     @Test
766     @Alerts({"\\n\\s\\s\\s\\scell1\\n\\s\\s", "[object\\sText]", "abc", "[object\\sText]", ""})
767     public void textContent() throws Exception {
768         final String html = DOCTYPE_HTML
769             + "<html><body>\n"
770             + "  <table id='tab'>\n"
771             + "    <tr><td>cell1</td></tr>\n"
772             + "  </table>\n"
773             + "<script>\n"
774             + LOG_TITLE_FUNCTION_NORMALIZE
775             + "  var node = document.getElementById('tab');\n"
776             + "  log(node.textContent);\n"
777             + "  log(node.firstChild);\n"
778 
779             + "  try { node.textContent = 'abc'; } catch(e) { logEx(e); }\n"
780             + "  log(node.textContent);\n"
781             + "  log(node.firstChild);\n"
782 
783             + "  try { node.textContent = ''; } catch(e) { logEx(e); }\n"
784             + "  log(node.textContent);\n"
785             + "</script></body></html>";
786 
787         loadPageVerifyTitle2(html);
788     }
789 
790     /**
791      * @throws Exception if the test fails
792      */
793     @Test
794     @Alerts({"undefined", "#667788", "unknown", "undefined", "undefined", "undefined"})
795     public void borderColor() throws Exception {
796         final String html = DOCTYPE_HTML
797             + "<html><body>\n"
798             + "  <table id='tab1'></table>\n"
799             + "  <table id='tab2' borderColor='red'></table>\n"
800             + "  <table id='tab3' borderColor='#123456'></table>\n"
801             + "  <table id='tab4' borderColor='unknown'></table>\n"
802             + "<script>\n"
803             + LOG_TITLE_FUNCTION
804             + "  var node = document.getElementById('tab1');\n"
805             + "  log(node.borderColor);\n"
806 
807             + "  node.borderColor = '#667788';\n"
808             + "  log(node.borderColor);\n"
809 
810             + "  node.borderColor = 'unknown';\n"
811             + "  log(node.borderColor);\n"
812 
813             + "  var node = document.getElementById('tab2');\n"
814             + "  log(node.borderColor);\n"
815             + "  var node = document.getElementById('tab3');\n"
816             + "  log(node.borderColor);\n"
817             + "  var node = document.getElementById('tab4');\n"
818             + "  log(node.borderColor);\n"
819 
820             + "</script></body></html>";
821 
822         loadPageVerifyTitle2(html);
823     }
824 
825     /**
826      * @throws Exception if the test fails
827      */
828     @Test
829     @Alerts({"undefined", "undefined", "undefined", "undefined", "undefined", "undefined"})
830     public void borderColorDark() throws Exception {
831         final String html = DOCTYPE_HTML
832             + "<html><body>\n"
833             + "  <table id='tab1'></table>\n"
834             + "  <table id='tab2' borderColorDark='red'></table>\n"
835             + "  <table id='tab3' borderColorDark='#123456'></table>\n"
836             + "  <table id='tab4' borderColorDark='unknown'></table>\n"
837             + "<script>\n"
838             + LOG_TITLE_FUNCTION
839             + "  var node = document.getElementById('tab1');\n"
840             + "  log(node.borderColorDark);\n"
841 
842             + "  node.borderColor = '#667788';\n"
843             + "  log(node.borderColorDark);\n"
844 
845             + "  node.borderColor = 'unknown';\n"
846             + "  log(node.borderColorDark);\n"
847 
848             + "  var node = document.getElementById('tab2');\n"
849             + "  log(node.borderColorDark);\n"
850             + "  var node = document.getElementById('tab3');\n"
851             + "  log(node.borderColorDark);\n"
852             + "  var node = document.getElementById('tab4');\n"
853             + "  log(node.borderColorDark);\n"
854 
855             + "</script></body></html>";
856 
857         loadPageVerifyTitle2(html);
858     }
859 
860     /**
861      * @throws Exception if the test fails
862      */
863     @Test
864     @Alerts({"undefined", "undefined", "undefined", "undefined", "undefined", "undefined"})
865     public void borderColorLight() throws Exception {
866         final String html = DOCTYPE_HTML
867             + "<html><body>\n"
868             + "  <table id='tab1'></table>\n"
869             + "  <table id='tab2' borderColorLight='red'></table>\n"
870             + "  <table id='tab3' borderColorLight='#123456'></table>\n"
871             + "  <table id='tab4' borderColorLight='unknown'></table>\n"
872             + "<script>\n"
873             + LOG_TITLE_FUNCTION
874             + "  var node = document.getElementById('tab1');\n"
875             + "  log(node.borderColorLight);\n"
876 
877             + "  node.borderColor = '#667788';\n"
878             + "  log(node.borderColorLight);\n"
879 
880             + "  node.borderColor = 'unknown';\n"
881             + "  log(node.borderColorLight);\n"
882 
883             + "  var node = document.getElementById('tab2');\n"
884             + "  log(node.borderColorLight);\n"
885             + "  var node = document.getElementById('tab3');\n"
886             + "  log(node.borderColorLight);\n"
887             + "  var node = document.getElementById('tab4');\n"
888             + "  log(node.borderColorLight);\n"
889 
890             + "</script></body></html>";
891 
892         loadPageVerifyTitle2(html);
893     }
894 
895     /**
896      * @throws Exception if the test fails
897      */
898     @Test
899     @Alerts({"", "hello", "unknown", "ReferenceError", "", "test"})
900     public void summary() throws Exception {
901         final String html = DOCTYPE_HTML
902             + "<html><body>\n"
903             + "  <table id='tab1'></table>\n"
904             + "  <table id='tab2' summary=''></table>\n"
905             + "  <table id='tab3' summary='test'></table>\n"
906             + "<script>\n"
907             + LOG_TITLE_FUNCTION
908             + "  var node = document.getElementById('tab1');\n"
909             + "  log(node.summary);\n"
910 
911             + "  node.summary = 'hello';\n"
912             + "  log(node.summary);\n"
913 
914             + "  node.summary = 'unknown';\n"
915             + "  log(node.summary);\n"
916 
917             + "  try { node.summary = unknown; } catch(e) { logEx(e) }\n"
918 
919             + "  var node = document.getElementById('tab2');\n"
920             + "  log(node.summary);\n"
921 
922             + "  var node = document.getElementById('tab3');\n"
923             + "  log(node.summary);\n"
924 
925             + "</script>\n"
926             + "</body></html>";
927 
928         loadPageVerifyTitle2(html);
929     }
930 
931     /**
932      * @throws Exception if an error occurs
933      */
934     @Test
935     @Alerts({"none", "groups", "rows", "cols", "wrong", ""})
936     public void getRules() throws Exception {
937         final String html = DOCTYPE_HTML
938             + "<html><body>\n"
939             + "  <table id='t1' rules='none'></table>\n"
940             + "  <table id='t2' rules='groups'></table>\n"
941             + "  <table id='t3' rules='rows'></table>\n"
942             + "  <table id='t4' rules='cols'></table>\n"
943             + "  <table id='t5' rules='wrong'></table>\n"
944             + "  <table id='t6'></table>\n"
945 
946             + "<script>\n"
947             + LOG_TITLE_FUNCTION
948             + "  for (var i = 1; i <= 6; i++) {\n"
949             + "    log(document.getElementById('t' + i).rules);\n"
950             + "  }\n"
951             + "</script>\n"
952             + "</body></html>";
953 
954         loadPageVerifyTitle2(html);
955     }
956 
957     /**
958      * @throws Exception if an error occurs
959      */
960     @Test
961     @Alerts({"groUPs", "8", "foo", "rows", "cols"})
962     public void setRules() throws Exception {
963         final String html = DOCTYPE_HTML
964             + "<html><body>\n"
965             + "  <table id='t1' rules='groups'></table>\n"
966 
967             + "<script>\n"
968             + LOG_TITLE_FUNCTION
969             + "  function setRules(elem, value) {\n"
970             + "    try {\n"
971             + "      elem.rules = value;\n"
972             + "    } catch(e) { logEx(e); }\n"
973             + "    log(elem.rules);\n"
974             + "  }\n"
975 
976             + "  var elem = document.getElementById('t1');\n"
977             + "  setRules(elem, 'groUPs');\n"
978 
979             + "  setRules(elem, '8');\n"
980             + "  setRules(elem, 'foo');\n"
981 
982             + "  setRules(elem, 'rows');\n"
983             + "  setRules(elem, 'cols');\n"
984             + "</script>\n"
985             + "</body></html>";
986 
987         loadPageVerifyTitle2(html);
988     }
989 }