Skip to content

Commit ce8cd61

Browse files
authored
fix(require-hook): check variables are either const or declarations (#959)
1 parent 5278fcb commit ce8cd61

File tree

3 files changed

+125
-1
lines changed

3 files changed

+125
-1
lines changed

docs/rules/require-hook.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ directly within the body of a `describe`, _except_ for the following:
1919

2020
- `import` statements
2121
- `const` variables
22-
- `let` _declarations_
22+
- `let` _declarations_, and initializations to `null` or `undefined`
2323
- Types
2424
- Calls to the standard Jest globals
2525

src/rules/__tests__/require-hook.test.ts

+107
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,20 @@ ruleTester.run('require-hook', rule, {
7676
});
7777
});
7878
`,
79+
dedent`
80+
let consoleErrorSpy = null;
81+
82+
beforeEach(() => {
83+
consoleErrorSpy = jest.spyOn(console, 'error');
84+
});
85+
`,
86+
dedent`
87+
let consoleErrorSpy = undefined;
88+
89+
beforeEach(() => {
90+
consoleErrorSpy = jest.spyOn(console, 'error');
91+
});
92+
`,
7993
dedent`
8094
describe('some tests', () => {
8195
beforeEach(() => {
@@ -145,6 +159,27 @@ ruleTester.run('require-hook', rule, {
145159
},
146160
],
147161
},
162+
{
163+
code: dedent`
164+
let { setup } = require('./test-utils');
165+
166+
describe('some tests', () => {
167+
setup();
168+
});
169+
`,
170+
errors: [
171+
{
172+
messageId: 'useHook',
173+
line: 1,
174+
column: 1,
175+
},
176+
{
177+
messageId: 'useHook',
178+
line: 4,
179+
column: 3,
180+
},
181+
],
182+
},
148183
{
149184
code: dedent`
150185
describe('some tests', () => {
@@ -176,6 +211,73 @@ ruleTester.run('require-hook', rule, {
176211
},
177212
],
178213
},
214+
{
215+
code: dedent`
216+
let consoleErrorSpy = jest.spyOn(console, 'error');
217+
218+
describe('when loading cities from the api', () => {
219+
let consoleWarnSpy = jest.spyOn(console, 'warn');
220+
});
221+
`,
222+
errors: [
223+
{
224+
messageId: 'useHook',
225+
line: 1,
226+
column: 1,
227+
},
228+
{
229+
messageId: 'useHook',
230+
line: 4,
231+
column: 3,
232+
},
233+
],
234+
},
235+
{
236+
code: dedent`
237+
let consoleErrorSpy = null;
238+
239+
describe('when loading cities from the api', () => {
240+
let consoleWarnSpy = jest.spyOn(console, 'warn');
241+
});
242+
`,
243+
errors: [
244+
{
245+
messageId: 'useHook',
246+
line: 4,
247+
column: 3,
248+
},
249+
],
250+
},
251+
{
252+
code: 'let value = 1',
253+
errors: [
254+
{
255+
messageId: 'useHook',
256+
line: 1,
257+
column: 1,
258+
},
259+
],
260+
},
261+
{
262+
code: "let consoleErrorSpy, consoleWarnSpy = jest.spyOn(console, 'error');",
263+
errors: [
264+
{
265+
messageId: 'useHook',
266+
line: 1,
267+
column: 1,
268+
},
269+
],
270+
},
271+
{
272+
code: "let consoleErrorSpy = jest.spyOn(console, 'error'), consoleWarnSpy;",
273+
errors: [
274+
{
275+
messageId: 'useHook',
276+
line: 1,
277+
column: 1,
278+
},
279+
],
280+
},
179281
{
180282
code: dedent`
181283
import { database, isCity } from '../database';
@@ -236,6 +338,11 @@ ruleTester.run('require-hook', rule, {
236338
line: 16,
237339
column: 1,
238340
},
341+
{
342+
messageId: 'useHook',
343+
line: 31,
344+
column: 3,
345+
},
239346
{
240347
messageId: 'useHook',
241348
line: 33,

src/rules/require-hook.ts

+17
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
isDescribeCall,
99
isFunction,
1010
isHook,
11+
isIdentifier,
1112
isTestCaseCall,
1213
} from './utils';
1314

@@ -19,12 +20,28 @@ const isJestFnCall = (node: TSESTree.CallExpression): boolean => {
1920
return !!getNodeName(node)?.startsWith('jest.');
2021
};
2122

23+
const isNullOrUndefined = (node: TSESTree.Expression): boolean => {
24+
return (
25+
(node.type === AST_NODE_TYPES.Literal && node.value === null) ||
26+
isIdentifier(node, 'undefined')
27+
);
28+
};
29+
2230
const shouldBeInHook = (node: TSESTree.Node): boolean => {
2331
switch (node.type) {
2432
case AST_NODE_TYPES.ExpressionStatement:
2533
return shouldBeInHook(node.expression);
2634
case AST_NODE_TYPES.CallExpression:
2735
return !isJestFnCall(node);
36+
case AST_NODE_TYPES.VariableDeclaration: {
37+
if (node.kind === 'const') {
38+
return false;
39+
}
40+
41+
return node.declarations.some(
42+
({ init }) => init !== null && !isNullOrUndefined(init),
43+
);
44+
}
2845

2946
default:
3047
return false;

0 commit comments

Comments
 (0)