From bb59331c920e76745ae29b09089dae803bba4865 Mon Sep 17 00:00:00 2001 From: Liubin Guo Date: Mon, 19 Sep 2016 20:42:20 +0800 Subject: [PATCH 1/3] Fixed for empty alt value. --- src/reactA11yImgHasAltRule.ts | 74 +++++--- ...asEmptyAltValueAndNotPresentationRole.tsx} | 2 +- ...HasNonEmptyAltValueAndPresentationRole.tsx | 11 ++ ...entHasEmptyAltValueAndPresentationRole.tsx | 10 ++ ...onEmptyAltValueAndNotPresentationRole.tsx} | 6 +- .../CustomElementHasPresentationRole.tsx | 10 -- ...asEmptyAltValueAndNotPresentationRole.tsx} | 2 +- ...HasNonEmptyAltValueAndPresentationRole.tsx | 8 + ...entHasEmptyAltValueAndPresentationRole.tsx | 6 + ...onEmptyAltValueAndNotPresentationRole.tsx} | 0 .../ImgElementHasPresentationRole.tsx | 6 - .../ImgElementNotLowerCase.tsx | 7 +- tests/ReactA11yProptypesRuleTest.ts | 2 +- tests/reactA11yImgHasAltRuleTests.ts | 165 +++++++++++++----- 14 files changed, 219 insertions(+), 90 deletions(-) rename test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/{CustomElementHasEmptyAltValue.tsx => CustomElementHasEmptyAltValueAndNotPresentationRole.tsx} (81%) create mode 100644 test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNonEmptyAltValueAndPresentationRole.tsx create mode 100644 test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasEmptyAltValueAndPresentationRole.tsx rename test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/{CustomElementHasValidAltValue.tsx => CustomElementHasNonEmptyAltValueAndNotPresentationRole.tsx} (52%) delete mode 100644 test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasPresentationRole.tsx rename test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/{ImgElementHasEmptyAltValue.tsx => ImgElementHasEmptyAltValueAndNotPresentationRole.tsx} (77%) create mode 100644 test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/imgElementHasNonEmptyAltValueAndPresentationRole.tsx create mode 100644 test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasEmptyAltValueAndPresentationRole.tsx rename test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/{ImgElementHasNotEmptyAltValue.tsx => ImgElementHasNonEmptyAltValueAndNotPresentationRole.tsx} (100%) delete mode 100644 test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ImgElementHasPresentationRole.tsx diff --git a/src/reactA11yImgHasAltRule.ts b/src/reactA11yImgHasAltRule.ts index 5d588a695..c7a434c38 100644 --- a/src/reactA11yImgHasAltRule.ts +++ b/src/reactA11yImgHasAltRule.ts @@ -10,17 +10,24 @@ 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. \ +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 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 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 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.`; } @@ -31,7 +38,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 or' + + 'empty alt attribute and `role="presentation"` for decorative image.', options: 'string[]', optionExamples: ['true', '[true, ["Image"]]'], issueClass: 'Non-SDL', @@ -49,9 +57,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 +89,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') } ] ); From b9bbed2b61fe93248b72fb9e32b9fd6da0fddb91 Mon Sep 17 00:00:00 2001 From: Liubin Guo Date: Mon, 19 Sep 2016 20:56:48 +0800 Subject: [PATCH 2/3] Fixed a file name. --- ...e.tsx => ImgElementHasNonEmptyAltValueAndPresentationRole.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/{imgElementHasNonEmptyAltValueAndPresentationRole.tsx => ImgElementHasNonEmptyAltValueAndPresentationRole.tsx} (100%) diff --git a/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/imgElementHasNonEmptyAltValueAndPresentationRole.tsx b/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNonEmptyAltValueAndPresentationRole.tsx similarity index 100% rename from test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/imgElementHasNonEmptyAltValueAndPresentationRole.tsx rename to test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNonEmptyAltValueAndPresentationRole.tsx From a3445b1ae05d73c36504fea9de3bdceebacc391b Mon Sep 17 00:00:00 2001 From: Liubin Guo Date: Tue, 20 Sep 2016 14:30:51 +0800 Subject: [PATCH 3/3] Fixed comments. --- src/reactA11yImgHasAltRule.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/reactA11yImgHasAltRule.ts b/src/reactA11yImgHasAltRule.ts index c7a434c38..572b6fb95 100644 --- a/src/reactA11yImgHasAltRule.ts +++ b/src/reactA11yImgHasAltRule.ts @@ -21,14 +21,12 @@ A reference for the presentation role can be found at https://www.w3.org/TR/wai- 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 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.`; +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 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.`; +Remove role='presentation' or specify 'alt' attributeto be empty when role attributes equals 'presentation'.`; } /** @@ -38,8 +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 non-empty `alt` attribute or' + - 'empty alt attribute and `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',