metricsDataSwitcher.spec.tsx 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. import {ProjectFixture} from 'sentry-fixture/project';
  2. import {addMetricsDataMock} from 'sentry-test/performance/addMetricsDataMock';
  3. import {initializeData} from 'sentry-test/performance/initializePerformanceData';
  4. import {makeTestQueryClient} from 'sentry-test/queryClient';
  5. import {act, render, screen} from 'sentry-test/reactTestingLibrary';
  6. import TeamStore from 'sentry/stores/teamStore';
  7. import {MetricsCardinalityProvider} from 'sentry/utils/performance/contexts/metricsCardinality';
  8. import {QueryClientProvider} from 'sentry/utils/queryClient';
  9. import {OrganizationContext} from 'sentry/views/organizationContext';
  10. import {generatePerformanceEventView} from 'sentry/views/performance/data';
  11. import {PerformanceLanding} from 'sentry/views/performance/landing';
  12. function WrappedComponent({data, withStaticFilters = true}) {
  13. const eventView = generatePerformanceEventView(
  14. data.router.location,
  15. data.projects,
  16. {
  17. withStaticFilters,
  18. },
  19. data.organization
  20. );
  21. return (
  22. <QueryClientProvider client={makeTestQueryClient()}>
  23. <OrganizationContext.Provider value={data.organization}>
  24. <MetricsCardinalityProvider
  25. location={data.router.location}
  26. organization={data.organization}
  27. >
  28. <PerformanceLanding
  29. router={data.router}
  30. organization={data.organization}
  31. location={data.router.location}
  32. eventView={eventView}
  33. projects={data.projects}
  34. selection={eventView.getPageFilters()}
  35. onboardingProject={undefined}
  36. handleSearch={() => {}}
  37. handleTrendsClick={() => {}}
  38. setError={() => {}}
  39. withStaticFilters={withStaticFilters}
  40. />
  41. </MetricsCardinalityProvider>
  42. </OrganizationContext.Provider>
  43. </QueryClientProvider>
  44. );
  45. }
  46. const features = [
  47. 'performance-transaction-name-only-search',
  48. 'organizations:performance-transaction-name-only-search',
  49. ];
  50. describe('Performance > Landing > MetricsDataSwitcher', function () {
  51. let wrapper: any;
  52. act(() => void TeamStore.loadInitialData([], false, null));
  53. beforeEach(function () {
  54. // eslint-disable-next-line no-console
  55. jest.spyOn(console, 'error').mockImplementation(jest.fn());
  56. MockApiClient.addMockResponse({
  57. url: '/organizations/org-slug/sdk-updates/',
  58. body: [],
  59. });
  60. MockApiClient.addMockResponse({
  61. url: '/organizations/org-slug/prompts-activity/',
  62. body: {},
  63. });
  64. MockApiClient.addMockResponse({
  65. url: '/organizations/org-slug/projects/',
  66. body: [],
  67. });
  68. MockApiClient.addMockResponse({
  69. method: 'GET',
  70. url: `/organizations/org-slug/key-transactions-list/`,
  71. body: [],
  72. });
  73. MockApiClient.addMockResponse({
  74. method: 'GET',
  75. url: `/organizations/org-slug/legacy-key-transactions-count/`,
  76. body: [],
  77. });
  78. MockApiClient.addMockResponse({
  79. method: 'GET',
  80. url: `/organizations/org-slug/events-stats/`,
  81. body: [],
  82. });
  83. MockApiClient.addMockResponse({
  84. method: 'GET',
  85. url: `/organizations/org-slug/events-trends-stats/`,
  86. body: [],
  87. });
  88. MockApiClient.addMockResponse({
  89. method: 'GET',
  90. url: `/organizations/org-slug/events-histogram/`,
  91. body: [],
  92. });
  93. MockApiClient.addMockResponse({
  94. method: 'GET',
  95. url: `/organizations/org-slug/eventsv2/`,
  96. body: {
  97. meta: {
  98. id: 'string',
  99. },
  100. data: [
  101. {
  102. id: '1234',
  103. },
  104. ],
  105. },
  106. });
  107. });
  108. afterEach(function () {
  109. MockApiClient.clearMockResponses();
  110. jest.restoreAllMocks();
  111. if (wrapper) {
  112. wrapper.unmount();
  113. wrapper = undefined;
  114. }
  115. });
  116. it('renders basic UI elements', function () {
  117. addMetricsDataMock();
  118. const project = ProjectFixture();
  119. const data = initializeData({
  120. project: project.id,
  121. projects: [project],
  122. features,
  123. });
  124. wrapper = render(<WrappedComponent data={data} />);
  125. expect(screen.getByTestId('performance-landing-v3')).toBeInTheDocument();
  126. });
  127. it('renders with feature flag and all metric data', async function () {
  128. addMetricsDataMock();
  129. const project = ProjectFixture();
  130. const data = initializeData({
  131. project: project.id,
  132. projects: [project],
  133. features,
  134. });
  135. wrapper = render(<WrappedComponent data={data} />);
  136. expect(await screen.findByTestId('transaction-search-bar')).toBeInTheDocument();
  137. });
  138. it('renders with feature flag and checking dynamic sampled projects exist', async function () {
  139. addMetricsDataMock({
  140. metricsCount: 100,
  141. nullCount: 0,
  142. unparamCount: 0,
  143. });
  144. const project = ProjectFixture();
  145. const data = initializeData({
  146. project: project.id,
  147. projects: [project],
  148. features,
  149. });
  150. wrapper = render(<WrappedComponent data={data} />);
  151. expect(await screen.findByTestId('transaction-search-bar')).toBeInTheDocument();
  152. });
  153. it('renders with feature flag and any incompatible data', async function () {
  154. addMetricsDataMock({
  155. metricsCount: 100,
  156. nullCount: 1,
  157. unparamCount: 0,
  158. });
  159. const project = ProjectFixture();
  160. const data = initializeData({
  161. project: project.id,
  162. projects: [project],
  163. features,
  164. });
  165. wrapper = render(<WrappedComponent data={data} />);
  166. expect(await screen.findByTestId('transaction-search-bar')).toBeInTheDocument();
  167. expect(
  168. await screen.findByTestId('landing-mep-alert-single-project-incompatible')
  169. ).toBeInTheDocument();
  170. });
  171. it('renders with feature flag and any incompatible transactions on multiple projects with at least one compatible project', async function () {
  172. addMetricsDataMock({
  173. metricsCount: 100,
  174. nullCount: 1,
  175. unparamCount: 0,
  176. compatibleProjects: [1],
  177. });
  178. const project = ProjectFixture({id: '1'});
  179. const project2 = ProjectFixture({id: '2'});
  180. const data = initializeData({
  181. project: '-1',
  182. projects: [project, project2],
  183. features,
  184. });
  185. wrapper = render(<WrappedComponent data={data} />);
  186. expect(await screen.findByTestId('transaction-search-bar')).toBeInTheDocument();
  187. expect(
  188. await screen.findByTestId('landing-mep-alert-multi-project-incompatible')
  189. ).toBeInTheDocument();
  190. });
  191. it('renders with feature flag and any incompatible transactions on multiple projects with no compatible project', async function () {
  192. addMetricsDataMock({
  193. metricsCount: 100,
  194. nullCount: 1,
  195. unparamCount: 0,
  196. compatibleProjects: [],
  197. });
  198. const project = ProjectFixture({id: '1'});
  199. const project2 = ProjectFixture({id: '2'});
  200. const data = initializeData({
  201. project: '-1',
  202. projects: [project, project2],
  203. features,
  204. });
  205. wrapper = render(<WrappedComponent data={data} />);
  206. expect(await screen.findByTestId('transaction-search-bar')).toBeInTheDocument();
  207. expect(
  208. await screen.findByTestId('landing-mep-alert-multi-project-all-incompatible')
  209. ).toBeInTheDocument();
  210. });
  211. it('renders with feature flag and all other(unparam) transactions', async function () {
  212. addMetricsDataMock({
  213. metricsCount: 100,
  214. nullCount: 0,
  215. unparamCount: 100,
  216. });
  217. const project = ProjectFixture();
  218. const data = initializeData({
  219. project: project.id,
  220. projects: [project],
  221. features,
  222. });
  223. wrapper = render(<WrappedComponent data={data} />);
  224. expect(await screen.findByTestId('transaction-search-bar')).toBeInTheDocument();
  225. expect(
  226. await screen.findByTestId('landing-mep-alert-unnamed-discover')
  227. ).toBeInTheDocument();
  228. });
  229. it('renders with feature flag and partial other(unparam) transactions and platform with docs', async function () {
  230. addMetricsDataMock({
  231. metricsCount: 100,
  232. nullCount: 0,
  233. unparamCount: 1,
  234. });
  235. const project = ProjectFixture({platform: 'javascript-react'});
  236. const data = initializeData({
  237. project: project.id,
  238. projects: [project],
  239. features,
  240. });
  241. wrapper = render(<WrappedComponent data={data} />);
  242. expect(await screen.findByTestId('transaction-search-bar')).toBeInTheDocument();
  243. expect(
  244. await screen.findByTestId('landing-mep-alert-unnamed-discover-or-set')
  245. ).toBeInTheDocument();
  246. });
  247. it('renders with feature flag and partial other(unparam) transactions', async function () {
  248. addMetricsDataMock({
  249. metricsCount: 100,
  250. nullCount: 0,
  251. unparamCount: 1,
  252. });
  253. const project = ProjectFixture();
  254. const data = initializeData({
  255. project: project.id,
  256. projects: [project],
  257. features,
  258. });
  259. wrapper = render(<WrappedComponent data={data} />);
  260. expect(await screen.findByTestId('transaction-search-bar')).toBeInTheDocument();
  261. expect(
  262. await screen.findByTestId('landing-mep-alert-unnamed-discover')
  263. ).toBeInTheDocument();
  264. });
  265. });