transactionsTable.spec.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {render, screen} from 'sentry-test/reactTestingLibrary';
  3. import {useLocation} from 'sentry/utils/useLocation';
  4. import {QueryParameterNames} from 'sentry/views/insights/common/views/queryParameters';
  5. import {TransactionsTable} from 'sentry/views/insights/queues/components/tables/transactionsTable';
  6. jest.mock('sentry/utils/useLocation');
  7. describe('transactionsTable', () => {
  8. const organization = OrganizationFixture();
  9. let eventsMock: jest.Mock;
  10. const pageLinks =
  11. '<https://sentry.io/fake/previous>; rel="previous"; results="false"; cursor="0:0:1", ' +
  12. '<https://sentry.io/fake/next>; rel="next"; results="true"; cursor="0:20:0"';
  13. beforeEach(() => {
  14. jest.mocked(useLocation).mockReturnValue({
  15. pathname: '',
  16. search: '',
  17. query: {statsPeriod: '10d', project: '1'},
  18. hash: '',
  19. state: undefined,
  20. action: 'PUSH',
  21. key: '',
  22. });
  23. eventsMock = MockApiClient.addMockResponse({
  24. url: `/organizations/${organization.slug}/events/`,
  25. headers: {Link: pageLinks},
  26. method: 'GET',
  27. body: {
  28. data: [
  29. {
  30. transaction: 'celery.backend_cleanup',
  31. 'span.op': 'queue.process',
  32. 'count()': 2,
  33. 'count_op(queue.publish)': 0,
  34. 'count_op(queue.process)': 2,
  35. 'sum(span.duration)': 6,
  36. 'avg(span.duration)': 3,
  37. 'avg_if(span.duration,span.op,queue.publish)': 0,
  38. 'avg_if(span.duration,span.op,queue.process)': 3,
  39. 'avg(messaging.message.receive.latency)': 20,
  40. 'trace_status_rate(ok)': 0.8,
  41. 'time_spent_percentage(app,span.duration)': 0.5,
  42. },
  43. ],
  44. meta: {
  45. fields: {
  46. 'count()': 'integer',
  47. 'count_op(queue.publish)': 'integer',
  48. 'count_op(queue.process)': 'integer',
  49. 'sum(span.duration)': 'duration',
  50. 'avg(span.duration)': 'duration',
  51. 'avg_if(span.duration,span.op,queue.publish)': 'duration',
  52. 'avg_if(span.duration,span.op,queue.process)': 'duration',
  53. 'avg(messaging.message.receive.latency)': 'duration',
  54. 'trace_status_rate(ok)': 'percentage',
  55. 'time_spent_percentage(app,span.duration)': 'percentage',
  56. },
  57. },
  58. },
  59. });
  60. });
  61. it('renders', async () => {
  62. render(<TransactionsTable />, {organization});
  63. expect(screen.getByRole('table', {name: 'Transactions'})).toBeInTheDocument();
  64. expect(screen.getByRole('columnheader', {name: 'Transactions'})).toBeInTheDocument();
  65. expect(screen.getByRole('columnheader', {name: 'Type'})).toBeInTheDocument();
  66. expect(
  67. screen.getByRole('columnheader', {name: 'Avg Time in Queue'})
  68. ).toBeInTheDocument();
  69. expect(
  70. screen.getByRole('columnheader', {name: 'Avg Processing Time'})
  71. ).toBeInTheDocument();
  72. expect(screen.getByRole('columnheader', {name: 'Error Rate'})).toBeInTheDocument();
  73. expect(screen.getByRole('columnheader', {name: 'Published'})).toBeInTheDocument();
  74. expect(screen.getByRole('columnheader', {name: 'Processed'})).toBeInTheDocument();
  75. expect(screen.getByRole('columnheader', {name: 'Time Spent'})).toBeInTheDocument();
  76. expect(eventsMock).toHaveBeenCalledWith(
  77. '/organizations/org-slug/events/',
  78. expect.objectContaining({
  79. query: expect.objectContaining({
  80. field: [
  81. 'transaction',
  82. 'span.op',
  83. 'count()',
  84. 'count_op(queue.publish)',
  85. 'count_op(queue.process)',
  86. 'sum(span.duration)',
  87. 'avg(span.duration)',
  88. 'avg_if(span.duration,span.op,queue.publish)',
  89. 'avg_if(span.duration,span.op,queue.process)',
  90. 'avg(messaging.message.receive.latency)',
  91. 'trace_status_rate(ok)',
  92. 'time_spent_percentage(app,span.duration)',
  93. ],
  94. dataset: 'spansMetrics',
  95. }),
  96. })
  97. );
  98. await screen.findByText('celery.backend_cleanup');
  99. expect(screen.getByRole('cell', {name: '3.00ms'})).toBeInTheDocument();
  100. expect(screen.getByRole('cell', {name: '2'})).toBeInTheDocument();
  101. expect(screen.getByRole('cell', {name: '6.00ms'})).toBeInTheDocument();
  102. expect(screen.getByRole('cell', {name: '20.00ms'})).toBeInTheDocument();
  103. expect(screen.getByRole('cell', {name: 'Consumer'})).toBeInTheDocument();
  104. expect(screen.getByRole('button', {name: 'Next'})).toBeInTheDocument();
  105. });
  106. it('sorts by processing time', async () => {
  107. jest.mocked(useLocation).mockReturnValue({
  108. pathname: '',
  109. search: '',
  110. query: {
  111. statsPeriod: '10d',
  112. project: '1',
  113. [QueryParameterNames.DESTINATIONS_SORT]:
  114. '-avg_if(span.duration,span.op,queue.process)',
  115. },
  116. hash: '',
  117. state: undefined,
  118. action: 'PUSH',
  119. key: '',
  120. });
  121. render(<TransactionsTable />, {organization});
  122. expect(eventsMock).toHaveBeenCalledWith(
  123. '/organizations/org-slug/events/',
  124. expect.objectContaining({
  125. query: expect.objectContaining({
  126. field: [
  127. 'transaction',
  128. 'span.op',
  129. 'count()',
  130. 'count_op(queue.publish)',
  131. 'count_op(queue.process)',
  132. 'sum(span.duration)',
  133. 'avg(span.duration)',
  134. 'avg_if(span.duration,span.op,queue.publish)',
  135. 'avg_if(span.duration,span.op,queue.process)',
  136. 'avg(messaging.message.receive.latency)',
  137. 'trace_status_rate(ok)',
  138. 'time_spent_percentage(app,span.duration)',
  139. ],
  140. dataset: 'spansMetrics',
  141. sort: '-avg_if(span.duration,span.op,queue.process)',
  142. }),
  143. })
  144. );
  145. await screen.findByText('celery.backend_cleanup');
  146. });
  147. });