diff --git a/README.md b/README.md index b960c85b6..fce6195c2 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ Rule Name | Description | Since `react-a11y-aria-unsupported-elements` | For accessibility of your website, enforce that elements that do not support ARIA roles, states, and properties do not have those attributes. | 2.0.11 `react-a11y-event-has-role` | For accessibility of your website, Elements with event handlers must have explicit role or implicit role.
References:
[WCAG Rule 94](http://oaa-accessibility.org/wcag20/rule/94/)
[Using the button role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role) | 2.0.11 `react-a11y-image-button-has-alt` | For accessibility of your website, enforce that inputs element with `type="image"` must have non-empty alt attribute. | 2.0.11 -`react-a11y-img-has-alt` | Enforce that an `img` element contains the `alt` attribute or `role='presentation'` for decorative image. All images must have `alt` text to convey their purpose and meaning to **screen reader users**. Besides, the `alt` attribute specifies an alternate text for an image, if the image cannot be displayed. This rule accepts as a parameter a string array for tag names other than img to also check. For example, if you use a custom tag named 'Image' then configure the rule with: `[true, ['Image']]`
References:
[Web Content Accessibility Guidelines 1.0](https://www.w3.org/TR/WCAG10/wai-pageauth.html#tech-text-equivalent)
[ARIA Presentation Role](https://www.w3.org/TR/wai-aria/roles#presentation) | 2.0.11 +`react-a11y-img-has-alt` | Enforce that an `img` element contains the `alt` attribute or `role='presentation'` for a decorative image. All images must have `alt` text to convey their purpose and meaning to **screen reader users**. Besides, the `alt` attribute specifies an alternate text for an image, if the image cannot be displayed. This rule accepts as a parameter a string array for tag names other than img to also check. For example, if you use a custom tag named 'Image' then configure the rule with: `[true, ['Image']]`
References:
[Web Content Accessibility Guidelines 1.0](https://www.w3.org/TR/WCAG10/wai-pageauth.html#tech-text-equivalent)
[ARIA Presentation Role](https://www.w3.org/TR/wai-aria/roles#presentation)
[WCAG Rule 31: If an image has an alt or title attribute, it should not have a presentation role](http://oaa-accessibility.org/wcag20/rule/31/) | 2.0.11 `react-a11y-lang` | For accessibility of your website, HTML elements must have a lang attribute and the attribute must be a valid language code.
References:
* [H58: Using language attributes to identify changes in the human language](https://www.w3.org/TR/WCAG20-TECHS/H58.html)
* [lang attribute must have a valid value](https://dequeuniversity.com/rules/axe/1.1/valid-lang)
[List of ISO 639-1 codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) | 2.0.11 `react-a11y-anchors` | For accessibility of your website, anchor element link text should be at least 4 characters long. Links with the same HREF should have the same link text. Links that point to different HREFs should have different link text. Links with images and text content, the alt attribute should be unique to the text content or empty. An an anchor element's href prop value must not be just #.
References:
[WCAG Rule 38: Link text should be as least four 4 characters long](http://oaa-accessibility.org/wcag20/rule/38/)
[WCAG Rule 39: Links with the same HREF should have the same link text](http://oaa-accessibility.org/wcag20/rule/39/)
[WCAG Rule 41: Links that point to different HREFs should have different link text](http://oaa-accessibility.org/wcag20/rule/41/)
[WCAG Rule 43: Links with images and text content, the alt attribute should be unique to the text content or empty](http://oaa-accessibility.org/wcag20/rule/43/)
| 2.0.11 `react-a11y-meta` | For accessibility of your website, HTML meta elements must not have http-equiv="refresh". | 2.0.11 diff --git a/src/reactA11yImgHasAltRule.ts b/src/reactA11yImgHasAltRule.ts index 5d588a695..572b6fb95 100644 --- a/src/reactA11yImgHasAltRule.ts +++ b/src/reactA11yImgHasAltRule.ts @@ -10,18 +10,23 @@ import { } from './utils/JsxAttribute'; import { isJsxSpreadAttribute } from './utils/TypeGuard'; -const roleString: string = 'role'; -const altString: string = 'alt'; +const ROLE_STRING: string = 'role'; +const ALT_STRING: string = 'alt'; export function getFailureStringNoAlt(tagName: string): string { - return `<${tagName}> elements must have an alt attribute or use role='presentation' for presentational images. \ + return `<${tagName}> elements must have an non-empty alt attribute or \ +use empty alt attribute and role='presentation' for presentational images. \ A reference for the presentation role can be found at https://www.w3.org/TR/wai-aria/roles#presentation.`; } -export function getFailureStringEmptyAlt(tagName: string): string { - return `The value of 'alt' attribute in <${tagName}> tag is undefined or empty. \ -Add more details in 'alt' attribute or use role='presentation' for presentational images. \ -A reference for the presentation role can be found at https://www.w3.org/TR/wai-aria/roles#presentation.`; +export function getFailureStringEmptyAltAndNotPresentationRole(tagName: string): string { + return `The value of alt attribute in <${tagName}> tag is empty and role value is not presentation. \ +Add more details in alt attribute or specify role attribute to equal 'presentation' when 'alt' attribute is empty.`; +} + +export function getFailureStringNonEmptyAltAndPresentationRole(tagName: string): string { + return `The value of alt attribute in <${tagName}> tag is non-empty and role value is presentation. \ +Remove role='presentation' or specify 'alt' attributeto be empty when role attributes equals 'presentation'.`; } /** @@ -31,7 +36,8 @@ export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { ruleName: 'react-a11y-img-has-alt', type: 'maintainability', - description: 'Enforce that an `img` element contains the `alt` attribute or `role="presentation"` for decorative image.', + description: 'Enforce that an img element contains the non-empty alt attribute. ' + + 'For decorative images, using empty alt attribute and role="presentation".', options: 'string[]', optionExamples: ['true', '[true, ["Image"]]'], issueClass: 'Non-SDL', @@ -49,9 +55,19 @@ export class Rule extends Lint.Rules.AbstractRule { } class ImgHasAltWalker extends Lint.RuleWalker { + public visitJsxElement(node: ts.JsxElement): void { + this.checkJsxOpeningElement(node.openingElement); + super.visitJsxElement(node); + } + public visitJsxSelfClosingElement(node: ts.JsxSelfClosingElement): void { + this.checkJsxOpeningElement(node); + super.visitJsxSelfClosingElement(node); + } + + private checkJsxOpeningElement(node: ts.JsxOpeningElement): void { // Tag name is sensitive on lowercase or uppercase, we shoudn't normalize tag names in this rule. - const tagName: string = node.tagName && node.tagName.getText(); + const tagName: string = node.tagName.getText(); const options: any[] = this.getOptions(); // tslint:disable-line:no-any // The additionalTagNames are specified by tslint config to check not only 'img' tag but also customized tag. @@ -71,31 +87,33 @@ class ImgHasAltWalker extends Lint.RuleWalker { } const attributes: { [propName: string]: ts.JsxAttribute } = getJsxAttributesFromJsxElement(node); - const role: ts.JsxAttribute = attributes[roleString]; - const roleValue: string = role && getStringLiteral(role); + const altAttribute: ts.JsxAttribute = attributes[ALT_STRING]; - // if element has role of 'presentation', it's presentational image, don't check it; - // @example - if (roleValue && roleValue.match(/\bpresentation\b/)) { - return; - } - - const altProp: ts.JsxAttribute = attributes[altString]; - - if (!altProp) { + if (!altAttribute) { this.addFailure(this.createFailure( node.getStart(), node.getWidth(), getFailureStringNoAlt(tagName) )); - } else if (isEmpty(altProp) || getStringLiteral(altProp) === '') { - this.addFailure(this.createFailure( - altProp.getStart(), - altProp.getWidth(), - getFailureStringEmptyAlt(tagName) - )); + } else { + const roleAttribute: ts.JsxAttribute = attributes[ROLE_STRING]; + const roleAttributeValue: string = roleAttribute ? getStringLiteral(roleAttribute) : ''; + const isPresentationRole: boolean = !!roleAttributeValue.toLowerCase().match(/\bpresentation\b/); + const isEmptyAlt: boolean = isEmpty(altAttribute) || getStringLiteral(altAttribute) === ''; + + if (!isEmptyAlt && isPresentationRole) { // altValue + this.addFailure(this.createFailure( + node.getStart(), + node.getWidth(), + getFailureStringNonEmptyAltAndPresentationRole(tagName) + )); + } else if (isEmptyAlt && !isPresentationRole) { // + this.addFailure(this.createFailure( + node.getStart(), + node.getWidth(), + getFailureStringEmptyAltAndNotPresentationRole(tagName) + )); + } } - - super.visitJsxSelfClosingElement(node); } } diff --git a/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasEmptyAltValue.tsx b/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasEmptyAltValueAndNotPresentationRole.tsx similarity index 81% rename from test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasEmptyAltValue.tsx rename to test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasEmptyAltValueAndNotPresentationRole.tsx index e23bf283d..d8667f89e 100644 --- a/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasEmptyAltValue.tsx +++ b/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasEmptyAltValueAndNotPresentationRole.tsx @@ -3,7 +3,7 @@ import React = require('react'); let Picture; const a = const b = -const c = +const c = const d = const e = const f = {''} diff --git a/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNonEmptyAltValueAndPresentationRole.tsx b/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNonEmptyAltValueAndPresentationRole.tsx new file mode 100644 index 000000000..aa8e72fae --- /dev/null +++ b/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNonEmptyAltValueAndPresentationRole.tsx @@ -0,0 +1,11 @@ +import React = require('react'); + +let Picture; +let altValue; + +const a = +const b = +const c = +const d = altValue +const e = altValue +const f = { diff --git a/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasEmptyAltValueAndPresentationRole.tsx b/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasEmptyAltValueAndPresentationRole.tsx new file mode 100644 index 000000000..223d54f33 --- /dev/null +++ b/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasEmptyAltValueAndPresentationRole.tsx @@ -0,0 +1,10 @@ +import React = require('react'); + +let Picture; + +const a = +const b = +const c = +const d = { +const e = { +const f = diff --git a/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasValidAltValue.tsx b/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasNonEmptyAltValueAndNotPresentationRole.tsx similarity index 52% rename from test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasValidAltValue.tsx rename to test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasNonEmptyAltValueAndNotPresentationRole.tsx index 678ecc27c..cd9ebc68e 100644 --- a/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasValidAltValue.tsx +++ b/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasNonEmptyAltValueAndNotPresentationRole.tsx @@ -2,9 +2,9 @@ import React = require('react'); let Picture, validAltValue; -const a = -const b = +const a = +const b = const c = -const d = validAltValue +const d = validAltValue const e = {validAltValue} const f = {'validAltValue'} diff --git a/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasPresentationRole.tsx b/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasPresentationRole.tsx deleted file mode 100644 index 52eef0bd9..000000000 --- a/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasPresentationRole.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React = require('react'); - -let Picture; - -const a = -const b = -const c = -const d = -const e = {''} -const f = diff --git a/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasEmptyAltValue.tsx b/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasEmptyAltValueAndNotPresentationRole.tsx similarity index 77% rename from test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasEmptyAltValue.tsx rename to test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasEmptyAltValueAndNotPresentationRole.tsx index 4a2a4ebca..c6564548b 100644 --- a/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasEmptyAltValue.tsx +++ b/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasEmptyAltValueAndNotPresentationRole.tsx @@ -1,6 +1,6 @@ import React = require('react'); -const a = +const a = const b = const c = {undefined} const d = {''} diff --git a/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNonEmptyAltValueAndPresentationRole.tsx b/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNonEmptyAltValueAndPresentationRole.tsx new file mode 100644 index 000000000..f5e40ffe2 --- /dev/null +++ b/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNonEmptyAltValueAndPresentationRole.tsx @@ -0,0 +1,8 @@ +import React = require('react'); + +let altValue; + +const a = altValue +const b = altValue +const c = { +const d = {'altValue'} diff --git a/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasEmptyAltValueAndPresentationRole.tsx b/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasEmptyAltValueAndPresentationRole.tsx new file mode 100644 index 000000000..9780b19b6 --- /dev/null +++ b/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasEmptyAltValueAndPresentationRole.tsx @@ -0,0 +1,6 @@ +import React = require('react'); + +const a = +const b = +const c = { +const d = {''} diff --git a/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasNotEmptyAltValue.tsx b/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasNonEmptyAltValueAndNotPresentationRole.tsx similarity index 100% rename from test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasNotEmptyAltValue.tsx rename to test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasNonEmptyAltValueAndNotPresentationRole.tsx diff --git a/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasPresentationRole.tsx b/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasPresentationRole.tsx deleted file mode 100644 index 063f88142..000000000 --- a/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasPresentationRole.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React = require('react'); - -const a = -const b = altValue -const c = -const d = {''} diff --git a/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementNotLowerCase.tsx b/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementNotLowerCase.tsx index 2dea5c368..6445d0bbb 100644 --- a/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementNotLowerCase.tsx +++ b/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementNotLowerCase.tsx @@ -1,4 +1,7 @@ import React = require('react'); -const a = -const b = \ No newline at end of file +let Img; +let IMG; + +const a = +const b = diff --git a/tests/ReactA11yProptypesRuleTest.ts b/tests/ReactA11yProptypesRuleTest.ts index c40379bd2..071d7d59a 100644 --- a/tests/ReactA11yProptypesRuleTest.ts +++ b/tests/ReactA11yProptypesRuleTest.ts @@ -11,7 +11,7 @@ describe('reactA11yProptypesRule', () => { const fileDirectory: string = 'test-data/ReactA11yProptypes/PassingTestInputs/'; it('when can not check the type of attribute value until running time', () => { - const fileName: string = fileDirectory + 'canNotCheckUtilRunTime'; + const fileName: string = fileDirectory + 'canNotCheckUntilRunTime.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); diff --git a/tests/reactA11yImgHasAltRuleTests.ts b/tests/reactA11yImgHasAltRuleTests.ts index bc00dde38..f4f546879 100644 --- a/tests/reactA11yImgHasAltRuleTests.ts +++ b/tests/reactA11yImgHasAltRuleTests.ts @@ -1,10 +1,14 @@ import { TestHelper } from './TestHelper'; -import { getFailureStringNoAlt, getFailureStringEmptyAlt } from '../src/reactA11yImgHasAltRule'; +import { + getFailureStringNoAlt, + getFailureStringNonEmptyAltAndPresentationRole, + getFailureStringEmptyAltAndNotPresentationRole +} from '../src/reactA11yImgHasAltRule'; /** - * Unit test for a11y-img-has-alt rule + * Unit test for react-a11y-img-has-alt rule */ -describe('a11yImgHasAlt', () => { +describe('reactA11yImgHasAlt', () => { const ruleName: string = 'react-a11y-img-has-alt'; describe('default tests', () => { @@ -16,23 +20,23 @@ describe('a11yImgHasAlt', () => { TestHelper.assertNoViolation(ruleName, fileName); }); - it('when the img element has presentation role', () => { - const fileName: string = fileDirectory + 'ImgElementHasPresentationRole'; + it('when the img tag name is not lower case', () => { + const fileName: string = fileDirectory + 'ImgElementNotLowerCase.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it('when the img element has no empty alt value', () => { - const fileName: string = fileDirectory + 'ImgElementHasAltAndAltValueNotEmpty'; + it('when the img element has spread attribute', () => { + const fileName: string = fileDirectory + 'ImgElementHasSpreadAttribute.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it('when the img tag name is not lower case', () => { - const fileName: string = fileDirectory + 'ImgElementNotLowerCase'; + it('when the img element has empty alt value and presentation role', () => { + const fileName: string = fileDirectory + 'ImgElementHasEmptyAltValueAndPresentationRole.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it('when the img element has spread attribute', () => { - const fileName: string = fileDirectory + 'ImgElementHasSpreadAttribute'; + it('when the img element has non-empty alt value and not presentation role', () => { + const fileName: string = fileDirectory + 'ImgElementHasNonEmptyAltValueAndNotPresentationRole.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); }); @@ -63,8 +67,43 @@ describe('a11yImgHasAlt', () => { ); }); - it('when the img element has empty alt value', () => { - const fileName: string = fileDirectory + 'ImgElementHasEmptyAltValue.tsx'; + it('when the img element has empty alt value and not presentation role', () => { + const fileName: string = fileDirectory + 'ImgElementHasEmptyAltValueAndNotPresentationRole.tsx'; + + TestHelper.assertViolations( + ruleName, + fileName, + [ + { + name: fileName, + ruleName: ruleName, + startPosition: { character: 11, line: 3 }, + failure: getFailureStringEmptyAltAndNotPresentationRole('img') + }, + { + name: fileName, + ruleName: ruleName, + startPosition: { character: 11, line: 4 }, + failure: getFailureStringEmptyAltAndNotPresentationRole('img') + }, + { + name: fileName, + ruleName: ruleName, + startPosition: { character: 11, line: 5 }, + failure: getFailureStringEmptyAltAndNotPresentationRole('img') + }, + { + name: fileName, + ruleName: ruleName, + startPosition: { character: 11, line: 6 }, + failure: getFailureStringEmptyAltAndNotPresentationRole('img') + } + ] + ); + }); + + it('when the img element has non-empty alt value and presentation role', () => { + const fileName: string = fileDirectory + 'ImgElementHasNonEmptyAltValueAndPresentationRole.tsx'; TestHelper.assertViolations( ruleName, @@ -73,26 +112,26 @@ describe('a11yImgHasAlt', () => { { name: fileName, ruleName: ruleName, - startPosition: { character: 16, line: 3 }, - failure: getFailureStringEmptyAlt('img') + startPosition: { character: 11, line: 5 }, + failure: getFailureStringNonEmptyAltAndPresentationRole('img') }, { name: fileName, ruleName: ruleName, - startPosition: { character: 16, line: 4 }, - failure: getFailureStringEmptyAlt('img') + startPosition: { character: 11, line: 6 }, + failure: getFailureStringNonEmptyAltAndPresentationRole('img') }, { name: fileName, ruleName: ruleName, - startPosition: { character: 16, line: 5 }, - failure: getFailureStringEmptyAlt('img') + startPosition: { character: 11, line: 7 }, + failure: getFailureStringNonEmptyAltAndPresentationRole('img') }, { name: fileName, ruleName: ruleName, - startPosition: { character: 16, line: 6 }, - failure: getFailureStringEmptyAlt('img') + startPosition: { character: 11, line: 8 }, + failure: getFailureStringNonEmptyAltAndPresentationRole('img') } ] ); @@ -111,13 +150,13 @@ describe('a11yImgHasAlt', () => { TestHelper.assertNoViolationWithOptions(ruleName, options, fileName); }); - it('when custom element or img has presentation role', () => { - const fileName: string = fileDirectory + 'CustomElementHasPresentationRole.tsx'; + it('when custom element or img has empty alt value and presentation role', () => { + const fileName: string = fileDirectory + 'CustomElementHasEmptyAltValueAndPresentationRole.tsx'; TestHelper.assertNoViolationWithOptions(ruleName, options, fileName); }); - it('when custom element or img has not empty alt value', () => { - const fileName: string = fileDirectory + 'CustomElementHasValidAltValue.tsx'; + it('when custom element or img has non-empty alt value and not presentation role', () => { + const fileName: string = fileDirectory + 'CustomElementHasNonEmptyAltValueAndNotPresentationRole.tsx'; TestHelper.assertNoViolationWithOptions(ruleName, options, fileName); }); }); @@ -161,8 +200,56 @@ describe('a11yImgHasAlt', () => { ); }); - it('when custom element or img has empty alt value', () => { - const fileName: string = fileDirectory + 'CustomElementHasEmptyAltValue.tsx'; + it('when custom element or img has non-empty alt value and presentation role', () => { + const fileName: string = fileDirectory + 'CustomElementHasNonEmptyAltValueAndPresentationRole.tsx'; + + TestHelper.assertViolationsWithOptions( + ruleName, + options, + fileName, + [ + { + name: fileName, + ruleName: ruleName, + startPosition: { character: 11, line: 6 }, + failure: getFailureStringNonEmptyAltAndPresentationRole('Picture') + }, + { + name: fileName, + ruleName: ruleName, + startPosition: { character: 11, line: 7 }, + failure: getFailureStringNonEmptyAltAndPresentationRole('Picture') + }, + { + name: fileName, + ruleName: ruleName, + startPosition: { character: 11, line: 8 }, + failure: getFailureStringNonEmptyAltAndPresentationRole('Picture') + }, + { + name: fileName, + ruleName: ruleName, + startPosition: { character: 11, line: 9 }, + failure: getFailureStringNonEmptyAltAndPresentationRole('img') + }, + { + name: fileName, + ruleName: ruleName, + startPosition: { character: 11, line: 10 }, + failure: getFailureStringNonEmptyAltAndPresentationRole('img') + }, + { + name: fileName, + ruleName: ruleName, + startPosition: { character: 11, line: 11 }, + failure: getFailureStringNonEmptyAltAndPresentationRole('img') + } + ] + ); + }); + + it('when custom element or img has empty alt value and not presentation role', () => { + const fileName: string = fileDirectory + 'CustomElementHasEmptyAltValueAndNotPresentationRole.tsx'; TestHelper.assertViolationsWithOptions( ruleName, @@ -172,38 +259,38 @@ describe('a11yImgHasAlt', () => { { name: fileName, ruleName: ruleName, - startPosition: { character: 20, line: 4 }, - failure: getFailureStringEmptyAlt('Picture') + startPosition: { character: 11, line: 4 }, + failure: getFailureStringEmptyAltAndNotPresentationRole('Picture') }, { name: fileName, ruleName: ruleName, - startPosition: { character: 20, line: 5 }, - failure: getFailureStringEmptyAlt('Picture') + startPosition: { character: 11, line: 5 }, + failure: getFailureStringEmptyAltAndNotPresentationRole('Picture') }, { name: fileName, ruleName: ruleName, - startPosition: { character: 20, line: 6 }, - failure: getFailureStringEmptyAlt('Picture') + startPosition: { character: 11, line: 6 }, + failure: getFailureStringEmptyAltAndNotPresentationRole('Picture') }, { name: fileName, ruleName: ruleName, - startPosition: { character: 16, line: 7 }, - failure: getFailureStringEmptyAlt('img') + startPosition: { character: 11, line: 7 }, + failure: getFailureStringEmptyAltAndNotPresentationRole('img') }, { name: fileName, ruleName: ruleName, - startPosition: { character: 16, line: 8 }, - failure: getFailureStringEmptyAlt('img') + startPosition: { character: 11, line: 8 }, + failure: getFailureStringEmptyAltAndNotPresentationRole('img') }, { name: fileName, ruleName: ruleName, - startPosition: { character: 16, line: 9 }, - failure: getFailureStringEmptyAlt('img') + startPosition: { character: 11, line: 9 }, + failure: getFailureStringEmptyAltAndNotPresentationRole('img') } ] ); diff --git a/tslint-warnings.csv b/tslint-warnings.csv index 32f55870d..0e5612f92 100644 --- a/tslint-warnings.csv +++ b/tslint-warnings.csv @@ -205,7 +205,7 @@ react-a11y-anchors,"For accessibility of your website, anchor elements must have react-a11y-aria-unsupported-elements,"Enforce that elements that do not support ARIA roles, states, and properties do not have those attributes.",TSLINTQ04S5L,tslint,Non-SDL,Warning,Important,Opportunity for Excellence,See description on the tslint or tslint-microsoft-contrib website,TSLint Procedure,, react-a11y-event-has-role,Elements with event handlers must have role attribute.,TSLINT18MKF94,tslint,Non-SDL,Warning,Important,Opportunity for Excellence,See description on the tslint or tslint-microsoft-contrib website,TSLint Procedure,, react-a11y-image-button-has-alt,Enforce that inputs element with type="image" must have alt attribute.,TSLINTVBN64L,tslint,Non-SDL,Warning,Important,Opportunity for Excellence,See description on the tslint or tslint-microsoft-contrib website,TSLint Procedure,, -react-a11y-img-has-alt,Enforce that an `img` element contains the `alt` attribute or `role="presentation"` for decorative image.,TSLINT1OM69KS,tslint,Non-SDL,Warning,Important,Opportunity for Excellence,See description on the tslint or tslint-microsoft-contrib website,TSLint Procedure,, +react-a11y-img-has-alt,"Enforce that an img element contains the non-empty alt attribute. For decorative images, using empty alt attribute and role="presentation".",TSLINT1OM69KS,tslint,Non-SDL,Warning,Important,Opportunity for Excellence,See description on the tslint or tslint-microsoft-contrib website,TSLint Procedure,, react-a11y-lang,"For accessibility of your website, html elements must have a valid lang attribute.",TSLINTQ046RM,tslint,Non-SDL,Warning,Low,Opportunity for Excellence,See description on the tslint or tslint-microsoft-contrib website,TSLint Procedure,, react-a11y-props,Enforce all `aria-*` attributes are valid. Elements cannot use an invalid `aria-*` attribute.,TSLINT1682S78,tslint,Non-SDL,Warning,Important,Opportunity for Excellence,See description on the tslint or tslint-microsoft-contrib website,TSLint Procedure,, react-a11y-proptypes,Enforce ARIA state and property values are valid.,TSLINT1DLB1JE,tslint,Non-SDL,Warning,Important,Opportunity for Excellence,See description on the tslint or tslint-microsoft-contrib website,TSLint Procedure,,