index.spec.tsx 5.1 KB

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