Skip to content

Commit

Permalink
feat: new rule landmark-complementary-is-top-level
Browse files Browse the repository at this point in the history
Best practice requiring asides and complementary landmarks to be top level, in line with the ARIA Authoring Practices Guide.

Closes #795
  • Loading branch information
Marcy Sutton committed Nov 19, 2018
1 parent 89d18d0 commit 65a8485
Show file tree
Hide file tree
Showing 11 changed files with 243 additions and 2 deletions.
1 change: 1 addition & 0 deletions doc/rule-descriptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
| label-title-only | Ensures that every form element is not solely labeled using the title or aria-describedby attributes | Serious | cat.forms, best-practice | true |
| label | Ensures every form element has a label | Minor, Critical | cat.forms, wcag2a, wcag332, wcag131, section508, section508.22.n | true |
| landmark-banner-is-top-level | Ensures the banner landmark is at top level | Moderate | cat.semantics, best-practice | true |
| landmark-complementary-is-top-level | Ensures the complementary landmark or aside is at top level | Moderate | cat.semantics, best-practice | true |
| landmark-contentinfo-is-top-level | Ensures the contentinfo landmark is at top level | Moderate | cat.semantics, best-practice | true |
| landmark-main-is-top-level | Ensures the main landmark is at top level | Moderate | cat.semantics, best-practice | true |
| landmark-no-duplicate-banner | Ensures the document has at most one banner landmark | Moderate | cat.semantics, best-practice | true |
Expand Down
18 changes: 18 additions & 0 deletions lib/rules/landmark-complementary-is-top-level.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"id": "landmark-complementary-is-top-level",
"selector": "aside:not([role]), [role=complementary]",
"matches": "landmark-has-body-context.js",
"tags": [
"cat.semantics",
"best-practice"
],
"metadata": {
"description": "Ensures the complementary landmark or aside is at top level",
"help": "Aside must not be contained in another landmark"
},
"all": [],
"any": [
"landmark-is-top-level"
],
"none": []
}
2 changes: 1 addition & 1 deletion lib/rules/landmark-has-body-context.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const nativeScopeFilter = 'article, aside, main, nav, section';

// 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
// e.g. a <header> inside a <main> is not a banner, but in the <body> context it is
return (
node.hasAttribute('role') ||
!axe.commons.dom.findUpVirtual(virtualNode, nativeScopeFilter)
Expand Down
12 changes: 11 additions & 1 deletion test/checks/keyboard/landmark-is-top-level.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('landmark-is-top-level', function() {
checkContext.reset();
});

it('should return false if the landmark is in another landmark', function() {
it('should return false if the banner landmark is in another landmark', function() {
var mainLandmark = document.createElement('main');
var bannerDiv = document.createElement('div');
bannerDiv.setAttribute('role', 'banner');
Expand All @@ -23,6 +23,16 @@ describe('landmark-is-top-level', function() {
assert.deepEqual(checkContext._data, { role: 'main' });
});

it('should return false if the complementary landmark is in another landmark', function() {
var mainLandmark = document.createElement('main');
var aside = document.createElement('div');
aside.setAttribute('role', 'complementary');
aside.appendChild(mainLandmark);
fixture.appendChild(aside);
assert.isFalse(check.evaluate.call(checkContext, mainLandmark));
assert.deepEqual(checkContext._data, { role: 'main' });
});

it('should return false if div with role set to main is in another landmark', function() {
var mainDiv = document.createElement('div');
mainDiv.setAttribute('role', 'main');
Expand Down
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>
<main>
<div role="complementary">
<p>This complementary landmark is in a main landmark</p>
</div>
</main>
</body>
</html>
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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html id="pass3">
<head>
<meta charset="utf8">
<script src="/axe.js"></script>
</head>
<body>
<p>This iframe should pass<p>
<aside>
<p>This aside is top level and should be ignored</p>
</aside>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!doctype html>
<html lang="en" id="violation1">
<head>
<title>landmark-complementary-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="complementary">
<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-complementary-is-top-level-fail.js"></script>
<script src="/test/integration/adapter.js"></script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
describe('landmark-complementary-is-top-level test fail', function() {
'use strict';
var results;
before(function(done) {
window.addEventListener('load', function() {
axe.run(
{
runOnly: {
type: 'rule',
values: ['landmark-complementary-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);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!doctype html>
<html lang="en" id="pass1">
<head>
<title>landmark-complementary-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>
<aside>
<p>This aside has an implicit role complementary</p>
</aside>
<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-complementary-is-top-level-pass.js"></script>
<script src="/test/integration/adapter.js"></script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
describe('landmark-complementary-is-top-level test pass', function() {
'use strict';
var results;
before(function(done) {
window.addEventListener('load', function() {
axe.run(
{
runOnly: {
type: 'rule',
values: ['landmark-complementary-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, 2);
});
});

it('should find 0 inapplicable', function() {
assert.lengthOf(results.inapplicable, 0);
});

it('should find 0 incomplete', function() {
assert.lengthOf(results.incomplete, 0);
});
});

0 comments on commit 65a8485

Please sign in to comment.