diff --git a/src/reactA11yRoleSupportsAriaPropsRule.ts b/src/reactA11yRoleSupportsAriaPropsRule.ts index 69c214969..eb90c52ef 100644 --- a/src/reactA11yRoleSupportsAriaPropsRule.ts +++ b/src/reactA11yRoleSupportsAriaPropsRule.ts @@ -7,7 +7,7 @@ import * as Lint from 'tslint/lib/lint'; import { ExtendedMetadata } from './utils/ExtendedMetadata'; import { getImplicitRole } from './utils/getImplicitRole'; -import { getJsxAttributesFromJsxElement, getStringLiteral } from './utils/JsxAttribute'; +import { getJsxAttributesFromJsxElement, getStringLiteral, isEmpty } from './utils/JsxAttribute'; import { IRole, IRoleSchema } from './utils/attributes/IRole'; import { IAria } from './utils/attributes/IAria'; @@ -69,9 +69,17 @@ class A11yRoleSupportsAriaPropsWalker extends Lint.RuleWalker { private checkJsxElement(node: ts.JsxOpeningElement): void { const attributesInElement: { [propName: string]: ts.JsxAttribute } = getJsxAttributesFromJsxElement(node); const roleProp: ts.JsxAttribute = attributesInElement[ROLE_STRING]; + let roleValue: string; + + if (roleProp != null) { + roleValue = getStringLiteral(roleProp); + if (!isEmpty(roleProp) && roleValue == null) { // Do NOT check if can't retrieve the right role. + return; + } + } else { + roleValue = getImplicitRole(node); // Get implicit role if not specified. + } - // If role attribute is specified, get the role value. Otherwise get the implicit role from tag name. - const roleValue: string = roleProp ? getStringLiteral(roleProp) : getImplicitRole(node); const isImplicitRole: boolean = !roleProp && !!roleValue; const normalizedRoles: string[] = (roleValue || '').toLowerCase().split(' ') .filter((role: string) => !!ROLES[role]); diff --git a/test-data/a11yRoleSupportsAriaProps/PassingTestInputs/UnretrievableRoleSupportsAllAriaPropsInElement.tsx b/test-data/a11yRoleSupportsAriaProps/PassingTestInputs/UnretrievableRoleSupportsAllAriaPropsInElement.tsx new file mode 100644 index 000000000..ab46aa3ee --- /dev/null +++ b/test-data/a11yRoleSupportsAriaProps/PassingTestInputs/UnretrievableRoleSupportsAllAriaPropsInElement.tsx @@ -0,0 +1,38 @@ +import React = require('react'); + +const role = 'some role'; + +// Only one role. +const a =
+const b = +const c = +const d = +const e = +const f = +const g = +const h = +const i = +const j = +const k = +const l = +const m = +const n = +const o = +const p = +const r = +const s = +const t = +const u = +const v = +const w = +const x = +const y = +const z = +const a1 = +const b1 = + +// Multiple roles. +const c1 = + +// when there have explicit role and implicit role, the explicit role will be used first. +const d1 = diff --git a/tests/reactA11yRoleSupportsAriaPropsRuleTests.ts b/tests/reactA11yRoleSupportsAriaPropsRuleTests.ts index 2e01c3a74..6f2364e19 100644 --- a/tests/reactA11yRoleSupportsAriaPropsRuleTests.ts +++ b/tests/reactA11yRoleSupportsAriaPropsRuleTests.ts @@ -28,6 +28,11 @@ describe('a11yRoleSupportsAriaPropsRule', () => { const fileName: string = fileDirectory + 'ImplicitRoleSupportsAllAriaPropsInElement.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); + + it('when role is defined but not retrievable', () => { + const fileName: string = fileDirectory + 'UnretrievableRoleSupportsAllAriaPropsInElement.tsx'; + TestHelper.assertNoViolation(ruleName, fileName); + }); }); describe('should fail', () => {