diff --git a/lib/rule-tester/rule-tester.js b/lib/rule-tester/rule-tester.js index 671de56064c..30445076a91 100644 --- a/lib/rule-tester/rule-tester.js +++ b/lib/rule-tester/rule-tester.js @@ -313,7 +313,7 @@ class RuleTester { */ function runRuleForItem(item) { let config = lodash.cloneDeep(testerConfig), - code, filename, beforeAST, afterAST; + code, filename, output, beforeAST, afterAST; if (typeof item === "string") { code = item; @@ -396,8 +396,29 @@ class RuleTester { validate(config, "rule-tester", id => (id === ruleName ? rule : null)); + // Verify the code. + const messages = linter.verify(code, config, filename); + + // Ignore syntax errors for backward compatibility if `errors` is a number. + if (typeof item.errors !== "number") { + const errorMessage = messages.find(m => m.fatal); + + assert(!errorMessage, `A fatal parsing error occurred: ${errorMessage && errorMessage.message}`); + } + + // Verify if autofix makes a syntax error or not. + if (messages.some(m => m.fix)) { + output = SourceCodeFixer.applyFixes(code, messages).output; + const errorMessageInFix = linter.verify(output, config, filename).find(m => m.fatal); + + assert(!errorMessageInFix, `A fatal parsing error occurred in autofix: ${errorMessageInFix && errorMessageInFix.message}`); + } else { + output = code; + } + return { - messages: linter.verify(code, config, filename, true), + messages, + output, beforeAST, afterAST: cloneDeeplyExcludesParent(afterAST) }; @@ -488,7 +509,6 @@ class RuleTester { const error = item.errors[i]; const message = messages[i]; - assert(!message.fatal, `A fatal parsing error occurred: ${message.message}`); assert(hasMessageOfThisRule, "Error rule name should be the same as the name of the rule being tested"); if (typeof error === "string" || error instanceof RegExp) { @@ -574,14 +594,12 @@ class RuleTester { if (Object.prototype.hasOwnProperty.call(item, "output")) { if (item.output === null) { assert.strictEqual( - messages.filter(message => message.fix).length, - 0, + result.output, + item.code, "Expected no autofixes to be suggested" ); } else { - const fixResult = SourceCodeFixer.applyFixes(item.code, messages); - - assert.strictEqual(fixResult.output, item.output, "Output is incorrect."); + assert.strictEqual(result.output, item.output, "Output is incorrect."); } } diff --git a/tests/lib/rule-tester/rule-tester.js b/tests/lib/rule-tester/rule-tester.js index 555d9786b1e..56e7ba65830 100644 --- a/tests/lib/rule-tester/rule-tester.js +++ b/tests/lib/rule-tester/rule-tester.js @@ -42,22 +42,28 @@ const NODE_ASSERT_STRICT_EQUAL_OPERATOR = (() => { const ruleTesterTestEmitter = new EventEmitter(); -RuleTester.describe = function(text, method) { - ruleTesterTestEmitter.emit("describe", text, method); - return method.call(this); -}; - -RuleTester.it = function(text, method) { - ruleTesterTestEmitter.emit("it", text, method); - return method.call(this); -}; - //------------------------------------------------------------------------------ // Tests //------------------------------------------------------------------------------ describe("RuleTester", () => { + // Stub `describe()` and `it()` while this test suite. + before(() => { + RuleTester.describe = function(text, method) { + ruleTesterTestEmitter.emit("describe", text, method); + return method.call(this); + }; + RuleTester.it = function(text, method) { + ruleTesterTestEmitter.emit("it", text, method); + return method.call(this); + }; + }); + after(() => { + RuleTester.describe = null; + RuleTester.it = null; + }); + let ruleTester; /** @@ -1042,4 +1048,28 @@ describe("RuleTester", () => { return assertion; }); }); + + // https://github.com/eslint/eslint/issues/11615 + it("should fail the case if autofix made a syntax error.", () => { + assert.throw(() => { + ruleTester.run( + "foo", + context => ({ + Identifier(node) { + context.report({ + node, + message: "make a syntax error", + fix(fixer) { + return fixer.replaceText(node, "one two"); + } + }); + } + }), + { + valid: ["one()"], + invalid: [] + } + ); + }, /A fatal parsing error occurred in autofix/u); + }); }); diff --git a/tests/lib/rules/complexity.js b/tests/lib/rules/complexity.js index 7196f710c46..b49ccfc5077 100644 --- a/tests/lib/rules/complexity.js +++ b/tests/lib/rules/complexity.js @@ -81,7 +81,7 @@ ruleTester.run("complexity", rule, { { code: "var func = function () {}", options: [0], errors: [makeError("Function", 1, 0)] }, { code: "var obj = { a(x) {} }", options: [0], parserOptions: { ecmaVersion: 6 }, errors: [makeError("Method 'a'", 1, 0)] }, { code: "class Test { a(x) {} }", options: [0], parserOptions: { ecmaVersion: 6 }, errors: [makeError("Method 'a'", 1, 0)] }, - { code: "var a = (x) => {if (true) {return x;}}", options: [1], errors: 1, settings: { ecmascript: 6 } }, + { code: "var a = (x) => {if (true) {return x;}}", options: [1], parserOptions: { ecmaVersion: 6 }, errors: 1 }, { code: "function a(x) {if (true) {return x;}}", options: [1], errors: 1 }, { code: "function a(x) {if (true) {return x;} else {return x+1;}}", options: [1], errors: 1 }, { code: "function a(x) {if (true) {return x;} else if (false) {return x+1;} else {return 4;}}", options: [2], errors: 1 }, diff --git a/tests/lib/rules/quotes.js b/tests/lib/rules/quotes.js index 113d8d68f0a..3245c745476 100644 --- a/tests/lib/rules/quotes.js +++ b/tests/lib/rules/quotes.js @@ -160,30 +160,35 @@ ruleTester.run("quotes", rule, { code: "var foo = 'bar';", output: "var foo = `bar`;", options: ["backtick"], + parserOptions: { ecmaVersion: 2015 }, errors: [{ message: "Strings must use backtick.", type: "Literal" }] }, { code: "var foo = 'b${x}a$r';", output: "var foo = `b\\${x}a$r`;", options: ["backtick"], + parserOptions: { ecmaVersion: 2015 }, errors: [{ message: "Strings must use backtick.", type: "Literal" }] }, { code: "var foo = \"bar\";", output: "var foo = `bar`;", options: ["backtick"], + parserOptions: { ecmaVersion: 2015 }, errors: [{ message: "Strings must use backtick.", type: "Literal" }] }, { code: "var foo = \"bar\";", output: "var foo = `bar`;", options: ["backtick", { avoidEscape: true }], + parserOptions: { ecmaVersion: 2015 }, errors: [{ message: "Strings must use backtick.", type: "Literal" }] }, { code: "var foo = 'bar';", output: "var foo = `bar`;", options: ["backtick", { avoidEscape: true }], + parserOptions: { ecmaVersion: 2015 }, errors: [{ message: "Strings must use backtick.", type: "Literal" }] }, @@ -255,7 +260,7 @@ ruleTester.run("quotes", rule, { code: "
", output: "
", options: ["backtick"], - parserOptions: { ecmaFeatures: { jsx: true } }, + parserOptions: { ecmaFeatures: { jsx: true }, ecmaVersion: 2015 }, errors: [ { message: "Strings must use backtick.", type: "Literal" } ]