valid-describe-callback
Ast Rule: function call
valid-describe-callback
const DESCRIBES = [
// astType = string
"describe",
"fdescribe",
"xdescribe",
// astType = member
"describe.only",
"describe.skip",
];
function visit(node, filename, code) {
// only run on .spec. or .test. files
if (!filename.includes(".spec.") && !filename.includes(".test.")) return;
if (
!node.functionName ||
!node.arguments ||
!node.arguments.values ||
node.arguments.values.length === 0
)
return;
function checkCallback(node) {
if (node.arguments.values[1].value.astType === "string") {
const error = buildError(
node.arguments.values[1].value.start.line,
node.arguments.values[1].value.start.col,
node.arguments.values[1].value.end.line,
node.arguments.values[1].value.end.col,
"Second argument must be function",
"WARNING",
"BEST_PRACTICE"
);
addError(error);
return true;
}
if (node.arguments.values[1].value.isAsync) {
const error = buildError(
node.arguments.values[1].value.start.line,
node.arguments.values[1].value.start.col,
node.arguments.values[1].value.end.line,
node.arguments.values[1].value.end.col,
"No async describe callback",
"WARNING",
"BEST_PRACTICE"
);
addError(error);
return true;
}
if (node.arguments.values[1].value?.parameters?.values?.length > 0) {
const error = buildError(
node.arguments.values[1].value?.parameters.values[0].name.start.line,
node.arguments.values[1].value?.parameters.values[0].name.start.col,
node.arguments.values[1].value?.parameters.values[0].name.end.line,
node.arguments.values[1].value?.parameters.values[0].name.end.col,
"Unexpected argument(s) in describe callback",
"WARNING",
"BEST_PRACTICE"
);
addError(error);
return true;
}
const content = node.arguments.values[1].value?.content;
if (!content) return;
// check if the callback has a return statement or is auto returned
if (content.elements) {
for (let i = 0; i < content.elements.length; i++) {
if (content.elements[i].astType === "return") {
const error = buildError(
content.elements[i].start.line,
content.elements[i].start.col,
content.elements[i].end.line,
content.elements[i].end.col,
"Unexpected return statement in describe callback",
"WARNING",
"BEST_PRACTICE"
);
addError(error);
return true;
}
}
} else {
const error = buildError(
node.arguments.values[1].value.start.line,
node.arguments.values[1].value.start.col,
node.arguments.values[1].value.end.line,
node.arguments.values[1].value.end.col,
"Unexpected return statement in describe callback",
"WARNING",
"BEST_PRACTICE"
);
addError(error);
return true;
}
return false;
}
if (node.functionName.astType === "string") {
const name = DESCRIBES.includes(node.functionName.value);
if (!name) return;
if (checkCallback(node)) return;
}
if (node.functionName.astType === "member") {
const first = node.functionName?.parent?.value;
if (!first) return;
const second = node.functionName?.name?.value;
if (!second) return;
const name = DESCRIBES.includes(`${first}.${second}`);
if (!name) return;
if (checkCallback(node)) return;
}
}
bad-with-aliases.spec.js
Expected test result: has error
The following are considered warning when you use aliases too.
bad.test.js
Expected test result: has error
The following are considered warnings
good.spec.js
Expected test result: no error
The following are not warnings