diff --git a/lib/rules/no-mocha-arrows.js b/lib/rules/no-mocha-arrows.js index 674a884..00ca039 100644 --- a/lib/rules/no-mocha-arrows.js +++ b/lib/rules/no-mocha-arrows.js @@ -41,6 +41,38 @@ module.exports = function (context) { return !R.find(R.propEq('name', name), scope.variables); } + function fixArrowFunction(fixer, fn) { + var sourceCode = context.getSourceCode(), + paramsLeftParen = sourceCode.getFirstToken(fn), + paramsRightParen = sourceCode.getTokenBefore(sourceCode.getTokenBefore(fn.body)), + paramsFullText = + sourceCode.text.slice(paramsLeftParen.range[0], paramsRightParen.range[1]), + functionKeyword = 'function ', + bodyText; + + if (fn.async) { + // When 'async' specified, take care about the keyword. + functionKeyword = 'async function'; + // Strip 'async (...)' to ' (...)' + paramsFullText = paramsFullText.slice(5); + } + + if (fn.body.type === 'BlockStatement') { + // When it((...) => { ... }), + // simply replace '(...) => ' with 'function () ' + return fixer.replaceTextRange( + [ fn.start, fn.body.start ], + functionKeyword + paramsFullText + ' ' + ); + } + + bodyText = sourceCode.text.slice(fn.body.range[0], fn.body.range[1]); + return fixer.replaceTextRange( + [ fn.start, fn.end ], + functionKeyword + paramsFullText + ' { return ' + bodyText + '; }' + ); + } + return { CallExpression: function (node) { var name = getCalleeName(node.callee), @@ -50,7 +82,13 @@ module.exports = function (context) { fnArg = node.arguments.slice(-1)[0]; if (fnArg && fnArg.type === 'ArrowFunctionExpression') { if (isLikelyMochaGlobal(context.getScope(), name)) { - context.report(node, 'Do not pass arrow functions to ' + name + '()'); + context.report({ + node: node, + message: 'Do not pass arrow functions to ' + name + '()', + fix: function (fixer) { + return fixArrowFunction(fixer, fnArg); + } + }); } } } diff --git a/test/rules/no-mocha-arrows.js b/test/rules/no-mocha-arrows.js index c9c5919..f7a899d 100644 --- a/test/rules/no-mocha-arrows.js +++ b/test/rules/no-mocha-arrows.js @@ -2,8 +2,11 @@ var RuleTester = require('eslint').RuleTester, rules = require('../../').rules, - ruleTester = new RuleTester(), - expectedErrorMessage = 'Do not pass arrow functions to it()'; + ruleTester = new RuleTester({ + parserOptions: { ecmaVersion: 2017 } + }), + expectedErrorMessage = 'Do not pass arrow functions to it()', + errors = [ { message: expectedErrorMessage, column: 1, line: 1 } ]; ruleTester.run('no-mocha-arrows', rules['no-mocha-arrows'], { @@ -11,40 +14,65 @@ ruleTester.run('no-mocha-arrows', rules['no-mocha-arrows'], { 'it()', 'it(function() { assert(something, false); })', 'it("should be false", function() { assert(something, false); })', - { - // In this example, `it` is not a global. - code: 'function it () {}; it(() => { console.log("okay") })', - parserOptions: { ecmaVersion: 6 } - }, - 'it.only()' + // In this example, `it` is not a global. + 'function it () {}; it(() => { console.log("okay") })', + 'it.only()', + 'it(function(done) { assert(something, false); done(); })', + 'it(function*() { assert(something, false) })', + 'it(async function () { assert(something, false) })' ], invalid: [ { code: 'it(() => { assert(something, false); })', - parserOptions: { ecmaVersion: 6 }, - errors: [ { message: expectedErrorMessage, column: 1, line: 1 } ] + errors: errors, + output: 'it(function () { assert(something, false); })' }, { code: 'it(() => { assert(something, false); })', globals: [ 'it' ], - parserOptions: { ecmaVersion: 6 }, - errors: [ { message: expectedErrorMessage, column: 1, line: 1 } ] + errors: errors, + output: 'it(function () { assert(something, false); })' }, { code: 'it(() => assert(something, false))', - parserOptions: { ecmaVersion: 6 }, - errors: [ { message: expectedErrorMessage, column: 1, line: 1 } ] + errors: errors, + output: 'it(function () { return assert(something, false); })' }, { code: 'it("should be false", () => { assert(something, false); })', - parserOptions: { ecmaVersion: 6 }, - errors: [ { message: expectedErrorMessage, column: 1, line: 1 } ] + errors: errors, + output: 'it("should be false", function () { assert(something, false); })' }, { code: 'it.only(() => { assert(something, false); })', - parserOptions: { ecmaVersion: 6 }, - errors: [ { message: 'Do not pass arrow functions to it.only()', column: 1, line: 1 } ] + errors: [ { message: 'Do not pass arrow functions to it.only()', column: 1, line: 1 } ], + output: 'it.only(function () { assert(something, false); })' + }, + { + code: 'it((done) => { assert(something, false); })', + errors: errors, + output: 'it(function (done) { assert(something, false); })' + }, + { + code: 'it("should be false", () => {\n assert(something, false);\n})', + errors: errors, + output: 'it("should be false", function () {\n assert(something, false);\n})' + }, + { + code: 'it(async () => { assert(something, false) })', + errors: errors, + output: 'it(async function () { assert(something, false) })' + }, + { + code: 'it(async () => assert(something, false))', + errors: errors, + output: 'it(async function () { return assert(something, false); })' + }, + { + code: 'it(async() => assert(something, false))', + errors: errors, + output: 'it(async function() { return assert(something, false); })' } ]