Skip to content

Commit ad377d8

Browse files
ismail-syedSimenB
authored andcommitted
feat: add lowercase-description rule (#56)
Fixes #46
1 parent a12a2d2 commit ad377d8

File tree

5 files changed

+226
-0
lines changed

5 files changed

+226
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ for more information about extending configuration files.
8181
| Rule | Description | Recommended | Fixable |
8282
| ------------------------------------------------------------------ | ----------------------------------------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------- |
8383
| [consistent-test-it](docs/rules/consistent-test-it.md) | Enforce consistent test or it keyword | | ![fixable](https://img.shields.io/badge/-fixable-green.svg) |
84+
| [lowercase-name](docs/rules/lowercase-name.md) | Disallow capitalized test names | | |
8485
| [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | |
8586
| [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | |
8687
| [no-hooks](docs/rules/no-hooks.md) | Disallow setup and teardown hooks | | |

docs/rules/lowercase-name.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Enforce lowercase test names (lowercase-name)
2+
3+
## Rule details
4+
5+
Enforce `it`, `test` and `describe` to have descriptions that begin with a
6+
lowercase letter. This provides more readable test failures. This rule is not
7+
enabled by default.
8+
9+
The following pattern is considered a warning:
10+
11+
```js
12+
it('Adds 1 + 2 to equal 3', () => {
13+
expect(sum(1, 2)).toBe(3);
14+
});
15+
```
16+
17+
The following pattern is not considered a warning:
18+
19+
```js
20+
it('adds 1 + 2 to equal 3', () => {
21+
expect(sum(1, 2)).toBe(3);
22+
});
23+
```

index.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const consistentTestIt = require('./rules/consistent-test-it');
4+
const lowercaseName = require('./rules/lowercase-name');
45
const noDisabledTests = require('./rules/no-disabled-tests');
56
const noFocusedTests = require('./rules/no-focused-tests');
67
const noHooks = require('./rules/no-hooks');
@@ -61,6 +62,7 @@ module.exports = {
6162
},
6263
rules: {
6364
'consistent-test-it': consistentTestIt,
65+
'lowercase-name': lowercaseName,
6466
'no-disabled-tests': noDisabledTests,
6567
'no-focused-tests': noFocusedTests,
6668
'no-hooks': noHooks,
+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
'use strict';
2+
3+
const RuleTester = require('eslint').RuleTester;
4+
const rules = require('../..').rules;
5+
6+
const ruleTester = new RuleTester({
7+
parserOptions: {
8+
ecmaVersion: 6,
9+
},
10+
});
11+
12+
ruleTester.run('lowercase-name', rules['lowercase-name'], {
13+
valid: [
14+
"it(' ', function () {})",
15+
'it(" ", function () {})',
16+
'it(` `, function () {})',
17+
"it('foo', function () {})",
18+
'it("foo", function () {})',
19+
'it(`foo`, function () {})',
20+
'it("<Foo/>", function () {})',
21+
'it("123 foo", function () {})',
22+
'it(42, function () {})',
23+
"test('foo', function () {})",
24+
'test("foo", function () {})',
25+
'test(`foo`, function () {})',
26+
'test("<Foo/>", function () {})',
27+
'test("123 foo", function () {})',
28+
'test("42", function () {})',
29+
"describe('foo', function () {})",
30+
'describe("foo", function () {})',
31+
'describe(`foo`, function () {})',
32+
'describe("<Foo/>", function () {})',
33+
'describe("123 foo", function () {})',
34+
'describe("42", function () {})',
35+
'describe(function () {})',
36+
],
37+
38+
invalid: [
39+
{
40+
code: "it('Foo', function () {})",
41+
errors: [
42+
{
43+
message: '`it`s should begin with lowercase',
44+
column: 1,
45+
line: 1,
46+
},
47+
],
48+
},
49+
{
50+
code: 'it("Foo", function () {})',
51+
errors: [
52+
{
53+
message: '`it`s should begin with lowercase',
54+
column: 1,
55+
line: 1,
56+
},
57+
],
58+
},
59+
{
60+
code: 'it(`Foo`, function () {})',
61+
errors: [
62+
{
63+
message: '`it`s should begin with lowercase',
64+
column: 1,
65+
line: 1,
66+
},
67+
],
68+
},
69+
{
70+
code: "test('Foo', function () {})",
71+
errors: [
72+
{
73+
message: '`test`s should begin with lowercase',
74+
column: 1,
75+
line: 1,
76+
},
77+
],
78+
},
79+
{
80+
code: 'test("Foo", function () {})',
81+
errors: [
82+
{
83+
message: '`test`s should begin with lowercase',
84+
column: 1,
85+
line: 1,
86+
},
87+
],
88+
},
89+
{
90+
code: 'test(`Foo`, function () {})',
91+
errors: [
92+
{
93+
message: '`test`s should begin with lowercase',
94+
column: 1,
95+
line: 1,
96+
},
97+
],
98+
},
99+
{
100+
code: "describe('Foo', function () {})",
101+
errors: [
102+
{
103+
message: '`describe`s should begin with lowercase',
104+
column: 1,
105+
line: 1,
106+
},
107+
],
108+
},
109+
{
110+
code: 'describe("Foo", function () {})',
111+
errors: [
112+
{
113+
message: '`describe`s should begin with lowercase',
114+
column: 1,
115+
line: 1,
116+
},
117+
],
118+
},
119+
{
120+
code: 'describe(`Foo`, function () {})',
121+
errors: [
122+
{
123+
message: '`describe`s should begin with lowercase',
124+
column: 1,
125+
line: 1,
126+
},
127+
],
128+
},
129+
],
130+
});

rules/lowercase-name.js

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
'use strict';
2+
3+
const isItTestOrDescribeFunction = node => {
4+
return (
5+
node.type === 'CallExpression' &&
6+
node.callee &&
7+
(node.callee.name === 'it' ||
8+
node.callee.name === 'test' ||
9+
node.callee.name === 'describe')
10+
);
11+
};
12+
13+
const isItDescription = node => {
14+
return (
15+
node.arguments &&
16+
node.arguments[0] &&
17+
(node.arguments[0].type === 'Literal' ||
18+
node.arguments[0].type === 'TemplateLiteral')
19+
);
20+
};
21+
22+
const testDescription = node => {
23+
const firstArgument = node.arguments[0];
24+
const type = firstArgument.type;
25+
26+
if (type === 'Literal') {
27+
return firstArgument.value;
28+
}
29+
30+
// `isItDescription` guarantees this is `type === 'TemplateLiteral'`
31+
return firstArgument.quasis[0].value.raw;
32+
};
33+
34+
const descriptionBeginsWithLowerCase = node => {
35+
if (isItTestOrDescribeFunction(node) && isItDescription(node)) {
36+
const description = testDescription(node);
37+
if (!description[0]) {
38+
return false;
39+
}
40+
41+
if (description[0] !== description[0].toLowerCase()) {
42+
return node.callee.name;
43+
}
44+
}
45+
return false;
46+
};
47+
48+
module.exports = {
49+
meta: {
50+
docs: {
51+
url:
52+
'https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/lowercase-name.md',
53+
},
54+
},
55+
create(context) {
56+
return {
57+
CallExpression(node) {
58+
const erroneousMethod = descriptionBeginsWithLowerCase(node);
59+
60+
if (erroneousMethod) {
61+
context.report({
62+
message: '`{{ method }}`s should begin with lowercase',
63+
data: { method: erroneousMethod },
64+
node: node,
65+
});
66+
}
67+
},
68+
};
69+
},
70+
};

0 commit comments

Comments
 (0)