From c5ba6166d808b4b64a22e0108e3a3c868ee9c38f Mon Sep 17 00:00:00 2001 From: Mathieu Suen Date: Tue, 24 Oct 2023 17:21:55 +0200 Subject: [PATCH] [NO JIRA] Add eslint rule to prevent within and refactor test --- server/sonar-web/.eslintrc | 3 +- server/sonar-web/.eslintrc-ci | 3 +- .../eslint-local-rules/__tests__/no-within.js | 56 +++++++++++++++++++ server/sonar-web/eslint-local-rules/index.js | 1 + .../sonar-web/eslint-local-rules/no-within.js | 44 +++++++++++++++ 5 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 server/sonar-web/eslint-local-rules/__tests__/no-within.js create mode 100644 server/sonar-web/eslint-local-rules/no-within.js diff --git a/server/sonar-web/.eslintrc b/server/sonar-web/.eslintrc index dd5618dbdf2..9cffb33b0da 100644 --- a/server/sonar-web/.eslintrc +++ b/server/sonar-web/.eslintrc @@ -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" } } diff --git a/server/sonar-web/.eslintrc-ci b/server/sonar-web/.eslintrc-ci index 3cdb61e0e2d..092580051a8 100644 --- a/server/sonar-web/.eslintrc-ci +++ b/server/sonar-web/.eslintrc-ci @@ -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 index 00000000000..35a4698bad5 --- /dev/null +++ b/server/sonar-web/eslint-local-rules/__tests__/no-within.js @@ -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' }], + }, + ], +}); diff --git a/server/sonar-web/eslint-local-rules/index.js b/server/sonar-web/eslint-local-rules/index.js index aecf29ef9c1..340594a1064 100644 --- a/server/sonar-web/eslint-local-rules/index.js +++ b/server/sonar-web/eslint-local-rules/index.js @@ -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 index 00000000000..6823f320fdc --- /dev/null +++ b/server/sonar-web/eslint-local-rules/no-within.js @@ -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', + }); + } + } + } + } + }, + }; + }, +}; -- 2.39.5