Skip to content

Commit 0d105df

Browse files
authored
fix(no-wait-for-side-effects): report implicit return in arrow functions (#352)
* fix(no-wait-for-side-effects): yield error with implicit arrow return * refactor: simplify functions * fix: call a function * refactor: consist return type * refactor: isCallerWaitFor function * test: add more cases
1 parent 67086c7 commit 0d105df

File tree

2 files changed

+88
-15
lines changed

2 files changed

+88
-15
lines changed

lib/rules/no-wait-for-side-effects.ts

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,23 @@ export default createTestingLibraryRule<Options, MessageIds>({
2626
},
2727
defaultOptions: [],
2828
create: function (context, _, helpers) {
29+
function isCallerWaitFor(
30+
node: TSESTree.BlockStatement | TSESTree.CallExpression
31+
): boolean {
32+
if (!node.parent) {
33+
return false;
34+
}
35+
const callExpressionNode = node.parent.parent as TSESTree.CallExpression;
36+
const callExpressionIdentifier = getPropertyIdentifierNode(
37+
callExpressionNode
38+
);
39+
40+
return (
41+
!!callExpressionIdentifier &&
42+
helpers.isAsyncUtil(callExpressionIdentifier, ['waitFor'])
43+
);
44+
}
45+
2946
function getSideEffectNodes(
3047
body: TSESTree.Node[]
3148
): TSESTree.ExpressionStatement[] {
@@ -47,19 +64,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
4764
}
4865

4966
function reportSideEffects(node: TSESTree.BlockStatement) {
50-
if (!node.parent) {
51-
return;
52-
}
53-
const callExpressionNode = node.parent.parent as TSESTree.CallExpression;
54-
const callExpressionIdentifier = getPropertyIdentifierNode(
55-
callExpressionNode
56-
);
57-
58-
if (!callExpressionIdentifier) {
59-
return;
60-
}
61-
62-
if (!helpers.isAsyncUtil(callExpressionIdentifier, ['waitFor'])) {
67+
if (!isCallerWaitFor(node)) {
6368
return;
6469
}
6570

@@ -76,8 +81,32 @@ export default createTestingLibraryRule<Options, MessageIds>({
7681
}
7782
}
7883

84+
function reportImplicitReturnSideEffect(node: TSESTree.CallExpression) {
85+
if (!isCallerWaitFor(node)) {
86+
return;
87+
}
88+
89+
const expressionIdentifier = getPropertyIdentifierNode(node.callee);
90+
if (!expressionIdentifier) {
91+
return;
92+
}
93+
94+
if (
95+
!helpers.isFireEventUtil(expressionIdentifier) &&
96+
!helpers.isUserEventUtil(expressionIdentifier)
97+
) {
98+
return;
99+
}
100+
101+
context.report({
102+
node,
103+
messageId: 'noSideEffectsWaitFor',
104+
});
105+
}
106+
79107
return {
80108
'CallExpression > ArrowFunctionExpression > BlockStatement': reportSideEffects,
109+
'CallExpression > ArrowFunctionExpression > CallExpression': reportImplicitReturnSideEffect,
81110
'CallExpression > FunctionExpression > BlockStatement': reportSideEffects,
82111
};
83112
},

tests/lib/rules/no-wait-for-side-effects.test.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,49 @@ ruleTester.run(RULE_NAME, rule, {
158158
})
159159
`,
160160
},
161+
{
162+
settings: { 'testing-library/utils-module': 'test-utils' },
163+
code: `
164+
import { waitFor } from 'somewhere-else';
165+
await waitFor(() => fireEvent.keyDown(input, {key: 'ArrowDown'}))
166+
`,
167+
},
168+
{
169+
settings: { 'testing-library/utils-module': 'test-utils' },
170+
code: `
171+
import { waitFor } from 'somewhere-else';
172+
import { userEvent } from '@testing-library/react';
173+
await waitFor(() => userEvent.click(button))
174+
`,
175+
},
176+
{
177+
settings: { 'testing-library/utils-module': '~/test-utils' },
178+
code: `
179+
import { waitFor, userEvent } from '~/test-utils';
180+
await waitFor(() => userEvent.click(button))
181+
`,
182+
},
161183
],
162184
invalid: [
163185
// fireEvent
164186
{
165187
code: `
166-
import { waitFor } from '@testing-library/react';
188+
import { waitFor } from '@testing-library/react';
189+
await waitFor(() => fireEvent.keyDown(input, {key: 'ArrowDown'}))
190+
`,
191+
errors: [{ line: 3, column: 29, messageId: 'noSideEffectsWaitFor' }],
192+
},
193+
{
194+
settings: { 'testing-library/utils-module': '~/test-utils' },
195+
code: `
196+
import { waitFor, fireEvent } from '~/test-utils';
197+
await waitFor(() => fireEvent.keyDown(input, {key: 'ArrowDown'}))
198+
`,
199+
errors: [{ line: 3, column: 29, messageId: 'noSideEffectsWaitFor' }],
200+
},
201+
{
202+
code: `
203+
import { waitFor } from '@testing-library/react';
167204
await waitFor(() => {
168205
fireEvent.keyDown(input, {key: 'ArrowDown'})
169206
})
@@ -241,7 +278,14 @@ ruleTester.run(RULE_NAME, rule, {
241278
// userEvent
242279
{
243280
code: `
244-
import { waitFor } from '@testing-library/react';
281+
import { waitFor } from '@testing-library/react';
282+
await waitFor(() => userEvent.click(button))
283+
`,
284+
errors: [{ line: 3, column: 29, messageId: 'noSideEffectsWaitFor' }],
285+
},
286+
{
287+
code: `
288+
import { waitFor } from '@testing-library/react';
245289
await waitFor(() => {
246290
userEvent.click(button)
247291
})

0 commit comments

Comments
 (0)