Skip to content

Conversation

@hainenber
Copy link
Contributor

@hainenber hainenber commented Nov 30, 2025

Closes #1722

I've implemented said rule to lint for unnecessary async wrapper for single await call inspired (or blatantly copied? :D) from @G-Rath's ESQuery selector in linked issue.

This is also put into recommended option as suggested. PTAL when you have time, folks!

…wait` call

Signed-off-by: hainenber <dotronghai96@gmail.com>
Copy link
Collaborator

@G-Rath G-Rath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't change our configs without doing a new major, so please remove this from recommended

(On mobile so can't currently do a full review, but figured I'd this in in case you get to it before me 🙂)

Signed-off-by: hainenber <dotronghai96@gmail.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
@hainenber
Copy link
Contributor Author

I've done removing this rule from recommended config. Aside from a crashed Jest worker in MacOS test setup, this is ready for review :D

Comment on lines 15 to 20
dedent`
it('pass', async () => {
expect();
})
`,
dedent`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you clean up the indentation of the code samples? the code should be indented one level from the indent level of the dedent, and the end backtick should be at the same indent as the dedent

i.e.

Suggested change
dedent`
it('pass', async () => {
expect();
})
`,
dedent`
dedent`
it('pass', async () => {
expect();
})
`,
dedent`

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. I'll amend in next commit.

Comment on lines 38 to 39
(awaitNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
awaitNode?.type !== AST_NODE_TYPES.FunctionExpression) ||
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we've got a utility for this

Suggested change
(awaitNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
awaitNode?.type !== AST_NODE_TYPES.FunctionExpression) ||
!awaitNode ||
!isFunction(awaitNode) ||

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL. I'll amend in next commit

fixable: 'code',
messages: {
noAsyncWrapperForExpectedPromise:
'Rejected/resolved promises should not be wrapped in async function',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of a phrasing more like "Unneeded async function"? that way we don't have to deal with the "rejected/resolved", and I think it's a bit more positive to be conveying we think you can have less code as an optimization

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm cool with that 👍

…lity + rephrase error message

Signed-off-by: hainenber <dotronghai96@gmail.com>
@hainenber
Copy link
Contributor Author

All amended in newest commit :D

@hainenber hainenber requested a review from G-Rath December 1, 2025 09:36
Signed-off-by: hainenber <dotronghai96@gmail.com>
Copy link
Collaborator

@G-Rath G-Rath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is pretty much there, just got a few more tests I'd like - also, I'm wondering if a name like no-unneeded-async-expect-function might be a better name?

I think the use of "unneeded" is good because it indicates the rule is about an optimization that lets you have less code, rather than guarding against a particular bug or gotcha


## Rule details

This rule triggers a warning if a single `await` function call is wrapped by an
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to say something like "This rule triggers a warning if expect is passed an async function that has a single await call", since that is what "unnecessary" means in this context

});

ruleTester.run('no-async-wrapper-for-expected-promise', rule, {
valid: [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be good to have some tests that:

  • pass a non-async function to expect
  • pass a reference to another function which is async
  • uses await within the expect call (e.g. expect(await x()))
  • uses of other matchers, to show that we don't actually care if rejects or resolve is being used
  • use of await within an array

invalid: [
{
code: dedent`
it('should be fix', async () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: these would be more correct as "should be fixed" 😅

})
`,
],
invalid: [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd be good if we could have a test with say a Promise.all, to help prove the fixer works in more complex situations

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: warn on unnecessary async wrapper in expect(...).rejects or expect(...).resolves

2 participants