Skip to content

Commit 489be04

Browse files
committed
feat(no-unnecessary-act): detect edge and mixed cases
1 parent 50d5d78 commit 489be04

File tree

3 files changed

+62
-25
lines changed

3 files changed

+62
-25
lines changed

lib/create-testing-library-rule/detect-testing-library-utils.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -689,14 +689,10 @@ export function detectTestingLibraryUtils<
689689
return false;
690690
}
691691

692-
const originalNodeName =
693-
isImportSpecifier(importedUtilSpecifier) &&
694-
importedUtilSpecifier.local.name !==
695-
importedUtilSpecifier.imported.name
696-
? importedUtilSpecifier.imported.name
697-
: undefined;
698-
699-
return [node.name, originalNodeName].filter(Boolean).includes('act');
692+
return hasImportMatch(
693+
importedUtilSpecifier,
694+
referenceNodeIdentifier.name
695+
);
700696
})();
701697

702698
return isTestingLibraryAct || isReactDomTestUtilsAct;
@@ -832,6 +828,12 @@ export function detectTestingLibraryUtils<
832828
return false;
833829
}
834830

831+
const referenceNode = getReferenceNode(node);
832+
const referenceNodeIdentifier = getPropertyIdentifierNode(referenceNode);
833+
if (!referenceNodeIdentifier) {
834+
return false;
835+
}
836+
835837
const importDeclaration = (() => {
836838
if (isImportDeclaration(importNode.parent)) {
837839
return importNode.parent;

lib/rules/no-unnecessary-act.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { TSESTree } from '@typescript-eslint/experimental-utils';
22
import { createTestingLibraryRule } from '../create-testing-library-rule';
33
import {
44
getDeepestIdentifierNode,
5-
getPropertyIdentifierNode,
65
getStatementCallExpression,
76
isEmptyFunction,
87
} from '../node-utils';
@@ -75,26 +74,23 @@ export default createTestingLibraryRule<[], MessageIds>({
7574
return;
7675
}
7776

78-
const callExpressionIdentifier = getPropertyIdentifierNode(
79-
callExpressionNode
80-
);
81-
82-
if (!callExpressionIdentifier) {
77+
const identifierNode = getDeepestIdentifierNode(callExpressionNode);
78+
if (!identifierNode) {
8379
return;
8480
}
8581

86-
if (!helpers.isActUtil(callExpressionIdentifier)) {
82+
if (!helpers.isActUtil(identifierNode)) {
8783
return;
8884
}
8985

9086
if (isEmptyFunction(functionNode)) {
9187
context.report({
92-
node: callExpressionIdentifier,
88+
node: identifierNode,
9389
messageId: 'noUnnecessaryActEmptyFunction',
9490
});
9591
} else if (!hasSomeNonTestingLibraryCall(blockStatementNode.body)) {
9692
context.report({
97-
node: callExpressionIdentifier,
93+
node: identifierNode,
9894
messageId: 'noUnnecessaryActTestingLibraryUtil',
9995
});
10096
}
@@ -117,15 +113,12 @@ export default createTestingLibraryRule<[], MessageIds>({
117113
return;
118114
}
119115

120-
const parentCallExpressionIdentifier = getPropertyIdentifierNode(
121-
parentCallExpression
122-
);
123-
124-
if (!parentCallExpressionIdentifier) {
116+
const identifierNode = getDeepestIdentifierNode(parentCallExpression);
117+
if (!identifierNode) {
125118
return;
126119
}
127120

128-
if (!helpers.isActUtil(parentCallExpressionIdentifier)) {
121+
if (!helpers.isActUtil(identifierNode)) {
129122
return;
130123
}
131124

@@ -134,7 +127,7 @@ export default createTestingLibraryRule<[], MessageIds>({
134127
}
135128

136129
context.report({
137-
node: parentCallExpressionIdentifier,
130+
node: identifierNode,
138131
messageId: 'noUnnecessaryActTestingLibraryUtil',
139132
});
140133
}

tests/lib/rules/no-unnecessary-act.test.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,48 @@ ruleTester.run(RULE_NAME, rule, {
735735
],
736736
},
737737

738-
// TODO case: mixed scenarios - AGR disabled
738+
{
739+
settings: {
740+
'testing-library/utils-module': 'custom-testing-module',
741+
'testing-library/custom-renders': 'off',
742+
},
743+
code: `// case: mixed scenarios - AGR disabled
744+
import * as ReactTestUtils from 'react-dom/test-utils';
745+
import { act as renamedAct, fireEvent, screen as renamedScreen, render, waitFor } from 'custom-testing-module'
746+
import userEvent from '@testing-library/user-event'
747+
import { act, waitForElementToBeRemoved } from 'somewhere-else'
748+
749+
test('invalid case', async () => {
750+
ReactTestUtils.act(() => {})
751+
await ReactTestUtils.act(() => render())
752+
await renamedAct(async () => waitFor())
753+
renamedAct(function() { renamedScreen.findByRole('button') })
754+
755+
// these are valid
756+
await renamedAct(() => waitForElementToBeRemoved(element))
757+
act(() => {})
758+
await act(async () => { userEvent.click(element) })
759+
act(function() { return renamedScreen.getByText('foo') })
760+
});
761+
`,
762+
errors: [
763+
{ messageId: 'noUnnecessaryActEmptyFunction', line: 8, column: 24 },
764+
{
765+
messageId: 'noUnnecessaryActTestingLibraryUtil',
766+
line: 9,
767+
column: 30,
768+
},
769+
{
770+
messageId: 'noUnnecessaryActTestingLibraryUtil',
771+
line: 10,
772+
column: 15,
773+
},
774+
{
775+
messageId: 'noUnnecessaryActTestingLibraryUtil',
776+
line: 11,
777+
column: 9,
778+
},
779+
],
780+
},
739781
],
740782
});

0 commit comments

Comments
 (0)