-
Notifications
You must be signed in to change notification settings - Fork 237
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement prefer-expect-assertions rule (#43)
* feat: implement missing_expect_assertions_call rule Intial code for missing_expect_assertions_call rule * style: lint auto fix * refactor: enhance missing_expect_assertions_call rule Report error when expect.assertions() call is present but the argument provided is not a number * refactor: enhance missing_expect_assertions_call rule Rule will not report any error, if expect.hasAssertions() call is present. After this change, either expect.hasAssertions() or expect.assertions({number of assertions}) is required to pass the rule * refactor(readability): improving missing-expect-assertions-call rule msg * refactor: missing-expect-assertions-call rule rename Rename missing-expect-assertions-call to prefer-expect-assertions * refactor: remove unnecessary return * fix: do not add the rule to recommended * refactor: update test message * test: adding missing tests and refactoring
- Loading branch information
1 parent
439c1f1
commit 4effb3c
Showing
3 changed files
with
174 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
'use strict'; | ||
|
||
const RuleTester = require('eslint').RuleTester; | ||
const rules = require('../..').rules; | ||
|
||
const ruleTester = new RuleTester({ | ||
parserOptions: { | ||
ecmaVersion: 6, | ||
}, | ||
}); | ||
|
||
const expectedMsg = | ||
'Every test should have either `expect.assertions(<number of assertions>)` or `expect.hasAssertions()` as its first expression'; | ||
|
||
ruleTester.run('prefer-expect-assertions', rules['prefer-expect-assertions'], { | ||
invalid: [ | ||
{ | ||
code: 'it("it1", () => {})', | ||
errors: [ | ||
{ | ||
message: expectedMsg, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'it("it1", () => { foo()})', | ||
errors: [ | ||
{ | ||
message: expectedMsg, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: | ||
'it("it1", function() {' + | ||
'\n\t\t\tsomeFunctionToDo();' + | ||
'\n\t\t\tsomeFunctionToDo2();\n' + | ||
'\t\t\t})', | ||
errors: [ | ||
{ | ||
message: expectedMsg, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'it("it1", function() {var a = 2;})', | ||
errors: [ | ||
{ | ||
message: expectedMsg, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'it("it1", function() {expect.assertions();})', | ||
errors: [ | ||
{ | ||
message: expectedMsg, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'it("it1", function() {expect.assertions(1,2);})', | ||
errors: [ | ||
{ | ||
message: expectedMsg, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'it("it1", function() {expect.assertions("1");})', | ||
errors: [ | ||
{ | ||
message: expectedMsg, | ||
}, | ||
], | ||
}, | ||
], | ||
|
||
valid: [ | ||
{ | ||
code: 'test("it1", () => {expect.assertions(0);})', | ||
}, | ||
'test("it1", function() {expect.assertions(0);})', | ||
'test("it1", function() {expect.hasAssertions();})', | ||
'it("it1", function() {expect.assertions(0);})', | ||
'it("it1", function() {\n\t\t\texpect.assertions(1);' + | ||
'\n\t\t\texpect(someValue).toBe(true)\n' + | ||
'\t\t\t})', | ||
'test("it1")', | ||
], | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
'use strict'; | ||
|
||
const ruleMsg = | ||
'Every test should have either `expect.assertions(<number of assertions>)` or `expect.hasAssertions()` as its first expression'; | ||
|
||
const validateArguments = expression => { | ||
return ( | ||
expression.arguments && | ||
expression.arguments.length === 1 && | ||
Number.isInteger(expression.arguments[0].value) | ||
); | ||
}; | ||
|
||
const isExpectAssertionsOrHasAssertionsCall = expression => { | ||
try { | ||
const expectAssertionOrHasAssertionCall = | ||
expression.type === 'CallExpression' && | ||
expression.callee.type === 'MemberExpression' && | ||
expression.callee.object.name === 'expect' && | ||
(expression.callee.property.name === 'assertions' || | ||
expression.callee.property.name === 'hasAssertions'); | ||
|
||
if (expression.callee.property.name === 'assertions') { | ||
return expectAssertionOrHasAssertionCall && validateArguments(expression); | ||
} | ||
return expectAssertionOrHasAssertionCall; | ||
} catch (e) { | ||
return false; | ||
} | ||
}; | ||
|
||
const isTestOrItFunction = node => { | ||
return ( | ||
node.type === 'CallExpression' && | ||
node.callee && | ||
(node.callee.name === 'it' || node.callee.name === 'test') | ||
); | ||
}; | ||
|
||
const getFunctionFirstLine = functionBody => { | ||
return functionBody[0] && functionBody[0].expression; | ||
}; | ||
|
||
const isFirstLineExprStmt = functionBody => { | ||
return functionBody[0] && functionBody[0].type === 'ExpressionStatement'; | ||
}; | ||
|
||
const getTestFunctionBody = node => { | ||
try { | ||
return node.arguments[1].body.body; | ||
} catch (e) { | ||
return undefined; | ||
} | ||
}; | ||
|
||
const reportMsg = (context, node) => { | ||
context.report({ | ||
message: ruleMsg, | ||
node, | ||
}); | ||
}; | ||
|
||
module.exports = context => { | ||
return { | ||
CallExpression(node) { | ||
if (isTestOrItFunction(node)) { | ||
const testFuncBody = getTestFunctionBody(node); | ||
if (testFuncBody) { | ||
if (!isFirstLineExprStmt(testFuncBody)) { | ||
reportMsg(context, node); | ||
} else { | ||
const testFuncFirstLine = getFunctionFirstLine(testFuncBody); | ||
if (!isExpectAssertionsOrHasAssertionsCall(testFuncFirstLine)) { | ||
reportMsg(context, node); | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
}; | ||
}; |