]> source.dussan.org Git - sonarqube.git/commitdiff
[NO JIRA] Add eslint rule to prevent within and refactor test
authorMathieu Suen <mathieu.suen@sonarsource.com>
Tue, 24 Oct 2023 15:21:55 +0000 (17:21 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 27 Oct 2023 20:03:00 +0000 (20:03 +0000)
server/sonar-web/.eslintrc
server/sonar-web/.eslintrc-ci
server/sonar-web/eslint-local-rules/__tests__/no-within.js [new file with mode: 0644]
server/sonar-web/eslint-local-rules/index.js
server/sonar-web/eslint-local-rules/no-within.js [new file with mode: 0644]

index dd5618dbdf266dcea4e3d4ee14188fb526c94b2b..9cffb33b0dae3fbe9345c752a4619e1525f2e8f8 100644 (file)
@@ -17,6 +17,7 @@
     "local-rules/use-jest-mocked": "warn",
     "local-rules/use-await-expect-async-matcher": "warn",
     "local-rules/no-implicit-coercion": "warn",
-    "local-rules/no-api-imports": "warn"
+    "local-rules/no-api-imports": "warn",
+    "local-rules/no-within": "warn"
   }
 }
index 3cdb61e0e2d247163d7745ede4c67efe6550bd06..092580051a80ebc4183758b08b18bdb5d2cf363c 100644 (file)
@@ -1,6 +1,7 @@
 {
   "extends": ".eslintrc",
   "rules": {
-    "local-rules/no-api-imports": "off"
+    "local-rules/no-api-imports": "off",
+    "local-rules/no-within": "off"
   }
 }
diff --git a/server/sonar-web/eslint-local-rules/__tests__/no-within.js b/server/sonar-web/eslint-local-rules/__tests__/no-within.js
new file mode 100644 (file)
index 0000000..35a4698
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-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.
+ */
+const { RuleTester } = require('eslint');
+const noWithin = require('../no-within');
+
+const ruleTester = new RuleTester({
+  parserOptions: {
+    ecmaFeatures: {
+      jsx: true,
+    },
+  },
+  parser: require.resolve('@typescript-eslint/parser'),
+});
+
+ruleTester.run('no-within', noWithin, {
+  valid: [
+    {
+      code: `
+      import {within} from '@testing-library/react';
+      test();
+      `,
+    },
+    {
+      code: `
+        within();
+      `,
+    },
+  ],
+  invalid: [
+    {
+      code: `
+      import {within} from '@testing-library/react';
+
+      within();
+      `,
+      errors: [{ messageId: 'noWithin' }],
+    },
+  ],
+});
index aecf29ef9c106963cb13b5e53fa8b4f1763367f2..340594a1064358697c911fc29ad284012d178c42 100644 (file)
@@ -28,4 +28,5 @@ module.exports = {
   'use-await-expect-async-matcher': require('./use-await-expect-async-matcher'),
   'no-implicit-coercion': require('./no-implicit-coercion'),
   'no-api-imports': require('./no-api-imports'),
+  'no-within': require('./no-within'),
 };
diff --git a/server/sonar-web/eslint-local-rules/no-within.js b/server/sonar-web/eslint-local-rules/no-within.js
new file mode 100644 (file)
index 0000000..6823f32
--- /dev/null
@@ -0,0 +1,44 @@
+// For now lets enable it on this extension
+// once we have made the refactoring we can add it to sonar-web and all other extension.
+module.exports = {
+  meta: {
+    type: 'problem',
+    docs: {
+      description: 'Prevent unsing within from testing library',
+      category: 'Best Practices',
+    },
+    messages: {
+      noWithin: "Don't use within as it may hide DOM update. Prefer using chain selector.",
+    },
+  },
+  // eslint-disable-next-line object-shorthand
+  create: function (context) {
+    const fnNames = [];
+    const currentFilePath = context.getFilename();
+    const sourceCode = context.sourceCode;
+    return {
+      // eslint-disable-next-line object-shorthand
+      CallExpression: function (node) {
+        if (node.callee.name === 'within') {
+          let scope = sourceCode.getScope(node);
+          while (node.callee.name && scope && scope.set.get(node.callee.name) === undefined) {
+            scope = scope.upper;
+          }
+
+          if (node.callee.name && scope) {
+            let variable = scope.set.get(node.callee.name);
+            if (variable.defs[0] && variable.defs[0].parent.source) {
+              const importPath = variable.defs[0].parent.source.value;
+              if (importPath.startsWith('@testing-library')) {
+                context.report({
+                  node: node.callee,
+                  messageId: 'noWithin',
+                });
+              }
+            }
+          }
+        }
+      },
+    };
+  },
+};