Skip to content

Commit

Permalink
fix(td-headers-attr): ignore hidden cells with headers attr (#3684)
Browse files Browse the repository at this point in the history
* fix(td-headers-attr): ignore table elements with their role changed

* add aria-hidden test
  • Loading branch information
WilcoFiers authored Sep 28, 2022
1 parent 902d07c commit e0403f4
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 66 deletions.
3 changes: 2 additions & 1 deletion lib/checks/tables/td-headers-attr-evaluate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { tokenList } from '../../core/utils';
import { isVisibleForScreenreader } from '../../commons/dom';

function tdHeadersAttrEvaluate(node) {
const cells = [];
Expand All @@ -24,7 +25,7 @@ function tdHeadersAttrEvaluate(node) {
let isSelf = false;
let notOfTable = false;

if (!cell.hasAttribute('headers')) {
if (!cell.hasAttribute('headers') || !isVisibleForScreenreader(cell)) {
return;
}

Expand Down
140 changes: 76 additions & 64 deletions test/checks/tables/td-headers-attr.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,122 +3,134 @@ describe('td-headers-attr', function () {

var fixture = document.getElementById('fixture');
var checkContext = axe.testUtils.MockCheckContext();
var fixtureSetup = axe.testUtils.fixtureSetup;
var check = axe.testUtils.getCheckEvaluate('td-headers-attr');

afterEach(function () {
fixture.innerHTML = '';
checkContext.reset();
});

it('returns true no headers attribute is present', function () {
fixture.innerHTML =
fixtureSetup(
'<table>' +
' <tr> <th>hi</th> <td>hello</td> </tr>' +
' <tr> <th>hi</th> <td>hello</td> </tr>' +
'</table>';
' <tr> <th>hi</th> <td>hello</td> </tr>' +
' <tr> <th>hi</th> <td>hello</td> </tr>' +
'</table>'
);

var node = fixture.querySelector('table');
assert.isTrue(
axe.testUtils.getCheckEvaluate('td-headers-attr').call(checkContext, node)
);
assert.isTrue(check.call(checkContext, node));
});

it('returns true if a valid header is present', function () {
fixture.innerHTML =
fixtureSetup(
'<table>' +
' <tr> <th id="hi">hello</th> </tr>' +
' <tr> <td headers="hi">goodbye</td> </tr>' +
'</table>';
' <tr> <th id="hi">hello</th> </tr>' +
' <tr> <td headers="hi">goodbye</td> </tr>' +
'</table>'
);

var node = fixture.querySelector('table');
assert.isTrue(
axe.testUtils.getCheckEvaluate('td-headers-attr').call(checkContext, node)
);
assert.isTrue(check.call(checkContext, node));
});

it('returns true if multiple valid headers are present', function () {
fixture.innerHTML =
fixtureSetup(
'<table>' +
' <tr> <th id="hi1">hello</th> <th id="hi2">hello</th> </tr>' +
' <tr> <td headers="hi1 \t\n hi2">goodbye</td> </tr>' +
'</table>';
' <tr> <th id="hi1">hello</th> <th id="hi2">hello</th> </tr>' +
' <tr> <td headers="hi1 \t\n hi2">goodbye</td> </tr>' +
'</table>'
);

var node = fixture.querySelector('table');
assert.isTrue(
axe.testUtils.getCheckEvaluate('td-headers-attr').call(checkContext, node)
);
assert.isTrue(check.call(checkContext, node));
});

it('returns true with an empty header', function () {
fixture.innerHTML =
fixtureSetup(
'<table>' +
' <tr> <th id="hi1"></th> </tr>' +
' <tr> <td headers="hi1">goodbye</td> </tr>' +
'</table>';
' <tr> <th id="hi1"></th> </tr>' +
' <tr> <td headers="hi1">goodbye</td> </tr>' +
'</table>'
);

var node = fixture.querySelector('table');
assert.isTrue(
axe.testUtils.getCheckEvaluate('td-headers-attr').call(checkContext, node)
);
assert.isTrue(check.call(checkContext, node));
});

it('returns undefined if headers is empty', function () {
fixture.innerHTML =
fixtureSetup(
'<table>' +
' <tr> <th id="hi"> </th> </tr>' +
' <tr> <td headers="">goodbye</td> </tr>' +
'</table>';
' <tr> <th id="hi"> </th> </tr>' +
' <tr> <td headers="">goodbye</td> </tr>' +
'</table>'
);

var node = fixture.querySelector('table');
assert.isUndefined(
axe.testUtils.getCheckEvaluate('td-headers-attr').call(checkContext, node)
);
assert.isUndefined(check.call(checkContext, node));
});

it('returns false if the header is a table cell', function () {
var node;

fixture.innerHTML =
fixtureSetup(
'<table>' +
' <tr> <th> <span id="hi">hello</span> </th> </tr>' +
' <tr> <td headers="h1">goodbye</td> </tr>' +
'</table>';
node = fixture.querySelector('table');
assert.isFalse(
axe.testUtils.getCheckEvaluate('td-headers-attr').call(checkContext, node)
' <tr> <th> <span id="hi">hello</span> </th> </tr>' +
' <tr> <td headers="h1">goodbye</td> </tr>' +
'</table>'
);
node = fixture.querySelector('table');
assert.isFalse(check.call(checkContext, node));

fixture.innerHTML =
fixtureSetup(
'<span id="hi">hello</span>' +
'<table>' +
' <tr> <th></th> </tr>' +
' <tr> <td headers="h1">goodbye</td> </tr>' +
'</table>';
node = fixture.querySelector('table');
assert.isFalse(
axe.testUtils.getCheckEvaluate('td-headers-attr').call(checkContext, node)
'<table>' +
' <tr> <th></th> </tr>' +
' <tr> <td headers="h1">goodbye</td> </tr>' +
'</table>'
);
node = fixture.querySelector('table');
assert.isFalse(check.call(checkContext, node));

fixture.innerHTML =
fixtureSetup(
'<table id="hi">' +
' <tr> <th>hello</th> </tr>' +
' <tr> <td headers="h1">goodbye</td> </tr>' +
'</table>';
node = fixture.querySelector('table');
assert.isFalse(
axe.testUtils.getCheckEvaluate('td-headers-attr').call(checkContext, node)
' <tr> <th>hello</th> </tr>' +
' <tr> <td headers="h1">goodbye</td> </tr>' +
'</table>'
);
node = fixture.querySelector('table');
assert.isFalse(check.call(checkContext, node));
});

it('returns false if the header refers to the same cell', function () {
fixture.innerHTML =
fixtureSetup(
'<table id="hi">' +
' <tr> <th>hello</th> </tr>' +
' <tr> <td id="bye" headers="bye">goodbye</td> </tr>' +
'</table>';
' <tr> <th>hello</th> </tr>' +
' <tr> <td id="bye" headers="bye">goodbye</td> </tr>' +
'</table>'
);

var node = fixture.querySelector('table');
assert.isFalse(
axe.testUtils.getCheckEvaluate('td-headers-attr').call(checkContext, node)
assert.isFalse(check.call(checkContext, node));
});

it('returns true if td[headers] is hidden', function () {
fixtureSetup(
'<table>' +
' <tr> <th>Hello</th> <td headers="h1" hidden>goodbye</td> </tr>' +
'</table>'
);
var node = fixture.querySelector('table');
assert.isTrue(check.call(checkContext, node));
});

it('returns true if td[headers] has aria-hidden=true', function () {
fixtureSetup(
'<table>' +
' <tr> <th>Hello</th> <td headers="h1" aria-hidden="true">goodbye</td> </tr>' +
'</table>'
);
var node = fixture.querySelector('table');
assert.isTrue(check.call(checkContext, node));
});
});
5 changes: 5 additions & 0 deletions test/integration/rules/td-headers-attr/td-headers-attr.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
<td headers="p3h1 p3h2">World</td>
</table>

<table id="pass4" role="treegrid">
<th id="p4h">Hello</th>
<td id="self" headers="self" hidden>World</td>
</table>

<table id="fail1">
<th id="f1h1">Hello</th>
<td headers="f1h1 non-existing">World</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"description": "td-headers-attr test",
"rule": "td-headers-attr",
"violations": [["#fail1"], ["#fail2"], ["#fail3"]],
"passes": [["#pass1"], ["#pass2"], ["#pass3"]]
"passes": [["#pass1"], ["#pass2"], ["#pass3"], ["#pass4"]]
}

0 comments on commit e0403f4

Please sign in to comment.