Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
function getText(node: ValidChainTarget): string {
if (node.type === AST_NODE_TYPES.BinaryExpression) {
return getText(
// isValidChainTarget ensures this is type safe
node.left as ValidChainTarget,
);
}
if (
node.type === AST_NODE_TYPES.CallExpression ||
node.type === AST_NODE_TYPES.OptionalCallExpression
) {
const calleeText = getText(
// isValidChainTarget ensures this is type safe
node.callee as ValidChainTarget,
);
// ensure that the call arguments are left untouched, or else we can break cases that _need_ whitespace:
// - JSX:
// - Unary Operators: typeof foo, await bar, delete baz
const closingParenToken = util.nullThrows(
sourceCode.getLastToken(node),
util.NullThrowsReasons.MissingToken('closing parenthesis', node.type),
);
const openingParenToken = util.nullThrows(
sourceCode.getFirstTokenBetween(
throw new Error(
`Unexpected BlockStatement. No parent defined. - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`,
);
}
// functionDeclaration: function func() {}
if (func.type === AST_NODE_TYPES.FunctionDeclaration) {
return 'function';
}
if (isFunction(func) && func.parent) {
const expr = func.parent;
// arrowfunction or function expr
if (expr.type === AST_NODE_TYPES.VariableDeclarator) {
return 'function';
}
// if it's not a variable, it will be callExpr, we only care about describe
if (expr.type === AST_NODE_TYPES.CallExpression && isDescribe(expr)) {
return DescribeAlias.describe;
}
}
return null;
};
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
const KNOWN_NODES = new Set([
AST_NODE_TYPES.AssignmentExpression,
AST_NODE_TYPES.AssignmentPattern,
AST_NODE_TYPES.ArrayExpression,
AST_NODE_TYPES.ArrayPattern,
AST_NODE_TYPES.ArrowFunctionExpression,
AST_NODE_TYPES.AwaitExpression,
AST_NODE_TYPES.BlockStatement,
AST_NODE_TYPES.BinaryExpression,
AST_NODE_TYPES.BreakStatement,
AST_NODE_TYPES.CallExpression,
AST_NODE_TYPES.CatchClause,
AST_NODE_TYPES.ClassBody,
AST_NODE_TYPES.ClassDeclaration,
AST_NODE_TYPES.ClassExpression,
AST_NODE_TYPES.ConditionalExpression,
AST_NODE_TYPES.ContinueStatement,
AST_NODE_TYPES.DoWhileStatement,
AST_NODE_TYPES.DebuggerStatement,
AST_NODE_TYPES.EmptyStatement,
AST_NODE_TYPES.ExpressionStatement,
AST_NODE_TYPES.ForStatement,
AST_NODE_TYPES.ForInStatement,
AST_NODE_TYPES.ForOfStatement,
AST_NODE_TYPES.FunctionDeclaration,
AST_NODE_TYPES.FunctionExpression,
AST_NODE_TYPES.Identifier,
const getPromiseCallExpressionNode = (node: TSESTree.Node) => {
if (
node &&
node.type === AST_NODE_TYPES.ArrayExpression &&
node.parent &&
node.parent.type === AST_NODE_TYPES.CallExpression
) {
node = node.parent;
}
if (
node.type === AST_NODE_TYPES.CallExpression &&
node.callee &&
node.callee.type === AST_NODE_TYPES.MemberExpression &&
isSupportedAccessor(node.callee.object) &&
getAccessorValue(node.callee.object) === 'Promise' &&
node.parent
) {
return node;
}
return null;
};
const getPromiseCallExpressionNode = (node: TSESTree.Node) => {
if (
node &&
node.type === AST_NODE_TYPES.ArrayExpression &&
node.parent &&
node.parent.type === AST_NODE_TYPES.CallExpression
) {
node = node.parent;
}
if (
node.type === AST_NODE_TYPES.CallExpression &&
node.callee &&
node.callee.type === AST_NODE_TYPES.MemberExpression &&
isSupportedAccessor(node.callee.object) &&
getAccessorValue(node.callee.object) === 'Promise' &&
node.parent
) {
return node;
}
return null;
const getJestFnCall = (node: TSESTree.Node): TSESTree.CallExpression | null => {
if (
node.type !== AST_NODE_TYPES.CallExpression &&
node.type !== AST_NODE_TYPES.MemberExpression
) {
return null;
}
const obj = findNodeObject(node);
if (!obj) {
return null;
}
if (obj.type === AST_NODE_TYPES.Identifier) {
return node.type === AST_NODE_TYPES.CallExpression &&
getNodeName(node.callee) === 'jest.fn'
? node
: null;
const isFixableIncludesCallExpression = (
node: TSESTree.Node,
): node is FixableIncludesCallExpression =>
node.type === AST_NODE_TYPES.CallExpression &&
node.callee.type === AST_NODE_TYPES.MemberExpression &&
isSupportedAccessor(node.callee.property, 'includes') &&
node.callee.property.type === AST_NODE_TYPES.Identifier &&
hasOnlyOneArgument(node);
*fix(fixer) {
const argNode = callNode.arguments[0];
const needsParen =
argNode.type !== AST_NODE_TYPES.Literal &&
argNode.type !== AST_NODE_TYPES.TemplateLiteral &&
argNode.type !== AST_NODE_TYPES.Identifier &&
argNode.type !== AST_NODE_TYPES.MemberExpression &&
argNode.type !== AST_NODE_TYPES.OptionalMemberExpression &&
argNode.type !== AST_NODE_TYPES.CallExpression &&
argNode.type !== AST_NODE_TYPES.OptionalCallExpression;
yield fixer.removeRange([callNode.range[0], argNode.range[0]]);
if (needsParen) {
yield fixer.insertTextBefore(argNode, '(');
yield fixer.insertTextAfter(argNode, ')');
}
yield fixer.insertTextAfter(
argNode,
`${
callNode.type === AST_NODE_TYPES.OptionalCallExpression
? '?.'
: '.'
}includes(${JSON.stringify(text)}`,
);
},
const { id, moduleReference } = node;
return rules.VariableDeclaration({
type: AST_NODE_TYPES.VariableDeclaration,
kind: 'const' as 'const',
declarations: [
{
type: AST_NODE_TYPES.VariableDeclarator,
range: [id.range[0], moduleReference.range[1]],
loc: {
start: id.loc.start,
end: moduleReference.loc.end,
},
id: id,
init: {
type: AST_NODE_TYPES.CallExpression,
callee: {
type: AST_NODE_TYPES.Identifier,
name: 'require',
range: [
moduleReference.range[0],
moduleReference.range[0] + 'require'.length,
],
loc: {
start: moduleReference.loc.start,
end: {
line: moduleReference.loc.end.line,
column: moduleReference.loc.start.line + 'require'.length,
},
},
},
arguments:
const reparseAsMatcher = (
parsedMember: ParsedExpectMember,
): ParsedExpectMatcher => ({
...parsedMember,
/**
* The arguments being passed to this `Matcher`, if any.
*
* If this matcher isn't called, this will be `null`.
*/
arguments:
parsedMember.node.parent &&
parsedMember.node.parent.type === AST_NODE_TYPES.CallExpression
? parsedMember.node.parent.arguments
: null,
});