index.spec.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import {LocationFixture} from 'sentry-fixture/locationFixture';
  2. import type {InitializeDataSettings} from 'sentry-test/performance/initializePerformanceData';
  3. import {initializeData as _initializeData} from 'sentry-test/performance/initializePerformanceData';
  4. import {act, render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  5. import ProjectsStore from 'sentry/stores/projectsStore';
  6. import {browserHistory} from 'sentry/utils/browserHistory';
  7. import {MEPSettingProvider} from 'sentry/utils/performance/contexts/metricsEnhancedSetting';
  8. import {useLocation} from 'sentry/utils/useLocation';
  9. import TransactionEvents from 'sentry/views/performance/transactionSummary/transactionEvents';
  10. import {
  11. EVENTS_TABLE_RESPONSE_FIELDS,
  12. MOCK_EVENTS_TABLE_DATA,
  13. } from 'sentry/views/performance/transactionSummary/transactionEvents/testUtils';
  14. jest.mock('sentry/utils/useLocation');
  15. const mockUseLocation = jest.mocked(useLocation);
  16. function WrappedComponent({data}) {
  17. return (
  18. <MEPSettingProvider>
  19. <TransactionEvents
  20. organization={data.organization}
  21. location={data.router.location}
  22. />
  23. </MEPSettingProvider>
  24. );
  25. }
  26. const setupMockApiResponeses = () => {
  27. MockApiClient.addMockResponse({
  28. url: '/organizations/org-slug/events-has-measurements/',
  29. body: {measurements: false},
  30. });
  31. MockApiClient.addMockResponse({
  32. url: '/organizations/org-slug/events/',
  33. body: {
  34. data: [
  35. {
  36. 'p100()': 9500,
  37. 'p99()': 9000,
  38. 'p95()': 7000,
  39. 'p75()': 5000,
  40. 'p50()': 500,
  41. },
  42. ],
  43. meta: {
  44. fields: {
  45. 'p100()': 'duration',
  46. 'p99()': 'duration',
  47. 'p95()': 'duration',
  48. 'p75()': 'duration',
  49. 'p50()': 'duration',
  50. },
  51. },
  52. },
  53. match: [
  54. (_, options) => {
  55. return options.query?.field?.includes('p95()');
  56. },
  57. ],
  58. });
  59. MockApiClient.addMockResponse({
  60. url: '/organizations/org-slug/events/',
  61. body: {
  62. data: [
  63. {
  64. 'count()': 4000,
  65. },
  66. ],
  67. meta: {
  68. fields: {
  69. 'count()': 'integer',
  70. },
  71. },
  72. },
  73. match: [
  74. (_, options) => {
  75. return options.query?.field?.includes('count()');
  76. },
  77. ],
  78. });
  79. MockApiClient.addMockResponse({
  80. url: '/organizations/org-slug/events/',
  81. body: {
  82. data: [
  83. {
  84. 'count()': 4000,
  85. },
  86. ],
  87. meta: {
  88. fields: {
  89. 'count()': 'integer',
  90. },
  91. },
  92. },
  93. match: [(_, options) => options.query?.field?.includes('count()')],
  94. });
  95. MockApiClient.addMockResponse({
  96. url: '/organizations/org-slug/events/',
  97. body: {
  98. data: MOCK_EVENTS_TABLE_DATA,
  99. meta: {
  100. fields: EVENTS_TABLE_RESPONSE_FIELDS,
  101. },
  102. },
  103. match: [
  104. (_, options) =>
  105. options.query?.field?.includes('transaction.duration') &&
  106. !options.query?.query.includes('transaction.duration'),
  107. ],
  108. });
  109. MockApiClient.addMockResponse({
  110. url: '/organizations/org-slug/events/',
  111. body: {
  112. data: [MOCK_EVENTS_TABLE_DATA[0]],
  113. meta: {
  114. fields: EVENTS_TABLE_RESPONSE_FIELDS,
  115. },
  116. },
  117. match: [
  118. (_, options) =>
  119. options.query?.field?.includes('transaction.duration') &&
  120. options.query?.query.includes('transaction.duration:<=500'), // 500 refers to p50 value
  121. ],
  122. });
  123. MockApiClient.addMockResponse({
  124. url: '/organizations/org-slug/replay-count/',
  125. body: {},
  126. });
  127. MockApiClient.addMockResponse({
  128. url: `/organizations/org-slug/recent-searches/`,
  129. body: [],
  130. });
  131. MockApiClient.addMockResponse({
  132. url: `/organizations/org-slug/tags/`,
  133. body: [],
  134. });
  135. };
  136. const setupMocks = () => {
  137. mockUseLocation.mockReturnValue(
  138. LocationFixture({pathname: '/organizations/org-slug/performance/summary'})
  139. );
  140. };
  141. const initializeData = (settings?: InitializeDataSettings) => {
  142. settings = {
  143. features: ['performance-view'],
  144. query: {project: '1', transaction: 'transaction'},
  145. ...settings,
  146. };
  147. const data = _initializeData(settings);
  148. act(() => void ProjectsStore.loadInitialData(data.projects));
  149. return data;
  150. };
  151. describe('Performance > Transaction Summary > Transaction Events > Index', () => {
  152. beforeEach(() => {
  153. setupMockApiResponeses();
  154. setupMocks();
  155. });
  156. afterEach(() => {
  157. MockApiClient.clearMockResponses();
  158. jest.clearAllMocks();
  159. });
  160. it('should contain all transaction events', async () => {
  161. const data = initializeData();
  162. render(<WrappedComponent data={data} />, {router: data.router});
  163. expect(await screen.findByText('uhoh@example.com')).toBeInTheDocument();
  164. expect(await screen.findByText('moreuhoh@example.com')).toBeInTheDocument();
  165. });
  166. it('should filter the transaction duration if in query', async () => {
  167. const data = initializeData({
  168. query: {project: '1', transaction: 'transaction', showTransactions: 'p50'},
  169. });
  170. render(<WrappedComponent data={data} />, {router: data.router});
  171. expect(await screen.findByText('uhoh@example.com')).toBeInTheDocument();
  172. expect(screen.queryByText('moreuhoh@example.com')).not.toBeInTheDocument();
  173. });
  174. it('should update transaction percentile query if selected', async () => {
  175. const data = initializeData();
  176. render(<WrappedComponent data={data} />, {router: data.router});
  177. const percentileButton = await screen.findByRole('button', {
  178. name: /percentile p100/i,
  179. });
  180. await userEvent.click(percentileButton);
  181. const p50 = screen.getByRole('option', {name: 'p50'});
  182. expect(p50).toBeInTheDocument();
  183. await userEvent.click(p50);
  184. expect(browserHistory.push).toHaveBeenCalledWith(
  185. expect.objectContaining({query: expect.objectContaining({showTransactions: 'p50'})})
  186. );
  187. });
  188. });