useTimeout.spec.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import {renderHook} from 'sentry-test/reactTestingLibrary';
  2. import useTimeout from './useTimeout';
  3. // biome-ignore lint/correctness/useHookAtTopLevel: not a hook
  4. jest.useFakeTimers();
  5. describe('useTimeout', () => {
  6. const timeMs = 500;
  7. const onTimeout = jest.fn();
  8. beforeEach(() => {
  9. onTimeout.mockReset();
  10. });
  11. it('should timeout after a specified delay', () => {
  12. const {result} = renderHook(useTimeout, {
  13. initialProps: {timeMs, onTimeout},
  14. });
  15. result.current.start();
  16. expect(onTimeout).not.toHaveBeenCalled();
  17. jest.advanceTimersByTime(timeMs + 10);
  18. expect(onTimeout).toHaveBeenCalled();
  19. });
  20. it('should call the callback if a timeout is ended early', () => {
  21. const {result} = renderHook(useTimeout, {
  22. initialProps: {timeMs, onTimeout},
  23. });
  24. result.current.start();
  25. expect(onTimeout).not.toHaveBeenCalled();
  26. result.current.end();
  27. expect(onTimeout).toHaveBeenCalled();
  28. });
  29. it('should not exec the callback if a timeout is cancelled', () => {
  30. const {result} = renderHook(useTimeout, {
  31. initialProps: {timeMs, onTimeout},
  32. });
  33. result.current.start();
  34. expect(onTimeout).not.toHaveBeenCalled();
  35. result.current.cancel();
  36. expect(onTimeout).not.toHaveBeenCalled();
  37. });
  38. it('should return stable start/cancel/end callbacks', () => {
  39. const {result, rerender} = renderHook(useTimeout, {
  40. initialProps: {timeMs, onTimeout},
  41. });
  42. const firstRender = {...result.current};
  43. rerender({timeMs, onTimeout});
  44. expect(result.current.start).toBe(firstRender.start);
  45. expect(result.current.cancel).toBe(firstRender.cancel);
  46. expect(result.current.end).toBe(firstRender.end);
  47. });
  48. it('should return a new start() method when timeMs changes', () => {
  49. const {result, rerender} = renderHook(useTimeout, {
  50. initialProps: {timeMs, onTimeout},
  51. });
  52. const firstRender = {...result.current};
  53. rerender({timeMs: 999, onTimeout});
  54. expect(result.current.cancel).toBe(firstRender.cancel);
  55. expect(result.current.end).toBe(firstRender.end);
  56. expect(result.current.start).not.toBe(firstRender.start);
  57. });
  58. it('should return a new start() and end() method when onTimeout changes', () => {
  59. const {result, rerender} = renderHook(useTimeout, {
  60. initialProps: {timeMs, onTimeout},
  61. });
  62. const firstRender = {...result.current};
  63. rerender({timeMs, onTimeout: jest.fn()});
  64. expect(result.current.cancel).toBe(firstRender.cancel);
  65. expect(result.current.start).not.toBe(firstRender.start);
  66. expect(result.current.end).not.toBe(firstRender.end);
  67. });
  68. it('should not exec the callback after unmount', () => {
  69. const {result, unmount} = renderHook(useTimeout, {
  70. initialProps: {timeMs, onTimeout},
  71. });
  72. result.current.start();
  73. unmount();
  74. jest.runAllTimers();
  75. expect(onTimeout).not.toHaveBeenCalled();
  76. });
  77. });