/** * @fileoverview Enforce that elements with ARIA roles must * have all required attributes for that role. * @author Ethan Cohen */ // ----------------------------------------------------------------------------- // Requirements // ----------------------------------------------------------------------------- import { roles } from 'aria-query'; import { RuleTester } from 'eslint'; import iterFrom from 'es-iterator-helpers/Iterator.from'; import map from 'es-iterator-helpers/Iterator.prototype.map'; import toArray from 'es-iterator-helpers/Iterator.prototype.toArray'; import parserOptionsMapper from '../../__util__/parserOptionsMapper'; import parsers from '../../__util__/helpers/parsers'; import rule from '../../../src/rules/role-has-required-aria-props'; // ----------------------------------------------------------------------------- // Tests // ----------------------------------------------------------------------------- const ruleTester = new RuleTester(); const errorMessage = (role) => { const requiredProps = Object.keys(roles.get(role).requiredProps); return { message: `Elements with the ARIA role "${role}" must have the following attributes defined: ${requiredProps}`, type: 'JSXAttribute', }; }; const componentsSettings = { 'jsx-a11y': { components: { MyComponent: 'div', }, }, }; // Create basic test cases using all valid role types. const basicValidityTests = toArray(map(iterFrom(roles.keys()), (role) => { const { requiredProps: requiredPropKeyValues, } = roles.get(role); const requiredProps = Object.keys(requiredPropKeyValues); const propChain = requiredProps.join(' '); return { code: `
`, }; })); ruleTester.run('role-has-required-aria-props', rule, { valid: parsers.all([].concat( { code: '' }, { code: '' }, // Variables should pass, as we are only testing literals. { code: '
' }, { code: '
' }, { code: '
' }, { code: '
' }, { code: '
' }, { code: '
' }, { code: '' }, { code: '' }, { code: '' }, { code: '', settings: componentsSettings }, )).concat(basicValidityTests).map(parserOptionsMapper), invalid: parsers.all([].concat( // SLIDER { code: '
', errors: [errorMessage('slider')] }, { code: '
', errors: [errorMessage('slider')], }, { code: '
', errors: [errorMessage('slider')], }, // CHECKBOX { code: '
', errors: [errorMessage('checkbox')] }, { code: '
', errors: [errorMessage('checkbox')] }, { code: '
', errors: [errorMessage('checkbox')], }, { code: '', errors: [errorMessage('checkbox')], }, // COMBOBOX { code: '
', errors: [errorMessage('combobox')] }, { code: '
', errors: [errorMessage('combobox')] }, { code: '
', errors: [errorMessage('combobox')], }, // SCROLLBAR { code: '
', errors: [errorMessage('scrollbar')] }, { code: '
', errors: [errorMessage('scrollbar')], }, { code: '
', errors: [errorMessage('scrollbar')], }, { code: '
', errors: [errorMessage('scrollbar')], }, { code: '
', errors: [errorMessage('scrollbar')], }, { code: '
', errors: [errorMessage('heading')], }, { code: '
', errors: [errorMessage('option')], }, // Custom element { code: '', settings: componentsSettings, errors: [errorMessage('combobox')] }, )).map(parserOptionsMapper), });