-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Implement support for async act
callbacks and nested calls to act
#1854
Conversation
Add a transform to convert async/await to Promises for use in tests. This is the same low-footprint transform used by microbundle. Slack discussion: https://preact.slack.com/archives/G9T60GUQ0/p1565514000140700
Implement initial support for `act` callbacks returning a Promise, in which case the promise is awaited before state updates and effects are flushed. See https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#async-act-for-testing for more details on the motivation.
When calls to act are nested, effects and component updates are only flushed when the outer `act` call returns, as per [1] and [2]. This is convenient for creating helper functions which may invoke `act` themselves. [1] facebook/react#15682 [2] facebook/react#15472
test-utils/src/index.js
Outdated
*/ | ||
export function act(cb) { | ||
++actDepth; | ||
if (actDepth > 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super super tiny nit: We can combine this line and the above one:
if (++actDepth > 1) { ... }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So good! I love your PRs 👍 The attention to details is amazing 😍💯
test-utils/test/shared/act.test.js
Outdated
|
||
act(() => { | ||
act(() => { | ||
button.dispatchEvent(new Event('click')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will fail in IE11 because it doesn't support new Event()
. I have a PR ready which introduces a helper method for that: https://github.com/preactjs/preact/pull/1856/files#diff-d429c5e5b8692f8b67a9d38592332a1eR8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching this. I've updated the code to use the helper.
test-utils/test/shared/act.test.js
Outdated
expect(counter).to.equal(0); | ||
|
||
act(() => { | ||
button.dispatchEvent(new Event('click')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same IE11 issue as below
Merge in `createEvent` test helper from master.
- Use `createEvent` helper instead of `new Event` for IE 11 compatibility - Combine `actDepth` increment with test
Feedback / IE 11 issues addressed. Thanks for the super-swift review :) |
This PR implements support for passing async callbacks to
act
and nesting calls toact
, matching React 16.9.0. This is useful in cases where triggering an effect or state change involves async steps, such as waiting for afetch
call to resolve.Following React's behavior,
act
returns a Promise which resolves immediately if the callback is synchronous or after the callback resolves if it is asynchronous. Awaiting the result ofact
before making assertions is optional if the callback is sync, but required if the callback is async, as effects/updates are not flushed until the callback's result has resolved in that case.When calls to
act
are nested, effects and updates are only flushed when the outeract
call returns. This also follows React's behavior.One feature of React's
act
that is not implemented yet is warning if you pass an async callback toact
but forget to await the result.act
act