react-testing-library version: 4.0.1react version: 16.4.1node version: 8.9.4npm (or yarn) version: (yarn 1.7.0) const { container, debug } = render(<input onKeyDown={console.log} />);
fireEvent(
container.getElementsByTagName('input')[0],
new KeyboardEvent('keyDown', { key: 'Enter', keyCode: 13, which: 13 })
);
I am trying to simulate keyboard events to validate my input component. To do that I tried to use fireEvent function with keydown and keyDown types but neither worked.
Event handlers are not getting called
https://codesandbox.io/s/n32nmp18rl
I can't simulate any input via keyboard
When i tried to simulate events using reacts ref and react-dom/test-utils Simulate class it seemed to work.
It's because you need to set the bubbles property to true so react's event delegation will work. Like so: https://codesandbox.io/s/rm4lqyn9mp
This is why I recommend you use fireEvent.keyDown instead which has defaults like this, like so: https://codesandbox.io/s/myyxkrn52j
Good luck.
The onChange callback on <input type='checkbox' /> is not called on simulating a spacebar event. The onChange is actually called if i press space when the checkbox is in focus.
See the README. For checkboxes you should fire the click event, not the change event.
But i am not firing the change event. I want to test keyboard interactions. In this case, i want to test the spacebar keydown.
Ah, I see what you mean. You want this: https://github.com/kentcdodds/dom-testing-library/issues/107
Don't know if i followed the thread correctly. Does it mean that to make the checkbox change state based on keyboard spacebar press, i need to fire a combination of events?
What is the best way to test accessibility related keyboard scenarios? E.g. tab to focus an element and then press space or enter to perform action on the element.
I'm honestly not sure. For your specific example, I think you should be able to rely on the way that browsers deal with checkboxes and use click. Don't bother testing the browser itself. Just trust that it does the right thing when a user hits the space-key when the checkbox has focus.
Hmm. I was trying to add these tests because we ran into a situation where a coworker of mine wrote a component and thought it was accessible but didn't test it for keyboard interactions manually. I caught it in code review but was wondering if we could make keyboard interaction tests a norm.
Will try to add those tests at selenium level for now. Thanks for your time!
Hmmm... Are you sure it was a checkbox? How did they make a checkbox that didn't work with the space bar?
It was a switch which had a checkbox underneath so that we could use the checkbox onChange and focus browser functionality. The switch was implemented by styling the accompanying label but the <input> was hidden which made it non-focusable (is that a word?).
Ah, I see, so you don't want to test the keyup on the input, you want to test it on the switch...
Yes, that's correct. I tried all combinations - on the input, the switch container, document and document.body. No luck.
So when the user's actually using the component, where are they focused when they hit the space bar?
I removed the display: none from <input> and instead made it position: aboslute; opacity: 0.
Now i can hit 'Tab' and the focus moves to the switch. On pressing space bar, the switch toggles between on/off, just like a checkbox.
You may consider doing the CSS like bootstrap's sr-only-focusable: https://getbootstrap.com/docs/3.3/css/#helper-classes-screen-readers
I know that some screen readers will skip elements that aren't visible unless it's done in a certain way.
Here's the CSS for sr-only:
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0,0,0,0);
border: 0;
I can't find the css for sr-only-focusable.
@kentcdodds HTML5Boilerplate has a focused one:
https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css#L148-L157
Thanks!
I wrote something very similar
position: absolute;
width: 1px;
height: 1px;
border: 0;
clip: rect(0, 0, 0, 0);
opacity; 0;
Had no idea there was so much css involved to have an element hidden behind another one but still be present in the DOM :)
Most helpful comment
@kentcdodds HTML5Boilerplate has a focused one:
https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css#L148-L157