From e2208252f7dd02208ed6c19305230a06c4bfbc26 Mon Sep 17 00:00:00 2001 From: Shunguo Date: Tue, 15 Aug 2023 15:43:28 -0500 Subject: [PATCH 01/10] initial test cases #1472 --- .../v2/checker/accessibility/util/legacy.ts | 3 +- .../table_bottom_headers.htm | 87 ++++++ .../table_column_headers.htm | 70 +++++ .../table_column_headers_css.htm | 71 +++++ .../table_double_headers.htm | 82 ++++++ .../table_mutiple_headers.htm | 263 ++++++++++++++++++ 6 files changed, 575 insertions(+), 1 deletion(-) create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers.htm create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers_css.htm create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers.htm create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_mutiple_headers.htm diff --git a/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts b/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts index e719110e9..4085fe1dd 100644 --- a/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts +++ b/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts @@ -1110,9 +1110,10 @@ export class RPTUtil { let passed = false; let rows = ruleContext.rows; - // Check if the first row is all TH's + if (rows != null && rows.length > 0) { let firstRow = rows[0]; + // Check if the cells with data in the first row are all TH's passed = firstRow.cells.length > 0 && RPTUtil.getChildByTagHidden(firstRow, "td", false, true).length === 0; // If the first row isn't a header row, try the first column if (!passed) { diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers.htm new file mode 100755 index 000000000..17d18bc31 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers.htm @@ -0,0 +1,87 @@ + + + + + +Data table is missing one row header + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bottom headers
row 1row 1row 1
datadatadata
datadatadata
Header 1Header 2Header 3
Footer
+ + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm new file mode 100755 index 000000000..be262e7dd --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm @@ -0,0 +1,70 @@ + + + + + +Data table is missing one row header + + + + + + + + + + + + + + + + + +
Column Headers in first cells
Header 1datadatadata
Header 2datadatadata
Header 2datadatadata
+ + + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers_css.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers_css.htm new file mode 100755 index 000000000..5464d92fc --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers_css.htm @@ -0,0 +1,71 @@ + + + + + +Data table is missing one row header + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Left headers in thead
Header 1
Header 2
Header 3
row 1row 1row 1
datadatadata
datadatadata
Footer
+ + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers.htm new file mode 100755 index 000000000..6c0493828 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers.htm @@ -0,0 +1,82 @@ + + + + + +Data table is missing one row header + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Shelly's Daughters
NameAgeBirthday
by birthJackie5April 5
Beth8January 14
by marriageBeth8January 14
+ + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_mutiple_headers.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_mutiple_headers.htm new file mode 100755 index 000000000..fdb55c690 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_mutiple_headers.htm @@ -0,0 +1,263 @@ + + + + + +Data table is missing one row header + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Complext data table with column headers in first two cells and bottom headers
+ Importance to Stakeholders + Not Determined + +
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
Very High +
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
High +
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
Medium +
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
Low +
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
Very Low +
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
+
+
0
+
+
Very + Low + Low + Medium + High + Very + High + Not + Determined
Importance + to Firm
+
+ + + From 81d780906e328dd783e4f34578c10be261ea3624 Mon Sep 17 00:00:00 2001 From: Shunguo Date: Wed, 16 Aug 2023 12:00:41 -0500 Subject: [PATCH 02/10] update the rule for table header check #1472 --- .../v2/checker/accessibility/util/legacy.ts | 22 ++++-- .../table_column_headers.htm | 7 +- .../table_column_headers_css.htm | 24 ++++++- ..._headers.htm => table_double_headers1.htm} | 0 .../table_double_headers2.htm | 70 +++++++++++++++++++ ...headers.htm => table_multiple_headers.htm} | 20 +++++- 6 files changed, 134 insertions(+), 9 deletions(-) rename accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/{table_double_headers.htm => table_double_headers1.htm} (100%) create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers2.htm rename accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/{table_mutiple_headers.htm => table_multiple_headers.htm} (95%) diff --git a/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts b/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts index 4085fe1dd..0367d519a 100644 --- a/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts +++ b/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts @@ -1108,24 +1108,36 @@ export class RPTUtil { // Return true if a table's header is in the first row or column public static isTableHeaderInFirstRowOrColumn(ruleContext) { - let passed = false; + let passed = true; let rows = ruleContext.rows; if (rows != null && rows.length > 0) { let firstRow = rows[0]; // Check if the cells with data in the first row are all TH's - passed = firstRow.cells.length > 0 && RPTUtil.getChildByTagHidden(firstRow, "td", false, true).length === 0; + //passed = firstRow.cells.length > 0 && RPTUtil.getChildByTagHidden(firstRow, "td", false, true).length === 0; + if (!firstRow.cells) + passed = false; + else { + for (let c=0; passed && c < firstRow.cells.length; c++) { + let cell = firstRow.cells[c]; + passed = !VisUtil.isNodeVisible(cell) || (cell.innerHTML.trim().length > 0 && cell.nodeName.toLowerCase() === 'th'); + } + } + // If the first row isn't a header row, try the first column if (!passed) { - // Assume that the first column has all TH's unless we find a TD in the first column. + // Assume that the first column has all TH's or a TD without data in the first column. passed = true; for (let i = 0; passed && i < rows.length; ++i) { - // If no cells in this row, that's okay too. + // ignore the rows from tfoot + if (rows[i].parentNode && rows[i].parentNode.nodeName.toLowerCase() === 'tfoot') continue; + // If no cells in this row, or no data at all, that's okay too. passed = !rows[i].cells || rows[i].cells.length === 0 || + rows[i].cells[0].innerHTML.trim().length === 0 || rows[i].cells[0].nodeName.toLowerCase() != "td"; } - } + } if (!passed) { // Special case - both first row and first column are headers, but they did not use // a th for the upper-left cell diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm index be262e7dd..377f9046a 100755 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm @@ -21,7 +21,7 @@ Data table is missing one row header @@ -41,6 +41,11 @@ Header 2 datadatadata + + + Footer + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers1.htm similarity index 100% rename from accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers.htm rename to accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers1.htm diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers2.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers2.htm new file mode 100755 index 000000000..28ed3b9ae --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_double_headers2.htm @@ -0,0 +1,70 @@ + + + + + +Data table is missing one row header + + + + + + + + + + + + + + + + + + + + +
+ Council budget (in £) 2018 +
ItemsExpenditure
Donuts3,000
Stationery18,000
+ + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_mutiple_headers.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_multiple_headers.htm similarity index 95% rename from accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_mutiple_headers.htm rename to accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_multiple_headers.htm index fdb55c690..f8b7d1ef0 100755 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_mutiple_headers.htm +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_multiple_headers.htm @@ -25,7 +25,8 @@
- + + @@ -255,7 +256,22 @@ UnitTest = { ruleIds: ["table_headers_exists"], results: [ - + { + "ruleId": "table_headers_exists", + "value": [ + "INFORMATION", + "PASS" + ], + "path": { + "dom": "/html[1]/body[1]/div[1]/table[1]", + "aria": "/document[1]/table[1]" + }, + "reasonId": "Pass_0", + "message": "Rule Passed", + "messageArgs": [], + "apiArgs": [], + "category": "Accessibility" + } ] }; From ff2c3d9bf62b263bc40588f9a603007a4817d6cf Mon Sep 17 00:00:00 2001 From: Shunguo Date: Fri, 18 Aug 2023 20:48:41 -0500 Subject: [PATCH 03/10] additional test cases #1472 --- ...> table_bottom_headers_no_association.htm} | 0 .../table_bottom_headers_with_association.htm | 87 +++++++++++++++++++ .../table_column_headers.htm | 8 +- .../table_column_headers_css.htm | 2 +- .../table_double_headers1.htm | 1 - .../table_double_headers2.htm | 7 +- .../table_multiple_headers.htm | 2 +- .../table_row_headers_bottom.htm | 71 +++++++++++++++ .../table_row_headers_middle.htm | 81 +++++++++++++++++ .../table_row_headers_multiple.htm | 86 ++++++++++++++++++ .../table_row_headers_top_th.htm | 73 ++++++++++++++++ .../table_row_headers_top_tr.htm | 71 +++++++++++++++ 12 files changed, 480 insertions(+), 9 deletions(-) rename accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/{table_bottom_headers.htm => table_bottom_headers_no_association.htm} (100%) create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_with_association.htm create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_bottom.htm create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_middle.htm create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_multiple.htm create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_top_th.htm create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_top_tr.htm diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_no_association.htm similarity index 100% rename from accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers.htm rename to accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_no_association.htm diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_with_association.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_with_association.htm new file mode 100755 index 000000000..ef1b6cd86 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_with_association.htm @@ -0,0 +1,87 @@ + + + + + +Data table is missing one row header + + + + + +
Complext data table with column headers in first two cells and bottom headers
Importance to Stakeholders
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bottom headers
row 1row 1row 1
datadatadata
datadatadata
Header 1Header 2Header 3
Footer
+ + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm index 377f9046a..d5292718b 100755 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers.htm @@ -19,7 +19,7 @@ -Data table is missing one row header + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Column Headers in first cells
datarow Header 1datadata
datarow Header 2datadata
datarow Header 3datadata
Footer
+ + + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers_right.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers_right.html new file mode 100755 index 000000000..4a1b7b055 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers_right.html @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Column Headers in first cells
datadatadatarow Header 1
datadatadatarow Header 2
datadatadatarow Header 3
Footer
+ + + + From 7036380551ef5889eb02d6935b94a0d9eac4626e Mon Sep 17 00:00:00 2001 From: Shunguo Date: Tue, 29 Aug 2023 15:30:58 -0500 Subject: [PATCH 09/10] update the rule #1472 --- .../v2/checker/accessibility/util/legacy.ts | 91 ++++++------------- 1 file changed, 27 insertions(+), 64 deletions(-) diff --git a/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts b/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts index a2c682f6e..463cb6b08 100644 --- a/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts +++ b/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts @@ -1137,7 +1137,7 @@ export class RPTUtil { // note that table.rows return all all the rows in the table, // including the rows contained within , , and elements. - //case 1: headers are in the very first row with data in tbody or thead + //case 1: headers are in the very first row with data in tbody or thead, but not in tfoot //get the first row with data, ignoring the rows with no data let passed = true; let firstRow = rows[0]; @@ -1154,7 +1154,6 @@ export class RPTUtil { return null; // Check if the cells with data in the first data row are all TH's - //passed = firstRow.cells.length > 0 && RPTUtil.getChildByTagHidden(firstRow, "td", false, true).length === 0; passed = true; for (let r=0; passed && r < firstRow.cells.length; r++) { let cell = firstRow.cells[r]; @@ -1164,56 +1163,7 @@ export class RPTUtil { if (passed) return true; - //case 2: headers are in the very last/bottom row with data in tbody or thead - //get the last row with data - passed = true; - let lastRow = rows[rows.length-1]; - for (let r=rows.length-1; passed && r >= 0; r--) { - lastRow = rows[r]; - // ignore the rows from tfoot - if (lastRow.parentNode && lastRow.parentNode.nodeName.toLowerCase() === 'tfoot') continue; - - passed = RPTUtil.isTableRowEmpty(lastRow); - } - - if (passed) //shouldn't happen! - return true; - - // Check if the cells with data in the last data row are all TH's - passed = true; - for (let r=0; passed && r < lastRow.cells.length; r++) { - let cell = lastRow.cells[r]; - passed = RPTUtil.isTableCellEmpty(cell) || cell.nodeName.toLowerCase() === 'th'; - } - - if (passed) - return true; - - //case 3: headers are in a row with data in tfoot - let footer = ruleContext.getElementsByTagName("tfoot"); - if (footer && footer.length > 0) { - let frows = footer[0].getElementsByTagName("tr"); - if (frows && frows.length > 0) { - let frow = frows[0]; - for (let r=0; r < frows.length; r++) { - frow = frows[r]; - passed = RPTUtil.isTableRowEmpty(frow); - if (passed) continue; - // Check if the cells with data in the last data row are all TH's - passed = true; - for (let r=0; passed && r < frow.cells.length; r++) { - let cell = frow.cells[r]; - passed = RPTUtil.isTableCellEmpty(cell) || cell.nodeName.toLowerCase() === 'th'; - } - - if (passed) - return true; - - } - } - } - - // Case 4: headers are in the first columns with data + // Case 2: headers are in the first column with data // Assume that the first column has all TH's or a TD without data in the first column. passed = true; for (let i = 0; passed && i < rows.length; ++i) { @@ -1229,21 +1179,34 @@ export class RPTUtil { if (passed) return true; - - // Case 5: Special case - both first row and first column are headers, but they did not use - // a th for the upper-left cell + + //case 3: all td data cells have headers attributes that point to the id of a th element in the same table. + // https://html.spec.whatwg.org/multipage/tables.html#attributes-common-to-td-and-th-elements passed = true; - for (let i = 1; passed && i < firstRow.cells.length; ++i) { - passed = firstRow.cells[i].nodeName.toLowerCase() != "td"; + let thIds = []; + let tdHeaders = []; + for (let r=0; passed && r < rows.length; r++) { + let row = rows[r]; + // Check if the cells with data in the last data row are all TH's + for (let c=0; c < row.cells.length; c++) { + let cell = row.cells[c]; + if (RPTUtil.isTableCellEmpty(cell)) continue; + if (cell.nodeName.toLowerCase() === 'td') { + if (!cell.getAttribute('headers') || cell.getAttribute('headers').trim().length === 0) + passed = false; + else + RPTUtil.concatUniqueArrayItemList(cell.getAttribute('headers').trim().split(" "), tdHeaders); + } else if (cell.nodeName.toLowerCase() === 'th' && cell.getAttribute('id') && cell.getAttribute('id').trim().length > 0) + RPTUtil.concatUniqueArrayItem(cell.getAttribute('id').trim(), thIds); + } } - for (let i = 1; passed && i < rows.length; ++i) { - // If no cells in this row, that's okay too. - passed = !rows[i].cells || - rows[i].cells.length === 0 || - rows[i].cells[0].nodeName.toLowerCase() != "td"; + + if (passed) { // all td elements have headers, to exam if the headers point to a th id + if (thIds.length > 0 && tdHeaders.some(header => thIds.includes(header))) + return true; } - - return passed; + + return false; } public static isNodeInGrid(node) { From 89823aeb7949e2fd8c9323ca0948628e183abfa3 Mon Sep 17 00:00:00 2001 From: Shunguo Date: Tue, 29 Aug 2023 16:39:51 -0500 Subject: [PATCH 10/10] update the rule and test results #1472 --- .../v2/checker/accessibility/util/legacy.ts | 18 ++--- .../table_bottom_headers_tfoot.htm | 8 +- .../table_bottom_headers_tfooter_headers.htm | 8 +- .../table_column_headers_middle.html | 19 ++--- .../table_column_headers_right.html | 6 +- .../table_headers_row_association.html | 76 +++++++++++++++++++ ...table_headers_row_association_missing.html | 76 +++++++++++++++++++ .../table_headers_row_association_wrong.html | 76 +++++++++++++++++++ .../table_row_headers_bottom.html | 6 +- .../table_row_headers_bottom_tr_empty.html | 6 +- 10 files changed, 261 insertions(+), 38 deletions(-) create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_headers_row_association.html create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_headers_row_association_missing.html create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_headers_row_association_wrong.html diff --git a/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts b/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts index 463cb6b08..9523e5bc8 100644 --- a/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts +++ b/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts @@ -1107,7 +1107,7 @@ export class RPTUtil { // Return true if a table cell is hidden or contain no data: public static isTableCellEmpty(cell) { - if (!cell || !VisUtil.isNodeVisible(cell) || cell.innerHTML.trim().length === 0) + if (!cell || !VisUtil.isNodeVisible(cell) || cell.innerHTML.replace(/ /g,' ').trim().length === 0) return true; return false; @@ -1156,7 +1156,7 @@ export class RPTUtil { // Check if the cells with data in the first data row are all TH's passed = true; for (let r=0; passed && r < firstRow.cells.length; r++) { - let cell = firstRow.cells[r]; + let cell = firstRow.cells[r]; passed = RPTUtil.isTableCellEmpty(cell) || cell.nodeName.toLowerCase() === 'th'; } @@ -1182,15 +1182,15 @@ export class RPTUtil { //case 3: all td data cells have headers attributes that point to the id of a th element in the same table. // https://html.spec.whatwg.org/multipage/tables.html#attributes-common-to-td-and-th-elements - passed = true; + passed = true; let thIds = []; let tdHeaders = []; for (let r=0; passed && r < rows.length; r++) { - let row = rows[r]; + let row = rows[r]; // Check if the cells with data in the last data row are all TH's for (let c=0; c < row.cells.length; c++) { let cell = row.cells[c]; - if (RPTUtil.isTableCellEmpty(cell)) continue; + if (RPTUtil.isTableCellEmpty(cell)) continue; if (cell.nodeName.toLowerCase() === 'td') { if (!cell.getAttribute('headers') || cell.getAttribute('headers').trim().length === 0) passed = false; @@ -1200,12 +1200,12 @@ export class RPTUtil { RPTUtil.concatUniqueArrayItem(cell.getAttribute('id').trim(), thIds); } } - + if (passed) { // all td elements have headers, to exam if the headers point to a th id - if (thIds.length > 0 && tdHeaders.some(header => thIds.includes(header))) - return true; + if (thIds.length > 0 && tdHeaders.every(header => thIds.includes(header))) + return true; } - + return false; } diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_tfoot.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_tfoot.htm index b9cd838db..94ee8aed7 100755 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_tfoot.htm +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_tfoot.htm @@ -64,18 +64,18 @@ UnitTest = { ruleIds: ["table_headers_exists"], results: [ - { + { "ruleId": "table_headers_exists", "value": [ "INFORMATION", - "PASS" + "FAIL" ], "path": { "dom": "/html[1]/body[1]/table[1]", "aria": "/document[1]/table[1]" }, - "reasonId": "Pass_0", - "message": "Rule Passed", + "reasonId": "Fail_1", + "message": "Table has no headers identified", "messageArgs": [], "apiArgs": [], "category": "Accessibility" diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_tfooter_headers.htm b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_tfooter_headers.htm index 3c0cd238b..759f75d45 100755 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_tfooter_headers.htm +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_bottom_headers_tfooter_headers.htm @@ -66,18 +66,18 @@ UnitTest = { ruleIds: ["table_headers_exists"], results: [ - { + { "ruleId": "table_headers_exists", "value": [ "INFORMATION", - "PASS" + "FAIL" ], "path": { "dom": "/html[1]/body[1]/table[1]", "aria": "/document[1]/table[1]" }, - "reasonId": "Pass_0", - "message": "Rule Passed", + "reasonId": "Fail_1", + "message": "Table has no headers identified", "messageArgs": [], "apiArgs": [], "category": "Accessibility" diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers_middle.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers_middle.html index 92d74e3b3..9661edb0c 100755 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers_middle.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_column_headers_middle.html @@ -30,30 +30,25 @@ - - + + - + - + - - - - -
Column Headers in first cells
datarow Header 1datarow Header 1 data data
datarow Header 2row Header 2 data data
datarow Header 3row Header 3 data data
Footer
+ + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_headers_row_association_missing.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_headers_row_association_missing.html new file mode 100755 index 000000000..520e987c6 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_headers_row_association_missing.html @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Column Headers in first cells
datadataHeader 1data
datadataHeader 2data
datadataHeader 2data
+ + + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_headers_row_association_wrong.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_headers_row_association_wrong.html new file mode 100755 index 000000000..c1d9f9838 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_headers_row_association_wrong.html @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Column Headers in first cells
datadataHeader 1data
datadataHeader 2data
datadataHeader 2data
+ + + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_bottom.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_bottom.html index a99beef6d..77e91961b 100755 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_bottom.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_bottom.html @@ -51,14 +51,14 @@ "ruleId": "table_headers_exists", "value": [ "INFORMATION", - "PASS" + "FAIL" ], "path": { "dom": "/html[1]/body[1]/table[1]", "aria": "/document[1]/table[1]" }, - "reasonId": "Pass_0", - "message": "Rule Passed", + "reasonId": "Fail_1", + "message": "Table has no headers identified", "messageArgs": [], "apiArgs": [], "category": "Accessibility" diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_bottom_tr_empty.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_bottom_tr_empty.html index e45c50789..b293928a2 100755 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_bottom_tr_empty.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/table_headers_exists_ruleunit/table_row_headers_bottom_tr_empty.html @@ -54,14 +54,14 @@ "ruleId": "table_headers_exists", "value": [ "INFORMATION", - "PASS" + "FAIL" ], "path": { "dom": "/html[1]/body[1]/table[1]", "aria": "/document[1]/table[1]" }, - "reasonId": "Pass_0", - "message": "Rule Passed", + "reasonId": "Fail_1", + "message": "Table has no headers identified", "messageArgs": [], "apiArgs": [], "category": "Accessibility"