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: button trigger space #409
fix: button trigger space #409
Conversation
Unfortunately the CI fails 😄 During implementation I needed to update the focus and blur behavior, because of a recent fix in jsdom: jsdom/jsdom#2708 I also updated However it looks like Travis is still loading a cached version. Maybe the new jsdom version is not defined in jest-dom. Do you know how to tell Travis to rerun with a cleared cache? |
Awesome! Just triggered a run of CI without the cache. This is a big change! I'll try to review it now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! Thank you for taking so much time on this. It's obviously quality work. I have a few nit-picky things I hope you don't mind.
button - pointerover | ||
button - pointerenter | ||
button - mouseover: Left (0) | ||
button - mouseenter: Left (0) | ||
button - pointermove | ||
button - mousemove: Left (0) | ||
button - pointerdown | ||
button - mousedown: Left (0) | ||
button - focus | ||
button - focusin | ||
button - pointerup | ||
button - mouseup: Left (0) | ||
button - click: Left (0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking this is probably a special case where simulating mousing over and clicking wouldn't make sense right? Because anyone trying to do: userEvent.type(button, '{space}')
is probably not wanting to fire two click events... Hmmm... Should we make this a special case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was asking myself the same question. For the sake of consistency I decided it should behave the same way it does with other elements.
Maybe we could add a section about this to the documentation? So it is clear that the most popular way to test keyboard events on a button would be:
button.focus()
userEvent.type(button, '{space}', { skipClick: true })
Another idea would be to use element.focus() instead of userEvent.click(element) as a default for type
.
The benefit would be, that it is less "magic" and we could get rid of skipClick
altogether.
Also the .focus()
would just fire additional events, if the element doesn't have focus already. So it would just be a minimal safety net.
For tests that require a click
beforehand, it would still be easy to do that:
userEvent.click(input)
userEvent.type(input, 'foo')
test(`' ' on a button`, () => { | ||
const {element, getEventSnapshot} = setup('<button />') | ||
|
||
userEvent.type(element, ' ') | ||
|
||
expect(getEventSnapshot()).toMatchInlineSnapshot(` | ||
Events fired on: button | ||
|
||
button - pointerover | ||
button - pointerenter | ||
button - mouseover: Left (0) | ||
button - mouseenter: Left (0) | ||
button - pointermove | ||
button - mousemove: Left (0) | ||
button - pointerdown | ||
button - mousedown: Left (0) | ||
button - focus | ||
button - focusin | ||
button - pointerup | ||
button - mouseup: Left (0) | ||
button - click: Left (0) | ||
button - keydown: (32) | ||
button - keypress: (32) | ||
button - keyup: (32) | ||
button - click: Left (0) | ||
`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we make it clear that all we're really testing is that ' '
is the same as '{space}'
?
test(`' ' on a button`, () => { | |
const {element, getEventSnapshot} = setup('<button />') | |
userEvent.type(element, ' ') | |
expect(getEventSnapshot()).toMatchInlineSnapshot(` | |
Events fired on: button | |
button - pointerover | |
button - pointerenter | |
button - mouseover: Left (0) | |
button - mouseenter: Left (0) | |
button - pointermove | |
button - mousemove: Left (0) | |
button - pointerdown | |
button - mousedown: Left (0) | |
button - focus | |
button - focusin | |
button - pointerup | |
button - mouseup: Left (0) | |
button - click: Left (0) | |
button - keydown: (32) | |
button - keypress: (32) | |
button - keyup: (32) | |
button - click: Left (0) | |
`) | |
test(`' ' on a button is the same as '{space}'`, () => { | |
const {element: e1, getEventSnapshot: snap1} = setup('<button />') | |
const {element: e2, getEventSnapshot: span2} = setup('<button />') | |
userEvent.type(e1, ' ') | |
userEvent.type(e2, '{space}') | |
expect(snap1()).toBe(snap2()) |
`) | ||
}) | ||
|
||
test('" " on an input type="color"', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's do the same to this one as we do with the button one above.
`) | ||
}) | ||
|
||
test('{space} on an input type="color"', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we make it clear (probably via a comment or the test title) what about this test is important? It's hard to tell as it looks just like all the other tests. Is there some special reason we want to test the color type? (I just tried out an input[type=color] and realized in chrome it renders a button with a color picker so that makes sense why we've got this test here, but a comment would be helpful).
`) | ||
}) | ||
|
||
test('{enter} on an input type="color"', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing as the space on a type color. Why is type color so special it needs a test? When this test fails, how does the developer know what part of the test is important for fixing?
|
||
function getTypeCallback(remainingString) { | ||
const character = remainingString[0] | ||
const callback = createTypeCharacter(character) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we need the createTypeCharacter function. This is a quick and easy one-liner.
const callback = createTypeCharacter(character) | |
const callback = context => typeCharacter(character, context) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, just had time to read this. That's true. Initially I used createTypeCharacter in more places, but now it is a bit too much 😄
function createTypeCharacter(character) { | ||
return context => typeCharacter(character, context) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the definition inline above we can remove this.
function createTypeCharacter(character) { | |
return context => typeCharacter(character, context) | |
} |
Oh, and the CI failures are ESLint related:
If you could fix those too that'd be super :) Thanks! |
Codecov Report
@@ Coverage Diff @@
## master #409 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 12 12
Lines 390 418 +28
Branches 111 116 +5
=========================================
+ Hits 390 418 +28
Continue to review full report at Codecov.
|
Fantastic. Thank you! |
@all-contributors please add @visualjerk for code, tests, and docs |
I've put up a pull request to add @visualjerk! 🎉 |
Thanks so much for your help! I've added you as a collaborator on the project. Please make sure that you review the |
🎉 This PR is included in version 12.0.13 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
@kentcdodds Thanks for your kind words 😄 As this is already merged, I can add the improvements you mentioned to the next PR. |
Oh, whoops 😅 I didn't check and just assumed you'd made the improvements in that one commit. Thanks! |
What:
This fixes #406
Why:
Because clickable inputs and buttons should be handled differently by
type
.How:
type
where it was necessarytype.js
to keep it understandable with these additionsChecklist: