import { h } from 'preact'; import { renderHook } from '@testing-library/preact-hooks'; import { fireEvent, render } from '@testing-library/preact'; import { KeyboardShortcuts, useKeyboardShortcuts, } from '../useKeyboardShortcuts'; describe('Keyboard shortcuts for components', () => { describe('useKeyboardShortcuts', () => { it('should fire a function when keydown is detected', () => { const shortcut = { KeyK: jest.fn(), }; renderHook(() => useKeyboardShortcuts(shortcut, document)); fireEvent.keyDown(document, { code: 'KeyK' }); expect(shortcut.KeyK).toHaveBeenCalledTimes(1); }); it('should fire a function when chained keydown is detected', () => { const shortcut = { 'KeyA~KeyB': jest.fn(), }; renderHook(() => useKeyboardShortcuts(shortcut, document)); fireEvent.keyDown(document, { code: 'KeyA' }); fireEvent.keyDown(document, { code: 'KeyB' }); expect(shortcut['KeyA~KeyB']).toHaveBeenCalledTimes(1); }); it('should not fire a function when chained keydown is missed, timeout should only be 0ms', async () => { const shortcut = { 'KeyA~KeyB': jest.fn(), }; const timeout = 0; renderHook(() => useKeyboardShortcuts(shortcut, document, { timeout })); fireEvent.keyDown(document, { code: 'KeyA' }); await new Promise((resolve) => setTimeout(() => { fireEvent.keyDown(document, { code: 'KeyB' }); resolve(); }, 25), ); expect(shortcut['KeyA~KeyB']).not.toHaveBeenCalled(); }); it('should not add event listener if shortcut object is empty', () => { HTMLDocument.prototype.addEventListener = jest.fn(); renderHook(() => useKeyboardShortcuts({}, document)); expect(HTMLDocument.prototype.addEventListener).not.toHaveBeenCalled(); }); it('should add event listener to window', () => { HTMLDocument.prototype.addEventListener = jest.fn(); const shortcut = { KeyK: null, }; renderHook(() => useKeyboardShortcuts(shortcut, document)); expect(HTMLDocument.prototype.addEventListener).toHaveBeenCalledTimes(1); }); it('should not fire a function when keydown is detected in element', () => { const shortcut = { KeyK: jest.fn(), }; const eventTarget = document.createElement('textarea'); // eventTarget set since the default is window renderHook(() => useKeyboardShortcuts(shortcut, document), eventTarget); fireEvent.keyDown(eventTarget, { code: 'KeyK' }); expect(shortcut.KeyK).not.toHaveBeenCalled(); }); it('should remove event listener when the hook is unmounted', () => { HTMLDocument.prototype.addEventListener = jest.fn(); HTMLDocument.prototype.removeEventListener = jest.fn(); const shortcut = { KeyK: null, }; const { unmount } = renderHook(() => useKeyboardShortcuts(shortcut, document), ); unmount(); expect(HTMLDocument.prototype.addEventListener).toHaveBeenCalledTimes(1); expect(HTMLDocument.prototype.removeEventListener).toHaveBeenCalledTimes( 1, ); }); }); describe('', () => { it('should not add event listener if shortcut object is empty', async () => { HTMLDocument.prototype.addEventListener = jest.fn(); render(); expect(HTMLDocument.prototype.addEventListener).not.toHaveBeenCalled(); }); it('should add event listener to window', async () => { HTMLDocument.prototype.addEventListener = jest.fn(); render( , ); expect(HTMLDocument.prototype.addEventListener).toHaveBeenCalledTimes(1); }); it('should remove event listener when the hook is unmounted', async () => { HTMLDocument.prototype.addEventListener = jest.fn(); HTMLDocument.prototype.removeEventListener = jest.fn(); const { unmount } = render( , ); unmount(); expect(HTMLDocument.prototype.addEventListener).toHaveBeenCalledTimes(1); expect(HTMLDocument.prototype.removeEventListener).toHaveBeenCalledTimes( 1, ); }); }); });