From c5fe17d72ae42a06a5fa15f0ccb2a73507c414f8 Mon Sep 17 00:00:00 2001 From: yassin-kammoun-sonarsource Date: Fri, 10 Nov 2023 09:22:23 +0100 Subject: [PATCH] Create rule S6843 (`jsx-a11y/no-interactive-element-to-noninteractive-role`): Interactive DOM elements should not have non-interactive ARIA roles --- .../jsts/file-for-rules/javascript-S139.json | 3 ++ .../jsts/file-for-rules/javascript-S1451.json | 3 ++ .../jsts/file-for-rules/javascript-S3798.json | 3 ++ .../jsts/file-for-rules/javascript-S6819.json | 3 ++ .../jsts/file-for-rules/javascript-S6843.json | 5 +++ its/sources/jsts/custom/S6843.js | 3 ++ .../sonar/javascript/checks/CheckList.java | 1 + ...ctiveElementToNoninteractiveRoleCheck.java | 36 +++++++++++++++++ .../javascript/rules/javascript/S6843.html | 39 +++++++++++++++++++ .../javascript/rules/javascript/S6843.json | 29 ++++++++++++++ .../rules/javascript/Sonar_way_profile.json | 3 +- 11 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6843.json create mode 100644 its/sources/jsts/custom/S6843.js create mode 100644 sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/NoInteractiveElementToNoninteractiveRoleCheck.java create mode 100644 sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6843.html create mode 100644 sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6843.json diff --git a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S139.json b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S139.json index 107bf0dfbd..47e33df728 100644 --- a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S139.json +++ b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S139.json @@ -70,5 +70,8 @@ ], "file-for-rules:S6789.js": [ 7 +], +"file-for-rules:S6843.js": [ +2 ] } diff --git a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S1451.json b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S1451.json index ad483d2445..ea89a44c7f 100644 --- a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S1451.json +++ b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S1451.json @@ -192,6 +192,9 @@ 0 ], "file-for-rules:S6840.js": [ + 0 +], +"file-for-rules:S6843.js": [ 0 ], "file-for-rules:boundOrAssignedEvalOrArguments.js": [ diff --git a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S3798.json b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S3798.json index 39cffa67f7..7551f33004 100644 --- a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S3798.json +++ b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S3798.json @@ -66,6 +66,9 @@ 2 ], "file-for-rules:S6840.js": [ + 1 +], +"file-for-rules:S6843.js": [ 1 ], "file-for-rules:boundOrAssignedEvalOrArguments.js": [ diff --git a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6819.json b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6819.json index 4edb0ae816..1e34f32d35 100644 --- a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6819.json +++ b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6819.json @@ -1,5 +1,8 @@ { "file-for-rules:S6807.js": [ 4 +], +"file-for-rules:S6843.js": [ +2 ] } diff --git a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6843.json b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6843.json new file mode 100644 index 0000000000..192932ab59 --- /dev/null +++ b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6843.json @@ -0,0 +1,5 @@ +{ +"file-for-rules:S6843.js": [ +2 +] +} diff --git a/its/sources/jsts/custom/S6843.js b/its/sources/jsts/custom/S6843.js new file mode 100644 index 0000000000..deb81dd0d6 --- /dev/null +++ b/its/sources/jsts/custom/S6843.js @@ -0,0 +1,3 @@ +function myButton() { + return ; // Noncompliant; "button" is interactive, but "article" isn't +} diff --git a/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java index 3ff7b9edf0..ebc4d2d81e 100644 --- a/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java +++ b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java @@ -275,6 +275,7 @@ public static List> getAllChecks() { NoInMisuseCheck.class, NoIncompleteAssertionsCheck.class, NoInferrableTypesCheck.class, + NoInteractiveElementToNoninteractiveRoleCheck.class, NoInvalidAwaitCheck.class, NoInvertedBooleanCheckCheck.class, NoIsMountedCheck.class, diff --git a/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/NoInteractiveElementToNoninteractiveRoleCheck.java b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/NoInteractiveElementToNoninteractiveRoleCheck.java new file mode 100644 index 0000000000..b9b9f1ba27 --- /dev/null +++ b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/NoInteractiveElementToNoninteractiveRoleCheck.java @@ -0,0 +1,36 @@ +/** + * SonarQube JavaScript Plugin + * Copyright (C) 2011-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.javascript.checks; + +import org.sonar.check.Rule; +import org.sonar.plugins.javascript.api.EslintBasedCheck; +import org.sonar.plugins.javascript.api.JavaScriptRule; +import org.sonar.plugins.javascript.api.TypeScriptRule; + +@JavaScriptRule +@TypeScriptRule +@Rule(key = "S6843") +public class NoInteractiveElementToNoninteractiveRoleCheck implements EslintBasedCheck { + + @Override + public String eslintKey() { + return "no-interactive-element-to-noninteractive-role"; + } +} diff --git a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6843.html b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6843.html new file mode 100644 index 0000000000..423b86c95c --- /dev/null +++ b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6843.html @@ -0,0 +1,39 @@ +

Why is this an issue?

+

Interactive DOM elements are elements that users can interact with. These include buttons, links, form inputs, and other elements that can be +clicked, focused, or otherwise manipulated by the user. ARIA roles, on the other hand, are used to improve accessibility by providing additional +semantic information about an element’s purpose and behavior. ARIA roles can be divided into two categories: interactive roles and non-interactive +roles.

+

Interactive ARIA roles are used for elements that a user can interact with, such as buttons or sliders. Non-interactive ARIA roles are used for +elements that are not meant to be interacted with, such as content containers or landmarks. Examples of non-interactive ARIA roles include +article, banner, complementary, contentinfo, definition, directory, +document, feed, figure, group, heading, img, list, +listitem, math, none, note, presentation, region, +separator, status, term, and tooltip.

+

Interactive DOM elements should not have non-interactive ARIA roles because it can confuse assistive technologies and their users. For example, if +a button (an interactive element) is given a non-interactive ARIA role like article, it can mislead users into thinking that the button +is just a piece of content, not something they can interact with. This can lead to a poor user experience, especially for users who rely on assistive +technologies to navigate the web.

+

Therefore, it’s important to ensure that interactive DOM elements are not given non-interactive ARIA roles.

+

How to fix it

+

Ensure that interactive DOM elements are not given non-interactive ARIA roles.

+

Code examples

+

Noncompliant code example

+
+function myButton() {
+    return <button role="article">Click me!</button>; // Noncompliant; "button" is interactive, but "article" isn't
+}
+
+

Compliant solution

+
+function myButton() {
+    return <button role="button">Click me!</button>;
+}
+
+

Resources

+

Documentation

+ + diff --git a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6843.json b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6843.json new file mode 100644 index 0000000000..ea417b8ab0 --- /dev/null +++ b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6843.json @@ -0,0 +1,29 @@ +{ + "title": "Interactive DOM elements should not have non-interactive ARIA roles", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "accessibility", + "react" + ], + "defaultSeverity": "Major", + "ruleSpecification": "RSPEC-6843", + "sqKey": "S6843", + "scope": "All", + "quickfix": "infeasible", + "code": { + "impacts": { + "MAINTAINABILITY": "LOW", + "RELIABILITY": "MEDIUM" + }, + "attribute": "CONVENTIONAL" + }, + "compatibleLanguages": [ + "JAVASCRIPT", + "TYPESCRIPT" + ] +} diff --git a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json index c4f3470b19..eadc549bd4 100644 --- a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json +++ b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json @@ -309,6 +309,7 @@ "S6836", "S6840", "S6841", - "S6842" + "S6842", + "S6843" ] }