eslint-plugin-chai-friendly
Advanced tools
Comparing version 0.3.6 to 0.4.0
@@ -29,2 +29,5 @@ /** | ||
type: "boolean" | ||
}, | ||
allowTaggedTemplates: { | ||
type: "boolean" | ||
} | ||
@@ -39,4 +42,6 @@ }, | ||
allowShortCircuit = config.allowShortCircuit || false, | ||
allowTernary = config.allowTernary || false; | ||
allowTernary = config.allowTernary || false, | ||
allowTaggedTemplates = config.allowTaggedTemplates || false; | ||
/** | ||
@@ -106,2 +111,6 @@ * @param {ASTNode} node - any node | ||
if (allowTaggedTemplates && node.type === "TaggedTemplateExpression") { | ||
return true; | ||
} | ||
return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/.test(node.type) || | ||
@@ -117,3 +126,3 @@ (node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0); | ||
*/ | ||
function isChaiExpectation(node) { | ||
function isChaiExpectCall(node) { | ||
var expression = node.expression; | ||
@@ -152,6 +161,50 @@ if (expression.type !== 'MemberExpression') { | ||
/** | ||
* Determines whether or not a given node is a chai's should statement. | ||
* e.g. foo.should.eventually.be.true; | ||
* @param {ASTNode} node - any node | ||
* @returns {boolean} whether the given node is a chai should statement | ||
*/ | ||
function isChaiShouldCall(node) { | ||
var expression = node.expression; | ||
if (expression.type !== 'MemberExpression') { | ||
return false; | ||
} | ||
var hasShouldCall = Boolean(findShouldCall(expression.object)); | ||
return hasShouldCall; | ||
} | ||
/** | ||
* Searches for the chai obj.should call down the AST. | ||
* @param {ASTNode} node - any node | ||
* @returns {ASTNode} obj.should call expression or null | ||
*/ | ||
function findShouldCall(node) { | ||
// Found obj.should call, return the node | ||
if (node.type === 'MemberExpression' && node.property && node.property.name === 'should') { | ||
return node; | ||
} | ||
// Continue search up the AST if it's a member call | ||
if (node.type === 'MemberExpression') { | ||
return findShouldCall(node.object); | ||
} | ||
if (node.type === 'CallExpression') { | ||
return findShouldCall(node.callee); | ||
} | ||
// Stop search, obj.should not found | ||
return null; | ||
}; | ||
return { | ||
ExpressionStatement: function(node) { | ||
if (!isValidExpression(node.expression) && !isDirective(node, context.getAncestors()) && !isChaiExpectation(node)) { | ||
var valid = isValidExpression(node.expression) | ||
|| isDirective(node, context.getAncestors()) | ||
|| isChaiExpectCall(node) | ||
|| isChaiShouldCall(node); | ||
if (!valid) { | ||
context.report(node, "Expected an assignment or function call and instead saw an expression."); | ||
@@ -158,0 +211,0 @@ } |
{ | ||
"name": "eslint-plugin-chai-friendly", | ||
"version": "0.3.6", | ||
"version": "0.4.0", | ||
"description": "This plugin makes 'no-unused-expressions' rule friendly towards chai expect statements.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
# eslint-plugin-chai-friendly | ||
This plugin overrides `no-unused-expressions` to make it friendly towards chai expect statements. | ||
This plugin overrides `no-unused-expressions` to make it friendly towards chai `expect` and `should` statements. | ||
@@ -8,5 +8,7 @@ ```javascript | ||
expect(foo).to.be.true; | ||
foo.should.be.true; | ||
// instead of this | ||
expect(foo).to.be.true; // eslint-disable-line no-unused-expressions | ||
foo.should.be.true; // eslint-disable-line no-unused-expressions | ||
``` | ||
@@ -13,0 +15,0 @@ |
@@ -30,6 +30,6 @@ /** | ||
"a()", | ||
{ code: "a && a()", options: [{ allowShortCircuit: true }] }, | ||
{ code: "a() || (b = c)", options: [{ allowShortCircuit: true }] }, | ||
{ code: "a ? b() : c()", options: [{ allowTernary: true }] }, | ||
{ code: "a ? b() || (c = d) : e()", options: [{ allowShortCircuit: true, allowTernary: true }] }, | ||
{ code: "a && a()", options: [{ allowShortCircuit: true }]}, | ||
{ code: "a() || (b = c)", options: [{ allowShortCircuit: true }]}, | ||
{ code: "a ? b() : c()", options: [{ allowTernary: true }]}, | ||
{ code: "a ? b() || (c = d) : e()", options: [{ allowShortCircuit: true, allowTernary: true }]}, | ||
"delete foo.bar", | ||
@@ -40,3 +40,3 @@ "void new C", | ||
"function foo() {\"use strict\"; return true; }", | ||
{ code: "var foo = () => {\"use strict\"; return true; }", parserOptions: { ecmaVersion: 6 } }, | ||
{ code: "var foo = () => {\"use strict\"; return true; }", parserOptions: { ecmaVersion: 6 }}, | ||
"function foo() {\"directive one\"; \"directive two\"; f(); }", | ||
@@ -66,31 +66,75 @@ "function foo() { var foo = \"use strict\"; return true; }", | ||
}, | ||
"expect(foo).to.be.ok", | ||
"expect(foo).be.ok", | ||
"expect(foo).to.eventually().be.ok" | ||
{ | ||
code: "tag`tagged template literal`", | ||
options: [{ allowTaggedTemplates: true }], | ||
parserOptions: { ecmaVersion: 6 } | ||
}, | ||
{ | ||
code: "shouldNotBeAffectedByAllowTemplateTagsOption()", | ||
options: [{ allowTaggedTemplates: true }], | ||
parserOptions: { ecmaVersion: 6 } | ||
}, | ||
// Chai statements | ||
"expect(foo).to.be.true;", | ||
"expect(foo).to.have.a.property('bar').which.is.true", | ||
"foo.should.be.true;", | ||
"foo.inner.nested.should.be.true", | ||
"foo.should.have.a.property('bar').which.is.true;" | ||
], | ||
invalid: [ | ||
{ code: "0", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "a", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "f(), 0", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "{0}", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "[]", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "a && b();", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "a() || false", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] }, | ||
{ code: "a || (b = c)", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] }, | ||
{ code: "a ? b() || (c = d) : e", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] }, | ||
{ code: "0", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "a", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "f(), 0", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "{0}", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "[]", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "a && b();", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "a() || false", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]}, | ||
{ code: "a || (b = c)", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]}, | ||
{ code: "a ? b() || (c = d) : e", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]}, | ||
{ code: "a && b()", options: [{ allowTernary: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]}, | ||
{ code: "a ? b() : c()", options: [{ allowShortCircuit: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]}, | ||
{ code: "a || b", options: [{ allowShortCircuit: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "a() && b", options: [{ allowShortCircuit: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "a ? b : 0", options: [{ allowTernary: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "a ? b : c()", options: [{ allowTernary: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "foo.bar;", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "!a", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "+a", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "\"directive one\"; f(); \"directive two\";", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "function foo() {\"directive one\"; f(); \"directive two\"; }", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "if (0) { \"not a directive\"; f(); }", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "function foo() { var foo = true; \"use strict\"; }", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] }, | ||
{ code: "var foo = () => { var foo = true; \"use strict\"; }", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}] } | ||
{ code: "a || b", options: [{ allowShortCircuit: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "a() && b", options: [{ allowShortCircuit: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "a ? b : 0", options: [{ allowTernary: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "a ? b : c()", options: [{ allowTernary: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "foo.bar;", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "!a", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "+a", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "\"directive one\"; f(); \"directive two\";", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "function foo() {\"directive one\"; f(); \"directive two\"; }", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "if (0) { \"not a directive\"; f(); }", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "function foo() { var foo = true; \"use strict\"; }", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ code: "var foo = () => { var foo = true; \"use strict\"; }", parserOptions: { ecmaVersion: 6}, errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]}, | ||
{ | ||
code: "`untagged template literal`", | ||
options: [{ allowTaggedTemplates: true }], | ||
parserOptions: { ecmaVersion: 6}, | ||
errors: ["Expected an assignment or function call and instead saw an expression."] | ||
}, | ||
{ | ||
code: "`untagged template literal`", | ||
options: [{ allowTaggedTemplates: false }], | ||
parserOptions: { ecmaVersion: 6}, | ||
errors: ["Expected an assignment or function call and instead saw an expression."] | ||
}, | ||
{ | ||
code: "tag`tagged template literal`", | ||
options: [{ allowTaggedTemplates: false }], | ||
parserOptions: { ecmaVersion: 6}, | ||
errors: ["Expected an assignment or function call and instead saw an expression."] | ||
}, | ||
{ | ||
code: "`untagged template literal`", | ||
parserOptions: { ecmaVersion: 6 }, | ||
errors: ["Expected an assignment or function call and instead saw an expression."] | ||
}, | ||
{ | ||
code: "tag`tagged template literal`", | ||
parserOptions: { ecmaVersion: 6 }, | ||
errors: ["Expected an assignment or function call and instead saw an expression."] | ||
}, | ||
// Chai statements | ||
{ code: "foo.expect('bar').not.to.pass;", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]}, | ||
{ code: "should.not.pass;", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] }, | ||
] | ||
}); |
25081
8
431
75