Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: role-supports-aria-props rule (no aria-label-misuse) #362

Merged
merged 8 commits into from Jan 10, 2023
Merged

Conversation

smockle
Copy link
Contributor

@smockle smockle commented Dec 17, 2022

Fixes https://github.com/github/accessibility/issues/2427

From that issue:

If you use <span aria-label="I’m a tooltip!">Info</span> in Rails, ERBLint’s NoAriaLabelMisue rule will flag it, since aria-label is not supported on non-interactive elements like span.

If you use <span aria-label="I’m a tooltip!">Info</span> in React, ESLint doesn’t flag it.

This PR adapts the work I did in jsx-eslint/eslint-plugin-jsx-a11y#911 into a custom rule we can use until the upstream role-suports-aria-props is updated to flag <span aria-label="I’m a tooltip!">Info</span>.

@smockle smockle requested a review from a team as a code owner December 17, 2022 06:21
@smockle smockle requested a review from jfuchs December 17, 2022 06:21
@smockle smockle changed the title Feat: role-supports-aria-props rule (no aria-label-misuse) feat: role-supports-aria-props rule (no aria-label-misuse) Dec 17, 2022
@smockle smockle requested a review from khiga8 December 17, 2022 06:22
@smockle
Copy link
Contributor Author

smockle commented Dec 17, 2022

@jfuchs Tests pass locally, but it looks like CI checks are failing with Node.js 12.x, but Node.js 12.x has reached end-of-life: https://nodejs.dev/en/about/releases/. Can the Node.js 12.x CI checks be removed?

.eslintrc.js Outdated
@@ -1,7 +1,7 @@
module.exports = {
root: true,
parserOptions: {
ecmaVersion: 2020
ecmaVersion: 13
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added to support private fields (#data on ObjectMap)

@@ -0,0 +1,74 @@
# Role Supports ARIA Props
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -0,0 +1,180 @@
// @ts-check
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every method of ObjectMap has at least one test in this file.

const {getElementType} = require('../utils/get-element-type')
const ObjectMap = require('../utils/object-map')

// Clean-up `elementRoles` from `aria-query`
Copy link
Contributor Author

@smockle smockle Dec 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eslint-plugin-jsx-a11y (the upstream project) holds that, “[W]e don't want to store knowledge of WAI-ARIA in this plugin. That knowledge should be stored in aria-query.”

I think that’s a good architectural principle in general, but unnecessary for temporary code like this file. Here, I’m okay mixing WAI-ARIA knowledge with rule code. It’ll get cleaned up once this custom rule is removed (replaced by the updated upstream rule).

@@ -0,0 +1,512 @@
// @ts-check

// Tests in this file were adapted from https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/__tests__/src/rules/role-supports-aria-props-test.js, which was authored by Ethan Cohen and is distributed under the MIT license as follows:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a convention for this kind of attribution?

@@ -0,0 +1,58 @@
// @ts-check
const {isDeepStrictEqual} = require('util')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shoutout to util.isDeepStrictEqual, which I (re?)discovered while working on this.

It’s better than JSON.stringify-based object comparison because it:

  1. Supports objects which can’t be serialized (e.g. due to circular references), and
  2. Ignores key order when determining equality

@@ -54,8 +54,8 @@ For each component, you may specify a `default` and/or `props`. `default` may ma
"settings": {
"github": {
"components": {
"Box": { "default": "p" },
"Link": { "props": {"as": { "undefined": "a", "a": "a", "button": "button"}}},
"Box": {"default": "p"},
Copy link
Contributor Author

@smockle smockle Dec 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was Prettier.

// - Get the element’s name
const key = {name: getElementType(context, node)}
// - Get the element’s disambiguating attributes
for (const prop of ['aria-expanded', 'type', 'size', 'role', 'href', 'multiple', 'scope']) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally, I’d dynamically generated this list of the attributes that are necessary for disambiguating elements with multiple roles (e.g. <input type="radio"> vs <input type="checkbox">). But, given my nonchalance towards separation of concerns, the readability and performance gains, and the fact that this can’t lead to false positives, I opted for this simpler hardcoded list.

README.md Outdated Show resolved Hide resolved
@smockle smockle requested a review from khiga8 December 19, 2022 16:44
Copy link
Contributor

@khiga8 khiga8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we additionally configure this rule in: configs/react.js? This will ensure that the rule is enabled by default for those using this plugin's react preset.

This otherwise looks good to me! Deferring to @github/web-systems-reviewers for final approval.

Comment on lines 504 to 509
code: '<div aria-label />',
errors: [getErrorMessage('aria-label', 'generic')]
},
{
code: '<div aria-labelledby />',
errors: [getErrorMessage('aria-labelledby', 'generic')]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

@smockle
Copy link
Contributor Author

smockle commented Dec 19, 2022

From @khiga8 in #362 (review):

Could we additionally configure this rule in: configs/react.js? This will ensure that the rule is enabled by default for those using this plugin's react preset.

Good point! Done in e2d8376.

I chose 'error', since that’s what we used previously, via jsx-a11y’s recommended set: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/4abc751d87a8491219a9a3d2dacd80ea8adcb79b/src/index.js#L196

@theinterned
Copy link
Contributor

@jfuchs Tests pass locally, but it looks like CI checks are failing with Node.js 12.x, but Node.js 12.x has reached end-of-life: https://nodejs.dev/en/about/releases/. Can the Node.js 12.x CI checks be removed?

@smockle I just saw this comment! Lo and behold, I also just opened this PR #369

@smockle
Copy link
Contributor Author

smockle commented Jan 3, 2023

@jfuchs Tests pass locally, but it looks like CI checks are failing with Node.js 12.x, but Node.js 12.x has reached end-of-life: https://nodejs.dev/en/about/releases/. Can the Node.js 12.x CI checks be removed?

@smockle I just saw this comment! Lo and behold, I also just opened this PR #369

Awesome, thanks @theinterned! I’ll wait for #369 to be merged, then rebase here.

@smockle
Copy link
Contributor Author

smockle commented Jan 10, 2023

…I’ll wait for #369 to be merged, then rebase here.

#380 (which supersedes #369) was merged; rebasing this PR now!

@jfuchs
Copy link
Contributor

jfuchs commented Jan 10, 2023

The prettier config update serial commas, sorry. eslint . --fix should get your branch right!

@smockle
Copy link
Contributor Author

smockle commented Jan 10, 2023

@jfuchs Thanks! I added the missing serial commas in cd0a526. Now CI is green and there are 2 approvals; is anything else required before I merge this?

Copy link
Contributor

@jfuchs jfuchs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jfuchs Thanks! I added the missing serial commas in cd0a526. Now CI is green and there are 2 approvals; is anything else required before I merge this?

Nope, but here's an approval for good measure!

@smockle smockle merged commit cc51b62 into main Jan 10, 2023
@smockle smockle deleted the smockle/wip branch January 10, 2023 20:36
renovate bot added a commit to WtfJoke/setup-tectonic that referenced this pull request Mar 1, 2023
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[eslint-plugin-github](https://togithub.com/github/eslint-plugin-github)
| [`4.6.0` ->
`4.6.1`](https://renovatebot.com/diffs/npm/eslint-plugin-github/4.6.0/4.6.1)
|
[![age](https://badges.renovateapi.com/packages/npm/eslint-plugin-github/4.6.1/age-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://badges.renovateapi.com/packages/npm/eslint-plugin-github/4.6.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://badges.renovateapi.com/packages/npm/eslint-plugin-github/4.6.1/compatibility-slim/4.6.0)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://badges.renovateapi.com/packages/npm/eslint-plugin-github/4.6.1/confidence-slim/4.6.0)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>github/eslint-plugin-github</summary>

###
[`v4.6.1`](https://togithub.com/github/eslint-plugin-github/releases/tag/v4.6.1)

[Compare
Source](https://togithub.com/github/eslint-plugin-github/compare/v4.6.0...v4.6.1)

#### What's Changed

- Update events handled by `no-useless-passive` and
`require-passive-events` by
[@&#8203;boris-petrov](https://togithub.com/boris-petrov) in
[github/eslint-plugin-github#354
- feat: `role-supports-aria-props` rule (no `aria-label`-misuse) by
[@&#8203;smockle](https://togithub.com/smockle) in
[github/eslint-plugin-github#362
-   Updated dependencies

#### New Contributors

- [@&#8203;boris-petrov](https://togithub.com/boris-petrov) made their
first contribution in
[github/eslint-plugin-github#354
- [@&#8203;smockle](https://togithub.com/smockle) made their first
contribution in
[github/eslint-plugin-github#362

**Full Changelog**:
github/eslint-plugin-github@v4.6.0...v4.6.1

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "monthly" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://app.renovatebot.com/dashboard#github/WtfJoke/setup-tectonic).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNC4xNTMuMiIsInVwZGF0ZWRJblZlciI6IjM0LjE1My4yIn0=-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants