Skip to content

fix(user-event): include selection in TextInput change event#1919

Open
nsbarsukov wants to merge 1 commit into
callstack:mainfrom
nsbarsukov:fix/userevent-change-selection
Open

fix(user-event): include selection in TextInput change event#1919
nsbarsukov wants to merge 1 commit into
callstack:mainfrom
nsbarsukov:fix/userevent-change-selection

Conversation

@nsbarsukov

@nsbarsukov nsbarsukov commented Jun 19, 2026

Copy link
Copy Markdown

Summary

React Native (>=0.85) reports the caret position via onChange's nativeEvent.selection (see commits from react-native repo 162627a and c1f5445).

userEvent.type() did not include selection in the change event's nativeEvent — it computed a selectionRange (caret at the end of the current text) and emitted it only via a separate selectionChange event. As a result, components that read the caret from event.nativeEvent.selection inside their onChange handler (e.g. input-masking libraries) could not be driven by userEvent.type(...): they saw no selection, mishandled every keystroke, and the value never updated.

This PR folds the already-computed selectionRange into the change event so it matches the real platform shape, while keeping the separate selectionChange event unchanged.

Changes:

  • buildTextChangeEvent(text, selection) now includes selection: { start, end } in the change event's nativeEvent.
  • type() (emitTypingEvents) and paste() pass the caret range (end of the current/inserted text) into the change event. clear() inherits this via emitTypingEvents.
  • submitEditing / endEditing are left as-is — the platform does not report a selection on those events.

Test plan

  • yarn test — all suites pass (snapshots for type, type-managed, paste, and clear regenerated to include selection).
  • yarn typecheck, yarn lint, yarn format:check — all pass.
  • New/updated unit tests in src/user-event/type/__tests__/type.test.tsx:
    • Asserts that after userEvent.type(input, 'Hello'), the onChange handler receives an event whose nativeEvent.selection equals { start: 5, end: 5 }.
    • Regression test mounting a masking-style TextInput that reads e.nativeEvent.selection in onChange and only updates its value when the caret is present — confirms it is now correctly driven by userEvent.type().
  • Updated src/event-builder/__tests__/text.test.ts to assert selection is present in the built change-event payload.

React Native (>=0.85) reports caret position via onChange's
nativeEvent.selection on all platforms, but userEvent.type only
emitted it on a separate selectionChange event. Components that read
the caret inside onChange (e.g. input masks) could not be driven by
userEvent. Fold the computed selectionRange into the change event.
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.

1 participant