Skip to content

Commit 4f75afd

Browse files
author
Ethan Cohen
committed
Add mouseEvents require associated keyEvents rule.
1 parent 122789e commit 4f75afd

File tree

5 files changed

+104
-2
lines changed

5 files changed

+104
-2
lines changed

index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
module.exports = {
44
rules: {
55
'img-uses-alt': require('./lib/rules/img-uses-alt'),
6-
'onClick-uses-role': require('./lib/rules/onClick-uses-role')
6+
'onClick-uses-role': require('./lib/rules/onClick-uses-role'),
7+
'mouseEvents-require-keyEvents': require('./lib/rules/mouseEvents-require-keyEvents')
78
},
89
configs: {
910
recommended: {

lib/rules/img-uses-alt.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ module.exports = function(context) {
1414

1515
return {
1616
JSXOpeningElement: function(node) {
17+
var type = node.name.name;
18+
if (type.toUpperCase() !== 'IMG') {
19+
return;
20+
}
21+
1722
var hasAltProp = hasAttribute(node.attributes, 'alt');
1823

1924
if (hasAltProp === false) {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* @fileoverview Enforce onmouseover/onmouseout are accompanied by onfocus/onblur.
3+
* @author Ethan Cohen
4+
*/
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Rule Definition
9+
// ------------------------------------------------------------------------------
10+
11+
var hasAttribute = require('../hasAttribute');
12+
13+
module.exports = function(context) {
14+
15+
return {
16+
JSXOpeningElement: function(node) {
17+
var attributes = node.attributes;
18+
19+
// Check onmouseover / onfocus pairing.
20+
var hasOnMouseOver = hasAttribute(attributes, 'onMouseOver');
21+
if (Boolean(hasOnMouseOver) === true) {
22+
var hasOnFocus = hasAttribute(attributes, 'onFocus');
23+
if (hasOnFocus === false) {
24+
context.report({
25+
node: node,
26+
message: 'onMouseOver must be accompanied by onFocus for accessibility.'
27+
});
28+
}
29+
}
30+
31+
// Checkout onmouseout / onblur pairing
32+
var hasOnMouseOut = hasAttribute(attributes, 'onMouseOut');
33+
if (Boolean(hasOnMouseOut) === true) {
34+
var hasOnBlur = hasAttribute(attributes, 'onBlur');
35+
if (hasOnBlur === false) {
36+
context.report({
37+
node: node,
38+
message: 'onMouseOut must be accompanied by onBlur for accessibility.'
39+
});
40+
}
41+
}
42+
}
43+
};
44+
};
45+
46+
module.exports.schema = [{
47+
type: 'object'
48+
}];

tests/lib/rules/img-uses-alt.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ ruleTester.run('img-uses-alt', rule, {
3636
{code: '<img ALT="foo" />;', parserOptions: parserOptions},
3737
{code: '<img ALt="foo" />;', parserOptions: parserOptions},
3838
{code: '<img {...this.props} alt="foo" />', parserOptions: parserOptions},
39-
{code: '<img {...this.props} />', parserOptions: parserOptions}
39+
{code: '<img {...this.props} />', parserOptions: parserOptions},
40+
{code: '<a />', parserOptions: parserOptions}
4041
],
4142
invalid: [
4243
{code: '<img />;', errors: [expectedError], parserOptions: parserOptions},
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @fileoverview Enforce img tags use alt attribute.
3+
* @author Ethan Cohen
4+
*/
5+
6+
'use strict';
7+
8+
// -----------------------------------------------------------------------------
9+
// Requirements
10+
// -----------------------------------------------------------------------------
11+
12+
var rule = require('../../../lib/rules/mouseEvents-require-keyEvents');
13+
var RuleTester = require('eslint').RuleTester;
14+
15+
var parserOptions = {
16+
ecmaVersion: 6,
17+
ecmaFeatures: {
18+
jsx: true
19+
}
20+
};
21+
22+
// -----------------------------------------------------------------------------
23+
// Tests
24+
// -----------------------------------------------------------------------------
25+
26+
var ruleTester = new RuleTester();
27+
28+
var mouseOverError = {
29+
message: 'onMouseOver must be accompanied by onFocus for accessibility.',
30+
type: 'JSXOpeningElement'
31+
};
32+
var mouseOutError = {
33+
message: 'onMouseOut must be accompanied by onBlur for accessibility.',
34+
type: 'JSXOpeningElement'
35+
};
36+
37+
ruleTester.run('mouseEvents-require-keyEvents', rule, {
38+
valid: [
39+
{code: '<div onMouseOver={() => void 0} onFocus={() => void 0} />;', parserOptions: parserOptions},
40+
{code: '<div />;', parserOptions: parserOptions},
41+
{code: '<div onMouseOut={() => void 0} onBlur={() => void 0} />', parserOptions: parserOptions}
42+
],
43+
invalid: [
44+
{code: '<div onMouseOver={() => void 0} />;', errors: [mouseOverError], parserOptions: parserOptions},
45+
{code: '<div onMouseOut={() => void 0} />', errors: [mouseOutError], parserOptions: parserOptions}
46+
]
47+
});

0 commit comments

Comments
 (0)