index.spec.tsx 5.1 KB

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