-
Notifications
You must be signed in to change notification settings - Fork 253
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
fix(keyboard): dispatch change event on blur #703
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit d9c9f54:
|
Codecov Report
@@ Coverage Diff @@
## main #703 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 50 50
Lines 935 947 +12
Branches 369 372 +3
=========================================
+ Hits 935 947 +12
Continue to review full report at Codecov.
|
@nickmccurdy What do you think about adding a |
What would usage look like? And this is unrelated from our internal |
For the problem at hand - i.e. keeping track of non-userevent changes: it('test something', () => {
// ... render empty text field ...
element.focus()
element.value = 'foo'
userEvent.keyboard('bar')
userEvent.keyboard('{Backspace}{Backspace}{Backspace}')
element.blur() // this triggers no change event but it should
})
it('test again with setup', () => {
// ... render empty text field ...
userEvent.setup({document: element.ownerDocument})
element.focus()
element.value = 'foo'
userEvent.keyboard('bar')
userEvent.keyboard('{Backspace}{Backspace}{Backspace}')
element.blur() // does trigger a change event because we tracked all changes since `focus()`
}) For it('act on some dialog that opened on [ctrl]+[mouseLeft]', () => {
// ... render ...
userEvent.setup({
keyboardState: userEvent.createKeyboardState('[ControlLeft>]'),
pointerState: userEvent.createPointerState('[MouseLeft>]'), // tbd how this API will exactly look like
})
// possibly some rudimentary pointer movement
// will not be accurate in jsdom but could be good enough for many cases
// e.g. testing that drag&drop handlers work in principle
userEvent.pointerMove(element, {x: 15, y: 20})
userEvent.pointer(element, '[/MouseLeft]') // trigger pointerUp, mouseUp, click with ctrl=true
}) |
I may be missing something, but I don't see an advantage to using function renderWithStates(element) {
render(element, { element: element.ownerDocument})
userEvent.keyboard('[ControlLeft>]')
userEvent.pointer('[MouseLeft>]')
} A more specific pointer API could help for testing edge cases, though I'm not sure how commonly that would be needed in JSDOM. |
For our blind spot regarding changes that happen before our API call the users would have to reimplement our workarounds for the change event in their render function. For the let keyboardState = userEvent.keyboard('[ControlLeft>]')
// ... do something ...
keyboardState = userEvent.keyboard('abc', {keyboardState}) // continue key events with ctrl=true
// ... do something else ...
userEvent.keyboard('[/ControlLeft]', {keyboardState}) // release control key But currently it is not (officially) possible to start off with some state without triggering the extra events that come with it. If that should happen in a setup function or right on the keyboard call or both would be to be determined. Just adding the note that it could be used for this. |
🎉 This PR is included in version 13.2.1 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
What:
Closes #682
Why:
The browser dispatches a
change
event when an element with changed value loses focus.When we alter the element
value
/textContent
, we dispatch aninput
event but no nativechange
event.How:
When setting the
value
/textContent
an event handler is added to the capture phase of theblur
event on thewindow
.If the
value
/textContent
on our element is different than the initial one, we dispatch achange
event.Checklist:
Constraints:
We could (also) set the initial value on the
focus
event, but for this we would either:import
(only works if thedocument
is global)setup
API (and/or implicitly when calling one of our other APIs)Therefore other event handlers on
blur
(that are added on the capture phase onwindow
) might be executed before we dispatch the change event.