Repository: lo1tuma/eslint-plugin-mocha
Pull request #237 (2020-02-18 17:58:48)

Check static template strings in valid-test-description and valid-suite-description
Fixes: #139

Using [`getStringIfConstant()`] from [`eslint-utils`](https://eslint-utils.mysticatea.dev/api/ast-utils.html#getstringifconstant) this should now also support things like computed strings e.g. `it('should' + 'work', () => {});`.


Patch:
diff --git a/lib/rules/valid-suite-description.js b/lib/rules/valid-suite-description.js
index 0010f5a..09987fc 100644
--- a/lib/rules/valid-suite-description.js
+++ b/lib/rules/valid-suite-description.js
@@ -1,11 +1,12 @@
 'use strict';
 
+const { getStringIfConstant } = require('eslint-utils');
+
 /**
  * @fileoverview Match suite descriptions to match a pre-configured regular expression
  * @author Alexander Afanasyev
  */
 
-const astUtils = require('../util/ast');
 const defaultSuiteNames = [ 'describe', 'context', 'suite' ];
 
 function inlineOptions(options) {
@@ -76,10 +77,11 @@ module.exports = {
 
         function hasValidSuiteDescription(mochaCallExpression) {
             const args = mochaCallExpression.arguments;
-            const description = args[0];
+            const descriptionArgument = args[0];
+            const description = getStringIfConstant(descriptionArgument, context.getScope());
 
-            if (astUtils.isStringLiteral(description)) {
-                return pattern.test(description.value);
+            if (description) {
+                return pattern.test(description);
             }
 
             return true;
diff --git a/lib/util/ast.js b/lib/util/ast.js
index 7482e4b..85db2c1 100644
--- a/lib/util/ast.js
+++ b/lib/util/ast.js
@@ -100,10 +100,6 @@ function isMochaFunctionCall(node, scope) {
     return isTestCase(node) || isDescribe(node) || isHookCall(node);
 }
 
-function isStringLiteral(node) {
-    return node && node.type === 'Literal' && typeof node.value === 'string';
-}
-
 function hasParentMochaFunctionCall(functionExpression) {
     return isTestCase(functionExpression.parent) || isHookCall(functionExpression.parent);
 }
@@ -130,7 +126,6 @@ module.exports = {
     isMochaFunctionCall,
     isHookCall,
     isSuiteConfigCall,
-    isStringLiteral,
     hasParentMochaFunctionCall,
     findReturnStatement,
     isReturnOfUndefined
diff --git a/package-lock.json b/package-lock.json
index 329d33d..1885004 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -729,7 +729,6 @@
                 "debug": "^4.0.1",
                 "doctrine": "^3.0.0",
                 "eslint-scope": "^5.0.0",
-                "eslint-utils": "^1.4.3",
                 "eslint-visitor-keys": "^1.1.0",
                 "espree": "^6.1.2",
                 "esquery": "^1.0.1",
@@ -781,6 +780,15 @@
                 "regexpp": "^3.0.0"
             },
             "dependencies": {
+                "eslint-utils": {
+                    "version": "1.4.3",
+                    "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+                    "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
+                    "dev": true,
+                    "requires": {
+                        "eslint-visitor-keys": "^1.1.0"
+                    }
+                },
                 "regexpp": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz",
@@ -803,6 +811,15 @@
                 "semver": "^6.1.0"
             },
             "dependencies": {
+                "eslint-utils": {
+                    "version": "1.4.3",
+                    "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+                    "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
+                    "dev": true,
+                    "requires": {
+                        "eslint-visitor-keys": "^1.1.0"
+                    }
+                },
                 "ignore": {
                     "version": "5.1.4",
                     "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz",
@@ -822,10 +839,9 @@
             }
         },
         "eslint-utils": {
-            "version": "1.4.3",
-            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
-            "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
-            "dev": true,
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz",
+            "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==",
             "requires": {
                 "eslint-visitor-keys": "^1.1.0"
             }
@@ -833,8 +849,7 @@
         "eslint-visitor-keys": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
-            "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
-            "dev": true
+            "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A=="
         },
         "espree": {
             "version": "6.1.2",
diff --git a/package.json b/package.json
index 2105037..e012ed2 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
         "changelog": "pr-log"
     },
     "dependencies": {
+        "eslint-utils": "^2.0.0",
         "ramda": "^0.26.1"
     },
     "devDependencies": {


Test patch:
diff --git a/lib/rules/valid-test-description.js b/lib/rules/valid-test-description.js
index 07b2f58..a44532c 100644
--- a/lib/rules/valid-test-description.js
+++ b/lib/rules/valid-test-description.js
@@ -1,12 +1,12 @@
 'use strict';
 
+const { getStringIfConstant } = require('eslint-utils');
+
 /**
  * @fileoverview Match test descriptions to match a pre-configured regular expression
  * @author Alexander Afanasyev
  */
 
-const astUtils = require('../util/ast');
-
 const defaultTestNames = [ 'it', 'test', 'specify' ];
 
 function inlineOptions(options) {
@@ -77,9 +77,10 @@ module.exports = {
         function hasValidTestDescription(mochaCallExpression) {
             const args = mochaCallExpression.arguments;
             const testDescriptionArgument = args[0];
+            const description = getStringIfConstant(testDescriptionArgument, context.getScope());
 
-            if (astUtils.isStringLiteral(testDescriptionArgument)) {
-                return pattern.test(testDescriptionArgument.value);
+            if (description) {
+                return pattern.test(description);
             }
 
             return true;
diff --git a/test/rules/valid-suite-description.js b/test/rules/valid-suite-description.js
index 5e4976f..da76bc6 100644
--- a/test/rules/valid-suite-description.js
+++ b/test/rules/valid-suite-description.js
@@ -43,6 +43,16 @@ ruleTester.run('valid-suite-description', rules['valid-suite-description'], {
             parserOptions: { ecmaVersion: 2017 },
             options: [ '^Foo' ],
             code: 'describe(`Foo with template strings`, function () {});'
+        },
+        {
+            parserOptions: { ecmaVersion: 2019 },
+            options: [ '^Foo' ],
+            code: 'describe(anyTag`with template strings`, function () {});'
+        },
+        {
+            parserOptions: { ecmaVersion: 2019 },
+            options: [ '^Foo' ],
+            code: 'describe(`${dynamicVar} with template strings`, function () {});'
         }
 
     ],
@@ -89,6 +99,26 @@ ruleTester.run('valid-suite-description', rules['valid-suite-description'], {
             errors: [
                 { message: 'some error message' }
             ]
+        },
+        {
+            options: [ '^[A-Z]' ],
+            code: 'describe(`this is a test`, function () { });',
+            parserOptions: {
+                ecmaVersion: 2019
+            },
+            errors: [
+                { message: 'Invalid "describe()" description found.', line: 1, column: 1 }
+            ]
+        },
+        {
+            options: [ '^[A-Z]' ],
+            code: 'const foo = "this"; describe(`${foo} is a test`, function () { });',
+            parserOptions: {
+                ecmaVersion: 2019
+            },
+            errors: [
+                { message: 'Invalid "describe()" description found.', line: 1, column: 21 }
+            ]
         }
     ]
 });
diff --git a/test/rules/valid-test-description.js b/test/rules/valid-test-description.js
index 52c651f..39a29e5 100644
--- a/test/rules/valid-test-description.js
+++ b/test/rules/valid-test-description.js
@@ -43,6 +43,14 @@ ruleTester.run('valid-test-description', rules['valid-test-description'], {
         {
             parserOptions: { ecmaVersion: 2017 },
             code: 'it(`should work with template strings`, function () {});'
+        },
+        {
+            parserOptions: { ecmaVersion: 2019 },
+            code: 'it(foo`work with template strings`, function () {});'
+        },
+        {
+            parserOptions: { ecmaVersion: 2019 },
+            code: 'it(`${foo} work with template strings`, function () {});'
         }
     ],
 
@@ -113,6 +121,24 @@ ruleTester.run('valid-test-description', rules['valid-test-description'], {
             errors: [
                 { message: 'Invalid "it()" description found.' }
             ]
+        },
+        {
+            code: 'it(`this is a test`, function () { });',
+            parserOptions: {
+                ecmaVersion: 2019
+            },
+            errors: [
+                { message: 'Invalid "it()" description found.', line: 1, column: 1 }
+            ]
+        },
+        {
+            code: 'const foo = "this"; it(`${foo} is a test`, function () { });',
+            parserOptions: {
+                ecmaVersion: 2019
+            },
+            errors: [
+                { message: 'Invalid "it()" description found.', line: 1, column: 21 }
+            ]
         }
     ]
 });