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