Repository navigation
fix: create userEvent session lazily on first use - #265
Open
monsterlag wants to merge 1 commit into
Open
monsterlag wants to merge 1 commit into
monsterlag wants to merge 1 commit into
Conversation
Calling userEvent.setup() in start() prepares the document and the currently focused element even when only navigation commands are used. When the consumer has a separate copy of @testing-library/user-event, this double-prepares a focused input and breaks later userEvent interactions on it (regression in 0.33.0). Fixes guidepup#250
Contributor
This sits awkwardly and makes me hesitant about doing a partial fix, ideally we resolve completely. Uncertain atm if there is a way to achieve without starting to expose the implementation detail that we use user-event ideally the interface wouldn’t ever couple to the testing lib package given we could choose to swap out the internals in future… I guess could be an abstraction where method delegates could be passed in, with the defaults being our internal userEvent instance? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Note
AI-generated, not reviewed by a human. This pull request was written by an AI coding agent and then checked by a separate AI review agent, which re-ran the tests described below. No human has reviewed the code. It is submitted by @monsterlag, who runs these agents. If that does not fit how you want to receive contributions, please feel free to close it.
Issue
Fixes #250.
Details
Since 0.33.0,
virtual.start()always callsuserEvent.setup(). That call prepares the document and the element that is focused at that moment (user-event installs value/selection interceptors on a focused<input>). When the test has its own, separate copy of@testing-library/user-event(for example one bundled by Storybook), the focused input ends up prepared twice, and later interactions from the test's own session (such asuserEvent.clear(input)) no longer reach React'sonChange, even for a walkthrough that only callsnext()/lastSpokenPhrase().This change follows the approach suggested in the issue:
start()now only stores the userEvent options (document,advanceTimers, defaults).#getUserEvent()creates the session on first use, soact(),click(),press()andtype()still share one persistent session for the walkthrough.stop()clears both the session and the stored options, so the nextstart()gets a fresh session.start()also discards any session left from an earlierstart()withoutstop(), so a repeatedstart()still gets a fresh session with the newdocument/advanceTimers, as before.Scope: this fixes walkthroughs that only navigate (
start()/next()/previous()/lastSpokenPhrase()/stop()), which no longer touch userEvent at all, as in 0.32.1. A walkthrough that callsact(),click(),press()ortype()still creates a userEvent session at that point, so with two copies of@testing-library/user-eventit can still hit the original problem on an input focused at that moment.A new test,
test/int/userEventIsolation.int.test.tsx, loads a separate module instance of@testing-library/user-eventwithjest.isolateModulesto simulate a second copy, types into a controlled React input, runs astart()/next()/stop()walkthrough, then clears the input and checks that React state updated.A second new test in
test/int/press.int.test.tscallsstart()twice withoutstop(), with a differentadvanceTimerseach time, and checks thatpress()after the secondstart()uses the secondadvanceTimers.How it was tested (in a Linux container, Node 24, yarn 1.22):
yarn jest test/int/userEventIsolation.int.test.tsxwithout thesrc/Virtual.tschange: fails (Unable to find an element with the text: Current value: empty, the input's value changed but React's state did not).yarn jest test/int/press.int.test.ts -t "should use the latest options": passes on base and with the change; fails ifstart()does not reset the session (Received number of calls: 0).yarn ci(clean, lint, test:coverage, build, types:test): passes; 58 suites / 337 tests, coverage thresholds met, attw reports no problems.CheckList