From 76498281fedc75377a9300d32b7634300f4cb65f Mon Sep 17 00:00:00 2001 From: Clay Miller Date: Tue, 6 Dec 2022 20:12:58 +0000 Subject: [PATCH 1/2] feat: Flag 'aria-label' on 'span' --- .../src/rules/role-supports-aria-props-test.js | 15 +++++++++++++-- src/rules/role-supports-aria-props.js | 4 +++- src/util/implicitRoles/index.js | 2 ++ src/util/implicitRoles/span.js | 6 ++++++ 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 src/util/implicitRoles/span.js diff --git a/__tests__/src/rules/role-supports-aria-props-test.js b/__tests__/src/rules/role-supports-aria-props-test.js index 5aa8019d8..bf3a3e5e7 100644 --- a/__tests__/src/rules/role-supports-aria-props-test.js +++ b/__tests__/src/rules/role-supports-aria-props-test.js @@ -50,11 +50,14 @@ const nonAbstractRoles = [...roles.keys()].filter((role) => roles.get(role).abst const createTests = (rolesNames) => rolesNames.reduce((tests, role) => { const { props: propKeyValues, + prohibitedProps, } = roles.get(role); - const validPropsForRole = Object.keys(propKeyValues); + const validPropsForRole = Object.keys(propKeyValues) + .filter((attribute) => prohibitedProps.indexOf(attribute) === -1); const invalidPropsForRole = [...aria.keys()] .map((attribute) => attribute.toLowerCase()) - .filter((attribute) => validPropsForRole.indexOf(attribute) === -1); + .filter((attribute) => validPropsForRole.indexOf(attribute) === -1) + .concat(prohibitedProps); const normalRole = role.toLowerCase(); const allTests = []; @@ -568,5 +571,13 @@ ruleTester.run('role-supports-aria-props', rule, { errors: [errorMessage('aria-checked', 'link', 'a', true)], settings: componentsSettings, }, + { + code: '', + errors: [errorMessage('aria-label', 'generic', 'span', true)], + }, + { + code: '', + errors: [errorMessage('aria-labelledby', 'generic', 'span', true)], + }, ].concat(invalidTests).map(parserOptionsMapper), }); diff --git a/src/rules/role-supports-aria-props.js b/src/rules/role-supports-aria-props.js index ec961032f..c1117f2f6 100644 --- a/src/rules/role-supports-aria-props.js +++ b/src/rules/role-supports-aria-props.js @@ -65,9 +65,11 @@ export default { // Make sure it has no aria-* properties defined outside of its property set. const { props: propKeyValues, + prohibitedProps, } = roles.get(roleValue); const invalidAriaPropsForRole = [...aria.keys()] - .filter((attribute) => !(attribute in propKeyValues)); + .filter((attribute) => !(attribute in propKeyValues)) + .concat(prohibitedProps); node.attributes.filter((prop) => ( getPropValue(prop) != null // Ignore the attribute if its value is null or undefined. diff --git a/src/util/implicitRoles/index.js b/src/util/implicitRoles/index.js index 027b62af4..6f5e9b3ba 100644 --- a/src/util/implicitRoles/index.js +++ b/src/util/implicitRoles/index.js @@ -29,6 +29,7 @@ import output from './output'; import progress from './progress'; import section from './section'; import select from './select'; +import span from './span'; import tbody from './tbody'; import textarea from './textarea'; import tfoot from './tfoot'; @@ -67,6 +68,7 @@ export default { progress, section, select, + span, tbody, textarea, tfoot, diff --git a/src/util/implicitRoles/span.js b/src/util/implicitRoles/span.js new file mode 100644 index 000000000..169a7057d --- /dev/null +++ b/src/util/implicitRoles/span.js @@ -0,0 +1,6 @@ +/** + * Returns the implicit role for a span tag. + */ +export default function getImplicitRoleForSpan() { + return 'generic'; +} From b8d17cbb262204bcc1907a17e016975a3cb357eb Mon Sep 17 00:00:00 2001 From: Clay Miller Date: Tue, 6 Dec 2022 20:13:27 +0000 Subject: [PATCH 2/2] feat: Flag 'aria-label' on 'div' --- __tests__/src/rules/role-supports-aria-props-test.js | 8 ++++++++ __tests__/src/util/getComputedRole-test.js | 6 +++--- __tests__/src/util/getExplicitRole-test.js | 4 ++-- __tests__/src/util/getImplicitRole-test.js | 2 +- src/util/implicitRoles/div.js | 6 ++++++ src/util/implicitRoles/index.js | 2 ++ 6 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 src/util/implicitRoles/div.js diff --git a/__tests__/src/rules/role-supports-aria-props-test.js b/__tests__/src/rules/role-supports-aria-props-test.js index bf3a3e5e7..314e7be71 100644 --- a/__tests__/src/rules/role-supports-aria-props-test.js +++ b/__tests__/src/rules/role-supports-aria-props-test.js @@ -579,5 +579,13 @@ ruleTester.run('role-supports-aria-props', rule, { code: '', errors: [errorMessage('aria-labelledby', 'generic', 'span', true)], }, + { + code: '
', + errors: [errorMessage('aria-label', 'generic', 'div', true)], + }, + { + code: '
', + errors: [errorMessage('aria-labelledby', 'generic', 'div', true)], + }, ].concat(invalidTests).map(parserOptionsMapper), }); diff --git a/__tests__/src/util/getComputedRole-test.js b/__tests__/src/util/getComputedRole-test.js index 33a2d8e0a..59898693c 100644 --- a/__tests__/src/util/getComputedRole-test.js +++ b/__tests__/src/util/getComputedRole-test.js @@ -24,7 +24,7 @@ describe('getComputedRole', () => { describe('lacks implicit', () => { it('should return null', () => { expect(getComputedRole( - 'div', + 'custom-element', [JSXAttributeMock('role', 'beeswax')], )).toBeNull(); }); @@ -43,7 +43,7 @@ describe('getComputedRole', () => { describe('lacks implicit', () => { it('should return null', () => { expect(getComputedRole( - 'div', + 'custom-element', [], )).toBeNull(); }); @@ -62,7 +62,7 @@ describe('getComputedRole', () => { describe('lacks implicit', () => { it('should return null', () => { expect(getComputedRole( - 'div', + 'custom-element', [], )).toBeNull(); }); diff --git a/__tests__/src/util/getExplicitRole-test.js b/__tests__/src/util/getExplicitRole-test.js index 102628c23..38fe88208 100644 --- a/__tests__/src/util/getExplicitRole-test.js +++ b/__tests__/src/util/getExplicitRole-test.js @@ -14,7 +14,7 @@ describe('getExplicitRole', () => { describe('invalid role', () => { it('should return null', () => { expect(getExplicitRole( - 'div', + 'custom-element', [JSXAttributeMock('role', 'beeswax')], )).toBeNull(); }); @@ -22,7 +22,7 @@ describe('getExplicitRole', () => { describe('no role', () => { it('should return null', () => { expect(getExplicitRole( - 'div', + 'custom-element', [], )).toBeNull(); }); diff --git a/__tests__/src/util/getImplicitRole-test.js b/__tests__/src/util/getImplicitRole-test.js index 76176ab6a..ed81ef7a5 100644 --- a/__tests__/src/util/getImplicitRole-test.js +++ b/__tests__/src/util/getImplicitRole-test.js @@ -13,7 +13,7 @@ describe('getImplicitRole', () => { describe('lacks implicit', () => { it('should return null', () => { expect(getImplicitRole( - 'div', + 'custom-element', [], )).toBeNull(); }); diff --git a/src/util/implicitRoles/div.js b/src/util/implicitRoles/div.js new file mode 100644 index 000000000..8ea7bffe0 --- /dev/null +++ b/src/util/implicitRoles/div.js @@ -0,0 +1,6 @@ +/** + * Returns the implicit role for a div tag. + */ +export default function getImplicitRoleForDiv() { + return 'generic'; +} diff --git a/src/util/implicitRoles/index.js b/src/util/implicitRoles/index.js index 6f5e9b3ba..b7243b8d7 100644 --- a/src/util/implicitRoles/index.js +++ b/src/util/implicitRoles/index.js @@ -7,6 +7,7 @@ import button from './button'; import datalist from './datalist'; import details from './details'; import dialog from './dialog'; +import div from './div'; import form from './form'; import h1 from './h1'; import h2 from './h2'; @@ -46,6 +47,7 @@ export default { datalist, details, dialog, + div, form, h1, h2,