eslint-plugin-jest
Version:
Eslint rules for Jest
129 lines (115 loc) • 4.34 kB
JavaScript
;
/*
* This implementation is ported from from eslint-plugin-jasmine.
* MIT license, Tom Vincent.
*/
const _require = require('./util'),
getDocsUrl = _require.getDocsUrl;
const expectProperties = ['not', 'resolves', 'rejects'];
module.exports = {
meta: {
docs: {
url: getDocsUrl(__filename)
},
messages: {
multipleArgs: 'More than one argument was passed to expect().',
noArgs: 'No arguments were passed to expect().',
noAssertions: 'No assertion was called on expect().',
invalidProperty: '"{{ propertyName }}" is not a valid property of expect.',
propertyWithoutMatcher: '"{{ propertyName }}" needs to call a matcher.',
matcherOnPropertyNotCalled: '"{{ propertyName }}" was not called.'
}
},
create(context) {
return {
CallExpression(node) {
const calleeName = node.callee.name;
if (calleeName === 'expect') {
// checking "expect()" arguments
if (node.arguments.length > 1) {
const secondArgumentLocStart = node.arguments[1].loc.start;
const lastArgumentLocEnd = node.arguments[node.arguments.length - 1].loc.end;
context.report({
loc: {
end: {
column: lastArgumentLocEnd.column - 1,
line: lastArgumentLocEnd.line
},
start: secondArgumentLocStart
},
messageId: 'multipleArgs',
node
});
} else if (node.arguments.length === 0) {
const expectLength = calleeName.length;
context.report({
loc: {
end: {
column: node.loc.start.column + expectLength + 1,
line: node.loc.start.line
},
start: {
column: node.loc.start.column + expectLength,
line: node.loc.start.line
}
},
messageId: 'noArgs',
node
});
} // something was called on `expect()`
if (node.parent && node.parent.type === 'MemberExpression' && node.parent.parent) {
let parentNode = node.parent;
let parentProperty = parentNode.property;
let propertyName = parentProperty.name;
let grandParent = parentNode.parent; // a property is accessed, get the next node
if (grandParent.type === 'MemberExpression') {
// a modifier is used, just get the next one
if (expectProperties.indexOf(propertyName) > -1) {
grandParent = grandParent.parent;
} else {
// only a few properties are allowed
context.report({
// For some reason `endColumn` isn't set in tests if `loc` is
// not added
loc: parentProperty.loc,
messageId: 'invalidProperty',
data: {
propertyName
},
node: parentProperty
});
} // this next one should be the matcher
parentNode = parentNode.parent;
parentProperty = parentNode.property;
propertyName = parentProperty.name;
} // matcher was not called
if (grandParent.type === 'ExpressionStatement') {
context.report({
// For some reason `endColumn` isn't set in tests if `loc` is not
// added
loc: parentProperty.loc,
data: {
propertyName
},
messageId: expectProperties.indexOf(propertyName) > -1 ? 'propertyWithoutMatcher' : 'matcherOnPropertyNotCalled',
node: parentProperty
});
}
}
}
},
// nothing called on "expect()"
'CallExpression:exit'(node) {
if (node.callee.name === 'expect' && node.parent.type === 'ExpressionStatement') {
context.report({
// For some reason `endColumn` isn't set in tests if `loc` is not
// added
loc: node.loc,
messageId: 'noAssertions',
node
});
}
}
};
}
};