Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rule): add no-await-sync-events rule #240

Merged
merged 6 commits into from
Oct 29, 2020

Conversation

J-Huang
Copy link
Contributor

@J-Huang J-Huang commented Oct 22, 2020

Feature request:
#219

All functions in "fireEvent" and "userEvent" are synchronous, meaning it's wrong to add "await" operator for those function calls, with an exception of userEvent.type.

This new rule "no-await-sync-events" disallows adding "await" for those function calls in order to avoid errors.

@Belco90
Copy link
Member

Belco90 commented Oct 22, 2020

Thanks! I'll try to review it during the weekend. Although I don't know if there is something pending since it's a draft PR.

@J-Huang
Copy link
Contributor Author

J-Huang commented Oct 22, 2020

@Belco90 it's in draft because would like to have @benmonro take a look first since he was the owner of the feature request. Thanks.

benmonro
benmonro previously approved these changes Oct 22, 2020
Copy link
Member

@benmonro benmonro left a comment

Choose a reason for hiding this comment

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

LGTM thanks @J-Huang

@J-Huang J-Huang marked this pull request as ready for review October 22, 2020 20:01
Copy link
Member

@Belco90 Belco90 left a comment

Choose a reason for hiding this comment

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

The rule implementation itself seems fine, but we need to improve few things:

  • handle userEvent.type special cases better
  • make tests more confident
  • add the rule to README


Functions in the event object provided by Testing Library, including
fireEvent and userEvent, do NOT return Promise, with an exception of
`userEvent.type`. Some examples are:
Copy link
Member

Choose a reason for hiding this comment

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

This is technically true, but you don't need to always wait for it. From user-event doc:

To be clear, userEvent.type always returns a promise, but you only need to await the promise it returns if you're using the delay option. Otherwise everything runs synchronously and you can ignore the promise.

So should this rule report about userEvent.type if no delay option passed? I think so

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree with that ☝️ we should only await if the delay option is used. It would be great if we can cover that scenario with the rule

Copy link
Contributor Author

@J-Huang J-Huang Oct 26, 2020

Choose a reason for hiding this comment

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

Agree. upgraded
the rule is, only if userEvent.type with delay option, await is valid. For all the other cases, it disallows await.

lib/utils.ts Outdated
@@ -63,6 +63,11 @@ const ASYNC_UTILS = [
'waitForDomChange',
];

const ASYNC_EVENTS = [
Copy link
Member

@Belco90 Belco90 Oct 23, 2020

Choose a reason for hiding this comment

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

These are SYNC_EVENTS actually, right?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I wouldn't say there are events either - there are helpers or utilities.. Events would be "tab", "input", "change", "click" and so on... 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

initially thought it should be no-await-sync-utils, but feel not so correct...I can rename it to utils if it makes more sense.

});

ruleTester.run(RULE_NAME, rule, {
valid: [
Copy link
Member

Choose a reason for hiding this comment

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

You need to include more tests for checking userEvent and fireEvent non-related to Testing Library are not reported so they are valid with await operator.

There is an ongoing refactor for v4 of the plugin which actually will check that for all rules out of the box, so I don't know if you prefer to wait for that version to be released.

Copy link
Contributor Author

@J-Huang J-Huang Oct 26, 2020

Choose a reason for hiding this comment

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

@Belco90
Do you mean how about if userEvent or fireEvent are user named objects, it should not apply the rule? Or, if extra functions are added to those objects, for those cases, await may be valid?
In order to ensure that, it has to check if the property name in userEvent or fireEvent is one of the expected event names, such as click, type, tab and so on. Even those methods can be overridden. Am I misunderstanding the question?

Copy link
Member

Choose a reason for hiding this comment

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

The former, so we don't report const declared by the user with the same name. As mentioned, the internal refactor for v4 will pass some helpers to all rules to check this generically, so I'm not sure if you prefer to wait for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the clarification.
will refactor the code by then if needed.

invalid: [
// sync events with await operator are not valid
...eventFunctions.map(func => ({
code: `() => {
Copy link
Member

Choose a reason for hiding this comment

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

Can you write more realistic code here? So you end up with something like:

import { fireEvent } from '@testing-library/framework'
import userEvent from '@testing-library/user-event'
import MyComponent from './MyComponent'

it('should report sync event awaited', async () => {
  render(<MyComponent />)
  
  await ${func}('foo')
  await findByQuery('some element')
})

and then check in the errors which line the error should appear.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

Copy link
Member

@Belco90 Belco90 left a comment

Choose a reason for hiding this comment

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

Just an extra correct example and I think it would be ready, apart from what we want to do with checking if reported objects are from Testing Library modules or not.


const baz = () => {
// ...
await userEvent.type(textInput, 'abc', {delay: 1000});
Copy link
Member

Choose a reason for hiding this comment

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

Can you add an extra correct example for userEvent.type without await and delay please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

@J-Huang J-Huang requested a review from Belco90 October 26, 2020 22:58
@J-Huang
Copy link
Contributor Author

J-Huang commented Oct 26, 2020

Not sure why CI chokes. My main computer died, so I just made a commit through github web page UI to my forked repo.

README.md Outdated Show resolved Hide resolved
@J-Huang J-Huang requested a review from Belco90 October 28, 2020 04:06
@Belco90 Belco90 added the new rule New rule to be included in the plugin label Oct 29, 2020
@Belco90 Belco90 merged commit 2cc2263 into testing-library:master Oct 29, 2020
@Belco90
Copy link
Member

Belco90 commented Oct 29, 2020

@all-contributors please add @J-Huang for code, test and docs

@allcontributors
Copy link
Contributor

@Belco90

I've put up a pull request to add @J-Huang! 🎉

@Belco90
Copy link
Member

Belco90 commented Oct 29, 2020

🎉 This PR is included in version 3.10.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new rule New rule to be included in the plugin released
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants