Skip to content

Commit 2894eaa

Browse files
garykingSimenB
authored andcommittedSep 30, 2018
feat(rules): no-alias-methods (#164)
1 parent 7515458 commit 2894eaa

File tree

5 files changed

+264
-0
lines changed

5 files changed

+264
-0
lines changed
 

Diff for: ‎README.md

+2
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ for more information about extending configuration files.
8383
| [consistent-test-it][] | Enforce consistent test or it keyword | | ![fixable-green][] |
8484
| [expect-expect][] | Enforce assertion to be made in a test body | | |
8585
| [lowercase-name][] | Disallow capitalized test names | | ![fixable-green][] |
86+
| [no-alias-methods][] | Disallow alias methods | | |
8687
| [no-disabled-tests][] | Disallow disabled tests | ![recommended][] | |
8788
| [no-focused-tests][] | Disallow focused tests | ![recommended][] | |
8889
| [no-hooks][] | Disallow setup and teardown hooks | | |
@@ -111,6 +112,7 @@ for more information about extending configuration files.
111112
[consistent-test-it]: docs/rules/consistent-test-it.md
112113
[expect-expect]: docs/rules/expect-expect.md
113114
[lowercase-name]: docs/rules/lowercase-name.md
115+
[no-alias-methods]: docs/rules/no-alias-methods.md
114116
[no-disabled-tests]: docs/rules/no-disabled-tests.md
115117
[no-focused-tests]: docs/rules/no-focused-tests.md
116118
[no-hooks]: docs/rules/no-hooks.md

Diff for: ‎docs/rules/no-alias-methods.md

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Don't use alias methods (no-alias-methods)
2+
3+
Several Jest methods have alias names, such as `toThrow` having the alias of
4+
`toThrowError`. This rule ensures that only the canonical name as used in the
5+
Jest documentation is used in the code. This makes it easier to search for all
6+
occurrences of the method within code, and it ensures consistency among the
7+
method names used.
8+
9+
## Rule details
10+
11+
This rule triggers a warning if the alias name, rather than the canonical name,
12+
of a method is used.
13+
14+
### Default configuration
15+
16+
The following patterns are considered warnings:
17+
18+
```js
19+
expect(a).toBeCalled();
20+
expect(a).toBeCalledTimes();
21+
expect(a).toBeCalledWith();
22+
expect(a).lastCalledWith();
23+
expect(a).nthCalledWith();
24+
expect(a).toReturn();
25+
expect(a).toReturnTimes();
26+
expect(a).toReturnWith();
27+
expect(a).lastReturnedWith();
28+
expect(a).nthReturnedWith();
29+
expect(a).toThrowError();
30+
```
31+
32+
The following patterns are not considered warnings:
33+
34+
```js
35+
expect(a).toHaveBeenCalled();
36+
expect(a).toHaveBeenCalledTimes();
37+
expect(a).toHaveBeenCalledWith();
38+
expect(a).toHaveBeenLastCalledWith();
39+
expect(a).toHaveBeenNthCalledWith();
40+
expect(a).toHaveReturned();
41+
expect(a).toHaveReturnedTimes();
42+
expect(a).toHaveReturnedWith();
43+
expect(a).toHaveLastReturnedWith();
44+
expect(a).toHaveNthReturnedWith();
45+
expect(a).toThrow();
46+
```

Diff for: ‎index.js

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const validExpectInPromise = require('./rules/valid-expect-in-promise');
2222
const preferInlineSnapshots = require('./rules/prefer-inline-snapshots');
2323
const preferStrictEqual = require('./rules/prefer-strict-equal');
2424
const requireTothrowMessage = require('./rules/require-tothrow-message');
25+
const noAliasMethods = require('./rules/no-alias-methods');
2526

2627
const snapshotProcessor = require('./processors/snapshot-processor');
2728

@@ -91,5 +92,6 @@ module.exports = {
9192
'prefer-inline-snapshots': preferInlineSnapshots,
9293
'prefer-strict-equal': preferStrictEqual,
9394
'require-tothrow-message': requireTothrowMessage,
95+
'no-alias-methods': noAliasMethods,
9496
},
9597
};

Diff for: ‎rules/__tests__/no-alias-methods.test.js

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
'use strict';
2+
3+
const RuleTester = require('eslint').RuleTester;
4+
const rule = require('../no-alias-methods');
5+
6+
const ruleTester = new RuleTester();
7+
8+
ruleTester.run('no-alias-methods', rule, {
9+
valid: [
10+
'expect(a).toHaveBeenCalled()',
11+
'expect(a).toHaveBeenCalledTimes()',
12+
'expect(a).toHaveBeenCalledWith()',
13+
'expect(a).toHaveBeenLastCalledWith()',
14+
'expect(a).toHaveBeenNthCalledWith()',
15+
'expect(a).toHaveReturned()',
16+
'expect(a).toHaveReturnedTimes()',
17+
'expect(a).toHaveReturnedWith()',
18+
'expect(a).toHaveLastReturnedWith()',
19+
'expect(a).toHaveNthReturnedWith()',
20+
'expect(a).toThrow()',
21+
],
22+
23+
invalid: [
24+
{
25+
code: 'expect(a).toBeCalled()',
26+
errors: [
27+
{
28+
message:
29+
'Replace toBeCalled() with its canonical name of toHaveBeenCalled()',
30+
column: 11,
31+
line: 1,
32+
},
33+
],
34+
output: 'expect(a).toHaveBeenCalled()',
35+
},
36+
{
37+
code: 'expect(a).toBeCalledTimes()',
38+
errors: [
39+
{
40+
message:
41+
'Replace toBeCalledTimes() with its canonical name of toHaveBeenCalledTimes()',
42+
column: 11,
43+
line: 1,
44+
},
45+
],
46+
output: 'expect(a).toHaveBeenCalledTimes()',
47+
},
48+
{
49+
code: 'expect(a).toBeCalledWith()',
50+
errors: [
51+
{
52+
message:
53+
'Replace toBeCalledWith() with its canonical name of toHaveBeenCalledWith()',
54+
column: 11,
55+
line: 1,
56+
},
57+
],
58+
output: 'expect(a).toHaveBeenCalledWith()',
59+
},
60+
{
61+
code: 'expect(a).lastCalledWith()',
62+
errors: [
63+
{
64+
message:
65+
'Replace lastCalledWith() with its canonical name of toHaveBeenLastCalledWith()',
66+
column: 11,
67+
line: 1,
68+
},
69+
],
70+
output: 'expect(a).toHaveBeenLastCalledWith()',
71+
},
72+
{
73+
code: 'expect(a).nthCalledWith()',
74+
errors: [
75+
{
76+
message:
77+
'Replace nthCalledWith() with its canonical name of toHaveBeenNthCalledWith()',
78+
column: 11,
79+
line: 1,
80+
},
81+
],
82+
output: 'expect(a).toHaveBeenNthCalledWith()',
83+
},
84+
{
85+
code: 'expect(a).toReturn()',
86+
errors: [
87+
{
88+
message:
89+
'Replace toReturn() with its canonical name of toHaveReturned()',
90+
column: 11,
91+
line: 1,
92+
},
93+
],
94+
output: 'expect(a).toHaveReturned()',
95+
},
96+
{
97+
code: 'expect(a).toReturnTimes()',
98+
errors: [
99+
{
100+
message:
101+
'Replace toReturnTimes() with its canonical name of toHaveReturnedTimes()',
102+
column: 11,
103+
line: 1,
104+
},
105+
],
106+
output: 'expect(a).toHaveReturnedTimes()',
107+
},
108+
{
109+
code: 'expect(a).toReturnWith()',
110+
errors: [
111+
{
112+
message:
113+
'Replace toReturnWith() with its canonical name of toHaveReturnedWith()',
114+
column: 11,
115+
line: 1,
116+
},
117+
],
118+
output: 'expect(a).toHaveReturnedWith()',
119+
},
120+
{
121+
code: 'expect(a).lastReturnedWith()',
122+
errors: [
123+
{
124+
message:
125+
'Replace lastReturnedWith() with its canonical name of toHaveLastReturnedWith()',
126+
column: 11,
127+
line: 1,
128+
},
129+
],
130+
output: 'expect(a).toHaveLastReturnedWith()',
131+
},
132+
{
133+
code: 'expect(a).nthReturnedWith()',
134+
errors: [
135+
{
136+
message:
137+
'Replace nthReturnedWith() with its canonical name of toHaveNthReturnedWith()',
138+
column: 11,
139+
line: 1,
140+
},
141+
],
142+
output: 'expect(a).toHaveNthReturnedWith()',
143+
},
144+
{
145+
code: 'expect(a).toThrowError()',
146+
errors: [
147+
{
148+
message:
149+
'Replace toThrowError() with its canonical name of toThrow()',
150+
column: 11,
151+
line: 1,
152+
},
153+
],
154+
output: 'expect(a).toThrow()',
155+
},
156+
],
157+
});

Diff for: ‎rules/no-alias-methods.js

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
'use strict';
2+
3+
const expectCase = require('./util').expectCase;
4+
const getDocsUrl = require('./util').getDocsUrl;
5+
const method = require('./util').method;
6+
7+
module.exports = {
8+
meta: {
9+
docs: {
10+
url: getDocsUrl(__filename),
11+
},
12+
fixable: 'code',
13+
},
14+
create(context) {
15+
// The Jest methods which have aliases. The canonical name is the first
16+
// index of each item.
17+
const methodNames = [
18+
['toHaveBeenCalled', 'toBeCalled'],
19+
['toHaveBeenCalledTimes', 'toBeCalledTimes'],
20+
['toHaveBeenCalledWith', 'toBeCalledWith'],
21+
['toHaveBeenLastCalledWith', 'lastCalledWith'],
22+
['toHaveBeenNthCalledWith', 'nthCalledWith'],
23+
['toHaveReturned', 'toReturn'],
24+
['toHaveReturnedTimes', 'toReturnTimes'],
25+
['toHaveReturnedWith', 'toReturnWith'],
26+
['toHaveLastReturnedWith', 'lastReturnedWith'],
27+
['toHaveNthReturnedWith', 'nthReturnedWith'],
28+
['toThrow', 'toThrowError'],
29+
];
30+
31+
return {
32+
CallExpression(node) {
33+
if (!expectCase(node)) {
34+
return;
35+
}
36+
37+
// Check if the method used matches any of ours.
38+
const propertyName = method(node) && method(node).name;
39+
const methodItem = methodNames.find(item => item[1] === propertyName);
40+
41+
if (methodItem) {
42+
context.report({
43+
message: `Replace {{ replace }}() with its canonical name of {{ canonical }}()`,
44+
data: {
45+
replace: methodItem[1],
46+
canonical: methodItem[0],
47+
},
48+
node: method(node),
49+
fix(fixer) {
50+
return [fixer.replaceText(method(node), methodItem[0])];
51+
},
52+
});
53+
}
54+
},
55+
};
56+
},
57+
};

0 commit comments

Comments
 (0)
Please sign in to comment.