-
Notifications
You must be signed in to change notification settings - Fork 783
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(landmark-banner-is-top-level: add rule ensuring top level banner
- Loading branch information
1 parent
3e2acb1
commit 7c0cf8e
Showing
12 changed files
with
335 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
const landmarks = axe.commons.aria.getRolesByType('landmark'); | ||
const sectioning = ['article', 'aside', 'main', 'navigation', 'section']; | ||
const nodeIsHeader = node.tagName.toLowerCase() === 'header' && node.getAttribute('role') !== 'banner'; | ||
var parent = axe.commons.dom.getComposedParent(node); | ||
|
||
while (parent){ | ||
var role = parent.getAttribute('role'); | ||
if (!role && (parent.tagName.toLowerCase() !== 'form')){ | ||
role = axe.commons.aria.implicitRole(parent); | ||
} | ||
if (role && nodeIsHeader && sectioning.includes(role)){ | ||
return true; | ||
} | ||
if (role && landmarks.includes(role)){ | ||
return false; | ||
} | ||
parent = axe.commons.dom.getComposedParent(parent); | ||
} | ||
return true; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"id": "banner-is-top-level", | ||
"evaluate": "banner-is-top-level.js", | ||
"metadata": { | ||
"impact": "moderate", | ||
"messages": { | ||
"pass": "Banner landmark is top level or header element is not a banner", | ||
"fail": "Banner landmark is not top level" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"id": "landmark-banner-is-top-level", | ||
"selector": "[role=banner], header", | ||
"tags": [ | ||
"best-practice" | ||
], | ||
"metadata": { | ||
"description": "A banner landmark identifies site-oriented content at the beginning of each page within a website", | ||
"help": "Banner landmark must be at top level" | ||
}, | ||
"all": [], | ||
"any": [ | ||
"banner-is-top-level" | ||
], | ||
"none": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
describe('banner-is-top-level', function () { | ||
'use strict'; | ||
|
||
var fixture = document.getElementById('fixture'); | ||
|
||
var checkSetup = axe.testUtils.checkSetup; | ||
var shadowSupported = axe.testUtils.shadowSupport.v1; | ||
|
||
afterEach(function () { | ||
fixture.innerHTML = ''; | ||
}); | ||
|
||
it('should return false if banner landmark is in main element', function() { | ||
var main = document.createElement('main'); | ||
var banner = document.createElement('div'); | ||
banner.setAttribute('role','banner'); | ||
main.appendChild(banner); | ||
fixture.appendChild(main); | ||
assert.isFalse(checks['banner-is-top-level'].evaluate(banner)); | ||
}); | ||
|
||
it('should return false if banner landmark is in main element', function () { | ||
var main = document.createElement('main'); | ||
var banner = document.createElement('div'); | ||
banner.setAttribute('role','banner'); | ||
main.appendChild(banner); | ||
fixture.appendChild(main); | ||
assert.isFalse(checks['banner-is-top-level'].evaluate(banner)); | ||
}); | ||
|
||
it('should return false if banner landmark is in div with role main', function () { | ||
var main = document.createElement('div'); | ||
main.setAttribute('role','main'); | ||
var banner = document.createElement('div'); | ||
banner.setAttribute('role','banner'); | ||
main.appendChild(banner); | ||
fixture.appendChild(main); | ||
assert.isFalse(checks['banner-is-top-level'].evaluate(banner)); | ||
}); | ||
|
||
it('should return false if header is not sectioning element and in div with role search', function () { | ||
var search = document.createElement('div'); | ||
search.setAttribute('role','search'); | ||
var banner = document.createElement('header'); | ||
search.appendChild(banner); | ||
fixture.appendChild(search); | ||
assert.isFalse(checks['banner-is-top-level'].evaluate(banner)); | ||
}); | ||
|
||
|
||
it('should return true if banner landmark is not contained in another landmark', function () { | ||
var banner = document.createElement('div'); | ||
banner.setAttribute('role','banner'); | ||
fixture.appendChild(banner); | ||
assert.isTrue(checks['banner-is-top-level'].evaluate(banner)); | ||
}); | ||
|
||
it('should return true if header element is not sectioning element and not contained in landmark', function () { | ||
var header = document.createElement('header'); | ||
fixture.appendChild(header); | ||
assert.isTrue(checks['banner-is-top-level'].evaluate(header)); | ||
}); | ||
|
||
it('should return true if header element is in sectioning element', function () { | ||
var header = document.createElement('header'); | ||
var article = document.createElement('div'); | ||
article.setAttribute('role', 'main'); | ||
article.appendChild(header); | ||
fixture.appendChild(article); | ||
assert.isTrue(checks['banner-is-top-level'].evaluate(header)); | ||
}); | ||
|
||
(shadowSupported ? it : xit)('should test if banner in shadow DOM is top level', function () { | ||
var div = document.createElement('div'); | ||
var shadow = div.attachShadow({ mode: 'open' }); | ||
shadow.innerHTML = '<div role="banner">Banner landmark</div>'; | ||
var checkArgs = checkSetup(shadow.querySelector('[role=banner], header')); | ||
assert.isTrue(checks['banner-is-top-level'].evaluate.apply(null, checkArgs)); | ||
}); | ||
|
||
(shadowSupported ? it : xit)('should test if header in shadow DOM is top level', function () { | ||
var div = document.createElement('div'); | ||
var shadow = div.attachShadow({ mode: 'open' }); | ||
shadow.innerHTML = '<header>Banner landmark</header>'; | ||
var checkArgs = checkSetup(shadow.querySelector('[role=banner], header')); | ||
assert.isTrue(checks['banner-is-top-level'].evaluate.apply(null, checkArgs)); | ||
}); | ||
|
||
}); |
15 changes: 15 additions & 0 deletions
15
test/integration/full/landmark-banner-is-top-level/frames/level1-fail.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<!doctype html> | ||
<html id="violation2"> | ||
<head> | ||
<meta charset="utf8"> | ||
<script src="/axe.js"></script> | ||
</head> | ||
<body> | ||
<p>This iframe should fail, too</p> | ||
<div role="complementary"> | ||
<header> | ||
<p>This banner landmark is in a complementary landmark</p> | ||
</header> | ||
</div> | ||
</body> | ||
</html> |
27 changes: 27 additions & 0 deletions
27
test/integration/full/landmark-banner-is-top-level/frames/level1.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<!doctype html> | ||
<html id="pass2"> | ||
<head> | ||
<meta charset="utf8"> | ||
<script src="/axe.js"></script> | ||
</head> | ||
<body> | ||
<p>This iframe should pass, too</p> | ||
|
||
<div role="navigation"> | ||
<p>This div has role navigation</p> | ||
</div> | ||
<header> | ||
<p>This banner content is not within another landmark</p> | ||
</header> | ||
<div role="complementary"> | ||
<p>This div has role complementary</p> | ||
</div> | ||
<div role="search"> | ||
<p>This div has role search</p> | ||
</div> | ||
<div role="form"> | ||
<p>This div has role form<p> | ||
</div> | ||
<iframe id="frame2" src="level2.html"></iframe> | ||
</body> | ||
</html> |
15 changes: 15 additions & 0 deletions
15
test/integration/full/landmark-banner-is-top-level/frames/level2.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<!doctype html> | ||
<html id="pass3"> | ||
<head> | ||
<meta charset="utf8"> | ||
<script src="/axe.js"></script> | ||
</head> | ||
<body> | ||
<p>This iframe should pass<p> | ||
<main> | ||
<header> | ||
<p>This header is in a main landmark</p> | ||
</header> | ||
</main> | ||
</body> | ||
</html> |
29 changes: 29 additions & 0 deletions
29
test/integration/full/landmark-banner-is-top-level/landmark-banner-is-top-level-fail.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<!doctype html> | ||
<html lang="en" id="violation1"> | ||
<head> | ||
<title>landmark-banner-is-top-level test</title> | ||
<meta charset="utf8"> | ||
<link rel="stylesheet" type="text/css" href="/node_modules/mocha/mocha.css" /> | ||
<script src="/node_modules/mocha/mocha.js"></script> | ||
<script src="/node_modules/chai/chai.js"></script> | ||
<script src="/axe.js"></script> | ||
<script> | ||
mocha.setup({ | ||
timeout: 10000, | ||
ui: 'bdd' | ||
}); | ||
var assert = chai.assert; | ||
</script> | ||
</head> | ||
<body> | ||
<div role="navigation"> | ||
<div role="banner"> | ||
<p>This is going to fail</p> | ||
</div> | ||
</div> | ||
<iframe id="frame1" src="frames/level1-fail.html"></iframe> | ||
<div id="mocha"></div> | ||
<script src="landmark-banner-is-top-level-fail.js"></script> | ||
<script src="/test/integration/adapter.js"></script> | ||
</body> | ||
</html> |
40 changes: 40 additions & 0 deletions
40
test/integration/full/landmark-banner-is-top-level/landmark-banner-is-top-level-fail.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
describe('landmark-banner-is-top-level test fail', function () { | ||
'use strict'; | ||
var results; | ||
before(function (done) { | ||
window.addEventListener('load', function () { | ||
axe.run({ runOnly: { type: 'rule', values: ['landmark-banner-is-top-level'] } }, function (err, r) { | ||
assert.isNull(err); | ||
results = r; | ||
done(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('violations', function () { | ||
it('should find 1', function () { | ||
assert.lengthOf(results.violations, 1); | ||
}); | ||
|
||
it('should find 2 nodes', function () { | ||
assert.lengthOf(results.violations[0].nodes, 2); | ||
}); | ||
}); | ||
|
||
describe('passes', function () { | ||
it('should find none', function () { | ||
assert.lengthOf(results.passes, 0); | ||
}); | ||
|
||
}); | ||
|
||
|
||
it('should find 0 inapplicable', function () { | ||
assert.lengthOf(results.inapplicable, 0); | ||
}); | ||
|
||
it('should find 0 incomplete', function () { | ||
assert.lengthOf(results.incomplete, 0); | ||
}); | ||
|
||
}); |
39 changes: 39 additions & 0 deletions
39
test/integration/full/landmark-banner-is-top-level/landmark-banner-is-top-level-pass.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<!doctype html> | ||
<html lang="en" id="pass1"> | ||
<head> | ||
<title>landmark-banner-is-top-level test</title> | ||
<meta charset="utf8"> | ||
<link rel="stylesheet" type="text/css" href="/node_modules/mocha/mocha.css" /> | ||
<script src="/node_modules/mocha/mocha.js"></script> | ||
<script src="/node_modules/chai/chai.js"></script> | ||
<script src="/axe.js"></script> | ||
<script> | ||
mocha.setup({ | ||
timeout: 10000, | ||
ui: 'bdd' | ||
}); | ||
var assert = chai.assert; | ||
</script> | ||
</head> | ||
<body> | ||
<div role="navigation"> | ||
<p>This div has role navigation</p> | ||
</div> | ||
<div role="banner"> | ||
<p>This banner content is not within another landmark</p> | ||
</div> | ||
<div role="complementary"> | ||
<p>This div has role complementary</p> | ||
</div> | ||
<div role="search"> | ||
<p>This div has role search</p> | ||
</div> | ||
<div role="form"> | ||
<p>This div has role form<p> | ||
</div> | ||
<iframe id="frame1" src="frames/level1.html"></iframe> | ||
<div id="mocha"></div> | ||
<script src="landmark-banner-is-top-level-pass.js"></script> | ||
<script src="/test/integration/adapter.js"></script> | ||
</body> | ||
</html> |
34 changes: 34 additions & 0 deletions
34
test/integration/full/landmark-banner-is-top-level/landmark-banner-is-top-level-pass.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
describe('landmark-banner-is-top-level test pass', function () { | ||
'use strict'; | ||
var results; | ||
before(function (done) { | ||
window.addEventListener('load', function () { | ||
axe.run({ runOnly: { type: 'rule', values: ['landmark-banner-is-top-level'] } }, function (err, r) { | ||
assert.isNull(err); | ||
results = r; | ||
done(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('violations', function () { | ||
it('should find 0', function () { | ||
assert.lengthOf(results.violations, 0); | ||
}); | ||
}); | ||
|
||
describe('passes', function () { | ||
it('should find 3', function () { | ||
assert.lengthOf(results.passes[0].nodes, 3); | ||
}); | ||
}); | ||
|
||
it('should find 0 inapplicable', function () { | ||
assert.lengthOf(results.inapplicable, 0); | ||
}); | ||
|
||
it('should find 0 incomplete', function () { | ||
assert.lengthOf(results.incomplete, 0); | ||
}); | ||
|
||
}); |