useHotkeys.spec.jsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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, {
  27. initialProps: [{match: 'ctrl+s', callback}],
  28. });
  29. expect(events.keydown).toBeDefined();
  30. expect(callback).not.toHaveBeenCalled();
  31. const evt = makeKeyEvent('s', {ctrlKey: true});
  32. events.keydown(evt);
  33. expect(evt.preventDefault).toHaveBeenCalled();
  34. expect(callback).toHaveBeenCalled();
  35. });
  36. it('handles multiple matches', function () {
  37. const callback = jest.fn();
  38. reactHooks.renderHook(useHotkeys, {
  39. initialProps: [{match: ['ctrl+s', 'cmd+m'], callback}],
  40. });
  41. expect(events.keydown).toBeDefined();
  42. expect(callback).not.toHaveBeenCalled();
  43. events.keydown(makeKeyEvent('s', {ctrlKey: true}));
  44. expect(callback).toHaveBeenCalled();
  45. callback.mockClear();
  46. events.keydown(makeKeyEvent('m', {metaKey: true}));
  47. expect(callback).toHaveBeenCalled();
  48. });
  49. it('handles a complex match', function () {
  50. const callback = jest.fn();
  51. reactHooks.renderHook(useHotkeys, {
  52. initialProps: [{match: ['cmd+control+option+shift+x'], callback}],
  53. });
  54. expect(events.keydown).toBeDefined();
  55. expect(callback).not.toHaveBeenCalled();
  56. events.keydown(
  57. makeKeyEvent('x', {
  58. altKey: true,
  59. metaKey: true,
  60. shiftKey: true,
  61. ctrlKey: true,
  62. })
  63. );
  64. expect(callback).toHaveBeenCalled();
  65. });
  66. it('updates with rerender', function () {
  67. const callback = jest.fn();
  68. const {rerender} = reactHooks.renderHook(
  69. p => useHotkeys([{match: p.match, callback}]),
  70. {
  71. initialProps: {match: 'ctrl+s'},
  72. }
  73. );
  74. expect(events.keydown).toBeDefined();
  75. expect(callback).not.toHaveBeenCalled();
  76. events.keydown(makeKeyEvent('s', {ctrlKey: true}));
  77. expect(callback).toHaveBeenCalled();
  78. callback.mockClear();
  79. rerender({match: 'cmd+m'});
  80. events.keydown(makeKeyEvent('s', {ctrlKey: true}));
  81. expect(callback).not.toHaveBeenCalled();
  82. events.keydown(makeKeyEvent('m', {metaKey: true}));
  83. expect(callback).toHaveBeenCalled();
  84. });
  85. it('skips input and textarea', function () {
  86. const callback = jest.fn();
  87. reactHooks.renderHook(useHotkeys, {initialProps: [{match: ['/'], callback}]});
  88. events.keydown(makeKeyEvent('/', {target: document.createElement('input')}));
  89. expect(callback).not.toHaveBeenCalled();
  90. });
  91. it('does not skips input and textarea with includesInputs', function () {
  92. const callback = jest.fn();
  93. reactHooks.renderHook(useHotkeys, {
  94. initialProps: [{match: ['/'], callback, includeInputs: true}],
  95. });
  96. events.keydown(makeKeyEvent('/', {target: document.createElement('input')}));
  97. expect(callback).toHaveBeenCalled();
  98. });
  99. it('skips preventDefault', function () {
  100. const callback = jest.fn();
  101. reactHooks.renderHook(useHotkeys, {
  102. initialProps: [{match: 'ctrl+s', callback, skipPreventDefault: true}],
  103. });
  104. const evt = makeKeyEvent('s', {ctrlKey: true});
  105. events.keydown(evt);
  106. expect(evt.preventDefault).not.toHaveBeenCalled();
  107. expect(callback).toHaveBeenCalled();
  108. });
  109. });