Skip to content

Commit

Permalink
Fix: fails the test case if autofix made syntax error (fixes #11615) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
mysticatea committed Jun 5, 2019
1 parent cb1922b commit 5509cdf
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 20 deletions.
34 changes: 26 additions & 8 deletions lib/rule-tester/rule-tester.js
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
};
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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.");
}
}

Expand Down
50 changes: 40 additions & 10 deletions tests/lib/rule-tester/rule-tester.js
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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);
});
});
2 changes: 1 addition & 1 deletion tests/lib/rules/complexity.js
Expand Up @@ -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 },
Expand Down
7 changes: 6 additions & 1 deletion tests/lib/rules/quotes.js
Expand Up @@ -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" }]
},

Expand Down Expand Up @@ -255,7 +260,7 @@ ruleTester.run("quotes", rule, {
code: "<div blah={'blah'} />",
output: "<div blah={`blah`} />",
options: ["backtick"],
parserOptions: { ecmaFeatures: { jsx: true } },
parserOptions: { ecmaFeatures: { jsx: true }, ecmaVersion: 2015 },
errors: [
{ message: "Strings must use backtick.", type: "Literal" }
]
Expand Down

0 comments on commit 5509cdf

Please sign in to comment.