canvasScheduler.spec.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import {CanvasScheduler, FlamegraphEvents} from 'sentry/utils/profiling/canvasScheduler';
  2. const handlers: (keyof FlamegraphEvents)[] = [
  3. 'reset zoom',
  4. 'set config view',
  5. 'highlight frame',
  6. 'transform config view',
  7. 'zoom at frame',
  8. ];
  9. describe('CanvasScheduler', () => {
  10. it.each([handlers])('registers and calls %s', key => {
  11. const handler = jest.fn();
  12. const scheduler = new CanvasScheduler();
  13. scheduler.on(key, handler);
  14. scheduler.dispatch(key, undefined as any);
  15. expect(scheduler.events[key].has(handler)).toBe(true);
  16. expect(handler).toHaveBeenCalledTimes(1);
  17. });
  18. it.each([handlers])(
  19. 'does not register duplicate handler and calls %s only once',
  20. (key: keyof FlamegraphEvents) => {
  21. const handler = jest.fn();
  22. const scheduler = new CanvasScheduler();
  23. scheduler.on(key, handler);
  24. scheduler.on(key, handler);
  25. scheduler.dispatch(key, undefined as any);
  26. expect(scheduler.events[key].has(handler)).toBe(true);
  27. expect(handler).toHaveBeenCalledTimes(1);
  28. }
  29. );
  30. it.each([handlers])('removes %s registered handler and does not call it', key => {
  31. const handler = jest.fn();
  32. const scheduler = new CanvasScheduler();
  33. scheduler.on(key, handler);
  34. scheduler.off(key, handler);
  35. scheduler.dispatch(key, undefined as any);
  36. expect(scheduler.events[key].has(handler)).toBe(false);
  37. expect(handler).not.toHaveBeenCalled();
  38. });
  39. it('registerBeforeFrameCallback', () => {
  40. jest.useFakeTimers();
  41. const drawFn = jest.fn();
  42. const scheduler = new CanvasScheduler();
  43. scheduler.registerBeforeFrameCallback(drawFn);
  44. scheduler.draw();
  45. jest.runAllTimers();
  46. expect(drawFn).toHaveBeenCalledTimes(1);
  47. });
  48. it('unregisterBeforeFrameCallback', () => {
  49. jest.useFakeTimers();
  50. const drawFn = jest.fn();
  51. const scheduler = new CanvasScheduler();
  52. scheduler.registerBeforeFrameCallback(drawFn);
  53. scheduler.unregisterBeforeFrameCallback(drawFn);
  54. scheduler.draw();
  55. jest.runAllTimers();
  56. expect(drawFn).not.toHaveBeenCalled();
  57. });
  58. it('registerAfterFrameCallback', () => {
  59. jest.useFakeTimers();
  60. const drawFn = jest.fn();
  61. const scheduler = new CanvasScheduler();
  62. scheduler.registerAfterFrameCallback(drawFn);
  63. scheduler.draw();
  64. jest.runAllTimers();
  65. expect(drawFn).toHaveBeenCalledTimes(1);
  66. });
  67. it('unregisterAfterFrameCallback', () => {
  68. jest.useFakeTimers();
  69. const drawFn = jest.fn();
  70. const scheduler = new CanvasScheduler();
  71. scheduler.registerAfterFrameCallback(drawFn);
  72. scheduler.unregisterAfterFrameCallback(drawFn);
  73. scheduler.draw();
  74. jest.runAllTimers();
  75. expect(drawFn).not.toHaveBeenCalled();
  76. });
  77. it('calls callbacks in correct order', () => {
  78. jest.useFakeTimers();
  79. const drawBeforeFn = jest.fn().mockImplementationOnce(() => {});
  80. const drawAfterFn = jest.fn();
  81. const scheduler = new CanvasScheduler();
  82. scheduler.registerBeforeFrameCallback(drawBeforeFn);
  83. scheduler.registerAfterFrameCallback(drawAfterFn);
  84. scheduler.draw();
  85. jest.runAllTimers();
  86. expect(drawBeforeFn.mock.invocationCallOrder[0]).toBeLessThan(
  87. drawAfterFn.mock.invocationCallOrder[0]
  88. );
  89. });
  90. it('drawSync', () => {
  91. const drawBeforeFn = jest.fn().mockImplementationOnce(() => {});
  92. const drawAfterFn = jest.fn();
  93. const scheduler = new CanvasScheduler();
  94. scheduler.registerBeforeFrameCallback(drawBeforeFn);
  95. scheduler.registerAfterFrameCallback(drawAfterFn);
  96. // If we do not call drawSync, the test will fail as the assertion will
  97. // be evaluated before the callbacks have ran.
  98. scheduler.drawSync();
  99. expect(drawBeforeFn.mock.invocationCallOrder[0]).toBeLessThan(
  100. drawAfterFn.mock.invocationCallOrder[0]
  101. );
  102. });
  103. it('dispose', () => {
  104. jest.useFakeTimers();
  105. const drawBeforeFn = jest.fn().mockImplementationOnce(() => {});
  106. const drawAfterFn = jest.fn();
  107. const handlerFns = handlers.map(key => [key, jest.fn()]);
  108. const scheduler = new CanvasScheduler();
  109. scheduler.registerBeforeFrameCallback(drawBeforeFn);
  110. scheduler.registerAfterFrameCallback(drawAfterFn);
  111. for (const [key, handler] of handlerFns) {
  112. // @ts-ignore register all handlers
  113. scheduler.on(key, handler);
  114. }
  115. scheduler.dispose();
  116. // If we do not call drawSync, the test will fail as the assertion will
  117. // be evaluated before the callbacks have ran.
  118. scheduler.draw();
  119. scheduler.drawSync();
  120. jest.runAllTimers();
  121. for (const [_, handler] of handlerFns) {
  122. expect(handler).not.toHaveBeenCalled();
  123. }
  124. });
  125. });