Skip to content

Commit 0a1aee3

Browse files
committed
Merge pull request #11 from lencioni/img-uses-alt-messages
Improve img-uses-alt error messages
2 parents 1827da3 + 612ca4b commit 0a1aee3

File tree

2 files changed

+75
-40
lines changed

2 files changed

+75
-40
lines changed

src/rules/img-uses-alt.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import hasAttribute from '../util/hasAttribute';
1212
import getAttributeValue from '../util/getAttributeValue';
1313
import getNodeType from '../util/getNodeType';
1414

15-
const errorMessage = type => `${type} elements must have an alt tag.`;
16-
1715
module.exports = context => ({
1816
JSXOpeningElement: node => {
1917
const typeCheck = [ 'img' ].concat(context.options[0]);
@@ -25,14 +23,22 @@ module.exports = context => ({
2523
}
2624

2725
const hasAltProp = hasAttribute(node.attributes, 'alt');
26+
27+
if (!hasAltProp) {
28+
context.report({
29+
node,
30+
message: `${nodeType} elements must have an alt prop`
31+
});
32+
return;
33+
}
34+
2835
const altProp = hasAltProp ? getAttributeValue(hasAltProp) : undefined;
2936
const isInvalid = hasAltProp === false || Boolean(altProp) === false;
3037

31-
// alt must have a value.
3238
if (isInvalid) {
3339
context.report({
3440
node,
35-
message: errorMessage(nodeType)
41+
message: `${nodeType} alt prop must have a value`
3642
});
3743
}
3844
}

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

Lines changed: 65 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,22 @@ const parserOptions = {
2525

2626
const ruleTester = new RuleTester();
2727

28-
const expectedError = {
29-
message: 'img elements must have an alt tag.',
28+
const customMissingPropError = type => ({
29+
message: `${type} elements must have an alt prop`,
3030
type: 'JSXOpeningElement'
31-
};
31+
});
32+
33+
const customAltValueError = type => ({
34+
message: `${type} alt prop must have a value`,
35+
type: 'JSXOpeningElement'
36+
});
37+
38+
const expectedMissingPropError = customMissingPropError('img');
39+
const expectedAltValueError = customAltValueError('img');
3240

3341
const string = [ 'Avatar' ];
3442
const array = [ [ 'Thumbnail', 'Image' ] ];
3543

36-
const customError = type => ({
37-
message: `${type} elements must have an alt tag.`,
38-
type: 'JSXOpeningElement'
39-
});
4044

4145
ruleTester.run('img-uses-alt', rule, {
4246
valid: [
@@ -111,38 +115,63 @@ ruleTester.run('img-uses-alt', rule, {
111115
],
112116
invalid: [
113117
// DEFAULT ELEMENT 'img' TESTS
114-
{ code: '<img />;', errors: [ expectedError ], parserOptions },
115-
{ code: '<img alt />;', errors: [ expectedError ], parserOptions },
116-
{ code: '<img alt={undefined} />;', errors: [ expectedError ], parserOptions },
117-
{ code: '<img alt={`${undefined}`} />;', errors: [ expectedError ], parserOptions },
118-
{ code: '<img alt="" />;', errors: [ expectedError ], parserOptions },
119-
{ code: '<img src="xyz" />', errors: [ expectedError ], parserOptions },
120-
{ code: '<img {...this.props} />', errors: [ expectedError ], parserOptions },
121-
{ code: '<img alt={false || false} />', errors: [ expectedError ], parserOptions },
118+
{ code: '<img />;', errors: [ expectedMissingPropError ], parserOptions },
119+
{ code: '<img alt />;', errors: [ expectedAltValueError ], parserOptions },
120+
{ code: '<img alt={undefined} />;', errors: [ expectedAltValueError ], parserOptions },
121+
{ code: '<img alt={`${undefined}`} />;', errors: [ expectedAltValueError ], parserOptions },
122+
{ code: '<img alt="" />;', errors: [ expectedAltValueError ], parserOptions },
123+
{ code: '<img src="xyz" />', errors: [ expectedMissingPropError ], parserOptions },
124+
{ code: '<img {...this.props} />', errors: [ expectedMissingPropError ], parserOptions },
125+
{ code: '<img alt={false || false} />', errors: [ expectedAltValueError ], parserOptions },
122126

123127
// CUSTOM ELEMENT TESTS FOR STRING OPTION
124-
{ code: '<Avatar />;', errors: [ customError('Avatar') ], options: string, parserOptions },
125-
{ code: '<Avatar alt />;', errors: [ customError('Avatar') ], options: string, parserOptions },
126-
{ code: '<Avatar alt={undefined} />;', errors: [ customError('Avatar') ], options: string, parserOptions },
127-
{ code: '<Avatar alt={`${undefined}`} />;', errors: [ customError('Avatar') ], options: string, parserOptions },
128-
{ code: '<Avatar alt="" />;', errors: [ customError('Avatar') ], options: string, parserOptions },
129-
{ code: '<Avatar src="xyz" />', errors: [ customError('Avatar') ], options: string, parserOptions },
130-
{ code: '<Avatar {...this.props} />', errors: [ customError('Avatar') ], options: string, parserOptions },
128+
{
129+
code: '<Avatar />;',
130+
errors: [ customMissingPropError('Avatar') ],
131+
options: string,
132+
parserOptions
133+
},
134+
{ code: '<Avatar alt />;', errors: [ customAltValueError('Avatar') ], options: string, parserOptions },
135+
{ code: '<Avatar alt={undefined} />;', errors: [ customAltValueError('Avatar') ], options: string, parserOptions },
136+
{
137+
code: '<Avatar alt={`${undefined}`} />;',
138+
errors: [ customAltValueError('Avatar') ],
139+
options: string,
140+
parserOptions
141+
},
142+
{ code: '<Avatar alt="" />;', errors: [ customAltValueError('Avatar') ], options: string, parserOptions },
143+
{ code: '<Avatar src="xyz" />', errors: [ customMissingPropError('Avatar') ], options: string, parserOptions },
144+
{ code: '<Avatar {...this.props} />', errors: [ customMissingPropError('Avatar') ], options: string, parserOptions },
131145

132146
// CUSTOM ELEMENT TESTS FOR ARRAY OPTION TESTS
133-
{ code: '<Thumbnail />;', errors: [ customError('Thumbnail') ], options: array, parserOptions },
134-
{ code: '<Thumbnail alt />;', errors: [ customError('Thumbnail') ], options: array, parserOptions },
135-
{ code: '<Thumbnail alt={undefined} />;', errors: [ customError('Thumbnail') ], options: array, parserOptions },
136-
{ code: '<Thumbnail alt={`${undefined}`} />;', errors: [ customError('Thumbnail') ], options: array, parserOptions },
137-
{ code: '<Thumbnail alt="" />;', errors: [ customError('Thumbnail') ], options: array, parserOptions },
138-
{ code: '<Thumbnail src="xyz" />', errors: [ customError('Thumbnail') ], options: array, parserOptions },
139-
{ code: '<Thumbnail {...this.props} />', errors: [ customError('Thumbnail') ], options: array, parserOptions },
140-
{ code: '<Image />;', errors: [ customError('Image') ], options: array, parserOptions },
141-
{ code: '<Image alt />;', errors: [ customError('Image') ], options: array, parserOptions },
142-
{ code: '<Image alt={undefined} />;', errors: [ customError('Image') ], options: array, parserOptions },
143-
{ code: '<Image alt={`${undefined}`} />;', errors: [ customError('Image') ], options: array, parserOptions },
144-
{ code: '<Image alt="" />;', errors: [ customError('Image') ], options: array, parserOptions },
145-
{ code: '<Image src="xyz" />', errors: [ customError('Image') ], options: array, parserOptions },
146-
{ code: '<Image {...this.props} />', errors: [ customError('Image') ], options: array, parserOptions }
147+
{ code: '<Thumbnail />;', errors: [ customMissingPropError('Thumbnail') ], options: array, parserOptions },
148+
{ code: '<Thumbnail alt />;', errors: [ customAltValueError('Thumbnail') ], options: array, parserOptions },
149+
{
150+
code: '<Thumbnail alt={undefined} />;',
151+
errors: [ customAltValueError('Thumbnail') ],
152+
options: array,
153+
parserOptions
154+
},
155+
{
156+
code: '<Thumbnail alt={`${undefined}`} />;',
157+
errors: [ customAltValueError('Thumbnail') ],
158+
options: array,
159+
parserOptions
160+
},
161+
{ code: '<Thumbnail alt="" />;', errors: [ customAltValueError('Thumbnail') ], options: array, parserOptions },
162+
{ code: '<Thumbnail src="xyz" />', errors: [ customMissingPropError('Thumbnail') ], options: array, parserOptions },
163+
{
164+
code: '<Thumbnail {...this.props} />',
165+
errors: [ customMissingPropError('Thumbnail') ],
166+
options: array,
167+
parserOptions
168+
},
169+
{ code: '<Image />;', errors: [ customMissingPropError('Image') ], options: array, parserOptions },
170+
{ code: '<Image alt />;', errors: [ customAltValueError('Image') ], options: array, parserOptions },
171+
{ code: '<Image alt={undefined} />;', errors: [ customAltValueError('Image') ], options: array, parserOptions },
172+
{ code: '<Image alt={`${undefined}`} />;', errors: [ customAltValueError('Image') ], options: array, parserOptions },
173+
{ code: '<Image alt="" />;', errors: [ customAltValueError('Image') ], options: array, parserOptions },
174+
{ code: '<Image src="xyz" />', errors: [ customMissingPropError('Image') ], options: array, parserOptions },
175+
{ code: '<Image {...this.props} />', errors: [ customMissingPropError('Image') ], options: array, parserOptions }
147176
]
148177
});

0 commit comments

Comments
 (0)