Fix dispatch wrapping for internal events #1283
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What
There a few places in the library where events are dispatched in response to already triggered events. These seemingly fix missing/differing functionality in JSDOM for events relating to focus. This includes handling focus/blur when
visibilityState
ishidden
and triggeringchange
events onblur
. However, these are also wrapped in the runtime's configuredeventWrapper
. In React, this is theact
wrapper. Due to how React flushes the update queue inact
environments, this can prematurely tear down the queue making future updates trigger...Users cannot avoid these error logs (and in our case, we elevate them and fail our tests as if they were real errors). This can be completely avoided though as when we trigger events for
focus
andblur
, we should already be in a wrapped scope. To further that point, imagine in user space we had a component that re-dispatches a customchange
event:In this case, it's obvious that we cannot wrap our
dispatchEvent
call inact
as it's part of the component yet this is totally fine because our synthetic Reactchange
event presumably was triggered by a wrapped call likeuserEvent.type(screen.getByTestId("input"), "some text")
. The same should be true here where the focus/blur events are already wrapped and the wrapping around the patched event is unnecessary (and, in the case of React, problematic).Why
In React, nested synchronous
act
calls can prematurely teardown theact
queue creating console warnings. In my team's case, we elevate these to real errors in our tests making them more visible. These warnings can be avoided as described in the What section. It's also possible React could warn aboutact
wrapped state updates on the queue and might even handle the nesting in async cases already. Nesting seems like it should be avoided though as users can't really create the same behavior in a real app. It's still not totally clear to me why this is allowed or if it should be handled already by React and is a bug. But in any case, I don't think we have to wrap the internal calls and can solve here.How
I removed the call to
wrapEvent
indispatchDOMEvent
which is currently only used for these focus/blur event. I am not sure this was the original intention for the split dispatch compared todispatchEvent
in the same file, but it seems very fitting as fixing here fixes all the current cases where wrapping should not be added and doesn't touch the places wrapping is required. I also passed through the boolean return value. It's not used anywhere but seemed like it fit the intention of the function to just be a simple wrapper around the nativedispatchEvent
API.Checklist
#1275 - Another user reported this issue while also introducing a new feature. I believe the solution in this PR is more universal and decouples from the feature request to hopefully move this along more quickly.