useSpanMetricsSeries.spec.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import type {ReactNode} from 'react';
  2. import {OrganizationFixture} from 'sentry-fixture/organization';
  3. import {makeTestQueryClient} from 'sentry-test/queryClient';
  4. import {reactHooks} from 'sentry-test/reactTestingLibrary';
  5. import {QueryClientProvider} from 'sentry/utils/queryClient';
  6. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  7. import {useLocation} from 'sentry/utils/useLocation';
  8. import useOrganization from 'sentry/utils/useOrganization';
  9. import usePageFilters from 'sentry/utils/usePageFilters';
  10. import {useSpanMetricsSeries} from 'sentry/views/starfish/queries/useSpanMetricsSeries';
  11. import type {MetricsProperty} from 'sentry/views/starfish/types';
  12. jest.mock('sentry/utils/useLocation');
  13. jest.mock('sentry/utils/usePageFilters');
  14. jest.mock('sentry/utils/useOrganization');
  15. function Wrapper({children}: {children?: ReactNode}) {
  16. return (
  17. <QueryClientProvider client={makeTestQueryClient()}>{children}</QueryClientProvider>
  18. );
  19. }
  20. describe('useSpanMetricsSeries', () => {
  21. const organization = OrganizationFixture();
  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. jest.mocked(useLocation).mockReturnValue({
  39. pathname: '',
  40. search: '',
  41. query: {},
  42. hash: '',
  43. state: undefined,
  44. action: 'PUSH',
  45. key: '',
  46. });
  47. jest.mocked(useOrganization).mockReturnValue(organization);
  48. it('respects the `enabled` prop', () => {
  49. const eventsRequest = MockApiClient.addMockResponse({
  50. url: `/organizations/${organization.slug}/events-stats/`,
  51. method: 'GET',
  52. body: {},
  53. });
  54. const {result} = reactHooks.renderHook(
  55. ({filters, enabled}) =>
  56. useSpanMetricsSeries({
  57. search: MutableSearch.fromQueryObject(filters),
  58. enabled,
  59. }),
  60. {
  61. wrapper: Wrapper,
  62. initialProps: {
  63. filters: {
  64. 'span.group': '221aa7ebd216',
  65. },
  66. enabled: false,
  67. },
  68. }
  69. );
  70. expect(result.current.isFetching).toEqual(false);
  71. expect(eventsRequest).not.toHaveBeenCalled();
  72. });
  73. it('queries for current selection', async () => {
  74. const eventsRequest = MockApiClient.addMockResponse({
  75. url: `/organizations/${organization.slug}/events-stats/`,
  76. method: 'GET',
  77. body: {
  78. 'spm()': {
  79. data: [
  80. [1699907700, [{count: 7810.2}]],
  81. [1699908000, [{count: 1216.8}]],
  82. ],
  83. },
  84. },
  85. });
  86. const {result, waitFor} = reactHooks.renderHook(
  87. ({filters, yAxis}) =>
  88. useSpanMetricsSeries({search: MutableSearch.fromQueryObject(filters), yAxis}),
  89. {
  90. wrapper: Wrapper,
  91. initialProps: {
  92. filters: {
  93. 'span.group': '221aa7ebd216',
  94. transaction: '/api/details',
  95. release: '0.0.1',
  96. 'resource.render_blocking_status': 'blocking' as const,
  97. environment: undefined,
  98. },
  99. yAxis: ['spm()'] as MetricsProperty[],
  100. },
  101. }
  102. );
  103. expect(result.current.isLoading).toEqual(true);
  104. expect(eventsRequest).toHaveBeenCalledWith(
  105. '/organizations/org-slug/events-stats/',
  106. expect.objectContaining({
  107. method: 'GET',
  108. query: expect.objectContaining({
  109. query: `span.group:221aa7ebd216 transaction:/api/details release:0.0.1 resource.render_blocking_status:blocking`,
  110. dataset: 'spansMetrics',
  111. statsPeriod: '10d',
  112. referrer: 'span-metrics-series',
  113. interval: '30m',
  114. yAxis: 'spm()',
  115. }),
  116. })
  117. );
  118. await waitFor(() => expect(result.current.isLoading).toEqual(false));
  119. expect(result.current.data).toEqual({
  120. 'spm()': {
  121. data: [
  122. {name: '2023-11-13T20:35:00+00:00', value: 7810.2},
  123. {name: '2023-11-13T20:40:00+00:00', value: 1216.8},
  124. ],
  125. seriesName: 'spm()',
  126. },
  127. });
  128. });
  129. it('adjusts interval based on the yAxis', async () => {
  130. const eventsRequest = MockApiClient.addMockResponse({
  131. url: `/organizations/${organization.slug}/events-stats/`,
  132. method: 'GET',
  133. body: {},
  134. });
  135. const {rerender, waitFor} = reactHooks.renderHook(
  136. ({yAxis}) => useSpanMetricsSeries({yAxis}),
  137. {
  138. wrapper: Wrapper,
  139. initialProps: {
  140. yAxis: ['avg(span.self_time)', 'spm()'] as MetricsProperty[],
  141. },
  142. }
  143. );
  144. expect(eventsRequest).toHaveBeenLastCalledWith(
  145. '/organizations/org-slug/events-stats/',
  146. expect.objectContaining({
  147. method: 'GET',
  148. query: expect.objectContaining({
  149. interval: '30m',
  150. yAxis: ['avg(span.self_time)', 'spm()'] as MetricsProperty[],
  151. }),
  152. })
  153. );
  154. rerender({
  155. yAxis: ['p95(span.self_time)', 'spm()'] as MetricsProperty[],
  156. });
  157. await waitFor(() =>
  158. expect(eventsRequest).toHaveBeenLastCalledWith(
  159. '/organizations/org-slug/events-stats/',
  160. expect.objectContaining({
  161. method: 'GET',
  162. query: expect.objectContaining({
  163. interval: '1h',
  164. yAxis: ['p95(span.self_time)', 'spm()'] as MetricsProperty[],
  165. }),
  166. })
  167. )
  168. );
  169. });
  170. });