eslint-plugin-jest
Advanced tools
Comparing version 21.24.1 to 21.24.2
{ | ||
"name": "eslint-plugin-jest", | ||
"version": "21.24.1", | ||
"version": "21.24.2", | ||
"description": "Eslint rules for Jest", | ||
@@ -5,0 +5,0 @@ "repository": "jest-community/eslint-plugin-jest", |
@@ -26,2 +26,10 @@ 'use strict'; | ||
}, | ||
{ | ||
code: [ | ||
'test("verifies the function call", () => {', | ||
' td.verify(someFunctionCall())', | ||
'})', | ||
].join('\n'), | ||
options: [{ assertFunctionNames: ['td.verify'] }], | ||
}, | ||
], | ||
@@ -28,0 +36,0 @@ |
@@ -9,2 +9,3 @@ 'use strict'; | ||
const getDocsUrl = require('./util').getDocsUrl; | ||
const getNodeName = require('./util').getNodeName; | ||
@@ -30,41 +31,24 @@ module.exports = { | ||
create(context) { | ||
// variables should be defined here | ||
const unchecked = []; | ||
const assertFunctionNames = | ||
const assertFunctionNames = new Set( | ||
context.options[0] && context.options[0].assertFunctionNames | ||
? context.options[0].assertFunctionNames | ||
: ['expect']; | ||
: ['expect'] | ||
); | ||
//---------------------------------------------------------------------- | ||
// Helpers | ||
//---------------------------------------------------------------------- | ||
const isExpectCall = node => | ||
// if we're not calling a function, ignore | ||
node.type === 'CallExpression' && | ||
// if we're not calling allowed assertion | ||
assertFunctionNames.some(name => name === node.callee.name); | ||
//---------------------------------------------------------------------- | ||
// Public | ||
//---------------------------------------------------------------------- | ||
return { | ||
// give me methods | ||
CallExpression(node) { | ||
// keep track of `it` calls | ||
if (['it', 'test'].indexOf(node.callee.name) > -1) { | ||
const name = getNodeName(node.callee); | ||
if (name === 'it' || name === 'test') { | ||
unchecked.push(node); | ||
return; | ||
} else if (assertFunctionNames.has(name)) { | ||
// Return early in case of nested `it` statements. | ||
for (const ancestor of context.getAncestors()) { | ||
const index = unchecked.indexOf(ancestor); | ||
if (index !== -1) { | ||
unchecked.splice(index, 1); | ||
break; | ||
} | ||
} | ||
} | ||
if (!isExpectCall(node)) { | ||
return; | ||
} | ||
// here, we do have a call to expect | ||
// use `some` to return early (in case of nested `it`s | ||
context.getAncestors().some(ancestor => { | ||
const index = unchecked.indexOf(ancestor); | ||
if (index !== -1) { | ||
unchecked.splice(index, 1); | ||
return true; | ||
} | ||
return false; | ||
}); | ||
}, | ||
@@ -71,0 +55,0 @@ 'Program:exit'() { |
'use strict'; | ||
const getDocsUrl = require('./util').getDocsUrl; | ||
const getNodeName = require('./util').getNodeName; | ||
function getName(node) { | ||
function joinNames(a, b) { | ||
return a && b ? `${a}.${b}` : null; | ||
} | ||
switch (node && node.type) { | ||
case 'Identifier': | ||
return node.name; | ||
case 'Literal': | ||
return node.value; | ||
case 'MemberExpression': | ||
return joinNames(getName(node.object), getName(node.property)); | ||
} | ||
return null; | ||
} | ||
function collectReferences(scope) { | ||
@@ -60,10 +44,18 @@ const locals = new Set(); | ||
return { | ||
'CallExpression[callee.name="describe"]'() { | ||
suiteDepth++; | ||
}, | ||
'CallExpression[callee.name=/^it|test$/]'() { | ||
testDepth++; | ||
}, | ||
'CallExpression[callee.name=/^it|test$/][arguments.length<2]'(node) { | ||
context.report({ | ||
message: 'Test is missing function argument', | ||
node, | ||
}); | ||
}, | ||
CallExpression(node) { | ||
const functionName = getName(node.callee); | ||
const functionName = getNodeName(node.callee); | ||
switch (functionName) { | ||
case 'describe': | ||
suiteDepth++; | ||
break; | ||
case 'describe.skip': | ||
@@ -73,13 +65,2 @@ context.report({ message: 'Skipped test suite', node }); | ||
case 'it': | ||
case 'test': | ||
testDepth++; | ||
if (node.arguments.length < 2) { | ||
context.report({ | ||
message: 'Test is missing function argument', | ||
node, | ||
}); | ||
} | ||
break; | ||
case 'it.skip': | ||
@@ -89,62 +70,48 @@ case 'test.skip': | ||
break; | ||
case 'pending': { | ||
const references = collectReferences(context.getScope()); | ||
if ( | ||
// `pending` was found as a local variable or function declaration. | ||
references.locals.has('pending') || | ||
// `pending` was not found as an unresolved reference, | ||
// meaning it is likely not an implicit global reference. | ||
!references.unresolved.has('pending') | ||
) { | ||
break; | ||
} | ||
if (testDepth > 0) { | ||
context.report({ | ||
message: 'Call to pending() within test', | ||
node, | ||
}); | ||
} else if (suiteDepth > 0) { | ||
context.report({ | ||
message: 'Call to pending() within test suite', | ||
node, | ||
}); | ||
} else { | ||
context.report({ | ||
message: 'Call to pending()', | ||
node, | ||
}); | ||
} | ||
break; | ||
} | ||
case 'xdescribe': | ||
context.report({ message: 'Disabled test suite', node }); | ||
break; | ||
case 'xit': | ||
case 'xtest': | ||
context.report({ message: 'Disabled test', node }); | ||
break; | ||
} | ||
}, | ||
'CallExpression[callee.name="pending"]'(node) { | ||
const references = collectReferences(context.getScope()); | ||
'CallExpression:exit'(node) { | ||
const functionName = getName(node.callee); | ||
if ( | ||
// `pending` was found as a local variable or function declaration. | ||
references.locals.has('pending') || | ||
// `pending` was not found as an unresolved reference, | ||
// meaning it is likely not an implicit global reference. | ||
!references.unresolved.has('pending') | ||
) { | ||
return; | ||
} | ||
switch (functionName) { | ||
case 'describe': | ||
suiteDepth--; | ||
break; | ||
case 'it': | ||
case 'test': | ||
testDepth--; | ||
break; | ||
if (testDepth > 0) { | ||
context.report({ | ||
message: 'Call to pending() within test', | ||
node, | ||
}); | ||
} else if (suiteDepth > 0) { | ||
context.report({ | ||
message: 'Call to pending() within test suite', | ||
node, | ||
}); | ||
} else { | ||
context.report({ | ||
message: 'Call to pending()', | ||
node, | ||
}); | ||
} | ||
}, | ||
'CallExpression[callee.name="xdescribe"]'(node) { | ||
context.report({ message: 'Disabled test suite', node }); | ||
}, | ||
'CallExpression[callee.name=/^xit|xtest$/]'(node) { | ||
context.report({ message: 'Disabled test', node }); | ||
}, | ||
'CallExpression[callee.name="describe"]:exit'() { | ||
suiteDepth--; | ||
}, | ||
'CallExpression[callee.name=/^it|test$/]:exit'() { | ||
testDepth--; | ||
}, | ||
}; | ||
}, | ||
}; |
@@ -34,10 +34,2 @@ 'use strict'; | ||
const isTestOrItFunction = node => { | ||
return ( | ||
node.type === 'CallExpression' && | ||
node.callee && | ||
(node.callee.name === 'it' || node.callee.name === 'test') | ||
); | ||
}; | ||
const getFunctionFirstLine = functionBody => { | ||
@@ -51,10 +43,2 @@ return functionBody[0] && functionBody[0].expression; | ||
const getTestFunctionBody = node => { | ||
try { | ||
return node.arguments[1].body.body; | ||
} catch (e) { | ||
return undefined; | ||
} | ||
}; | ||
const reportMsg = (context, node) => { | ||
@@ -75,14 +59,11 @@ context.report({ | ||
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); | ||
} | ||
} | ||
'CallExpression[callee.name=/^it|test$/][arguments.1.body.body]'(node) { | ||
const testFuncBody = node.arguments[1].body.body; | ||
if (!isFirstLineExprStmt(testFuncBody)) { | ||
reportMsg(context, node); | ||
} else { | ||
const testFuncFirstLine = getFunctionFirstLine(testFuncBody); | ||
if (!isExpectAssertionsOrHasAssertionsCall(testFuncFirstLine)) { | ||
reportMsg(context, node); | ||
} | ||
@@ -89,0 +70,0 @@ } |
@@ -101,6 +101,16 @@ 'use strict'; | ||
const getNodeName = node => { | ||
if (node.type === 'MemberExpression') { | ||
return `${node.object.name}.${node.property.name}`; | ||
function joinNames(a, b) { | ||
return a && b ? `${a}.${b}` : null; | ||
} | ||
return node.name; | ||
switch (node && node.type) { | ||
case 'Identifier': | ||
return node.name; | ||
case 'Literal': | ||
return node.value; | ||
case 'MemberExpression': | ||
return joinNames(getNodeName(node.object), getNodeName(node.property)); | ||
} | ||
return null; | ||
}; | ||
@@ -107,0 +117,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
162961
4602