visualizationStep.spec.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. import {initializeOrg} from 'sentry-test/initializeOrg';
  2. import {act, render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  3. import {DEFAULT_DEBOUNCE_DURATION} from 'sentry/constants';
  4. import {Organization} from 'sentry/types';
  5. import {DashboardWidgetSource} from 'sentry/views/dashboardsV2/types';
  6. import WidgetBuilder from 'sentry/views/dashboardsV2/widgetBuilder';
  7. jest.unmock('lodash/debounce');
  8. function mockRequests(orgSlug: Organization['slug']) {
  9. const eventsv2Mock = MockApiClient.addMockResponse({
  10. url: `/organizations/${orgSlug}/eventsv2/`,
  11. method: 'GET',
  12. statusCode: 200,
  13. body: {
  14. meta: {},
  15. data: [],
  16. },
  17. });
  18. MockApiClient.addMockResponse({
  19. url: '/organizations/org-slug/tags/',
  20. method: 'GET',
  21. body: TestStubs.Tags(),
  22. });
  23. MockApiClient.addMockResponse({
  24. url: '/organizations/org-slug/users/',
  25. body: [],
  26. });
  27. MockApiClient.addMockResponse({
  28. url: '/organizations/org-slug/projects/',
  29. method: 'GET',
  30. body: [],
  31. });
  32. MockApiClient.addMockResponse({
  33. url: '/organizations/org-slug/measurements-meta/',
  34. method: 'GET',
  35. body: {'measurements.custom.measurement': {functions: ['p99']}},
  36. });
  37. MockApiClient.addMockResponse({
  38. url: '/organizations/org-slug/metrics-compatibility/',
  39. method: 'GET',
  40. body: {
  41. incompatible_projects: [],
  42. compatible_projects: [1],
  43. dynamic_sampling_projects: [1],
  44. },
  45. });
  46. MockApiClient.addMockResponse({
  47. url: '/organizations/org-slug/metrics-compatibility-sums/',
  48. method: 'GET',
  49. body: {
  50. sum: {
  51. metrics: 988803,
  52. metrics_null: 0,
  53. metrics_unparam: 132,
  54. },
  55. },
  56. });
  57. return {eventsv2Mock};
  58. }
  59. describe('VisualizationStep', function () {
  60. const {organization, router, routerContext} = initializeOrg({
  61. ...initializeOrg(),
  62. organization: {
  63. features: ['dashboards-edit', 'global-views', 'dashboards-mep'],
  64. },
  65. router: {
  66. location: {
  67. query: {
  68. source: DashboardWidgetSource.DASHBOARDS,
  69. },
  70. },
  71. },
  72. });
  73. it('debounce works as expected and requests are not triggered often', async function () {
  74. const {eventsv2Mock} = mockRequests(organization.slug);
  75. jest.useFakeTimers();
  76. render(
  77. <WidgetBuilder
  78. route={{}}
  79. router={router}
  80. routes={router.routes}
  81. routeParams={router.params}
  82. location={router.location}
  83. dashboard={{
  84. id: 'new',
  85. title: 'Dashboard',
  86. createdBy: undefined,
  87. dateCreated: '2020-01-01T00:00:00.000Z',
  88. widgets: [],
  89. projects: [],
  90. filters: {},
  91. }}
  92. onSave={jest.fn()}
  93. params={{
  94. orgId: organization.slug,
  95. dashboardId: 'new',
  96. }}
  97. />,
  98. {
  99. context: routerContext,
  100. organization,
  101. }
  102. );
  103. await waitFor(() => expect(eventsv2Mock).toHaveBeenCalledTimes(1));
  104. userEvent.type(await screen.findByPlaceholderText('Alias'), 'abc');
  105. act(() => {
  106. jest.advanceTimersByTime(DEFAULT_DEBOUNCE_DURATION + 1);
  107. });
  108. await waitFor(() => expect(eventsv2Mock).toHaveBeenCalledTimes(2));
  109. });
  110. it('displays stored data alert', async function () {
  111. mockRequests(organization.slug);
  112. MockApiClient.addMockResponse({
  113. url: `/organizations/${organization.slug}/eventsv2/`,
  114. method: 'GET',
  115. statusCode: 200,
  116. body: {
  117. meta: {isMetricsData: false},
  118. data: [],
  119. },
  120. });
  121. render(
  122. <WidgetBuilder
  123. route={{}}
  124. router={router}
  125. routes={router.routes}
  126. routeParams={router.params}
  127. location={router.location}
  128. dashboard={{
  129. id: 'new',
  130. title: 'Dashboard',
  131. createdBy: undefined,
  132. dateCreated: '2020-01-01T00:00:00.000Z',
  133. widgets: [],
  134. projects: [],
  135. filters: {},
  136. }}
  137. onSave={jest.fn()}
  138. params={{
  139. orgId: organization.slug,
  140. dashboardId: 'new',
  141. }}
  142. />,
  143. {
  144. context: routerContext,
  145. organization: {
  146. ...organization,
  147. features: [
  148. ...organization.features,
  149. 'server-side-sampling',
  150. 'mep-rollout-flag',
  151. ],
  152. },
  153. }
  154. );
  155. await screen.findByText(/we've automatically adjusted your results/i);
  156. });
  157. it('uses release from URL params when querying', async function () {
  158. const {eventsv2Mock} = mockRequests(organization.slug);
  159. render(
  160. <WidgetBuilder
  161. route={{}}
  162. router={router}
  163. routes={router.routes}
  164. routeParams={router.params}
  165. location={{
  166. ...router.location,
  167. query: {
  168. ...router.location.query,
  169. release: ['v1'],
  170. },
  171. }}
  172. dashboard={{
  173. id: 'new',
  174. title: 'Dashboard',
  175. createdBy: undefined,
  176. dateCreated: '2020-01-01T00:00:00.000Z',
  177. widgets: [],
  178. projects: [],
  179. filters: {},
  180. }}
  181. onSave={jest.fn()}
  182. params={{
  183. orgId: organization.slug,
  184. dashboardId: 'new',
  185. }}
  186. />,
  187. {
  188. context: routerContext,
  189. organization,
  190. }
  191. );
  192. await waitFor(() =>
  193. expect(eventsv2Mock).toHaveBeenCalledWith(
  194. '/organizations/org-slug/eventsv2/',
  195. expect.objectContaining({
  196. query: expect.objectContaining({query: ' release:v1 '}),
  197. })
  198. )
  199. );
  200. });
  201. });