spanDetail.spec.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import {EventFixture} from 'sentry-fixture/event';
  2. import {OrganizationFixture} from 'sentry-fixture/organization';
  3. import {ProjectFixture} from 'sentry-fixture/project';
  4. import {SpanFixture} from 'sentry-fixture/span';
  5. import {render, screen} from 'sentry-test/reactTestingLibrary';
  6. import SpanDetail from 'sentry/components/events/interfaces/spans/spanDetail';
  7. import {TransactionProfileIdProvider} from 'sentry/components/profiling/transactionProfileIdProvider';
  8. import type {EventTransaction} from 'sentry/types';
  9. describe('SpanDetail', function () {
  10. const organization = OrganizationFixture();
  11. const project = ProjectFixture();
  12. const trace = {
  13. op: 'http.server',
  14. spans: [],
  15. traceID: '',
  16. traceStartTimestamp: 0,
  17. traceEndTimestamp: 0,
  18. childSpans: {},
  19. rootSpanID: '',
  20. rootSpanStatus: undefined,
  21. };
  22. const event = EventFixture({
  23. title: '/api/0/detail',
  24. projectID: project.id,
  25. startTimestamp: 0,
  26. }) as EventTransaction;
  27. const span = SpanFixture({
  28. op: 'db',
  29. hash: 'a',
  30. description: 'SELECT * FROM users;',
  31. });
  32. beforeEach(function () {
  33. MockApiClient.addMockResponse({
  34. url: `/organizations/${organization.slug}/events/`,
  35. method: 'GET',
  36. });
  37. });
  38. function renderSpanDetail(props: Partial<React.ComponentProps<typeof SpanDetail>>) {
  39. return (
  40. <TransactionProfileIdProvider
  41. projectId={project.id}
  42. transactionId={event.id}
  43. timestamp={event.dateReceived}
  44. >
  45. <SpanDetail
  46. organization={organization}
  47. event={event}
  48. resetCellMeasureCache={jest.fn()}
  49. scrollToHash={jest.fn()}
  50. isRoot={false}
  51. relatedErrors={[]}
  52. trace={trace}
  53. childTransactions={[]}
  54. span={span}
  55. {...props}
  56. />
  57. </TransactionProfileIdProvider>
  58. );
  59. }
  60. describe('resource spans', function () {
  61. it('shows size fields', function () {
  62. render(
  63. renderSpanDetail({
  64. span: SpanFixture({
  65. op: 'resource.link',
  66. description: 'static.assets/content.js',
  67. data: {
  68. 'http.response_content_length': 132,
  69. 'http.response_transfer_size': 0,
  70. 'http.decoded_response_content_length': null,
  71. },
  72. }),
  73. })
  74. );
  75. expect(
  76. screen.queryByText('http.decoded_response_content_length')
  77. ).not.toBeInTheDocument();
  78. expect(screen.getByText('http.response_transfer_size')).toBeInTheDocument();
  79. expect(screen.getByText('http.response_content_length')).toBeInTheDocument();
  80. expect(screen.getByText('132.0 B')).toBeInTheDocument();
  81. });
  82. });
  83. describe('http.client spans', function () {
  84. it('shows size fields for integer and string values', function () {
  85. render(
  86. renderSpanDetail({
  87. span: SpanFixture({
  88. op: 'http.client',
  89. description: 'POST /resources.json',
  90. data: {
  91. 'http.response_content_length': '143',
  92. 'http.request_content_length': 12,
  93. },
  94. }),
  95. })
  96. );
  97. expect(screen.getByText('http.response_content_length')).toBeInTheDocument();
  98. expect(screen.getByText('143.0 B')).toBeInTheDocument();
  99. expect(screen.getByText('http.request_content_length')).toBeInTheDocument();
  100. expect(screen.getByText('12.0 B')).toBeInTheDocument();
  101. });
  102. });
  103. describe('db spans', function () {
  104. it('renders "Similar Span" button but no Query Details button by default', function () {
  105. render(
  106. renderSpanDetail({
  107. span: SpanFixture({
  108. op: 'db',
  109. hash: 'a',
  110. description: 'SELECT * FROM users;',
  111. }),
  112. })
  113. );
  114. expect(screen.getByText('SELECT * FROM users;')).toBeInTheDocument();
  115. expect(
  116. screen.getByRole('button', {name: 'View Similar Spans'})
  117. ).toBeInTheDocument();
  118. expect(
  119. screen.queryByRole('button', {name: 'View Query Summary'})
  120. ).not.toBeInTheDocument();
  121. });
  122. it('renders "View Query Details" button if "Queries" view is enabled and span group is available', function () {
  123. render(
  124. renderSpanDetail({
  125. span: SpanFixture({
  126. op: 'db',
  127. hash: 'a',
  128. description: 'SELECT * FROM users;',
  129. sentry_tags: {
  130. group: 'a7ebd21614897',
  131. category: 'db',
  132. },
  133. }),
  134. organization: OrganizationFixture({
  135. ...organization,
  136. features: ['performance-database-view'],
  137. }),
  138. })
  139. );
  140. expect(screen.getByText('SELECT * FROM users;')).toBeInTheDocument();
  141. expect(
  142. screen.getByRole('button', {name: 'View Similar Spans'})
  143. ).toBeInTheDocument();
  144. expect(
  145. screen.getByRole('button', {name: 'View Query Summary'})
  146. ).toBeInTheDocument();
  147. expect(screen.getByRole('button', {name: 'View Query Summary'})).toHaveAttribute(
  148. 'href',
  149. '/organizations/org-slug/performance/database/spans/span/a7ebd21614897/?project=2'
  150. );
  151. });
  152. });
  153. });