Skip to content

Commit 93b81f5

Browse files
committed
fix(no-wait-for-side-effects): report on each side effect node
1 parent 592c128 commit 93b81f5

File tree

4 files changed

+82
-37
lines changed

4 files changed

+82
-37
lines changed

lib/detect-testing-library-utils.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -335,12 +335,20 @@ export function detectTestingLibraryUtils<
335335
* Not to be confused with {@link isUserEventMethod}
336336
*/
337337
const isUserEventUtil = (node: TSESTree.Identifier): boolean => {
338-
return isTestingLibraryUtil(
339-
node,
340-
(identifierNodeName, originalNodeName) => {
341-
return [identifierNodeName, originalNodeName].includes('userEvent');
342-
}
343-
);
338+
const userEvent = findImportedUserEventSpecifier();
339+
let userEventName: string | undefined;
340+
341+
if (userEvent) {
342+
userEventName = userEvent.name;
343+
} else if (isAggressiveModuleReportingEnabled()) {
344+
userEventName = USER_EVENT_NAME;
345+
}
346+
347+
if (!userEventName) {
348+
return false;
349+
}
350+
351+
return node.name === userEventName;
344352
};
345353

346354
/**

lib/rules/no-wait-for-multiple-assertions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
3030
function getExpectNodes(
3131
body: Array<TSESTree.Node>
3232
): Array<TSESTree.ExpressionStatement> {
33-
return body.filter((node: TSESTree.Node) => {
33+
return body.filter((node) => {
3434
if (!isExpressionStatement(node)) {
3535
return false;
3636
}

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

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { TSESTree } from '@typescript-eslint/experimental-utils';
2-
import { getPropertyIdentifierNode } from '../node-utils';
2+
import {
3+
getPropertyIdentifierNode,
4+
isExpressionStatement,
5+
} from '../node-utils';
36
import { createTestingLibraryRule } from '../create-testing-library-rule';
47

58
export const RULE_NAME = 'no-wait-for-side-effects';
@@ -24,10 +27,15 @@ export default createTestingLibraryRule<Options, MessageIds>({
2427
},
2528
defaultOptions: [],
2629
create: function (context, _, helpers) {
27-
function hasSideEffects(body: Array<TSESTree.Node>): boolean {
28-
return body.some((node: TSESTree.ExpressionStatement) => {
29-
const expressionIdentifier = getPropertyIdentifierNode(node);
30+
function getSideEffectNodes(
31+
body: TSESTree.Node[]
32+
): TSESTree.ExpressionStatement[] {
33+
return body.filter((node) => {
34+
if (!isExpressionStatement(node)) {
35+
return false;
36+
}
3037

38+
const expressionIdentifier = getPropertyIdentifierNode(node);
3139
if (!expressionIdentifier) {
3240
return false;
3341
}
@@ -36,7 +44,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
3644
helpers.isFireEventUtil(expressionIdentifier) ||
3745
helpers.isUserEventUtil(expressionIdentifier)
3846
);
39-
});
47+
}) as TSESTree.ExpressionStatement[];
4048
}
4149

4250
function reportSideEffects(node: TSESTree.BlockStatement) {
@@ -49,14 +57,17 @@ export default createTestingLibraryRule<Options, MessageIds>({
4957
return;
5058
}
5159

52-
if (!hasSideEffects(node.body)) {
60+
const sideEffectNodes = getSideEffectNodes(node.body);
61+
if (sideEffectNodes.length === 0) {
5362
return;
5463
}
5564

56-
context.report({
57-
node: callExpressionNode,
58-
messageId: 'noSideEffectsWaitFor',
59-
});
65+
for (const sideEffectNode of sideEffectNodes) {
66+
context.report({
67+
node: sideEffectNode,
68+
messageId: 'noSideEffectsWaitFor',
69+
});
70+
}
6071
}
6172

6273
return {

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

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ ruleTester.run(RULE_NAME, rule, {
130130
{
131131
settings: { 'testing-library/utils-module': 'test-utils' },
132132
code: `
133-
import { waitFor as renamedWaitFor, fireEvent, userEvent } from 'test-utils';
134-
import { waitFor } from 'somewhere-else';
133+
import { waitFor as renamedWaitFor, fireEvent } from 'test-utils';
134+
import { waitFor, userEvent } from 'somewhere-else';
135135
136136
await waitFor(() => {
137137
fireEvent.keyDown(input, {key: 'ArrowDown'})
@@ -168,7 +168,7 @@ ruleTester.run(RULE_NAME, rule, {
168168
fireEvent.keyDown(input, {key: 'ArrowDown'})
169169
})
170170
`,
171-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
171+
errors: [{ line: 4, column: 11, messageId: 'noSideEffectsWaitFor' }],
172172
},
173173
{
174174
code: `
@@ -177,7 +177,7 @@ ruleTester.run(RULE_NAME, rule, {
177177
renamedFireEvent.keyDown(input, {key: 'ArrowDown'})
178178
})
179179
`,
180-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
180+
errors: [{ line: 4, column: 11, messageId: 'noSideEffectsWaitFor' }],
181181
},
182182
{
183183
settings: { 'testing-library/utils-module': '~/test-utils' },
@@ -187,7 +187,7 @@ ruleTester.run(RULE_NAME, rule, {
187187
fireEvent.keyDown(input, {key: 'ArrowDown'})
188188
})
189189
`,
190-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
190+
errors: [{ line: 4, column: 11, messageId: 'noSideEffectsWaitFor' }],
191191
},
192192
{
193193
code: `
@@ -197,7 +197,7 @@ ruleTester.run(RULE_NAME, rule, {
197197
fireEvent.keyDown(input, {key: 'ArrowDown'})
198198
})
199199
`,
200-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
200+
errors: [{ line: 5, column: 11, messageId: 'noSideEffectsWaitFor' }],
201201
},
202202
{
203203
code: `
@@ -207,7 +207,7 @@ ruleTester.run(RULE_NAME, rule, {
207207
expect(b).toEqual('b')
208208
})
209209
`,
210-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
210+
errors: [{ line: 4, column: 11, messageId: 'noSideEffectsWaitFor' }],
211211
},
212212
{
213213
code: `
@@ -216,7 +216,7 @@ ruleTester.run(RULE_NAME, rule, {
216216
fireEvent.keyDown(input, {key: 'ArrowDown'})
217217
})
218218
`,
219-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
219+
errors: [{ line: 4, column: 11, messageId: 'noSideEffectsWaitFor' }],
220220
},
221221
{
222222
code: `
@@ -226,7 +226,7 @@ ruleTester.run(RULE_NAME, rule, {
226226
fireEvent.keyDown(input, {key: 'ArrowDown'})
227227
})
228228
`,
229-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
229+
errors: [{ line: 5, column: 11, messageId: 'noSideEffectsWaitFor' }],
230230
},
231231
{
232232
code: `
@@ -236,7 +236,7 @@ ruleTester.run(RULE_NAME, rule, {
236236
expect(b).toEqual('b')
237237
})
238238
`,
239-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
239+
errors: [{ line: 4, column: 11, messageId: 'noSideEffectsWaitFor' }],
240240
},
241241
// userEvent
242242
{
@@ -246,26 +246,28 @@ ruleTester.run(RULE_NAME, rule, {
246246
userEvent.click(button)
247247
})
248248
`,
249-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
249+
errors: [{ line: 4, column: 11, messageId: 'noSideEffectsWaitFor' }],
250250
},
251251
{
252252
code: `
253-
import { waitFor, userEvent as renamedUserEvent } from '@testing-library/react';
253+
import { waitFor } from '@testing-library/react';
254+
import renamedUserEvent from '@testing-library/user-event'
254255
await waitFor(() => {
255256
renamedUserEvent.click(button)
256257
})
257258
`,
258-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
259+
errors: [{ line: 5, column: 11, messageId: 'noSideEffectsWaitFor' }],
259260
},
260261
{
261262
settings: { 'testing-library/utils-module': '~/test-utils' },
262263
code: `
263-
import { waitFor, userEvent } from '~/test-utils';
264+
import { waitFor } from '~/test-utils';
265+
import userEvent from '@testing-library/user-event'
264266
await waitFor(() => {
265267
userEvent.click();
266268
})
267269
`,
268-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
270+
errors: [{ line: 5, column: 11, messageId: 'noSideEffectsWaitFor' }],
269271
},
270272
{
271273
code: `
@@ -275,7 +277,7 @@ ruleTester.run(RULE_NAME, rule, {
275277
userEvent.click(button)
276278
})
277279
`,
278-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
280+
errors: [{ line: 5, column: 11, messageId: 'noSideEffectsWaitFor' }],
279281
},
280282
{
281283
code: `
@@ -285,7 +287,7 @@ ruleTester.run(RULE_NAME, rule, {
285287
expect(b).toEqual('b')
286288
})
287289
`,
288-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
290+
errors: [{ line: 4, column: 11, messageId: 'noSideEffectsWaitFor' }],
289291
},
290292
{
291293
code: `
@@ -294,7 +296,7 @@ ruleTester.run(RULE_NAME, rule, {
294296
userEvent.click(button)
295297
})
296298
`,
297-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
299+
errors: [{ line: 4, column: 11, messageId: 'noSideEffectsWaitFor' }],
298300
},
299301
{
300302
code: `
@@ -304,7 +306,7 @@ ruleTester.run(RULE_NAME, rule, {
304306
userEvent.click(button)
305307
})
306308
`,
307-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
309+
errors: [{ line: 5, column: 11, messageId: 'noSideEffectsWaitFor' }],
308310
},
309311
{
310312
code: `
@@ -314,7 +316,31 @@ ruleTester.run(RULE_NAME, rule, {
314316
expect(b).toEqual('b')
315317
})
316318
`,
317-
errors: [{ line: 3, column: 15, messageId: 'noSideEffectsWaitFor' }],
319+
errors: [{ line: 4, column: 11, messageId: 'noSideEffectsWaitFor' }],
320+
},
321+
322+
{
323+
settings: { 'testing-library/utils-module': 'test-utils' },
324+
code: `// all mixed
325+
import { waitFor, fireEvent as renamedFireEvent, screen } from '~/test-utils';
326+
import userEvent from '@testing-library/user-event'
327+
import { fireEvent } from 'somewhere-else'
328+
329+
test('check all mixed', async () => {
330+
const button = await screen.findByRole('button')
331+
await waitFor(() => {
332+
renamedFireEvent.keyDown(input, {key: 'ArrowDown'})
333+
expect(b).toEqual('b')
334+
fireEvent.keyDown(input, {key: 'ArrowDown'})
335+
userEvent.click(button)
336+
someBool ? 'a' : 'b' // cover expression statement without identifier for 100% coverage
337+
})
338+
})
339+
`,
340+
errors: [
341+
{ line: 9, column: 13, messageId: 'noSideEffectsWaitFor' },
342+
{ line: 12, column: 13, messageId: 'noSideEffectsWaitFor' },
343+
],
318344
},
319345
],
320346
});

0 commit comments

Comments
 (0)