-
Notifications
You must be signed in to change notification settings - Fork 794
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #760 from dequelabs/landmark-no-duplicate
New rules: No duplicate header/footer
- Loading branch information
Showing
25 changed files
with
633 additions
and
50 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 was deleted.
Oops, something went wrong.
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 @@ | ||
{ | ||
"id": "page-no-duplicate-banner", | ||
"evaluate": "page-no-duplicate.js", | ||
"options": { | ||
"selector": "header:not([role]), [role=banner]", | ||
"nativeScopeFilter": "article, aside, main, nav, section" | ||
}, | ||
"metadata": { | ||
"impact": "moderate", | ||
"messages": { | ||
"pass": "Document has no more than one banner landmark", | ||
"fail": "Document has more than one banner landmark" | ||
} | ||
} | ||
} |
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 @@ | ||
{ | ||
"id": "page-no-duplicate-contentinfo", | ||
"evaluate": "page-no-duplicate.js", | ||
"options": { | ||
"selector": "footer:not([role]), [role=contentinfo]", | ||
"nativeScopeFilter": "article, aside, main, nav, section" | ||
}, | ||
"metadata": { | ||
"impact": "moderate", | ||
"messages": { | ||
"pass": "Document has no more than one contentinfo landmark", | ||
"fail": "Document has more than one contentinfo landmark" | ||
} | ||
} | ||
} |
7 changes: 5 additions & 2 deletions
7
...s/keyboard/has-no-more-than-one-main.json → ...ecks/keyboard/page-no-duplicate-main.json
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,18 @@ | ||
if (!options || !options.selector || typeof options.selector !== 'string') { | ||
throw new TypeError('visible-in-page requires options.selector to be a string'); | ||
} | ||
|
||
let elms = axe.utils.querySelectorAll(virtualNode, options.selector); | ||
|
||
// Filter elements that, within certain contexts, don't map their role. | ||
// e.g. a <footer> inside a <main> is not a banner, but in the <body> context it is | ||
if (typeof options.nativeScopeFilter === 'string') { | ||
elms = elms.filter(elm => { | ||
return (elm.actualNode.hasAttribute('role') || | ||
!axe.commons.dom.findUpVirtual(elm, options.nativeScopeFilter)); | ||
}); | ||
} | ||
|
||
this.relatedNodes(elms.map(elm => elm.actualNode)); | ||
|
||
return elms.length <= 1; |
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-no-duplicate-banner", | ||
"selector": "html", | ||
"tags": [ | ||
"best-practice" | ||
], | ||
"metadata": { | ||
"description": "Ensures the document has no more than one banner landmark", | ||
"help": "Document contain at most one banner landmark" | ||
}, | ||
"all": [], | ||
"any": [ | ||
"page-no-duplicate-banner" | ||
], | ||
"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,16 @@ | ||
{ | ||
"id": "landmark-no-duplicate-contentinfo", | ||
"selector": "html", | ||
"tags": [ | ||
"best-practice" | ||
], | ||
"metadata": { | ||
"description": "Ensures the document has no more than one contentinfo landmark", | ||
"help": "Document contain at most one contentinfo landmark" | ||
}, | ||
"all": [], | ||
"any": [ | ||
"page-no-duplicate-contentinfo" | ||
], | ||
"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
This file was deleted.
Oops, something went wrong.
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,103 @@ | ||
describe('page-no-duplicate', function () { | ||
'use strict'; | ||
|
||
var fixture = document.getElementById('fixture'); | ||
var checkContext = new axe.testUtils.MockCheckContext(); | ||
var checkSetup = axe.testUtils.checkSetup; | ||
var shadowSupported = axe.testUtils.shadowSupport.v1; | ||
|
||
var check = checks['page-no-duplicate-main']; | ||
|
||
afterEach(function () { | ||
fixture.innerHTML = ''; | ||
checkContext.reset(); | ||
}); | ||
|
||
describe('options.selector', function () { | ||
it('throws if there is no selector', function () { | ||
assert.throws(function () { | ||
var params = checkSetup('<div id="target"></div>', undefined); | ||
assert.isFalse(check.evaluate.apply(checkContext, params)); | ||
}); | ||
}); | ||
|
||
it('should return false if there is more than one element matching the selector', function () { | ||
var options = { selector: 'main' }; | ||
var params = checkSetup('<div id="target"><main></main><main></main></div>', options); | ||
|
||
assert.isFalse(check.evaluate.apply(checkContext, params)); | ||
assert.deepEqual(checkContext._relatedNodes, | ||
Array.from(fixture.querySelectorAll('main'))); | ||
}); | ||
|
||
it('should return true if there is only one element matching the selector', function(){ | ||
var options = { selector: 'main' }; | ||
var params = checkSetup('<div role="main" id="target"></div>', options); | ||
assert.isTrue(check.evaluate.apply(checkContext, params)); | ||
}); | ||
|
||
it('should return true if there are no element matching the selector', function(){ | ||
var options = { selector: 'footer' }; | ||
var params = checkSetup('<div id="target"><main></main><main></main></div>', options); | ||
assert.isTrue(check.evaluate.apply(checkContext, params)); | ||
}); | ||
|
||
(shadowSupported ? it : xit) | ||
('should return false if there is a second matching element inside the shadow dom', function () { | ||
var options = { selector: 'main' }; | ||
var div = document.createElement('div'); | ||
div.innerHTML = '<div id="shadow"></div><main></main>'; | ||
|
||
var shadow = div.querySelector('#shadow').attachShadow({ mode: 'open' }); | ||
shadow.innerHTML = '<main></main>'; | ||
axe.testUtils.fixtureSetup(div); | ||
|
||
assert.isFalse(check.evaluate.call(checkContext, fixture, options, axe._tree[0])); | ||
assert.deepEqual(checkContext._relatedNodes, [ | ||
shadow.querySelector('main'), | ||
div.querySelector('main') | ||
]); | ||
}); | ||
}); | ||
|
||
describe('option.nativeScopeFilter', function () { | ||
it('should ignore element contained in a nativeScopeFilter match', function () { | ||
var options = { | ||
selector: 'footer', | ||
nativeScopeFilter: 'main' | ||
}; | ||
var params = checkSetup('<div id="target"><footer></footer>' + | ||
'<main><footer></footer></main>' + | ||
'</div>', options); | ||
assert.isTrue(check.evaluate.apply(checkContext, params)); | ||
}); | ||
|
||
it('should not ignore element contained in a nativeScopeFilter match with their roles redefined', function () { | ||
var options = { | ||
selector: 'footer, [role="contentinfo"]', | ||
nativeScopeFilter: 'main' | ||
}; | ||
var params = checkSetup('<div id="target"><footer></footer>' + | ||
'<main><div role="contentinfo"></div></main>' + | ||
'</div>', options); | ||
assert.isFalse(check.evaluate.apply(checkContext, params)); | ||
}); | ||
|
||
(shadowSupported ? it : xit) | ||
('elements if its ancestor is outside the shadow DOM tree', function () { | ||
var options = { | ||
selector: 'footer', | ||
nativeScopeFilter: 'main' | ||
}; | ||
|
||
var div = document.createElement('div'); | ||
div.innerHTML = '<main id="shadow"></main><footer></footer>'; | ||
div.querySelector('#shadow') | ||
.attachShadow({ mode: 'open' }) | ||
.innerHTML = '<footer></footer>'; | ||
axe.testUtils.fixtureSetup(div); | ||
|
||
assert.isTrue(check.evaluate.call(checkContext, fixture, options, axe._tree[0])); | ||
}); | ||
}); | ||
}); |
16 changes: 16 additions & 0 deletions
16
test/integration/full/landmark-no-duplicate-banner/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,16 @@ | ||
<!doctype html> | ||
<html lang="en" id="fail2"> | ||
<head> | ||
<meta charset="utf8"> | ||
<script src="/axe.js"></script> | ||
</head> | ||
<body> | ||
<header> | ||
Header 1 | ||
</header> | ||
<header> | ||
Header 2 | ||
</header> | ||
<iframe id="frame2" src="level2.html"></iframe> | ||
</body> | ||
</html> |
37 changes: 37 additions & 0 deletions
37
test/integration/full/landmark-no-duplicate-banner/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,37 @@ | ||
<!doctype html> | ||
<html lang="en" id="pass2"> | ||
<head> | ||
<meta charset="utf8"> | ||
<script src="/axe.js"></script> | ||
</head> | ||
<body> | ||
<header> | ||
Top level header | ||
</header> | ||
<article> | ||
<header> | ||
Header in article | ||
</header> | ||
</article> | ||
<aside> | ||
<header> | ||
Header in aside | ||
</header> | ||
</aside> | ||
<main> | ||
<header> | ||
Header in main landmark | ||
</header> | ||
</main> | ||
<nav> | ||
<header> | ||
Header in nav | ||
</header> | ||
</nav> | ||
<section> | ||
<header> | ||
Header in section | ||
</header> | ||
</section> | ||
</body> | ||
</html> |
17 changes: 17 additions & 0 deletions
17
test/integration/full/landmark-no-duplicate-banner/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,17 @@ | ||
<!doctype html> | ||
<html lang="en" id="fail3"> | ||
<head> | ||
<meta charset="utf8"> | ||
<script src="/axe.js"></script> | ||
</head> | ||
<body> | ||
<main> | ||
<div role="banner"> | ||
Div 1 with role banner in main landmark | ||
</div> | ||
<div role="banner"> | ||
Div 2 with role banner in main landmark | ||
</div> | ||
</main> | ||
</body> | ||
</html> |
29 changes: 29 additions & 0 deletions
29
test/integration/full/landmark-no-duplicate-banner/landmark-no-duplicate-banner-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="fail1"> | ||
<head> | ||
<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="banner"> | ||
Div 1 with role of "banner" | ||
</div> | ||
<div role="banner"> | ||
Div 2 with role of "banner" | ||
</div> | ||
<iframe id="frame1" src="frames/level1-fail.html"></iframe> | ||
<div id="mocha"></div> | ||
<script src="landmark-no-duplicate-banner-fail.js"></script> | ||
<script src="/test/integration/adapter.js"></script> | ||
</body> | ||
</html> |
Oops, something went wrong.