UNPKG

eslint-plugin-mocha

Version:

Eslint rules for mocha.

115 lines 4.8 kB
import { extractMemberExpressionPath, isConstantPath } from "../ast/member-expression.js"; import { createMochaVisitors } from "../ast/mocha-visitors.js"; import { isSuiteConfigCall } from "../mocha/config-call.js"; import { reformatLastPathSegmentWithCallExpressions } from "../mocha/name-details.js"; import { convertNameToPathArray, isSamePath } from "../mocha/path.js"; import { getRuleOption } from "../rule-options.js"; import { allowMochaCallOptionSchema, defaultAllowMochaCallOption, normalizeMochaCallName } from "./mocha-call-allowance.js"; const FUNCTION = 1; const SUITE = 2; function isNestedInSuiteBlock(nesting) { return nesting.at(-1) === SUITE; } function reportCallExpression(context, callExpression) { context.report({ messageId: 'unexpectedFunctionCall', node: callExpression.callee }); } function reportMemberExpression(context, memberExpression) { context.report({ messageId: 'unexpectedMemberExpression', node: memberExpression }); } function normalizeAllowedCall(value) { const path = convertNameToPathArray(normalizeMochaCallName(value)); const [lastPathSegment] = path.slice(-1); return [...path.slice(0, -1), normalizeMochaCallName(lastPathSegment)]; } export const noSetupInSuiteRule = { meta: { type: 'suggestion', docs: { description: 'Disallow setup in suite blocks', recommended: false, url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/documentation/rules/no-setup-in-suite.md' }, schema: [allowMochaCallOptionSchema], defaultOptions: [defaultAllowMochaCallOption], messages: { unexpectedFunctionCall: 'Unexpected function call in suite block.', unexpectedMemberExpression: 'Unexpected member expression in suite block. Member expressions may call functions via getters.' }, languages: ['js/js'] }, create(context) { const { allow } = getRuleOption(context); const allowedCalls = allow.map(normalizeAllowedCall); let nesting = []; const suiteNodes = new WeakSet(); function isAllowedCall(node) { const calleeWithParent = { ...node.callee, parent: node }; const path = reformatLastPathSegmentWithCallExpressions(extractMemberExpressionPath(context.sourceCode, calleeWithParent), 1); return isConstantPath(path) && allowedCalls.some(function (allowedCall) { return isSamePath(path, allowedCall); }); } function isAllowedCallMemberExpression(node) { return node.parent.type === 'CallExpression' && node.parent.callee === node && isAllowedCall(node.parent); } function handleCallExpressionInSuite(node) { if (isNestedInSuiteBlock(nesting) && !isSuiteConfigCall(node) && !isAllowedCall(node)) { reportCallExpression(context, node); } } return createMochaVisitors(context, { suite(visitorContext) { nesting = [...nesting, SUITE]; suiteNodes.add(visitorContext.node); }, 'suite:exit'() { nesting = nesting.slice(0, -1); }, nonMochaCallExpression(node) { handleCallExpressionInSuite(node); }, nonMochaMemberExpression(node) { if (!suiteNodes.has(node.parent) && isNestedInSuiteBlock(nesting) && !isSuiteConfigCall(node.parent) && !isAllowedCallMemberExpression(node)) { reportMemberExpression(context, node); } }, FunctionDeclaration() { nesting = [...nesting, FUNCTION]; }, 'FunctionDeclaration:exit'() { nesting = nesting.slice(0, -1); }, FunctionExpression(node) { if (nesting.length > 0 && !suiteNodes.has(node.parent)) { nesting = [...nesting, FUNCTION]; } }, 'FunctionExpression:exit'(node) { if (!suiteNodes.has(node.parent)) { nesting = nesting.slice(0, -1); } }, ArrowFunctionExpression(node) { if (nesting.length > 0 && !suiteNodes.has(node.parent)) { nesting = [...nesting, FUNCTION]; } }, 'ArrowFunctionExpression:exit'(node) { if (!suiteNodes.has(node.parent)) { nesting = nesting.slice(0, -1); } } }); } }; //# sourceMappingURL=no-setup-in-suite.js.map