index.spec.tsx 5.2 KB

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