Skip to content

Commit d68af4c

Browse files
authored
fix: td-has-heading to ignore td with its role changed (#928)
1 parent 130efed commit d68af4c

File tree

5 files changed

+73
-7
lines changed

5 files changed

+73
-7
lines changed

lib/checks/tables/td-has-header.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ cells.forEach((cell) => {
99
!axe.commons.aria.label(cell)
1010
) {
1111
// Check if it has any headers
12-
var hasHeaders = tableUtils.getHeaders(cell);
13-
hasHeaders = hasHeaders.reduce(function (hasHeaders, header) {
14-
return (hasHeaders || header !== null && !!axe.commons.dom.hasContent(header));
15-
}, false);
12+
const hasHeaders = tableUtils.getHeaders(cell).some(header => {
13+
return header !== null && !!axe.commons.dom.hasContent(header);
14+
});
1615

1716
// If no headers, put it on the naughty list
1817
if (!hasHeaders) {

lib/commons/table/is-data-cell.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,10 @@ table.isDataCell = function (cell) {
1313
if (!cell.children.length && !cell.textContent.trim()) {
1414
return false;
1515
}
16-
return cell.nodeName.toUpperCase() === 'TD';
16+
const role = cell.getAttribute('role');
17+
if (axe.commons.aria.isValidRole(role)) {
18+
return ['cell', 'gridcell'].includes(role);
19+
} else {
20+
return cell.nodeName.toUpperCase() === 'TD';
21+
}
1722
};

test/commons/table/is-data-cell.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,42 @@ describe('table.isDataCell', function () {
4040
assert.isFalse(axe.commons.table.isDataCell(target));
4141
});
4242

43+
it('should ignore TDs with a valid role other than (grid)cell', function () {
44+
fixture.innerHTML = '<table>' +
45+
'<tr><td id="target1" role="columnheader">heading</td></tr>' +
46+
'<tr><td id="target2" role="rowheader">heading</td></tr>' +
47+
'<tr><td id="target3" role="presentation">heading</td></tr>' +
48+
'</table>';
49+
50+
var target1 = $id('target1');
51+
var target2 = $id('target2');
52+
var target3 = $id('target3');
53+
assert.isFalse(axe.commons.table.isDataCell(target1));
54+
assert.isFalse(axe.commons.table.isDataCell(target2));
55+
assert.isFalse(axe.commons.table.isDataCell(target3));
56+
});
57+
58+
it('should return true for elements with role="(grid)cell"', function () {
59+
fixture.innerHTML = '<table>' +
60+
'<tr><th id="target1" role="cell">heading</th></tr>' +
61+
'<tr><th id="target2" role="gridcell">heading</th></tr>' +
62+
'</table>';
63+
64+
var target1 = $id('target1');
65+
var target2 = $id('target2');
66+
assert.isTrue(axe.commons.table.isDataCell(target1));
67+
assert.isTrue(axe.commons.table.isDataCell(target2));
68+
});
69+
70+
it('should ignore invalid roles', function () {
71+
fixture.innerHTML = '<table>' +
72+
'<tr><td id="target1" role="foobar">heading</td></tr>' +
73+
'<tr><th id="target2" role="foobar">heading</th></tr>' +
74+
'</table>';
75+
76+
var target1 = $id('target1');
77+
var target2 = $id('target2');
78+
assert.isTrue(axe.commons.table.isDataCell(target1));
79+
assert.isFalse(axe.commons.table.isDataCell(target2));
80+
});
4381
});

test/integration/rules/td-has-header/td-has-header.html

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,32 @@
2727
<tr> <th>AXE</th> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>
2828
</table>
2929

30-
</table>
3130
<table id="pass3">
3231
<tr> <th>AXE</th> <th>AXE</th> <th>AXE</th> <th>AXE</th> </tr>
3332
<tr> <th>AXE</th> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>
3433
<tr> <th>AXE</th> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>
3534
<tr> <th>AXE</th> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>
3635
</table>
3736

37+
<table id="pass4">
38+
<tr>
39+
<td role="columnheader">AXE</td>
40+
<td role="columnheader">AXE</td>
41+
<td role="columnheader">AXE</td>
42+
<td role="columnheader">AXE</td>
43+
</tr>
44+
<tr> <td>aXe</td> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>
45+
<tr> <td>aXe</td> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>
46+
<tr> <td>aXe</td> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>
47+
</table>
48+
49+
<table id="pass5">
50+
<tr> <td role="rowheader">AXE</td> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>
51+
<tr> <td role="rowheader">AXE</td> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>
52+
<tr> <td role="rowheader">AXE</td> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>
53+
<tr> <td role="rowheader">AXE</td> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>
54+
</table>
55+
3856
<table id="fail1">
3957
<tr> <th>AXE</th> <th>AXE</th> <th>AXE</th> <td>aXe</td> </tr>
4058
<tr> <td>aXe</td> <td>aXe</td> <td>aXe</td> <td>aXe</td> </tr>

test/integration/rules/td-has-header/td-has-header.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,11 @@
22
"description": "td-has-header test",
33
"rule": "td-has-header",
44
"violations": [["#fail1"], ["#fail2"]],
5-
"passes": [["#pass1"], ["#pass2"], ["#pass3"]]
5+
"passes": [
6+
["#pass1"],
7+
["#pass2"],
8+
["#pass3"],
9+
["#pass4"],
10+
["#pass5"]
11+
]
612
}

0 commit comments

Comments
 (0)