useHotkeys.spec.jsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import {reactHooks} from 'sentry-test/reactTestingLibrary';
  2. import {getKeyCode} from 'sentry/utils/getKeyCode';
  3. import {useHotkeys} from 'sentry/utils/useHotkeys';
  4. describe('useHotkeys', function () {
  5. let events = {};
  6. function makeKeyEvent(keyCode, options) {
  7. return {
  8. keyCode: getKeyCode(keyCode),
  9. preventDefault: jest.fn(),
  10. ...options,
  11. };
  12. }
  13. beforeEach(() => {
  14. // Empty our events before each test case
  15. events = {};
  16. // Define the addEventListener method with a Jest mock function
  17. document.addEventListener = jest.fn((event, callback) => {
  18. events[event] = callback;
  19. });
  20. document.removeEventListener = jest.fn(event => {
  21. delete events[event];
  22. });
  23. });
  24. it('handles a simple match', function () {
  25. const callback = jest.fn();
  26. reactHooks.renderHook(() => useHotkeys([{match: 'ctrl+s', callback}]));
  27. expect(events.keydown).toBeDefined();
  28. expect(callback).not.toHaveBeenCalled();
  29. const evt = makeKeyEvent('s', {ctrlKey: true});
  30. events.keydown(evt);
  31. expect(evt.preventDefault).toHaveBeenCalled();
  32. expect(callback).toHaveBeenCalled();
  33. });
  34. it('handles multiple matches', function () {
  35. const callback = jest.fn();
  36. reactHooks.renderHook(() => useHotkeys([{match: ['ctrl+s', 'cmd+m'], callback}]));
  37. expect(events.keydown).toBeDefined();
  38. expect(callback).not.toHaveBeenCalled();
  39. events.keydown(makeKeyEvent('s', {ctrlKey: true}));
  40. expect(callback).toHaveBeenCalled();
  41. callback.mockClear();
  42. events.keydown(makeKeyEvent('m', {metaKey: true}));
  43. expect(callback).toHaveBeenCalled();
  44. });
  45. it('handles a complex match', function () {
  46. const callback = jest.fn();
  47. reactHooks.renderHook(() =>
  48. useHotkeys([{match: ['cmd+control+option+shift+x'], callback}])
  49. );
  50. expect(events.keydown).toBeDefined();
  51. expect(callback).not.toHaveBeenCalled();
  52. events.keydown(
  53. makeKeyEvent('x', {
  54. altKey: true,
  55. metaKey: true,
  56. shiftKey: true,
  57. ctrlKey: true,
  58. })
  59. );
  60. expect(callback).toHaveBeenCalled();
  61. });
  62. it('updates with rerender', function () {
  63. const callback = jest.fn();
  64. const {rerender} = reactHooks.renderHook(
  65. p => useHotkeys([{match: p.match, callback}]),
  66. {
  67. initialProps: {match: 'ctrl+s'},
  68. }
  69. );
  70. expect(events.keydown).toBeDefined();
  71. expect(callback).not.toHaveBeenCalled();
  72. events.keydown(makeKeyEvent('s', {ctrlKey: true}));
  73. expect(callback).toHaveBeenCalled();
  74. callback.mockClear();
  75. rerender({match: 'cmd+m'});
  76. events.keydown(makeKeyEvent('s', {ctrlKey: true}));
  77. expect(callback).not.toHaveBeenCalled();
  78. events.keydown(makeKeyEvent('m', {metaKey: true}));
  79. expect(callback).toHaveBeenCalled();
  80. });
  81. it('skips input and textarea', function () {
  82. const callback = jest.fn();
  83. reactHooks.renderHook(() => useHotkeys([{match: ['/'], callback}]));
  84. events.keydown(makeKeyEvent('/', {target: document.createElement('input')}));
  85. expect(callback).not.toHaveBeenCalled();
  86. });
  87. it('does not skips input and textarea with includesInputs', function () {
  88. const callback = jest.fn();
  89. reactHooks.renderHook(() =>
  90. useHotkeys([{match: ['/'], callback, includeInputs: true}])
  91. );
  92. events.keydown(makeKeyEvent('/', {target: document.createElement('input')}));
  93. expect(callback).toHaveBeenCalled();
  94. });
  95. it('skips preventDefault', function () {
  96. const callback = jest.fn();
  97. reactHooks.renderHook(() =>
  98. useHotkeys([{match: 'ctrl+s', callback, skipPreventDefault: true}])
  99. );
  100. const evt = makeKeyEvent('s', {ctrlKey: true});
  101. events.keydown(evt);
  102. expect(evt.preventDefault).not.toHaveBeenCalled();
  103. expect(callback).toHaveBeenCalled();
  104. });
  105. });