-
Notifications
You must be signed in to change notification settings - Fork 256
fix(keyboard): dispatch change event on blur #703
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
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 keyBut 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
changeevent when an element with changed value loses focus.When we alter the element
value/textContent, we dispatch aninputevent but no nativechangeevent.How:
When setting the
value/textContentan event handler is added to the capture phase of theblurevent on thewindow.If the
value/textContenton our element is different than the initial one, we dispatch achangeevent.Checklist:
Constraints:
We could (also) set the initial value on the
focusevent, but for this we would either:import(only works if thedocumentis global)setupAPI (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.