Repository: lo1tuma/eslint-plugin-mocha
Pull request #236 (2020-02-18 17:00:25)

no-hooks: add option to allow certain kind of hooks
Fixes: #110
Closes: #101


Patch:
diff --git a/docs/rules/no-hooks.md b/docs/rules/no-hooks.md
index 276673d..59753a7 100644
--- a/docs/rules/no-hooks.md
+++ b/docs/rules/no-hooks.md
@@ -43,6 +43,21 @@ describe('foo', function () {
 });
 ```
 
+## Options
+
+This rule supports the following options:
+
+* `allow`: An array containing the names of hooks to allow. Defaults to an empty array.
+
+```json
+{
+    "rules": {
+        "mocha/no-hooks": ["error", {"allow": ["after"]}]
+    }
+}
+```
+
+
 ## When Not To Use It
 
 * If you use another library which exposes a similar API as mocha (e.g. `before`, `after`), you should turn this rule off, because it would raise warnings.
diff --git a/lib/rules/no-hooks.js b/lib/rules/no-hooks.js
index d3f5617..f1ee203 100644
--- a/lib/rules/no-hooks.js
+++ b/lib/rules/no-hooks.js
@@ -3,10 +3,32 @@
 const astUtil = require('../util/ast');
 
 module.exports = {
+    meta: {
+        schema: [
+            {
+                type: 'object',
+                properties: {
+                    allow: {
+                        type: 'array',
+                        items: {
+                            type: 'string'
+                        }
+                    }
+                },
+                additionalProperties: false
+            }
+        ]
+    },
+
     create(context) {
+        const [ config = {} ] = context.options;
+        const { allow = [] } = config;
+
         return {
             CallExpression(node) {
-                if (astUtil.isHookIdentifier(node.callee)) {
+                const isHookAllowed = allow.includes(node.callee.name);
+
+                if (astUtil.isHookIdentifier(node.callee) && !isHookAllowed) {
                     context.report({
                         node: node.callee,
                         message: `Unexpected use of Mocha \`${ node.callee.name }\` hook`


Test patch:
diff --git a/test/rules/no-hooks.js b/test/rules/no-hooks.js
index 9380186..12eba34 100644
--- a/test/rules/no-hooks.js
+++ b/test/rules/no-hooks.js
@@ -18,7 +18,47 @@ ruleTester.run('no-hooks', rules['no-hooks'], {
         'after.foo()',
         'beforeEach.foo()',
         'afterEach.foo()',
-        'var before = 2; before + 3;'
+        'var before = 2; before + 3;',
+        {
+            code: 'describe(function() { before(function() {}); });',
+            options: [ { allow: [ 'before' ] } ]
+        },
+        {
+            code: 'describe(function() { after(function() {}); });',
+            options: [ { allow: [ 'after' ] } ]
+        },
+        {
+            code: 'describe(function() { beforeEach(function() {}); });',
+            options: [ { allow: [ 'beforeEach' ] } ]
+        },
+        {
+            code: 'describe(function() { afterEach(function() {}); });',
+            options: [ { allow: [ 'afterEach' ] } ]
+        },
+        {
+            code: 'describe(function() { beforeAll(function() {}); });',
+            options: [ { allow: [ 'beforeAll' ] } ]
+        },
+        {
+            code: 'describe(function() { afterAll(function() {}); });',
+            options: [ { allow: [ 'afterAll' ] } ]
+        },
+        {
+            code: 'describe(function() { setup(function() {}); });',
+            options: [ { allow: [ 'setup' ] } ]
+        },
+        {
+            code: 'describe(function() { teardown(function() {}); });',
+            options: [ { allow: [ 'teardown' ] } ]
+        },
+        {
+            code: 'describe(function() { suiteSetup(function() {}); });',
+            options: [ { allow: [ 'suiteSetup' ] } ]
+        },
+        {
+            code: 'describe(function() { suiteTeardown(function() {}); });',
+            options: [ { allow: [ 'suiteTeardown' ] } ]
+        }
     ],
 
     invalid: [
@@ -41,6 +81,11 @@ ruleTester.run('no-hooks', rules['no-hooks'], {
         {
             code: 'describe(function() { describe(function() { before(function() {}); }); });',
             errors: [ { message: 'Unexpected use of Mocha `before` hook', column: 45, line: 1 } ]
+        },
+        {
+            code: 'describe(function() { after(function() {}); });',
+            options: [ { allow: [ 'before' ] } ],
+            errors: [ { message: 'Unexpected use of Mocha `after` hook', column: 23, line: 1 } ]
         }
     ]