Skip to content

Commit 5720a80

Browse files
committed
refactor(no-wait-for-empty-callback): use new rule creator and helpers
1 parent dd30d02 commit 5720a80

File tree

3 files changed

+54
-20
lines changed

3 files changed

+54
-20
lines changed

lib/detect-testing-library-utils.ts

+12-5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
ASYNC_UTILS,
2323
PRESENCE_MATCHERS,
2424
ALL_QUERIES_COMBINATIONS,
25+
VALID_ASYNC_UTILS,
2526
} from './utils';
2627

2728
export type TestingLibrarySettings = {
@@ -63,7 +64,10 @@ type IsSyncQueryFn = (node: TSESTree.Identifier) => boolean;
6364
type IsAsyncQueryFn = (node: TSESTree.Identifier) => boolean;
6465
type IsQueryFn = (node: TSESTree.Identifier) => boolean;
6566
type IsCustomQueryFn = (node: TSESTree.Identifier) => boolean;
66-
type IsAsyncUtilFn = (node: TSESTree.Identifier) => boolean;
67+
type IsAsyncUtilFn = (
68+
node: TSESTree.Identifier,
69+
validNames?: VALID_ASYNC_UTILS[]
70+
) => boolean;
6771
type IsFireEventMethodFn = (node: TSESTree.Identifier) => boolean;
6872
type IsRenderUtilFn = (node: TSESTree.Identifier) => boolean;
6973
type IsPresenceAssertFn = (node: TSESTree.MemberExpression) => boolean;
@@ -298,10 +302,13 @@ export function detectTestingLibraryUtils<
298302
* Otherwise, it means `custom-module` has been set up, so only those nodes
299303
* coming from Testing Library will be considered as valid.
300304
*/
301-
const isAsyncUtil: IsAsyncUtilFn = (node) => {
302-
return isTestingLibraryUtil(node, (identifierNodeName) =>
303-
ASYNC_UTILS.includes(identifierNodeName)
304-
);
305+
const isAsyncUtil: IsAsyncUtilFn = (node, validNames) => {
306+
return isTestingLibraryUtil(node, (identifierNodeName) => {
307+
if (validNames && validNames.length > 0) {
308+
return (validNames as string[]).includes(identifierNodeName);
309+
}
310+
return ASYNC_UTILS.includes(identifierNodeName);
311+
});
305312
};
306313

307314
/**

lib/rules/no-wait-for-empty-callback.ts

+35-15
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
1+
import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils';
12
import {
2-
ESLintUtils,
3-
TSESTree,
4-
ASTUtils,
5-
} from '@typescript-eslint/experimental-utils';
6-
import { getDocsUrl } from '../utils';
7-
import { isBlockStatement, isCallExpression } from '../node-utils';
3+
getPropertyIdentifierNode,
4+
isBlockStatement,
5+
isCallExpression,
6+
} from '../node-utils';
7+
import { createTestingLibraryRule } from '../create-testing-library-rule';
88

99
export const RULE_NAME = 'no-wait-for-empty-callback';
1010
export type MessageIds = 'noWaitForEmptyCallback';
1111
type Options = [];
1212

13-
const WAIT_EXPRESSION_QUERY =
14-
'CallExpression[callee.name=/^(waitFor|waitForElementToBeRemoved)$/]';
15-
16-
export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
13+
export default createTestingLibraryRule<Options, MessageIds>({
1714
name: RULE_NAME,
1815
meta: {
1916
type: 'suggestion',
@@ -33,11 +30,24 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
3330
defaultOptions: [],
3431

3532
// trimmed down implementation of https://github.com/eslint/eslint/blob/master/lib/rules/no-empty-function.js
36-
// TODO: var referencing any of previously mentioned?
37-
create: function (context) {
33+
create(context, _, helpers) {
34+
function isValidWaitFor(node: TSESTree.Node): boolean {
35+
const parentCallExpression = node.parent as TSESTree.CallExpression;
36+
const parentIdentifier = getPropertyIdentifierNode(parentCallExpression);
37+
38+
return helpers.isAsyncUtil(parentIdentifier, [
39+
'waitFor',
40+
'waitForElementToBeRemoved',
41+
]);
42+
}
43+
3844
function reportIfEmpty(
3945
node: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression
4046
) {
47+
if (!isValidWaitFor(node)) {
48+
return;
49+
}
50+
4151
if (
4252
isBlockStatement(node.body) &&
4353
node.body.body.length === 0 &&
@@ -56,17 +66,27 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
5666
}
5767

5868
function reportNoop(node: TSESTree.Identifier) {
69+
if (!isValidWaitFor(node)) {
70+
return;
71+
}
72+
5973
context.report({
6074
node,
6175
loc: node.loc.start,
6276
messageId: 'noWaitForEmptyCallback',
77+
data: {
78+
methodName:
79+
isCallExpression(node.parent) &&
80+
ASTUtils.isIdentifier(node.parent.callee) &&
81+
node.parent.callee.name,
82+
},
6383
});
6484
}
6585

6686
return {
67-
[`${WAIT_EXPRESSION_QUERY} > ArrowFunctionExpression`]: reportIfEmpty,
68-
[`${WAIT_EXPRESSION_QUERY} > FunctionExpression`]: reportIfEmpty,
69-
[`${WAIT_EXPRESSION_QUERY} > Identifier[name="noop"]`]: reportNoop,
87+
'CallExpression > ArrowFunctionExpression': reportIfEmpty,
88+
'CallExpression > FunctionExpression': reportIfEmpty,
89+
'CallExpression > Identifier[name="noop"]': reportNoop,
7090
};
7191
},
7292
});

lib/utils.ts

+7
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ const ALL_RETURNING_NODES = [
114114
const PRESENCE_MATCHERS = ['toBeInTheDocument', 'toBeTruthy', 'toBeDefined'];
115115
const ABSENCE_MATCHERS = ['toBeNull', 'toBeFalsy'];
116116

117+
export type VALID_ASYNC_UTILS =
118+
| 'waitFor'
119+
| 'waitForElementToBeRemoved'
120+
| 'wait'
121+
| 'waitForElement'
122+
| 'waitForDomChange';
123+
117124
export {
118125
combineQueries,
119126
getDocsUrl,

0 commit comments

Comments
 (0)