enzyme: Unable to simulate keyboard events
Problem
I’m truing to simulate keyboard events with enzyme but I couldn’t find a single line of documentation or code example where keyboard events are implemented. I’ve tried using
wrapper.find(".myclass").simulate("keyDown", {
target: {
keyCode: 40,
which: 40,
key: "down arrow"
}
});
and
wrapper.find(".myclass").simulate("keyDown", {
keyCode: 40,
which: 40,
key: "down arrow"
});
I’ve also tried using other types of casing on the event name and key names but nothing worked.
While there’s no error using any of the two examples I’ve mentioned the output just isn’t the expected and using TestUtils.Simulate.keyDown(searchInput, { keyCode: 40 });
all works as expected.
Am I not using the correct syntax?
About this issue
- Original URL
- State: open
- Created 8 years ago
- Reactions: 22
- Comments: 34 (3 by maintainers)
Commits related to this issue
- example for: https://github.com/airbnb/enzyme/issues/441 — committed to eugene-matvejev/react-battleship by deleted user 7 years ago
- more and better test cases for <GameResultsHandler/>, for https://github.com/airbnb/enzyme/issues/441 — committed to eugene-matvejev/react-battleship by deleted user 7 years ago
It did not work for me until I used the
which
property.wrapper.find('.myclass').simulate('keyDown', { key: 'Tab', keyCode: 9, which: 9 });
I can remove both
key
andkeyCode
properties and it still works, but it’s nice to see in the test what key it refers to.@darkjoker @springuper try this, worked for me
@darkjoker you can see a working example that I wrote this morning to verify the behavior: https://github.com/Aweary/enzyme-test-repo/blob/issue-441/test.js
This passes as I’d expect. If you can share a simplified reproducible case where it’s not working that would be great. Feel free to fork that ^ repo to do so, if you’d like.
When working with events created by
addEventListener()
, it seems thatsimulate()
does not work properly ( usingmount()
), e.g.And writing the unit test for that component with Enzyme…
So, as mentioned before, it seems the
simulate()
method only works with events registered on the components themselves, but when dealing with events attached to the underlying DOM nodes, it does not work.Using ReactTestUtils.Simulate is not working as expected neither 😦
BTW, it’s worth mentioning the Enzyme Future Work.
For me the problem was I had added event listeners on the DOM elements themselves, and not in JSX (e.g.
<div onKeyDown={} />
. I guess thesimulate
method only works when events are registered on the components themselves, not the underlying DOM nodes.I sure wish you could trigger a
click
event from the keyboard for accessibility testing usingbuttonComponent.simulate('keydown', {which: 13})
or similar, like real DOM nodes do. It’s a great way to assert an HTML element is focusable and works from the keyboard, rather than testing only for mouse clicks.onClick
bindings never respond from key events in Enzyme with JSDOM, and binding to bothkeydown
andmousedown
just for testing purposes creates unnecessary complexity.This is one of the hairiest accessibility problems I’ve come across in React testing. I’ve tried every relevant trick I could come up with, and I’m having to concede and write keyboard compatibility tests in Selenium Webdriver instead. Even Simulant doesn’t seem to trigger event callbacks in this scenario, I suspect because of the way SyntheticEvent is delegating events through the DOM tree rather than on a specific button node.
@danyim @prijuly2000 if you use onChange to simulate input fields, only the last character in the string will be reflected in the keyDown event so you can use that to test keyPress
So you can slice the string input and check for each last character to simulate a simulation on keyPress via keyDown events!
NOTE
for(let i in st)
is the same asfor(i=0; i < st.length; i++)
0, 1, 2, 3, 4, 5
for(let i of st)
will returni
as values of strings, t, r, i, n, g
@tomitrescak that would require a keypress for
s
withctrlKey
set totrue
, iirc.i found that if the events attached by
element.addEventListener()
.simulate()
will not trigger the listener.so my suggested solution is to simulate the event manually by
element.dispatchEvent()
I believe this is true. The
simulate
function will only trigger the exact event handler that you specify. It is not doing a real simulation that causes events to get triggered but rather actually calling the specified event handler directly instead. For real simulation, you may need to use something like simulant.+1, waiting for a solution.
simulate
should be avoided. It does not faithfully simulate anything - it’s just sugar for.prop('onClick')()
or similar.@darkjoker for
mount
, thesimulate
method is a thin wrapper aroundReactTestUtils.Simulate
, so I feel like there’s something else going on with your component that’s causing it to fail. Can you share a simplified case reproducing the issue? TheComboBox
is rather large (and compiled) so it’s hard to parse what’s going on there.No, I have been using TestUtils for this kind of tests
@leon0707 the
simulate
API doesn’t actually simulate anything - what you can do, however, is manually invoke anonKeyDown
prop or similar, and pass a fake event object that has the right properties to mimic a shift+enter.@aweary I managed to get it working on mount by using
.simulate('keyDown', { key: 'Enter', keyCode: 13, which: 13 })
However, the same example using
shallow
rendering didn’t work, Is any reason why shallow render doesn’t allow to handlekeyDown
?@pranjalk Honestly I don’t know where to start to comment your post even if you example achieve the question asked. Personally, it’s over engineer from my point of view because you are storing the event on the
state
just for test that the event gets fire with the value expected.Otherwise, you should target examples like “Brandon dail” propose, but replacing
keyDown
forkeyPress
.Is it possible to simulate multiple keys, such as ctrls+s? Sorry for breaking into this discussion though 😕
I’ll post a simplified version of the component asap only maintaining the core functionality I’m trying to test