/
no-identical-title.ts
95 lines (82 loc) · 2.19 KB
/
no-identical-title.ts
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
import {
createRule,
getStringValue,
isStringNode,
isSupportedAccessor,
isTypeOfJestFnCall,
parseJestFnCall,
} from './utils';
interface DescribeContext {
describeTitles: string[];
testTitles: string[];
}
const newDescribeContext = (): DescribeContext => ({
describeTitles: [],
testTitles: [],
});
export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow identical titles',
recommended: 'error',
},
messages: {
multipleTestTitle:
'Test title is used multiple times in the same describe block.',
multipleDescribeTitle:
'Describe block title is used multiple times in the same describe block.',
},
schema: [],
type: 'suggestion',
},
defaultOptions: [],
create(context) {
const contexts = [newDescribeContext()];
return {
CallExpression(node) {
const currentLayer = contexts[contexts.length - 1];
const jestFnCall = parseJestFnCall(node, context);
if (!jestFnCall) {
return;
}
if (jestFnCall.type === 'describe') {
contexts.push(newDescribeContext());
}
if (jestFnCall.members.find(s => isSupportedAccessor(s, 'each'))) {
return;
}
const [argument] = node.arguments;
if (!argument || !isStringNode(argument)) {
return;
}
const title = getStringValue(argument);
if (jestFnCall.type === 'test') {
if (currentLayer.testTitles.includes(title)) {
context.report({
messageId: 'multipleTestTitle',
node: argument,
});
}
currentLayer.testTitles.push(title);
}
if (jestFnCall.type !== 'describe') {
return;
}
if (currentLayer.describeTitles.includes(title)) {
context.report({
messageId: 'multipleDescribeTitle',
node: argument,
});
}
currentLayer.describeTitles.push(title);
},
'CallExpression:exit'(node) {
if (isTypeOfJestFnCall(node, context, ['describe'])) {
contexts.pop();
}
},
};
},
});