Skip to content

Commit 7707e14

Browse files
authoredMay 27, 2018
feat(rules): add no-jasmine-globals (#116)
1 parent 523e2f4 commit 7707e14

File tree

4 files changed

+399
-0
lines changed

4 files changed

+399
-0
lines changed
 

‎docs/rules/no-jasmine-globals.md

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Disallow Jasmine globals
2+
3+
`jest` uses `jasmine` as a test runner. A side effect of this is that both a
4+
`jasmine` object, and some jasmine-specific globals, are exposed to the test
5+
environment. Most functionality offered by Jasmine has been ported to Jest, and
6+
the Jasmine globals will stop working in the future. Developers should therefor
7+
migrate to Jest's documented API instead of relying on the undocumented Jasmine
8+
API.
9+
10+
### Rule details
11+
12+
This rule reports on any usage of Jasmine globals which is not ported to Jest,
13+
and suggests alternative from Jest's own API.
14+
15+
### Default configuration
16+
17+
The following patterns are considered warnings:
18+
19+
```js
20+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
21+
22+
test('my test', () => {
23+
pending();
24+
});
25+
26+
test('my test', () => {
27+
fail();
28+
});
29+
30+
test('my test', () => {
31+
spyOn(some, 'object');
32+
});
33+
34+
test('my test', () => {
35+
jasmine.createSpy();
36+
});
37+
38+
test('my test', () => {
39+
expect('foo').toEqual(jasmine.anything());
40+
});
41+
```
42+
43+
The following patterns would not be considered warnings:
44+
45+
```js
46+
jest.setTimeout(5000);
47+
48+
test('my test', () => {
49+
jest.spyOn(some, 'object');
50+
});
51+
52+
test('my test', () => {
53+
jest.fn();
54+
});
55+
56+
test('my test', () => {
57+
expect('foo').toEqual(expect.anything());
58+
});
59+
```

‎index.js

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const noDisabledTests = require('./rules/no-disabled-tests');
66
const noFocusedTests = require('./rules/no-focused-tests');
77
const noHooks = require('./rules/no-hooks');
88
const noIdenticalTitle = require('./rules/no-identical-title');
9+
const noJasmineGlobals = require('./rules/no-jasmine-globals');
910
const noJestImport = require('./rules/no-jest-import');
1011
const noLargeSnapshots = require('./rules/no-large-snapshots');
1112
const noTestPrefixes = require('./rules/no-test-prefixes');
@@ -69,6 +70,7 @@ module.exports = {
6970
'no-focused-tests': noFocusedTests,
7071
'no-hooks': noHooks,
7172
'no-identical-title': noIdenticalTitle,
73+
'no-jasmine-globals': noJasmineGlobals,
7274
'no-jest-import': noJestImport,
7375
'no-large-snapshots': noLargeSnapshots,
7476
'no-test-prefixes': noTestPrefixes,
+224
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
'use strict';
2+
3+
const RuleTester = require('eslint').RuleTester;
4+
const rule = require('../no-jasmine-globals');
5+
6+
const ruleTester = new RuleTester();
7+
8+
ruleTester.run('no-jasmine-globals', rule, {
9+
valid: [
10+
'jest.spyOn()',
11+
'jest.fn()',
12+
'expect.extend()',
13+
'expect.any()',
14+
'it("foo", function () {})',
15+
'test("foo", function () {})',
16+
'foo()',
17+
],
18+
invalid: [
19+
{
20+
code: 'spyOn(some, "object")',
21+
errors: [
22+
{
23+
message: 'Illegal usage of global `spyOn`, prefer `jest.spyOn`',
24+
column: 1,
25+
line: 1,
26+
},
27+
],
28+
},
29+
{
30+
code: 'spyOnProperty(some, "object")',
31+
errors: [
32+
{
33+
message:
34+
'Illegal usage of global `spyOnProperty`, prefer `jest.spyOn`',
35+
column: 1,
36+
line: 1,
37+
},
38+
],
39+
},
40+
{
41+
code: 'fail()',
42+
errors: [
43+
{
44+
message:
45+
'Illegal usage of `fail`, prefer throwing an error, or the `done.fail` callback',
46+
column: 1,
47+
line: 1,
48+
},
49+
],
50+
},
51+
{
52+
code: 'pending()',
53+
errors: [
54+
{
55+
message:
56+
'Illegal usage of `pending`, prefer explicitly skipping a test using `test.skip`',
57+
column: 1,
58+
line: 1,
59+
},
60+
],
61+
},
62+
{
63+
code: 'jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;',
64+
errors: [
65+
{
66+
message: 'Illegal usage of jasmine global',
67+
column: 1,
68+
line: 1,
69+
},
70+
],
71+
output: 'jest.setTimeout(5000);',
72+
},
73+
{
74+
code: 'jasmine.addMatchers(matchers)',
75+
errors: [
76+
{
77+
message:
78+
'Illegal usage of `jasmine.addMatchers`, prefer `expect.extend`',
79+
column: 1,
80+
line: 1,
81+
},
82+
],
83+
},
84+
{
85+
code: 'jasmine.createSpy()',
86+
errors: [
87+
{
88+
message: 'Illegal usage of `jasmine.createSpy`, prefer `jest.fn`',
89+
column: 1,
90+
line: 1,
91+
},
92+
],
93+
},
94+
{
95+
code: 'jasmine.any()',
96+
errors: [
97+
{
98+
message: 'Illegal usage of `jasmine.any`, prefer `expect.any`',
99+
column: 1,
100+
line: 1,
101+
},
102+
],
103+
output: 'expect.any()',
104+
},
105+
{
106+
code: 'jasmine.anything()',
107+
errors: [
108+
{
109+
message:
110+
'Illegal usage of `jasmine.anything`, prefer `expect.anything`',
111+
column: 1,
112+
line: 1,
113+
},
114+
],
115+
output: 'expect.anything()',
116+
},
117+
{
118+
code: 'jasmine.arrayContaining()',
119+
errors: [
120+
{
121+
message:
122+
'Illegal usage of `jasmine.arrayContaining`, prefer `expect.arrayContaining`',
123+
column: 1,
124+
line: 1,
125+
},
126+
],
127+
output: 'expect.arrayContaining()',
128+
},
129+
{
130+
code: 'jasmine.objectContaining()',
131+
errors: [
132+
{
133+
message:
134+
'Illegal usage of `jasmine.objectContaining`, prefer `expect.objectContaining`',
135+
column: 1,
136+
line: 1,
137+
},
138+
],
139+
output: 'expect.objectContaining()',
140+
},
141+
{
142+
code: 'jasmine.stringMatching()',
143+
errors: [
144+
{
145+
message:
146+
'Illegal usage of `jasmine.stringMatching`, prefer `expect.stringMatching`',
147+
column: 1,
148+
line: 1,
149+
},
150+
],
151+
output: 'expect.stringMatching()',
152+
},
153+
{
154+
code: 'jasmine.getEnv()',
155+
errors: [
156+
{
157+
message: 'Illegal usage of jasmine global',
158+
column: 1,
159+
line: 1,
160+
},
161+
],
162+
},
163+
{
164+
code: 'jasmine.empty()',
165+
errors: [
166+
{
167+
message: 'Illegal usage of jasmine global',
168+
column: 1,
169+
line: 1,
170+
},
171+
],
172+
},
173+
{
174+
code: 'jasmine.falsy()',
175+
errors: [
176+
{
177+
message: 'Illegal usage of jasmine global',
178+
column: 1,
179+
line: 1,
180+
},
181+
],
182+
},
183+
{
184+
code: 'jasmine.truthy()',
185+
errors: [
186+
{
187+
message: 'Illegal usage of jasmine global',
188+
column: 1,
189+
line: 1,
190+
},
191+
],
192+
},
193+
{
194+
code: 'jasmine.arrayWithExactContents()',
195+
errors: [
196+
{
197+
message: 'Illegal usage of jasmine global',
198+
column: 1,
199+
line: 1,
200+
},
201+
],
202+
},
203+
{
204+
code: 'jasmine.clock()',
205+
errors: [
206+
{
207+
message: 'Illegal usage of jasmine global',
208+
column: 1,
209+
line: 1,
210+
},
211+
],
212+
},
213+
{
214+
code: 'jasmine.MAX_PRETTY_PRINT_ARRAY_LENGTH = 42',
215+
errors: [
216+
{
217+
message: 'Illegal usage of jasmine global',
218+
column: 1,
219+
line: 1,
220+
},
221+
],
222+
},
223+
],
224+
});

‎rules/no-jasmine-globals.js

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
'use strict';
2+
3+
const getDocsUrl = require('./util').getDocsUrl;
4+
const getNodeName = require('./util').getNodeName;
5+
6+
module.exports = {
7+
meta: {
8+
docs: {
9+
url: getDocsUrl(__filename),
10+
},
11+
fixable: 'code',
12+
},
13+
create(context) {
14+
return {
15+
CallExpression(node) {
16+
const calleeName = getNodeName(node.callee);
17+
18+
if (calleeName === 'spyOn' || calleeName === 'spyOnProperty') {
19+
context.report({
20+
node,
21+
message: `Illegal usage of global \`${calleeName}\`, prefer \`jest.spyOn\``,
22+
});
23+
return;
24+
}
25+
26+
if (calleeName === 'fail') {
27+
context.report({
28+
node,
29+
message:
30+
'Illegal usage of `fail`, prefer throwing an error, or the `done.fail` callback',
31+
});
32+
return;
33+
}
34+
35+
if (calleeName === 'pending') {
36+
context.report({
37+
node,
38+
message:
39+
'Illegal usage of `pending`, prefer explicitly skipping a test using `test.skip`',
40+
});
41+
return;
42+
}
43+
44+
if (calleeName.startsWith('jasmine.')) {
45+
const functionName = calleeName.replace('jasmine.', '');
46+
47+
if (
48+
functionName === 'any' ||
49+
functionName === 'anything' ||
50+
functionName === 'arrayContaining' ||
51+
functionName === 'objectContaining' ||
52+
functionName === 'stringMatching'
53+
) {
54+
context.report({
55+
fix(fixer) {
56+
return [fixer.replaceText(node.callee.object, 'expect')];
57+
},
58+
node,
59+
message: `Illegal usage of \`${calleeName}\`, prefer \`expect.${functionName}\``,
60+
});
61+
return;
62+
}
63+
64+
if (functionName === 'addMatchers') {
65+
context.report({
66+
node,
67+
message: `Illegal usage of \`${calleeName}\`, prefer \`expect.extend\``,
68+
});
69+
return;
70+
}
71+
72+
if (functionName === 'createSpy') {
73+
context.report({
74+
node,
75+
message: `Illegal usage of \`${calleeName}\`, prefer \`jest.fn\``,
76+
});
77+
return;
78+
}
79+
80+
context.report({
81+
node,
82+
message: 'Illegal usage of jasmine global',
83+
});
84+
}
85+
},
86+
MemberExpression(node) {
87+
if (node.object.name === 'jasmine') {
88+
if (node.parent.type === 'AssignmentExpression') {
89+
if (node.property.name === 'DEFAULT_TIMEOUT_INTERVAL') {
90+
context.report({
91+
fix(fixer) {
92+
return [
93+
fixer.replaceText(
94+
node.parent,
95+
`jest.setTimeout(${node.parent.right.value})`
96+
),
97+
];
98+
},
99+
node,
100+
message: 'Illegal usage of jasmine global',
101+
});
102+
return;
103+
}
104+
105+
context.report({
106+
node,
107+
message: 'Illegal usage of jasmine global',
108+
});
109+
}
110+
}
111+
},
112+
};
113+
},
114+
};

0 commit comments

Comments
 (0)
Please sign in to comment.