/
lowercase-name.js
115 lines (101 loc) · 2.82 KB
/
lowercase-name.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
106
107
108
109
110
111
112
113
114
115
'use strict';
const { getDocsUrl } = require('./util');
const isItTestOrDescribeFunction = node => {
return (
node.type === 'CallExpression' &&
node.callee &&
(node.callee.name === 'it' ||
node.callee.name === 'test' ||
node.callee.name === 'describe')
);
};
const isItDescription = node => {
return (
node.arguments &&
node.arguments[0] &&
(node.arguments[0].type === 'Literal' ||
node.arguments[0].type === 'TemplateLiteral')
);
};
const testDescription = node => {
const [firstArgument] = node.arguments;
const { type } = firstArgument;
if (type === 'Literal') {
return firstArgument.value;
}
// `isItDescription` guarantees this is `type === 'TemplateLiteral'`
return firstArgument.quasis[0].value.raw;
};
const descriptionBeginsWithLowerCase = node => {
if (isItTestOrDescribeFunction(node) && isItDescription(node)) {
const description = testDescription(node);
if (!description[0]) {
return false;
}
if (description[0] !== description[0].toLowerCase()) {
return node.callee.name;
}
}
return false;
};
module.exports = {
meta: {
docs: {
url: getDocsUrl(__filename),
},
messages: {
unexpectedLowercase: '`{{ method }}`s should begin with lowercase',
},
schema: [
{
type: 'object',
properties: {
ignore: {
type: 'array',
items: {
enum: ['describe', 'test', 'it'],
},
additionalItems: false,
},
},
additionalProperties: false,
},
],
fixable: 'code',
},
create(context) {
const ignore = (context.options[0] && context.options[0].ignore) || [];
const ignoredFunctionNames = ignore.reduce((accumulator, value) => {
accumulator[value] = true;
return accumulator;
}, Object.create(null));
const isIgnoredFunctionName = node =>
ignoredFunctionNames[node.callee.name];
return {
CallExpression(node) {
const erroneousMethod = descriptionBeginsWithLowerCase(node);
if (erroneousMethod && !isIgnoredFunctionName(node)) {
context.report({
messageId: 'unexpectedLowercase',
data: { method: erroneousMethod },
node,
fix(fixer) {
const [firstArg] = node.arguments;
const description = testDescription(node);
const rangeIgnoringQuotes = [
firstArg.range[0] + 1,
firstArg.range[1] - 1,
];
const newDescription =
description.substring(0, 1).toLowerCase() +
description.substring(1);
return [
fixer.replaceTextRange(rangeIgnoringQuotes, newDescription),
];
},
});
}
},
};
},
};