utils.spec.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import {mat3, vec2} from 'gl-matrix';
  2. import type {ViewHierarchyWindow} from 'sentry/components/events/viewHierarchy';
  3. import {
  4. calculateScale,
  5. getDeepestNodeAtPoint,
  6. getHierarchyDimensions,
  7. } from 'sentry/components/events/viewHierarchy/utils';
  8. import {defined} from 'sentry/utils';
  9. import {Rect} from 'sentry/utils/profiling/speedscope';
  10. const LEAF_NODE = {
  11. x: 2,
  12. y: 2,
  13. width: 5,
  14. height: 5,
  15. };
  16. const INTERMEDIATE_NODE = {
  17. x: 10,
  18. y: 5,
  19. width: 10,
  20. height: 10,
  21. children: [LEAF_NODE],
  22. };
  23. const DEFAULT_MOCK_HIERARCHY = [
  24. {
  25. x: 0,
  26. y: 0,
  27. width: 10,
  28. height: 10,
  29. children: [INTERMEDIATE_NODE],
  30. },
  31. {x: 10, y: 0, width: 20, height: 20},
  32. ] as ViewHierarchyWindow[];
  33. describe('View Hierarchy Utils', function () {
  34. let MOCK_HIERARCHY: ViewHierarchyWindow[];
  35. beforeEach(function () {
  36. MOCK_HIERARCHY = [...DEFAULT_MOCK_HIERARCHY];
  37. });
  38. describe('getHierarchyDimensions', function () {
  39. it('properly calculates coordinates and shifts children by default', function () {
  40. const actual = getHierarchyDimensions(MOCK_HIERARCHY);
  41. expect(actual).toEqual({
  42. nodes: [
  43. {node: MOCK_HIERARCHY[0], rect: new Rect(0, 0, 10, 10)},
  44. {node: INTERMEDIATE_NODE, rect: new Rect(10, 5, 10, 10)},
  45. {node: LEAF_NODE, rect: new Rect(12, 7, 5, 5)},
  46. {node: MOCK_HIERARCHY[1], rect: new Rect(10, 0, 20, 20)},
  47. ],
  48. maxWidth: 30,
  49. maxHeight: 20,
  50. });
  51. });
  52. it('does not shift children when specified', function () {
  53. const actual = getHierarchyDimensions(MOCK_HIERARCHY, true);
  54. // One array for each root
  55. expect(actual).toEqual({
  56. nodes: [
  57. {node: MOCK_HIERARCHY[0], rect: new Rect(0, 0, 10, 10)},
  58. {node: INTERMEDIATE_NODE, rect: new Rect(10, 5, 10, 10)},
  59. {node: LEAF_NODE, rect: new Rect(2, 2, 5, 5)},
  60. {node: MOCK_HIERARCHY[1], rect: new Rect(10, 0, 20, 20)},
  61. ],
  62. maxWidth: 30,
  63. maxHeight: 20,
  64. });
  65. });
  66. });
  67. describe('calculateScale', function () {
  68. let maxCoordinateDimensions: {height: number; width: number},
  69. actual: number,
  70. border: {x: number; y: number};
  71. const bounds = {
  72. height: 10,
  73. width: 10,
  74. };
  75. beforeEach(function () {
  76. border = {x: 0, y: 0};
  77. });
  78. it('zooms in on small content', function () {
  79. maxCoordinateDimensions = {height: 2, width: 2};
  80. actual = calculateScale(bounds, maxCoordinateDimensions, border);
  81. expect(actual).toEqual(5);
  82. });
  83. it('shrinks larger content', function () {
  84. maxCoordinateDimensions = {height: 20, width: 20};
  85. actual = calculateScale(bounds, maxCoordinateDimensions, border);
  86. expect(actual).toEqual(0.5);
  87. });
  88. it('works with an irregular size where height is the dominant factor', function () {
  89. maxCoordinateDimensions = {height: 20, width: 2};
  90. actual = calculateScale(bounds, maxCoordinateDimensions, border);
  91. expect(actual).toEqual(0.5);
  92. });
  93. it('works with an irregular size where width is the dominant factor', function () {
  94. maxCoordinateDimensions = {height: 10, width: 32};
  95. actual = calculateScale(bounds, maxCoordinateDimensions, border);
  96. expect(actual).toEqual(0.3125);
  97. });
  98. it('factors in the border', function () {
  99. maxCoordinateDimensions = {height: 20, width: 20};
  100. border = {x: 2, y: 2};
  101. actual = calculateScale(bounds, maxCoordinateDimensions, border);
  102. expect(actual).toEqual(0.4);
  103. });
  104. });
  105. describe('getDeepestNodeAtPoint', function () {
  106. beforeEach(function () {
  107. MOCK_HIERARCHY = [
  108. {
  109. x: 0,
  110. y: 0,
  111. width: 10,
  112. height: 10,
  113. children: [INTERMEDIATE_NODE],
  114. },
  115. ] as ViewHierarchyWindow[];
  116. });
  117. it('returns the deepest node at a point', function () {
  118. const hierarchyDimensions = getHierarchyDimensions(MOCK_HIERARCHY);
  119. const actual = getDeepestNodeAtPoint(
  120. hierarchyDimensions.nodes,
  121. [10, 5],
  122. mat3.create(),
  123. 1
  124. );
  125. if (!defined(actual)) {
  126. throw new Error('Expected a node to be returned');
  127. }
  128. expect(actual.node).toEqual(INTERMEDIATE_NODE);
  129. });
  130. it('returns the deepest node at a point with a scale', function () {
  131. const hierarchyDimensions = getHierarchyDimensions(MOCK_HIERARCHY);
  132. const actual = getDeepestNodeAtPoint(
  133. hierarchyDimensions.nodes,
  134. [24, 14],
  135. mat3.create(),
  136. 0.5
  137. );
  138. if (!defined(actual)) {
  139. throw new Error('Expected a node to be returned');
  140. }
  141. expect(actual.node).toEqual(LEAF_NODE);
  142. });
  143. it('returns the deepest node at a point with a translation', function () {
  144. const hierarchyDimensions = getHierarchyDimensions(MOCK_HIERARCHY);
  145. const actual = getDeepestNodeAtPoint(
  146. hierarchyDimensions.nodes,
  147. [22, 17],
  148. mat3.translate(mat3.create(), mat3.create(), vec2.fromValues(10, 10)), // Translate by 10, 10
  149. 1
  150. );
  151. if (!defined(actual)) {
  152. throw new Error('Expected a node to be returned');
  153. }
  154. expect(actual.node).toEqual(LEAF_NODE);
  155. });
  156. it('returns the root if the root is clicked', function () {
  157. const hierarchyDimensions = getHierarchyDimensions([...DEFAULT_MOCK_HIERARCHY]);
  158. const actual = getDeepestNodeAtPoint(
  159. hierarchyDimensions.nodes,
  160. [0, 0],
  161. mat3.create(),
  162. 1
  163. );
  164. if (!defined(actual)) {
  165. throw new Error('Expected a node to be returned');
  166. }
  167. expect(actual.node).toEqual(MOCK_HIERARCHY[0]);
  168. });
  169. it('returns null if no node is found', function () {
  170. const hierarchyDimensions = getHierarchyDimensions(MOCK_HIERARCHY);
  171. const actual = getDeepestNodeAtPoint(
  172. hierarchyDimensions.nodes,
  173. [100, 100], // The click is outside of any nodes
  174. mat3.create(),
  175. 1
  176. );
  177. expect(actual).toBeNull();
  178. });
  179. });
  180. });