Skip to content

Instantly share code, notes, and snippets.

@yairEO
Created January 13, 2023 19:44
Show Gist options
  • Save yairEO/f592afe2efe6ed5a3dc202093b5fd212 to your computer and use it in GitHub Desktop.
Save yairEO/f592afe2efe6ed5a3dc202093b5fd212 to your computer and use it in GitHub Desktop.
chai + sinon: testing code with DOM events

How to test a React hooks which is binding a global window/document event(s):

This is an easy approach for testing DOM events in hooks/components without actually emmitting/triggering any "fake" events, which is much easier:

  1. In the tests file, create a dummy React component and call the hook. if the hook is returning something, then assign it to a varaible which should be defined from outside the component so it will be available for the tests cases.
const Dummy = ({focused}) => {
    useGlobalEvents(focused, callbackSpy);
    return null;
};
  1. Mock document.addEventListener with sinon (globally is preferable):
import sinon from 'sinon';

global.window.addEventListener = sinon.spy();
  1. Mount the dummy component (using Enzyme or whichever other React-testing library), so the hook(s) would be called.

  2. Test the DOM event by manually firing the callback of the spied-on addEventListener:

// get the last call to the "addEventListener" spy
const call = document.addEventListener.lastCall;

// manually call the event handler's callback with the desired `event` argument object, tailored for a specific test:
call.args[1]({code: 'Space'});

// Test the logic inside the event's callback (`useGlobalEvents.js` lines 10-12)
expect(callbackSpy.calledOnce).to.be.true;
import {useDocumentListeners} from 'hooks';
/**
* Add hook to handle input selection with keyboard 'Space'
* @param {boolean} control - focused: whether this input is focused or not
* @param {function} cb - callback that fires when the user select this input with space navigation
*/
export default (focused, cb) => useDocumentListeners({
keydown: e => {
if (focused && e.code === 'Space') {
cb();
}
},
});
import React from 'react';
import {mount} from 'enzyme';
import {expect} from 'chai';
import sinon from 'sinon';
import useGlobalEvents from './useGlobalEvents';
describe('useTriggerOnSpace()', () => {
const callbackSpy = sinon.spy();
// to test hooks, a React component is needed:
const Dummy = ({focused}) => {
useGlobalEvents(focused, callbackSpy);
return null;
};
it('should not call the callback if not focused', () => {
mount(<Dummy focused={false}/>);
const call = document.addEventListener.lastCall;
call.args[1]({code: 'Space'});
expect(callbackSpy.calledOnce).to.be.false;
});
it('should call the callback if focused', () => {
mount(<Dummy focused={true}/>);
const call = document.addEventListener.lastCall;
call.args[1]({code: 'Space'});
expect(callbackSpy.calledOnce).to.be.true;
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment