/
no-empty-description.js
105 lines (87 loc) · 2.87 KB
/
no-empty-description.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
'use strict';
const { getStringIfConstant } = require('eslint-utils');
const DEFAULT_TEST_NAMES = [ 'describe', 'context', 'suite', 'it', 'test', 'specify' ];
const ERROR_MESSAGE = 'Unexpected empty test description.';
function objectOptions(options = {}) {
const {
testNames = DEFAULT_TEST_NAMES,
message
} = options;
return { testNames, message };
}
function isLiteral(node) {
return node && node.type === 'Literal';
}
function isStaticallyAnalyzableDescription(node, extractedText) {
if (extractedText === null) {
return isLiteral(node);
}
return true;
}
function isValidDescriptionArgumentNode(node) {
if (!node) {
return false;
}
return [
'Literal', 'TemplateLiteral', 'TaggedTemplateExpression',
'Identifier', 'MemberExpression', 'CallExpression',
'LogicalExpression', 'BinaryExpression', 'ConditionalExpression',
'UnaryExpression', 'SpreadElement', 'AwaitExpression',
'YieldExpression', 'NewExpression' ].includes(node.type);
}
module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'Disallow empty test descriptions',
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-empty-description.md'
},
schema: [
{
type: 'object',
properties: {
testNames: {
type: 'array',
items: {
type: 'string'
}
},
message: {
type: 'string'
}
},
additionalProperties: false
}
]
},
create(context) {
const options = context.options[0];
const { testNames, message } = objectOptions(options);
function isTest(node) {
return node.callee && node.callee.name && testNames.includes(node.callee.name);
}
function isNonEmptyDescription(mochaCallExpression) {
const description = mochaCallExpression.arguments[0];
if (!isValidDescriptionArgumentNode(description)) {
return false;
}
const text = getStringIfConstant(description, context.getScope());
if (!isStaticallyAnalyzableDescription(description, text)) {
return true;
}
return text && text.trim().length;
}
return {
CallExpression(node) {
if (isTest(node)) {
if (!isNonEmptyDescription(node)) {
context.report({
node,
message: message || ERROR_MESSAGE
});
}
}
}
};
}
};