Socket
Socket
Sign inDemoInstall

eslint-plugin-jest

Package Overview
Dependencies
Maintainers
11
Versions
325
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-jest - npm Package Compare versions

Comparing version 24.3.5 to 24.3.6

9

CHANGELOG.md

@@ -0,1 +1,10 @@

## [24.3.6](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.5...v24.3.6) (2021-04-26)
### Bug Fixes
* **no-conditional-expect:** check for expects in `catch`s on promises ([#819](https://github.com/jest-community/eslint-plugin-jest/issues/819)) ([1fee973](https://github.com/jest-community/eslint-plugin-jest/commit/1fee973429a74c60b14eead6a335623b4349b5f2))
* **valid-expect:** support async `expect` in ternary statements ([#833](https://github.com/jest-community/eslint-plugin-jest/issues/833)) ([7b7a396](https://github.com/jest-community/eslint-plugin-jest/commit/7b7a396e12c46d3087b467227887ed64854480c0))
* improve handling of `.each` calls and with tagged literals ([#814](https://github.com/jest-community/eslint-plugin-jest/issues/814)) ([040c605](https://github.com/jest-community/eslint-plugin-jest/commit/040c605cf7929a00980b3fa58331cd78ac6274f6))
## [24.3.5](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.4...v24.3.5) (2021-04-10)

@@ -2,0 +11,0 @@

4

docs/rules/expect-expect.md

@@ -90,6 +90,6 @@ # Enforce assertion to be made in a test body (`expect-expect`)

[SuperTest](https://www.npmjs.com/package/supertest) with the
`{ "assertFunctionNames": ["expect", "request.*.expect"] }` option:
`{ "assertFunctionNames": ["expect", "request.**.expect"] }` option:
```js
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "request.*.expect"] }] */
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "request.**.expect"] }] */
const request = require('supertest');

@@ -96,0 +96,0 @@ const express = require('express');

@@ -6,2 +6,5 @@ # Prevent calling `expect` conditionally (`no-conditional-expect`)

This includes using `expect` in callbacks to functions named `catch`, which are
assumed to be promises.
## Rule Details

@@ -41,2 +44,6 @@

});
it('throws an error', async () => {
await foo().catch(error => expect(error).toBeInstanceOf(error));
});
```

@@ -72,2 +79,6 @@

});
it('throws an error', async () => {
await expect(foo).rejects.toThrow(Error);
});
```

@@ -63,3 +63,3 @@ "use strict";

const funcNode = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee;
const funcNode = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;

@@ -94,3 +94,3 @@ if ((0, _utils.isTestCaseCall)(node) && describeNestingLevel === 0 && !nodeName.includes(testKeyword)) {

'CallExpression:exit'(node) {
if ((0, _utils.isDescribeCall)(node) && !(0, _utils.isEachCall)(node)) {
if ((0, _utils.isDescribeCall)(node)) {
describeNestingLevel--;

@@ -97,0 +97,0 @@ }

@@ -8,4 +8,2 @@ "use strict";

var _experimentalUtils = require("@typescript-eslint/experimental-utils");
var _utils = require("./utils");

@@ -20,15 +18,7 @@

if ((0, _utils.isEachCall)(node)) {
if (node.parent.arguments.length > 0 && (0, _utils.isStringNode)(node.parent.arguments[0])) {
return [node.callee.object.name, node.parent.arguments[0]];
}
if (!hasStringAsFirstArgument(node)) {
return null;
}
if (node.callee.type !== _experimentalUtils.AST_NODE_TYPES.Identifier || !hasStringAsFirstArgument(node)) {
return null;
}
return [node.callee.name, node.arguments[0]];
return [(0, _utils.getNodeName)(node).split('.')[0], node.arguments[0]];
};

@@ -35,0 +25,0 @@

@@ -8,4 +8,8 @@ "use strict";

var _experimentalUtils = require("@typescript-eslint/experimental-utils");
var _utils = require("./utils");
const isCatchCall = node => node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && (0, _utils.isSupportedAccessor)(node.callee.property, 'catch');
var _default = (0, _utils.createRule)({

@@ -30,2 +34,3 @@ name: __filename,

let inTestCase = false;
let inPromiseCatch = false;

@@ -51,2 +56,6 @@ const increaseConditionalDepth = () => inTestCase && conditionalDepth++;

if (isCatchCall(node)) {
inPromiseCatch = true;
}
if (inTestCase && (0, _utils.isExpectCall)(node) && conditionalDepth > 0) {

@@ -58,2 +67,9 @@ context.report({

}
if (inPromiseCatch && (0, _utils.isExpectCall)(node)) {
context.report({
messageId: 'conditionalExpect',
node
});
}
},

@@ -65,2 +81,6 @@

}
if (isCatchCall(node)) {
inPromiseCatch = false;
}
},

@@ -67,0 +87,0 @@

@@ -58,3 +58,3 @@ "use strict";

'CallExpression:exit'(node) {
if ((0, _utils.isDescribeCall)(node) && !(0, _utils.isEachCall)(node)) {
if ((0, _utils.isDescribeCall)(node)) {
hookContexts.pop();

@@ -61,0 +61,0 @@ }

@@ -12,13 +12,20 @@ "use strict";

const validTestCaseNames = [_utils.TestCaseName.test, _utils.TestCaseName.it];
const testFunctions = new Set([_utils.DescribeAlias.describe, ...validTestCaseNames]);
const findOnlyNode = node => {
const callee = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
const isConcurrentExpression = expression => (0, _utils.isSupportedAccessor)(expression.property, _utils.TestCaseProperty.concurrent) && !!expression.parent && expression.parent.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression;
if (callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
if (callee.object.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
if ((0, _utils.isSupportedAccessor)(callee.object.property, 'only')) {
return callee.object.property;
}
}
const matchesTestFunction = object => 'name' in object && typeof object.name === 'string' && (object.name in _utils.TestCaseName || object.name in _utils.DescribeAlias);
if ((0, _utils.isSupportedAccessor)(callee.property, 'only')) {
return callee.property;
}
}
const isCallToFocusedTestFunction = object => object.name.startsWith('f') && testFunctions.has(object.name.substring(1));
return null;
};
const isCallToTestOnlyFunction = callee => matchesTestFunction(callee.object) && (0, _utils.isSupportedAccessor)(isConcurrentExpression(callee) ? callee.parent.property : callee.property, 'only');
var _default = (0, _utils.createRule)({

@@ -43,74 +50,32 @@ name: __filename,

CallExpression(node) {
const callee = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee;
if (callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
const calleeObject = callee.object;
if (calleeObject.type === _experimentalUtils.AST_NODE_TYPES.Identifier && isCallToFocusedTestFunction(calleeObject)) {
context.report({
messageId: 'focusedTest',
node: calleeObject,
suggest: [{
messageId: 'suggestRemoveFocus',
fix(fixer) {
return fixer.removeRange([calleeObject.range[0], calleeObject.range[0] + 1]);
}
}]
});
return;
}
if (calleeObject.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && isCallToTestOnlyFunction(calleeObject)) {
context.report({
messageId: 'focusedTest',
node: isConcurrentExpression(calleeObject) ? callee.property : calleeObject.property,
suggest: [{
messageId: 'suggestRemoveFocus',
fix(fixer) {
if (calleeObject.property.type === _experimentalUtils.AST_NODE_TYPES.Identifier && calleeObject.property.name === 'only') {
return fixer.removeRange([calleeObject.object.range[1], calleeObject.range[1]]);
}
return fixer.removeRange([calleeObject.range[1], callee.range[1]]);
}
}]
});
return;
}
if (isCallToTestOnlyFunction(callee)) {
context.report({
messageId: 'focusedTest',
node: callee.property,
suggest: [{
messageId: 'suggestRemoveFocus',
fix(fixer) {
return fixer.removeRange([calleeObject.range[1], callee.range[1]]);
}
}]
});
return;
}
if (!(0, _utils.isDescribeCall)(node) && !(0, _utils.isTestCaseCall)(node)) {
return;
}
if (callee.type === _experimentalUtils.AST_NODE_TYPES.Identifier && isCallToFocusedTestFunction(callee)) {
if ((0, _utils.getNodeName)(node).startsWith('f')) {
context.report({
messageId: 'focusedTest',
node: callee,
node,
suggest: [{
messageId: 'suggestRemoveFocus',
fix(fixer) {
return fixer.removeRange([callee.range[0], callee.range[0] + 1]);
}
fix: fixer => fixer.removeRange([node.range[0], node.range[0] + 1])
}]
});
return;
}
const onlyNode = findOnlyNode(node);
if (!onlyNode) {
return;
}
context.report({
messageId: 'focusedTest',
node: onlyNode,
suggest: [{
messageId: 'suggestRemoveFocus',
fix: fixer => fixer.removeRange([onlyNode.range[0] - 1, onlyNode.range[1] + Number(onlyNode.type !== _experimentalUtils.AST_NODE_TYPES.Identifier)])
}]
});
}

@@ -117,0 +82,0 @@

@@ -61,2 +61,6 @@ "use strict";

stack.push(true);
if ((0, _utils.getNodeName)(node).endsWith('each')) {
stack.push(true);
}
}

@@ -63,0 +67,0 @@ },

@@ -41,4 +41,2 @@ "use strict";

const isEach = node => node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.callee.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && node.callee.callee.property.type === _experimentalUtils.AST_NODE_TYPES.Identifier && node.callee.callee.property.name === 'each' && node.callee.callee.object.type === _experimentalUtils.AST_NODE_TYPES.Identifier && _utils.TestCaseName.hasOwnProperty(node.callee.callee.object.name);
var _default = (0, _utils.createRule)({

@@ -108,3 +106,3 @@ name: __filename,

if (top === 'test' && (isEach(node) || isTestBlock(node) && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.MemberExpression) || top === 'template' && node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression) {
if (top === 'test' && isTestBlock(node) && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.MemberExpression || top === 'template' && node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression) {
callStack.pop();

@@ -111,0 +109,0 @@ }

@@ -36,3 +36,3 @@ "use strict";

if (!preferredNodeName) return;
const funcNode = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee;
const funcNode = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
context.report({

@@ -39,0 +39,0 @@ messageId: 'usePreferredName',

@@ -63,9 +63,7 @@ "use strict";

const args = (0, _utils.isEachCall)(node) ? node.parent.arguments : node.arguments;
if (args.length < 2) {
if (node.arguments.length < 2) {
return;
}
const [, testFn] = args;
const [, testFn] = node.arguments;

@@ -72,0 +70,0 @@ if (!(0, _utils.isFunction)(testFn) || testFn.body.type !== _experimentalUtils.AST_NODE_TYPES.BlockStatement || options.onlyFunctionsWithAsyncKeyword && !testFn.async) {

@@ -21,7 +21,7 @@ "use strict";

function createTodoFixer(node, fixer) {
const testName = (0, _utils.getNodeName)(node.callee).split('.').shift();
const testName = (0, _utils.getNodeName)(node).split('.').shift();
return fixer.replaceText(node.callee, `${testName}.todo`);
}
const isTargetedTestCase = node => (0, _utils.isTestCaseCall)(node) && [_utils.TestCaseName.it, _utils.TestCaseName.test, 'it.skip', 'test.skip'].includes((0, _utils.getNodeName)(node.callee));
const isTargetedTestCase = node => (0, _utils.isTestCaseCall)(node) && [_utils.TestCaseName.it, _utils.TestCaseName.test, 'it.skip', 'test.skip'].includes((0, _utils.getNodeName)(node));

@@ -28,0 +28,0 @@ var _default = (0, _utils.createRule)({

@@ -56,3 +56,3 @@ "use strict";

'CallExpression:exit'(node) {
if ((0, _utils.isDescribeCall)(node) && !(0, _utils.isEachCall)(node)) {
if ((0, _utils.isDescribeCall)(node)) {
numberOfDescribeBlocks--;

@@ -59,0 +59,0 @@ }

@@ -7,3 +7,3 @@ "use strict";

exports.getNodeName = getNodeName;
exports.scopeHasLocalReference = exports.getJestFunctionArguments = exports.isEachCall = exports.isDescribeCall = exports.isTestCaseCall = exports.getTestCallExpressionsFromDeclaredVariables = exports.isHook = exports.isFunction = exports.TestCaseProperty = exports.DescribeProperty = exports.HookName = exports.TestCaseName = exports.DescribeAlias = exports.parseExpectCall = exports.isParsedEqualityMatcherCall = exports.EqualityMatcher = exports.ModifierName = exports.isExpectMember = exports.isExpectCall = exports.getAccessorValue = exports.isSupportedAccessor = exports.hasOnlyOneArgument = exports.getStringValue = exports.isStringNode = exports.followTypeAssertionChain = exports.createRule = void 0;
exports.scopeHasLocalReference = exports.isDescribeCall = exports.isTestCaseCall = exports.getTestCallExpressionsFromDeclaredVariables = exports.isHook = exports.isFunction = exports.TestCaseProperty = exports.DescribeProperty = exports.HookName = exports.TestCaseName = exports.DescribeAlias = exports.parseExpectCall = exports.isParsedEqualityMatcherCall = exports.EqualityMatcher = exports.ModifierName = exports.isExpectMember = exports.isExpectCall = exports.getAccessorValue = exports.isSupportedAccessor = exports.hasOnlyOneArgument = exports.getStringValue = exports.isStringNode = exports.followTypeAssertionChain = exports.createRule = void 0;

@@ -420,9 +420,7 @@ var _path = require("path");

const callee = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee;
const callee = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
if (callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && isTestCaseProperty(callee.property)) {
var _node$parent;
// if we're an `each()`, ensure we're being called (i.e `.each()()`)
if (node.callee.type !== _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression && ((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type) !== _experimentalUtils.AST_NODE_TYPES.CallExpression && getAccessorValue(callee.property) === 'each') {
// if we're an `each()`, ensure we're the outer CallExpression (i.e `.each()()`)
if (getAccessorValue(callee.property) === 'each' && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.CallExpression) {
return false;

@@ -460,9 +458,7 @@ }

const callee = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee;
const callee = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
if (callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && isDescribeProperty(callee.property)) {
var _node$parent2;
// if we're an `each()`, ensure we're being called (i.e `.each()()`)
if (node.callee.type !== _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression && ((_node$parent2 = node.parent) === null || _node$parent2 === void 0 ? void 0 : _node$parent2.type) !== _experimentalUtils.AST_NODE_TYPES.CallExpression && getAccessorValue(callee.property) === 'each') {
// if we're an `each()`, ensure we're the outer CallExpression (i.e `.each()()`)
if (getAccessorValue(callee.property) === 'each' && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.CallExpression) {
return false;

@@ -476,37 +472,5 @@ }

};
/**
* Checks if the given node` is a call to `<describe|test|it>.each(...)()`.
* If `true`, the code must look like `<method>.each(...)()`.
*
* @param {JestFunctionCallExpression<DescribeAlias | TestCaseName>} node
*
* @return {node is JestFunctionCallExpressionWithMemberExpressionCallee<DescribeAlias | TestCaseName, DescribeProperty.each | TestCaseProperty.each> & {parent: TSESTree.CallExpression}}
*/
exports.isDescribeCall = isDescribeCall;
const isEachCall = node => {
var _node$parent3;
return ((_node$parent3 = node.parent) === null || _node$parent3 === void 0 ? void 0 : _node$parent3.type) === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && isSupportedAccessor(node.callee.property, DescribeProperty.each);
};
/**
* Gets the arguments of the given `JestFunctionCallExpression`.
*
* If the `node` is an `each` call, then the arguments of the actual suite
* are returned, rather then the `each` array argument.
*
* @param {JestFunctionCallExpression<DescribeAlias | TestCaseName>} node
*
* @return {Expression[]}
*/
exports.isEachCall = isEachCall;
const getJestFunctionArguments = node => node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && isSupportedAccessor(node.callee.property, DescribeProperty.each) && node.parent && node.parent.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.parent.arguments : node.arguments;
exports.getJestFunctionArguments = getJestFunctionArguments;
const collectReferences = scope => {

@@ -513,0 +477,0 @@ const locals = new Set();

@@ -44,9 +44,7 @@ "use strict";

CallExpression(node) {
if (!(0, _utils.isDescribeCall)(node) || node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression) {
if (!(0, _utils.isDescribeCall)(node)) {
return;
}
const nodeArguments = (0, _utils.getJestFunctionArguments)(node);
if (nodeArguments.length < 1) {
if (node.arguments.length < 1) {
return context.report({

@@ -58,3 +56,3 @@ messageId: 'nameAndCallback',

const [, callback] = nodeArguments;
const [, callback] = node.arguments;

@@ -64,3 +62,3 @@ if (!callback) {

messageId: 'nameAndCallback',
loc: paramsLocation(nodeArguments)
loc: paramsLocation(node.arguments)
});

@@ -73,3 +71,3 @@ return;

messageId: 'secondArgumentMustBeFunction',
loc: paramsLocation(nodeArguments)
loc: paramsLocation(node.arguments)
});

@@ -86,3 +84,3 @@ return;

if (!(0, _utils.isEachCall)(node) && callback.params.length) {
if (!(0, _utils.getNodeName)(node).endsWith('each') && callback.params.length) {
context.report({

@@ -89,0 +87,0 @@ messageId: 'unexpectedDescribeArgument',

@@ -49,4 +49,14 @@ "use strict";

const isAcceptableReturnNode = (node, allowReturn) => allowReturn && node.type === _experimentalUtils.AST_NODE_TYPES.ReturnStatement || [_experimentalUtils.AST_NODE_TYPES.ArrowFunctionExpression, _experimentalUtils.AST_NODE_TYPES.AwaitExpression].includes(node.type);
const isAcceptableReturnNode = (node, allowReturn) => {
if (allowReturn && node.type === _experimentalUtils.AST_NODE_TYPES.ReturnStatement) {
return true;
}
if (node.type === _experimentalUtils.AST_NODE_TYPES.ConditionalExpression && node.parent) {
return isAcceptableReturnNode(node.parent, allowReturn);
}
return [_experimentalUtils.AST_NODE_TYPES.ArrowFunctionExpression, _experimentalUtils.AST_NODE_TYPES.AwaitExpression].includes(node.type);
};
const isNoAssertionsParentNode = node => node.type === _experimentalUtils.AST_NODE_TYPES.ExpressionStatement || node.type === _experimentalUtils.AST_NODE_TYPES.AwaitExpression && node.parent !== undefined && node.parent.type === _experimentalUtils.AST_NODE_TYPES.ExpressionStatement;

@@ -53,0 +63,0 @@

@@ -139,3 +139,3 @@ "use strict";

const [argument] = (0, _utils.getJestFunctionArguments)(node);
const [argument] = node.arguments;

@@ -197,3 +197,3 @@ if (!argument) {

const nodeName = trimFXprefix((0, _utils.getNodeName)(node.callee));
const nodeName = trimFXprefix((0, _utils.getNodeName)(node));
const [firstWord] = title.split(' ');

@@ -200,0 +200,0 @@

{
"name": "eslint-plugin-jest",
"version": "24.3.5",
"version": "24.3.6",
"description": "Eslint rules for Jest",

@@ -5,0 +5,0 @@ "keywords": [

@@ -217,2 +217,9 @@ <div align="center">

### eslint-plugin-istanbul
A set of rules to enforce good practices for Istanbul, one of the code coverage
tools used by Jest.
https://github.com/istanbuljs/eslint-plugin-istanbul
[recommended]: https://img.shields.io/badge/-recommended-lightgrey.svg

@@ -219,0 +226,0 @@ [suggest]: https://img.shields.io/badge/-suggest-yellow.svg

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc