webVitalsDetailPanel.spec.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {render, screen, waitForElementToBeRemoved} from 'sentry-test/reactTestingLibrary';
  3. import {useLocation} from 'sentry/utils/useLocation';
  4. import usePageFilters from 'sentry/utils/usePageFilters';
  5. import {WebVitalsDetailPanel} from 'sentry/views/insights/browser/webVitals/components/webVitalsDetailPanel';
  6. jest.mock('sentry/utils/useLocation');
  7. jest.mock('sentry/utils/usePageFilters');
  8. describe('WebVitalsDetailPanel', function () {
  9. const organization = OrganizationFixture();
  10. let eventsMock: jest.Mock;
  11. let eventsStatsMock: jest.Mock;
  12. beforeEach(function () {
  13. jest.mocked(useLocation).mockReturnValue({
  14. pathname: '',
  15. search: '',
  16. query: {},
  17. hash: '',
  18. state: undefined,
  19. action: 'PUSH',
  20. key: '',
  21. });
  22. jest.mocked(usePageFilters).mockReturnValue({
  23. isReady: true,
  24. desyncedFilters: new Set(),
  25. pinnedFilters: new Set(),
  26. shouldPersist: true,
  27. selection: {
  28. datetime: {
  29. period: '10d',
  30. start: null,
  31. end: null,
  32. utc: false,
  33. },
  34. environments: [],
  35. projects: [],
  36. },
  37. });
  38. eventsMock = MockApiClient.addMockResponse({
  39. url: `/organizations/${organization.slug}/events/`,
  40. body: {
  41. data: [],
  42. },
  43. });
  44. eventsStatsMock = MockApiClient.addMockResponse({
  45. url: `/organizations/${organization.slug}/events-stats/`,
  46. body: {},
  47. });
  48. });
  49. afterEach(function () {
  50. jest.resetAllMocks();
  51. });
  52. it('renders correctly with empty results', async () => {
  53. render(<WebVitalsDetailPanel onClose={() => undefined} webVital="lcp" />, {
  54. organization,
  55. });
  56. await waitForElementToBeRemoved(() => screen.queryByTestId('loading-indicator'));
  57. // Raw web vital metric tile queries
  58. expect(eventsMock).toHaveBeenNthCalledWith(
  59. 1,
  60. expect.anything(),
  61. expect.objectContaining({
  62. query: expect.objectContaining({
  63. dataset: 'metrics',
  64. field: [
  65. 'p75(measurements.lcp)',
  66. 'p75(measurements.fcp)',
  67. 'p75(measurements.cls)',
  68. 'p75(measurements.ttfb)',
  69. 'p75(measurements.inp)',
  70. 'p75(transaction.duration)',
  71. 'count_web_vitals(measurements.lcp, any)',
  72. 'count_web_vitals(measurements.fcp, any)',
  73. 'count_web_vitals(measurements.cls, any)',
  74. 'count_web_vitals(measurements.ttfb, any)',
  75. 'count_web_vitals(measurements.inp, any)',
  76. 'count()',
  77. ],
  78. query:
  79. 'transaction.op:[pageload,""] span.op:[ui.interaction.click,ui.interaction.hover,ui.interaction.drag,ui.interaction.press,ui.webvital.cls,""] !transaction:"<< unparameterized >>"',
  80. }),
  81. })
  82. );
  83. // Project performance score ring query
  84. expect(eventsMock).toHaveBeenNthCalledWith(
  85. 2,
  86. expect.anything(),
  87. expect.objectContaining({
  88. query: expect.objectContaining({
  89. dataset: 'metrics',
  90. field: [
  91. 'performance_score(measurements.score.lcp)',
  92. 'performance_score(measurements.score.fcp)',
  93. 'performance_score(measurements.score.cls)',
  94. `performance_score(measurements.score.inp)`,
  95. 'performance_score(measurements.score.ttfb)',
  96. 'performance_score(measurements.score.total)',
  97. 'avg(measurements.score.weight.lcp)',
  98. 'avg(measurements.score.weight.fcp)',
  99. 'avg(measurements.score.weight.cls)',
  100. `avg(measurements.score.weight.inp)`,
  101. 'avg(measurements.score.weight.ttfb)',
  102. 'count()',
  103. 'count_scores(measurements.score.total)',
  104. 'count_scores(measurements.score.lcp)',
  105. 'count_scores(measurements.score.fcp)',
  106. 'count_scores(measurements.score.cls)',
  107. 'count_scores(measurements.score.ttfb)',
  108. 'count_scores(measurements.score.inp)',
  109. 'sum(measurements.score.weight.lcp)',
  110. ],
  111. query:
  112. 'transaction.op:[pageload,""] span.op:[ui.interaction.click,ui.interaction.hover,ui.interaction.drag,ui.interaction.press,ui.webvital.cls,""] !transaction:"<< unparameterized >>"',
  113. }),
  114. })
  115. );
  116. // Table query
  117. expect(eventsMock).toHaveBeenNthCalledWith(
  118. 3,
  119. expect.anything(),
  120. expect.objectContaining({
  121. query: expect.objectContaining({
  122. dataset: 'metrics',
  123. field: [
  124. 'project.id',
  125. 'project',
  126. 'transaction',
  127. 'p75(measurements.lcp)',
  128. 'p75(measurements.fcp)',
  129. 'p75(measurements.cls)',
  130. 'p75(measurements.ttfb)',
  131. 'p75(measurements.inp)',
  132. 'performance_score(measurements.score.lcp)',
  133. 'opportunity_score(measurements.score.lcp)',
  134. 'performance_score(measurements.score.total)',
  135. 'count()',
  136. 'count_scores(measurements.score.lcp)',
  137. 'count_scores(measurements.score.fcp)',
  138. 'count_scores(measurements.score.cls)',
  139. 'count_scores(measurements.score.inp)',
  140. 'count_scores(measurements.score.ttfb)',
  141. 'total_opportunity_score()',
  142. ],
  143. query:
  144. 'transaction.op:[pageload,""] span.op:[ui.interaction.click,ui.interaction.hover,ui.interaction.drag,ui.interaction.press,ui.webvital.cls,""] !transaction:"<< unparameterized >>" avg(measurements.score.total):>=0 count_scores(measurements.score.lcp):>0',
  145. }),
  146. })
  147. );
  148. expect(eventsStatsMock).toHaveBeenCalledTimes(1);
  149. expect(screen.getByText('Largest Contentful Paint (P75)')).toBeInTheDocument();
  150. expect(screen.getByText('—')).toBeInTheDocument();
  151. expect(
  152. screen.getByText(/Largest Contentful Paint \(LCP\) measures the render/)
  153. ).toBeInTheDocument();
  154. });
  155. });