content.spec.tsx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {ProjectFixture} from 'sentry-fixture/project';
  3. import {initializeOrg} from 'sentry-test/initializeOrg';
  4. import {render, screen} from 'sentry-test/reactTestingLibrary';
  5. import type {InjectedRouter} from 'sentry/types/legacyReactRouter';
  6. import EventView from 'sentry/utils/discover/eventView';
  7. import {MEPSettingProvider} from 'sentry/utils/performance/contexts/metricsEnhancedSetting';
  8. import {useLocation} from 'sentry/utils/useLocation';
  9. import {SpanOperationBreakdownFilter} from 'sentry/views/performance/transactionSummary/filter';
  10. import SummaryContent from 'sentry/views/performance/transactionSummary/transactionOverview/content';
  11. jest.mock('sentry/utils/useLocation');
  12. jest.mocked(useLocation).mockReturnValue({
  13. action: 'POP',
  14. hash: '',
  15. key: 'abc123',
  16. pathname: '/organizations/org-slug/performance/',
  17. query: {},
  18. search: '',
  19. state: undefined,
  20. });
  21. function initialize(query, additionalFeatures: string[] = []) {
  22. const features = ['transaction-event', 'performance-view', ...additionalFeatures];
  23. const organization = OrganizationFixture({
  24. features,
  25. });
  26. const initialData = initializeOrg({
  27. organization,
  28. router: {
  29. location: {
  30. query: {...query},
  31. },
  32. },
  33. projects: [],
  34. });
  35. const eventView = EventView.fromNewQueryWithLocation(
  36. {
  37. id: undefined,
  38. version: 2,
  39. name: 'test-transaction',
  40. fields: ['id', 'user.display', 'transaction.duration', 'trace', 'timestamp'],
  41. projects: [],
  42. },
  43. initialData.router.location
  44. );
  45. const spanOperationBreakdownFilter = SpanOperationBreakdownFilter.NONE;
  46. const transactionName = 'example-transaction';
  47. return {
  48. ...initialData,
  49. spanOperationBreakdownFilter,
  50. transactionName,
  51. location: initialData.router.location,
  52. eventView,
  53. };
  54. }
  55. function WrappedComponent({
  56. organization,
  57. ...props
  58. }: React.ComponentProps<typeof SummaryContent> & {
  59. router: InjectedRouter<Record<string, string>, any>;
  60. }) {
  61. return (
  62. <MEPSettingProvider>
  63. <SummaryContent organization={organization} {...props} />
  64. </MEPSettingProvider>
  65. );
  66. }
  67. describe('Transaction Summary Content', function () {
  68. beforeEach(function () {
  69. MockApiClient.addMockResponse({
  70. method: 'GET',
  71. url: '/organizations/org-slug/prompts-activity/',
  72. body: {},
  73. });
  74. MockApiClient.addMockResponse({
  75. url: '/organizations/org-slug/sdk-updates/',
  76. body: [],
  77. });
  78. MockApiClient.addMockResponse({
  79. url: '/organizations/org-slug/events/',
  80. body: {data: [{'event.type': 'error'}], meta: {fields: {'event.type': 'string'}}},
  81. });
  82. MockApiClient.addMockResponse({
  83. url: '/organizations/org-slug/users/',
  84. body: [],
  85. });
  86. MockApiClient.addMockResponse({
  87. url: '/organizations/org-slug/issues/?limit=5&query=is%3Aunresolved%20transaction%3Aexample-transaction&sort=trends&statsPeriod=14d',
  88. body: [],
  89. });
  90. MockApiClient.addMockResponse({
  91. url: '/organizations/org-slug/events-facets/',
  92. body: [],
  93. });
  94. MockApiClient.addMockResponse({
  95. url: '/organizations/org-slug/releases/stats/',
  96. body: [],
  97. });
  98. MockApiClient.addMockResponse({
  99. url: '/organizations/org-slug/events-stats/',
  100. body: [],
  101. });
  102. MockApiClient.addMockResponse({
  103. url: '/organizations/org-slug/events-facets-performance/',
  104. body: {},
  105. });
  106. MockApiClient.addMockResponse({
  107. url: '/organizations/org-slug/events-has-measurements/',
  108. body: {measurements: false},
  109. });
  110. MockApiClient.addMockResponse({
  111. url: '/organizations/org-slug/events-spans-performance/',
  112. body: [
  113. {
  114. op: 'ui.long-task',
  115. group: 'c777169faad84eb4',
  116. description: 'Main UI thread blocked',
  117. frequency: 713,
  118. count: 9040,
  119. avgOccurrences: null,
  120. sumExclusiveTime: 1743893.9822921753,
  121. p50ExclusiveTime: null,
  122. p75ExclusiveTime: 244.9998779296875,
  123. p95ExclusiveTime: null,
  124. p99ExclusiveTime: null,
  125. },
  126. ],
  127. });
  128. MockApiClient.addMockResponse({
  129. url: `/projects/org-slug/project-slug/profiling/functions/`,
  130. body: {functions: []},
  131. });
  132. MockApiClient.addMockResponse({
  133. url: '/organizations/org-slug/dynamic-sampling/custom-rules/',
  134. body: '',
  135. });
  136. MockApiClient.addMockResponse({
  137. url: '/organizations/org-slug/profiling/flamegraph/',
  138. body: {
  139. activeProfileIndex: 0,
  140. metadata: {
  141. deviceClassification: '',
  142. deviceLocale: '',
  143. deviceManufacturer: '',
  144. deviceModel: '',
  145. deviceOSName: '',
  146. deviceOSVersion: '',
  147. durationNS: 0,
  148. organizationID: 0,
  149. platform: '',
  150. profileID: '',
  151. projectID: 0,
  152. received: '0001-01-01T00:00:00Z',
  153. sampled: false,
  154. timestamp: '0001-01-01T00:00:00Z',
  155. traceID: '',
  156. transactionID: '',
  157. transactionName: '',
  158. version: '',
  159. },
  160. platform: '',
  161. profiles: [
  162. {
  163. endValue: 0,
  164. isMainThread: true,
  165. name: '',
  166. samples: [],
  167. startValue: 0,
  168. threadID: 0,
  169. type: 'sampled',
  170. unit: 'count',
  171. weights: [],
  172. sample_durations_ns: null,
  173. },
  174. ],
  175. projectID: 0,
  176. shared: {
  177. frames: [],
  178. },
  179. transactionName: '',
  180. metrics: [],
  181. },
  182. });
  183. });
  184. afterEach(function () {
  185. MockApiClient.clearMockResponses();
  186. });
  187. it('performs basic rendering', async function () {
  188. const project = ProjectFixture();
  189. const {
  190. organization,
  191. location,
  192. eventView,
  193. spanOperationBreakdownFilter,
  194. transactionName,
  195. router,
  196. } = initialize({});
  197. render(
  198. <WrappedComponent
  199. location={location}
  200. organization={organization}
  201. eventView={eventView}
  202. projectId={project.id}
  203. transactionName={transactionName}
  204. isLoading={false}
  205. totalValues={null}
  206. spanOperationBreakdownFilter={spanOperationBreakdownFilter}
  207. error={null}
  208. onChangeFilter={() => {}}
  209. router={router}
  210. />,
  211. {router, organization}
  212. );
  213. expect(
  214. await screen.findByTestId('page-filter-environment-selector')
  215. ).toBeInTheDocument();
  216. expect(screen.getByTestId('page-filter-timerange-selector')).toBeInTheDocument();
  217. expect(screen.getByTestId('smart-search-bar')).toBeInTheDocument();
  218. expect(screen.getByTestId('transaction-summary-charts')).toBeInTheDocument();
  219. expect(screen.getByRole('heading', {name: /user misery/i})).toBeInTheDocument();
  220. expect(screen.getByRole('heading', {name: /status breakdown/i})).toBeInTheDocument();
  221. expect(screen.getByRole('heading', {name: /apdex/i})).toBeInTheDocument();
  222. expect(screen.getByTestId('apdex-summary-value')).toBeInTheDocument();
  223. expect(screen.getByRole('heading', {name: /failure rate/i})).toBeInTheDocument();
  224. expect(screen.getByTestId('failure-rate-summary-value')).toBeInTheDocument();
  225. });
  226. });