Skip to content

Commit c1daa48

Browse files
author
Todd Kloots
committed
Add filtering for different device types. Fixes #37.
1 parent 6475a4a commit c1daa48

4 files changed

Lines changed: 51 additions & 5 deletions

File tree

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,11 @@ All failures are also accessible via the `getFailures()` method.
6363
```
6464
a11y.getFailures();
6565
```
66+
67+
Some test are only relevant for certain device types. For example,
68+
if you are building a mobile web app, you can filter out
69+
desktop-specific rules by specifying a specific device type:
70+
71+
```
72+
a11y(React, { device: ['mobile'] });
73+
```

lib/__tests__/index-test.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,5 +276,30 @@ describe('getFailures()', () => {
276276
assert(a11y.getFailures().length == 2);
277277
});
278278
});
279+
});
280+
281+
describe('device is set to mobile', () => {
282+
var createElement = React.createElement;
283+
284+
before(() => {
285+
a11y(React, { device: ['mobile'] });
286+
});
287+
288+
after(() => {
289+
React.createElement = createElement;
290+
});
291+
292+
describe('when role="button"', () => {
293+
it('does not require onKeyDown', () => {
294+
doNotExpectWarning(assertions.props.onClick.BUTTON_ROLE_SPACE.msg, () => {
295+
<span onClick={k} role="button"/>;
296+
});
297+
});
279298

299+
it('does not require onKeyDown', () => {
300+
doNotExpectWarning(assertions.props.onClick.BUTTON_ROLE_ENTER.msg, () => {
301+
<span onClick={k} role="button"/>;
302+
});
303+
});
304+
});
280305
});

lib/assertions.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ var INTERACTIVE = {
1313
}
1414
};
1515

16+
const DEVICE = { 'DESKTOP': 'desktop', 'MOBILE': 'mobile' };
17+
1618
var hasAlt = (props) => {
1719
return typeof props.alt === 'string';
1820
};
@@ -51,6 +53,7 @@ exports.props = {
5153
},
5254

5355
NO_TABINDEX: {
56+
device: DEVICE.DESKTOP,
5457
msg: 'You have a click handler on a non-interactive element but no `tabIndex` DOM property. The element will not be navigable or interactive by keyboard users. http://www.w3.org/TR/wai-aria-practices/#focus_tabindex',
5558
test (tagName, props, children) {
5659
return !(
@@ -73,13 +76,15 @@ exports.props = {
7376
},
7477

7578
BUTTON_ROLE_SPACE: {
79+
device: DEVICE.DESKTOP,
7680
msg: 'You have `role="button"` but did not define an `onKeyDown` handler. Add it, and have the "Space" key do the same thing as an `onClick` handler.',
7781
test (tagName, props, children) {
7882
return !(props.role === 'button' && !props.onKeyDown);
7983
}
8084
},
8185

8286
BUTTON_ROLE_ENTER: {
87+
device: DEVICE.DESKTOP,
8388
msg: 'You have `role="button"` but did not define an `onKeyDown` handler. Add it, and have the "Enter" key do the same thing as an `onClick` handler.',
8489
test (tagName, props, children) {
8590
return !(props.role === 'button' && !props.onKeyDown);

lib/index.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
var assertions = require('./assertions');
22

3-
var assertAccessibility = (tagName, props, children) => {
3+
var deviceMatches = (test, deviceFilter) => {
4+
if (!test.device) {
5+
return true;
6+
}
7+
8+
return (deviceFilter.indexOf(test.device) != -1);
9+
};
10+
11+
var assertAccessibility = (tagName, props, children, deviceFilter) => {
412
var key;
513
var failures = [];
6-
714
var tagTests = assertions.tags[tagName] || [];
815
for (key in tagTests)
9-
if (tagTests[key] && !tagTests[key].test(tagName, props, children))
16+
if (tagTests[key] && deviceMatches(tagTests[key], deviceFilter) && !tagTests[key].test(tagName, props, children))
1017
failures.push(tagTests[key].msg);
1118

1219
var propTests;
1320
for (var propName in props) {
1421
if (props[propName] === null || props[propName] === undefined) continue;
1522
propTests = assertions.props[propName] || [];
1623
for (key in propTests)
17-
if (propTests[key] && !propTests[key].test(tagName, props, children))
24+
if (propTests[key] && deviceMatches(propTests[key], deviceFilter) && !propTests[key].test(tagName, props, children))
1825
failures.push(propTests[key].msg);
1926
}
2027
return failures;
@@ -104,13 +111,14 @@ var reactA11y = (React, options) => {
104111
totalFailures = [];
105112
var _createElement = React.createElement;
106113
var includeSrcNode = options && !!options.includeSrcNode;
114+
var deviceFilter = options && options.device || ['desktop'];
107115

108116
React.createElement = (type, _props, ...children) => {
109117
var props = _props || {};
110118
var reactEl;
111119

112120
if (typeof type === 'string') {
113-
let failures = assertAccessibility(type, props, children);
121+
let failures = assertAccessibility(type, props, children, deviceFilter);
114122
if (failures.length) {
115123
// Generate an id if one doesn't exist
116124
props.id = (props.id || 'a11y-' + nextId++);

0 commit comments

Comments
 (0)