Skip to content

Commit f4b80d1

Browse files
committed
[breaking] update recommended and strict configs
1 parent 905dc27 commit f4b80d1

14 files changed

+203
-237
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,9 @@ To restrict polymorphic linting to specified components, additionally set `polym
237237

238238
| Name                                          | Description | 💼 | 🚫 ||
239239
| :----------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------- | :---- | :---- | :- |
240-
| [accessible-emoji](docs/rules/accessible-emoji.md) | Enforce emojis are wrapped in `<span>` and provide screen reader access. | | ||
240+
| [accessible-emoji](docs/rules/accessible-emoji.md) | Enforce emojis are wrapped in `<span>` and provide screen reader access. | | ☑️ 🔒 ||
241241
| [alt-text](docs/rules/alt-text.md) | Enforce all elements that require alternative text have meaningful information to relay back to end user. | ☑️ 🔒 | | |
242-
| [anchor-ambiguous-text](docs/rules/anchor-ambiguous-text.md) | Enforce `<a>` text to not exactly match "click here", "here", "link", or "a link". | | ☑️ | |
242+
| [anchor-ambiguous-text](docs/rules/anchor-ambiguous-text.md) | Enforce `<a>` text to not exactly match "click here", "here", "link", or "a link". | ☑️ 🔒 | | |
243243
| [anchor-has-content](docs/rules/anchor-has-content.md) | Enforce all anchors to contain accessible content. | ☑️ 🔒 | | |
244244
| [anchor-is-valid](docs/rules/anchor-is-valid.md) | Enforce all anchors are valid, navigable elements. | ☑️ 🔒 | | |
245245
| [aria-activedescendant-has-tabindex](docs/rules/aria-activedescendant-has-tabindex.md) | Enforce elements with aria-activedescendant are tabbable. | ☑️ 🔒 | | |
@@ -249,29 +249,29 @@ To restrict polymorphic linting to specified components, additionally set `polym
249249
| [aria-unsupported-elements](docs/rules/aria-unsupported-elements.md) | Enforce that elements that do not support ARIA roles, states, and properties do not have those attributes. | ☑️ 🔒 | | |
250250
| [autocomplete-valid](docs/rules/autocomplete-valid.md) | Enforce that autocomplete attributes are used correctly. | ☑️ 🔒 | | |
251251
| [click-events-have-key-events](docs/rules/click-events-have-key-events.md) | Enforce a clickable non-interactive element has at least one keyboard event listener. | ☑️ 🔒 | | |
252-
| [control-has-associated-label](docs/rules/control-has-associated-label.md) | Enforce that a control (an interactive element) has a text label. | | ☑️ 🔒 | |
252+
| [control-has-associated-label](docs/rules/control-has-associated-label.md) | Enforce that a control (an interactive element) has a text label. | ☑️ 🔒 | | |
253253
| [heading-has-content](docs/rules/heading-has-content.md) | Enforce heading (`h1`, `h2`, etc) elements contain accessible content. | ☑️ 🔒 | | |
254254
| [html-has-lang](docs/rules/html-has-lang.md) | Enforce `<html>` element has `lang` prop. | ☑️ 🔒 | | |
255255
| [iframe-has-title](docs/rules/iframe-has-title.md) | Enforce iframe elements have a title attribute. | ☑️ 🔒 | | |
256256
| [img-redundant-alt](docs/rules/img-redundant-alt.md) | Enforce `<img>` alt prop does not contain the word "image", "picture", or "photo". | ☑️ 🔒 | | |
257257
| [interactive-supports-focus](docs/rules/interactive-supports-focus.md) | Enforce that elements with interactive handlers like `onClick` must be focusable. | ☑️ 🔒 | | |
258258
| [label-has-associated-control](docs/rules/label-has-associated-control.md) | Enforce that a `label` tag has a text label and an associated control. | ☑️ 🔒 | | |
259259
| [label-has-for](docs/rules/label-has-for.md) | Enforce that `<label>` elements have the `htmlFor` prop. | | ☑️ 🔒 ||
260-
| [lang](docs/rules/lang.md) | Enforce lang attribute has a valid value. | | | |
260+
| [lang](docs/rules/lang.md) | Enforce lang attribute has a valid value. | ☑️ 🔒 | | |
261261
| [media-has-caption](docs/rules/media-has-caption.md) | Enforces that `<audio>` and `<video>` elements must have a `<track>` for captions. | ☑️ 🔒 | | |
262262
| [mouse-events-have-key-events](docs/rules/mouse-events-have-key-events.md) | Enforce that `onMouseOver`/`onMouseOut` are accompanied by `onFocus`/`onBlur` for keyboard-only users. | ☑️ 🔒 | | |
263263
| [no-access-key](docs/rules/no-access-key.md) | Enforce that the `accessKey` prop is not used on any element to avoid complications with keyboard commands used by a screen reader. | ☑️ 🔒 | | |
264-
| [no-aria-hidden-on-focusable](docs/rules/no-aria-hidden-on-focusable.md) | Disallow `aria-hidden="true"` from being set on focusable elements. | | | |
264+
| [no-aria-hidden-on-focusable](docs/rules/no-aria-hidden-on-focusable.md) | Disallow `aria-hidden="true"` from being set on focusable elements. | ☑️ 🔒 | | |
265265
| [no-autofocus](docs/rules/no-autofocus.md) | Enforce autoFocus prop is not used. | ☑️ 🔒 | | |
266266
| [no-distracting-elements](docs/rules/no-distracting-elements.md) | Enforce distracting elements are not used. | ☑️ 🔒 | | |
267267
| [no-interactive-element-to-noninteractive-role](docs/rules/no-interactive-element-to-noninteractive-role.md) | Interactive elements should not be assigned non-interactive roles. | ☑️ 🔒 | | |
268268
| [no-noninteractive-element-interactions](docs/rules/no-noninteractive-element-interactions.md) | Non-interactive elements should not be assigned mouse or keyboard event listeners. | ☑️ 🔒 | | |
269269
| [no-noninteractive-element-to-interactive-role](docs/rules/no-noninteractive-element-to-interactive-role.md) | Non-interactive elements should not be assigned interactive roles. | ☑️ 🔒 | | |
270270
| [no-noninteractive-tabindex](docs/rules/no-noninteractive-tabindex.md) | `tabIndex` should only be declared on interactive elements. | ☑️ 🔒 | | |
271-
| [no-onchange](docs/rules/no-onchange.md) | Enforce usage of `onBlur` over `onChange` on select menus for accessibility. | | ||
271+
| [no-onchange](docs/rules/no-onchange.md) | Enforce usage of `onBlur` over `onChange` on select menus for accessibility. | | ☑️ 🔒 ||
272272
| [no-redundant-roles](docs/rules/no-redundant-roles.md) | Enforce explicit role property is not the same as implicit/default role property on element. | ☑️ 🔒 | | |
273273
| [no-static-element-interactions](docs/rules/no-static-element-interactions.md) | Enforce that non-interactive, visible elements (such as `<div>`) that have click handlers use the role attribute. | ☑️ 🔒 | | |
274-
| [prefer-tag-over-role](docs/rules/prefer-tag-over-role.md) | Enforces using semantic DOM elements over the ARIA `role` property. | | | |
274+
| [prefer-tag-over-role](docs/rules/prefer-tag-over-role.md) | Enforces using semantic DOM elements over the ARIA `role` property. | ☑️ 🔒 | | |
275275
| [role-has-required-aria-props](docs/rules/role-has-required-aria-props.md) | Enforce that elements with ARIA roles must have all required attributes for that role. | ☑️ 🔒 | | |
276276
| [role-supports-aria-props](docs/rules/role-supports-aria-props.md) | Enforce that elements with explicit or implicit roles defined contain only `aria-*` properties supported by that `role`. | ☑️ 🔒 | | |
277277
| [scope](docs/rules/scope.md) | Enforce `scope` prop is only used on `<th>` elements. | ☑️ 🔒 | | |

__tests__/src/rules/control-has-associated-label-test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const alwaysValid = [
3232
{ code: '<CustomControl><span><span>Save</span></span></CustomControl>', options: [{ depth: 3, controlComponents: ['CustomControl'] }] },
3333
{ code: '<CustomControl><span><span label="Save"></span></span></CustomControl>', options: [{ depth: 3, controlComponents: ['CustomControl'], labelAttributes: ['label'] }] },
3434
{ code: '<CustomControl>Save</CustomControl>', settings: { 'jsx-a11y': { components: { CustomControl: 'button' } } } },
35+
{ code: '<CustomControl><span><span></span></span></CustomControl>', options: [{ depth: 3, controlComponents: ['CustomControl'] }] },
3536
// Interactive Elements
3637
{ code: '<button>Save</button>' },
3738
{ code: '<button><span>Save</span></button>' },
@@ -43,7 +44,7 @@ const alwaysValid = [
4344
{ code: '<button aria-labelledby="js_1" />' },
4445
{ code: '<button><span aria-labelledby="js_1" /></button>' },
4546
{ code: '<button>{sureWhyNot}</button>' },
46-
{ code: '<button><span><span label="Save"></span></span></button>', options: [{ depth: 3, labelAttributes: ['label'] }] },
47+
{ code: '<button><span><span><span>Save</span></span></span></button>', options: [{ depth: 3 }] },
4748
{ code: '<a href="#">Save</a>' },
4849
{ code: '<area href="#">Save</area>' },
4950
{ code: '<link>Save</link>' },
@@ -254,8 +255,7 @@ const neverValid = [
254255
{ code: '<button><span /></button>', errors: [expectedError] },
255256
{ code: '<button><img /></button>', errors: [expectedError] },
256257
{ code: '<button><span title="This is not a real label" /></button>', errors: [expectedError] },
257-
{ code: '<button><span><span><span>Save</span></span></span></button>', options: [{ depth: 3 }], errors: [expectedError] },
258-
{ code: '<CustomControl><span><span></span></span></CustomControl>', options: [{ depth: 3, controlComponents: ['CustomControl'] }], errors: [expectedError] },
258+
{ code: '<button><span><span label="Save"></span></span></button>', options: [{ depth: 3, labelAttributes: ['label'] }], errors: [expectedError] },
259259
{ code: '<CustomControl></CustomControl>', errors: [expectedError], settings: { 'jsx-a11y': { components: { CustomControl: 'button' } } } },
260260
{ code: '<a href="#" />', errors: [expectedError] },
261261
{ code: '<area href="#" />', errors: [expectedError] },

__tests__/src/rules/img-redundant-alt-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ ruleTester.run('img-redundant-alt', rule, {
6464
{ code: '<img alt />' },
6565
{ code: '<img alt={imageAlt} />' },
6666
{ code: '<img alt={imageAlt.name} />' },
67-
{ code: '<img alt={imageAlt?.name} />', parserOptions: { ecmaVersion: 2020 } },
68-
{ code: '<img alt="Doing cool things" aria-hidden={foo?.bar}/>', parserOptions: { ecmaVersion: 2020 } },
67+
{ code: '<img alt={imageAlt?.name} />', languageOptions: { ecmaVersion: 2020 } },
68+
{ code: '<img alt="Doing cool things" aria-hidden={foo?.bar}/>', languageOptions: { ecmaVersion: 2020 } },
6969
{ code: '<img alt="Photography" />;' },
7070
{ code: '<img alt="ImageMagick" />;' },
7171
{ code: '<Image alt="Photo of a friend" />' },

__tests__/src/rules/interactive-supports-focus-test.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,6 @@ const interactiveRoles = [
154154
];
155155

156156
const recommendedRoles = [
157-
'button',
158-
'checkbox',
159-
'link',
160-
'searchbox',
161-
'spinbutton',
162-
'switch',
163-
'textbox',
164-
];
165-
166-
const strictRoles = [
167157
'button',
168158
'checkbox',
169159
'link',
@@ -175,6 +165,8 @@ const strictRoles = [
175165
'textbox',
176166
];
177167

168+
const strictRoles = recommendedRoles.concat();
169+
178170
const staticElements = [
179171
'div',
180172
];

__tests__/src/rules/no-noninteractive-element-interactions-test.js

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,20 +124,17 @@ const alwaysValid = [
124124
{ code: '<header onClick={() => {}} />;' },
125125
{ code: '<hgroup onClick={() => {}} />;' },
126126
{ code: '<i onClick={() => {}} />;' },
127-
{ code: '<iframe onLoad={() => {}} />;' },
128127
{
129128
code: `
130129
<iframe
131130
name="embeddedExternalPayment"
132131
ref="embeddedExternalPayment"
133132
style={iframeStyle}
134-
onLoad={this.handleLoadIframe}
135133
/>
136134
`,
137135
},
138-
{ code: '<img {...props} onError={() => {}} />;' },
139-
{ code: '<img onLoad={() => {}} />;' },
140-
{ code: '<img src={currentPhoto.imageUrl} onLoad={this.handleImageLoad} alt="for review" />' },
136+
{ code: '<img {...props} />;' },
137+
{ code: '<img src={currentPhoto.imageUrl} alt="for review" />' },
141138
{
142139
code: `
143140
<img
@@ -146,7 +143,6 @@ const alwaysValid = [
146143
src={src}
147144
alt={alt}
148145
data-test-id="test-id"
149-
onLoad={this.fetchCompleteImage}
150146
/>
151147
`,
152148
},
@@ -463,6 +459,34 @@ ruleTester.run(`${ruleName}:recommended`, rule, {
463459
.map(parserOptionsMapper),
464460
invalid: parsers.all([].concat(
465461
...neverValid,
462+
{ code: '<iframe onLoad={() => {}} />;', errors: [expectedError] },
463+
{
464+
code: `
465+
<iframe
466+
name="embeddedExternalPayment"
467+
ref="embeddedExternalPayment"
468+
style={iframeStyle}
469+
onLoad={this.handleLoadIframe}
470+
/>
471+
`,
472+
errors: [expectedError],
473+
},
474+
{ code: '<img {...props} onError={() => {}} />;', errors: [expectedError] },
475+
{ code: '<img onLoad={() => {}} />;', errors: [expectedError] },
476+
{ code: '<img src={currentPhoto.imageUrl} onLoad={this.handleImageLoad} alt="for review" />', errors: [expectedError] },
477+
{
478+
code: `
479+
<img
480+
ref={this.ref}
481+
className="c-responsive-image-placeholder__image"
482+
src={src}
483+
alt={alt}
484+
data-test-id="test-id"
485+
onLoad={this.fetchCompleteImage}
486+
/>
487+
`,
488+
errors: [expectedError],
489+
},
466490
))
467491
.map(ruleOptionsMapperFactory(recommendedOptions))
468492
.map(parserOptionsMapper),
@@ -472,6 +496,33 @@ const strictOptions = configs.strict.rules[`jsx-a11y/${ruleName}`][1] || {};
472496
ruleTester.run(`${ruleName}:strict`, rule, {
473497
valid: parsers.all([].concat(
474498
...alwaysValid,
499+
{ code: '<iframe onLoad={() => {}} />;' },
500+
{
501+
code: `
502+
<iframe
503+
name="embeddedExternalPayment"
504+
ref="embeddedExternalPayment"
505+
style={iframeStyle}
506+
onLoad={this.handleLoadIframe}
507+
/>
508+
`,
509+
errors: [expectedError],
510+
},
511+
{ code: '<img {...props} onError={() => {}} />;' },
512+
{ code: '<img onLoad={() => {}} />;' },
513+
{ code: '<img src={currentPhoto.imageUrl} onLoad={this.handleImageLoad} alt="for review" />' },
514+
{
515+
code: `
516+
<img
517+
ref={this.ref}
518+
className="c-responsive-image-placeholder__image"
519+
src={src}
520+
alt={alt}
521+
data-test-id="test-id"
522+
onLoad={this.fetchCompleteImage}
523+
/>
524+
`,
525+
},
475526
))
476527
.map(ruleOptionsMapperFactory(strictOptions))
477528
.map(parserOptionsMapper),

__tests__/src/rules/no-noninteractive-element-to-interactive-role-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,6 @@ ruleTester.run(`${ruleName}:recommended`, rule, {
457457
{ code: '<ol role="treegrid" />;' },
458458
{ code: '<li role="tab" />;' },
459459
{ code: '<li role="menuitem" />;' },
460-
{ code: '<li role="menuitemcheckbox" />;' },
461-
{ code: '<li role="menuitemradio" />;' },
462460
{ code: '<li role="row" />;' },
463461
{ code: '<li role="treeitem" />;' },
464462
{ code: '<Component role="treeitem" />;' },
@@ -469,6 +467,8 @@ ruleTester.run(`${ruleName}:recommended`, rule, {
469467
.map(parserOptionsMapper),
470468
invalid: parsers.all([].concat(
471469
...neverValid,
470+
{ code: '<li role="menuitemcheckbox" />;', errors: [expectedError] },
471+
{ code: '<li role="menuitemradio" />;', errors: [expectedError] },
472472
))
473473
.map(ruleOptionsMapperFactory(recommendedOptions))
474474
.map(parserOptionsMapper),

docs/rules/accessible-emoji.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
❌ This rule is deprecated.
44

5+
🚫 This rule is _disabled_ in the following configs: ☑️ `recommended`, 🔒 `strict`.
6+
57
<!-- end auto-generated rule header -->
68

79
Emoji have become a common way of communicating content to the end user. To a person using a screen reader, however, they may not be aware that this content is there at all. By wrapping the emoji in a `<span>`, giving it the `role="img"`, and providing a useful description in `aria-label`, the screen reader will treat the emoji as an image in the accessibility tree with an accessible name for the end user.

0 commit comments

Comments
 (0)