traceTree.incremental.spec.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import type {Location} from 'history';
  2. import {OrganizationFixture} from 'sentry-fixture/organization';
  3. import {waitFor} from 'sentry-test/reactTestingLibrary';
  4. import * as useOrganization from 'sentry/utils/useOrganization';
  5. import {TraceTree} from './traceTree';
  6. import {makeTrace, makeTransaction} from './traceTreeTestUtils';
  7. describe('incremental trace fetch', () => {
  8. const organization = OrganizationFixture();
  9. beforeEach(function () {
  10. jest.clearAllMocks();
  11. jest.spyOn(useOrganization, 'default').mockReturnValue(organization);
  12. });
  13. it('Fetches and updates tree with fetched trace', async () => {
  14. const traces = [
  15. {traceSlug: 'slug1', timestamp: 1},
  16. {traceSlug: 'slug2', timestamp: 2},
  17. ];
  18. const tree: TraceTree = TraceTree.FromTrace(
  19. makeTrace({
  20. transactions: [
  21. makeTransaction({
  22. transaction: 'txn 1',
  23. start_timestamp: 0,
  24. children: [makeTransaction({start_timestamp: 1, transaction: 'txn 2'})],
  25. }),
  26. ],
  27. }),
  28. {replay: null, meta: null}
  29. );
  30. // Mock the API calls
  31. MockApiClient.addMockResponse({
  32. method: 'GET',
  33. url: '/organizations/org-slug/events-trace/slug1/?limit=10000&timestamp=1&useSpans=1',
  34. body: {
  35. transactions: [
  36. makeTransaction({
  37. transaction: 'txn 3',
  38. start_timestamp: 0,
  39. children: [makeTransaction({start_timestamp: 1, transaction: 'txn 4'})],
  40. }),
  41. ],
  42. orphan_errors: [],
  43. },
  44. });
  45. MockApiClient.addMockResponse({
  46. method: 'GET',
  47. url: '/organizations/org-slug/events-trace/slug2/?limit=10000&timestamp=2&useSpans=1',
  48. body: {
  49. transactions: [
  50. makeTransaction({
  51. transaction: 'txn 5',
  52. start_timestamp: 0,
  53. children: [makeTransaction({start_timestamp: 1, transaction: 'txn 6'})],
  54. }),
  55. ],
  56. orphan_errors: [],
  57. },
  58. });
  59. MockApiClient.addMockResponse({
  60. method: 'GET',
  61. url: '/organizations/org-slug/events-trace/slug1/?limit=10000&timestamp=1&useSpans=1',
  62. body: {
  63. transactions: [
  64. makeTransaction({
  65. transaction: 'txn 3',
  66. start_timestamp: 0,
  67. children: [makeTransaction({start_timestamp: 1, transaction: 'txn 4'})],
  68. }),
  69. ],
  70. orphan_errors: [],
  71. },
  72. });
  73. tree.build();
  74. expect(tree.list.length).toBe(3);
  75. tree.fetchAdditionalTraces({
  76. replayTraces: traces,
  77. api: new MockApiClient(),
  78. filters: {},
  79. organization,
  80. rerender: () => {},
  81. urlParams: {} as Location['query'],
  82. meta: null,
  83. });
  84. await waitFor(() => expect(tree.root.children[0].fetchStatus).toBe('idle'));
  85. expect(tree.list.length).toBe(7);
  86. });
  87. it('Does not infinitely fetch on error', async () => {
  88. const traces = [
  89. {traceSlug: 'slug1', timestamp: 1},
  90. {traceSlug: 'slug2', timestamp: 2},
  91. {traceSlug: 'slug3', timestamp: 3},
  92. ];
  93. const tree: TraceTree = TraceTree.FromTrace(
  94. makeTrace({
  95. transactions: [
  96. makeTransaction({
  97. transaction: 'txn 1',
  98. start_timestamp: 0,
  99. children: [makeTransaction({start_timestamp: 1, transaction: 'txn 2'})],
  100. }),
  101. ],
  102. }),
  103. {replay: null, meta: null}
  104. );
  105. // Mock the API calls
  106. const mockedResponse1 = MockApiClient.addMockResponse({
  107. method: 'GET',
  108. url: '/organizations/org-slug/events-trace/slug1/?limit=10000&timestamp=1&useSpans=1',
  109. statusCode: 400,
  110. });
  111. const mockedResponse2 = MockApiClient.addMockResponse({
  112. method: 'GET',
  113. url: '/organizations/org-slug/events-trace/slug2/?limit=10000&timestamp=2&useSpans=1',
  114. body: {
  115. transactions: [
  116. makeTransaction({
  117. transaction: 'txn 5',
  118. start_timestamp: 0,
  119. children: [makeTransaction({start_timestamp: 1, transaction: 'txn 6'})],
  120. }),
  121. ],
  122. orphan_errors: [],
  123. },
  124. });
  125. const mockedResponse3 = MockApiClient.addMockResponse({
  126. method: 'GET',
  127. url: '/organizations/org-slug/events-trace/slug3/?limit=10000&timestamp=3&useSpans=1',
  128. body: {
  129. transactions: [
  130. makeTransaction({
  131. transaction: 'txn 7',
  132. start_timestamp: 0,
  133. children: [makeTransaction({start_timestamp: 1, transaction: 'txn 8'})],
  134. }),
  135. ],
  136. orphan_errors: [],
  137. },
  138. });
  139. tree.build();
  140. expect(tree.list.length).toBe(3);
  141. tree.fetchAdditionalTraces({
  142. replayTraces: traces,
  143. api: new MockApiClient(),
  144. filters: {},
  145. organization,
  146. rerender: () => {},
  147. urlParams: {} as Location['query'],
  148. meta: null,
  149. });
  150. await waitFor(() => expect(tree.root.children[0].fetchStatus).toBe('idle'));
  151. tree.build();
  152. expect(tree.list.length).toBe(7);
  153. expect(mockedResponse1).toHaveBeenCalledTimes(1);
  154. expect(mockedResponse2).toHaveBeenCalledTimes(1);
  155. expect(mockedResponse3).toHaveBeenCalledTimes(1);
  156. });
  157. });