eslint-plugin-mocha
Version:
Eslint rules for mocha.
85 lines • 3.15 kB
JavaScript
import { createMochaVisitors } from "../ast/mocha-visitors.js";
import { getLastOrThrow } from "../list.js";
import { getRuleOption } from "../rule-options.js";
import { allowMochaCallOptionSchema, defaultAllowMochaCallOption, normalizeMochaCallName } from "./mocha-call-allowance.js";
function newSuiteLayer(suiteNode) {
return {
suiteNode,
hookNodes: [],
testCount: 0
};
}
export const noHooksForSingleChildRule = {
meta: {
type: 'suggestion',
docs: {
description: 'Disallow hooks with a single direct child',
recommended: false,
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/documentation/rules/no-hooks-for-single-child.md'
},
schema: [allowMochaCallOptionSchema],
defaultOptions: [defaultAllowMochaCallOption],
messages: {
unexpectedHookForSingleChild: 'Unexpected use of Mocha `{{name}}` hook with only one direct child.'
},
languages: ['js/js']
},
create(context) {
const { allow } = getRuleOption(context);
const allowedHooks = new Set(allow.map(normalizeMochaCallName));
let layers = [];
function increaseTestCount() {
layers = layers.map(function (layer) {
return {
suiteNode: layer.suiteNode,
hookNodes: layer.hookNodes,
testCount: layer.testCount + 1
};
});
}
function popLayer(node) {
const layer = layers.at(-1);
if (layer?.suiteNode === node) {
if (layer.testCount <= 1) {
layer
.hookNodes
.filter(function (hookNode) {
return !allowedHooks.has(hookNode.name);
})
.forEach(function (hookNode) {
context.report({
node: hookNode.node,
messageId: 'unexpectedHookForSingleChild',
data: { name: hookNode.name }
});
});
}
layers.pop();
}
}
return createMochaVisitors(context, {
suite(visitorContext) {
increaseTestCount();
layers.push(newSuiteLayer(visitorContext.node));
},
testCase() {
increaseTestCount();
},
'anyTestEntity:exit'(visitorContext) {
popLayer(visitorContext.node);
},
Program(node) {
layers.push(newSuiteLayer(node));
},
'Program:exit': popLayer,
hook(visitorContext) {
const currentLayer = getLastOrThrow(layers);
layers[layers.length - 1] = {
...currentLayer,
hookNodes: [...currentLayer.hookNodes, visitorContext]
};
}
});
}
};
//# sourceMappingURL=no-hooks-for-single-child.js.map