Test event listeners in enzyme/jest within useEffect

Viewed 422

I have a piece of code in one of my components as following where if the user uses the ESCAPE key the modal will close:

    React.useEffect(() => {
    function keyListener(e) {
        if (e.key === 'Escape' || e.keyCode === escapeKey || e.which === escapeKey) {
            props.toggleShowModal();
        }
    }

    document.addEventListener('keydown', keyListener);

    return () => document.removeEventListener('keydown', keyListener);
});

I tried testing this in several ways but nothing worked, the last thing I tried was this:

    test('it calls the dismiss callback on ESC key', () => {
    global.document.addEventListener = jest.fn();

    const wrapper = mount(
        <Modal
            toggleShowModal={jest.fn()}
        />
    );
    expect(global.document.addEventListener).toHaveBeenCalled();

    const KEYBOARD_ESCAPE_CODE = 27;

    const spyOnToggleShowModal = jest.spyOn(wrapper.props(), 'toggleShowModal');
    var event = new KeyboardEvent('keydown', { key: 'Escape', keyCode: KEYBOARD_ESCAPE_CODE, which: KEYBOARD_ESCAPE_CODE });
    document.dispatchEvent(event);
    expect(spyOnToggleShowModal).toHaveBeenCalled();
});
1 Answers

I know I'm late to the party but this might still help some people

test("executes handler on escape keydown and unsubscribes after unmount", () => {
    const callback = jest.fn();
    const wrapper = mount(<Modal toggleShowModal={callback} />);

    document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape" }));
    expect(callback).toHaveBeenCalledTimes(1);

    wrapper.unmount();

    document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape" }));
    expect(callback).toHaveBeenCalledTimes(1);
  });

mind the document.dispatchEvent(). It might need to be dispatched on window or other element depending where EventListener was added

Related