index.spec.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {RouterFixture} from 'sentry-fixture/routerFixture';
  3. import {render, screen} from 'sentry-test/reactTestingLibrary';
  4. import {GroupRelatedIssues} from 'sentry/views/issueDetails/groupRelatedIssues';
  5. describe('Related Issues View', function () {
  6. let sameRootIssuesMock: jest.Mock;
  7. let traceIssuesMock: jest.Mock;
  8. let issuesMock: jest.Mock;
  9. const router = RouterFixture();
  10. const organization = OrganizationFixture();
  11. const orgSlug = organization.slug;
  12. const groupId = '12345678';
  13. const group1 = '15';
  14. const group2 = '20';
  15. // query=issue.id:[15,20] -> query=issue.id%3A%5B15%2C20%5D
  16. const orgIssuesEndpoint = `/organizations/${orgSlug}/issues/?query=issue.id%3A%5B${group1}%2C${group2}%5D`;
  17. const params = {groupId: groupId};
  18. const errorType = 'RuntimeError';
  19. const noData = {
  20. type: 'irrelevant',
  21. data: [],
  22. };
  23. const onlySameRootData = {
  24. type: 'same_root_cause',
  25. data: [group1, group2],
  26. };
  27. const onlyTraceConnectedData = {
  28. type: 'trace_connected',
  29. data: [group1, group2],
  30. meta: {
  31. event_id: 'abcd',
  32. trace_id: '1234',
  33. },
  34. };
  35. const issuesData = [
  36. {
  37. id: group1,
  38. shortId: `EARTH-${group1}`,
  39. project: {id: '3', name: 'Earth', slug: 'earth', platform: null},
  40. type: 'error',
  41. metadata: {
  42. type: errorType,
  43. },
  44. issueCategory: 'error',
  45. lastSeen: '2024-03-15T20:15:30Z',
  46. },
  47. {
  48. id: group2,
  49. shortId: `EARTH-${group2}`,
  50. project: {id: '3', name: 'Earth', slug: 'earth', platform: null},
  51. type: 'error',
  52. metadata: {
  53. type: errorType,
  54. },
  55. issueCategory: 'error',
  56. lastSeen: '2024-03-16T20:15:30Z',
  57. },
  58. ];
  59. beforeEach(function () {
  60. // GroupList calls this but we don't need it for this test
  61. MockApiClient.addMockResponse({
  62. url: `/organizations/${orgSlug}/users/`,
  63. body: {},
  64. });
  65. });
  66. afterEach(() => {
  67. MockApiClient.clearMockResponses();
  68. jest.clearAllMocks();
  69. });
  70. it('renders with no data', async function () {
  71. sameRootIssuesMock = MockApiClient.addMockResponse({
  72. url: `/issues/${groupId}/related-issues/?type=same_root_cause`,
  73. body: noData,
  74. });
  75. traceIssuesMock = MockApiClient.addMockResponse({
  76. url: `/issues/${groupId}/related-issues/?type=trace_connected`,
  77. body: noData,
  78. });
  79. render(
  80. <GroupRelatedIssues
  81. params={params}
  82. location={router.location}
  83. router={router}
  84. routeParams={router.params}
  85. routes={router.routes}
  86. route={{}}
  87. />
  88. );
  89. expect(
  90. await screen.findByText('No same-root-cause related issues were found.')
  91. ).toBeInTheDocument();
  92. expect(
  93. await screen.findByText('No trace-connected related issues were found.')
  94. ).toBeInTheDocument();
  95. expect(sameRootIssuesMock).toHaveBeenCalled();
  96. expect(traceIssuesMock).toHaveBeenCalled();
  97. });
  98. it('renders with same root issues', async function () {
  99. sameRootIssuesMock = MockApiClient.addMockResponse({
  100. url: `/issues/${groupId}/related-issues/?type=same_root_cause`,
  101. body: onlySameRootData,
  102. });
  103. MockApiClient.addMockResponse({
  104. url: `/issues/${groupId}/related-issues/?type=trace_connected`,
  105. body: [],
  106. });
  107. issuesMock = MockApiClient.addMockResponse({
  108. url: orgIssuesEndpoint,
  109. body: issuesData,
  110. });
  111. render(
  112. <GroupRelatedIssues
  113. params={params}
  114. location={router.location}
  115. router={router}
  116. routeParams={router.params}
  117. routes={router.routes}
  118. route={{}}
  119. />
  120. );
  121. // Wait for the issues showing up on the table
  122. expect(await screen.findByText(`EARTH-${group1}`)).toBeInTheDocument();
  123. expect(await screen.findByText(`EARTH-${group2}`)).toBeInTheDocument();
  124. expect(sameRootIssuesMock).toHaveBeenCalled();
  125. expect(issuesMock).toHaveBeenCalled();
  126. expect(
  127. await screen.findByText('No trace-connected related issues were found.')
  128. ).toBeInTheDocument();
  129. const linkButton = screen.getByRole('button', {name: /open in issues/i});
  130. expect(linkButton).toHaveAttribute(
  131. 'href',
  132. // Opening in Issues needs to include the group we are currently viewing
  133. `/organizations/org-slug/issues/?project=-1&query=issue.id:[${groupId},${group1},${group2}]`
  134. );
  135. });
  136. it('renders with trace connected issues', async function () {
  137. MockApiClient.addMockResponse({
  138. url: `/issues/${groupId}/related-issues/?type=same_root_cause`,
  139. body: [],
  140. });
  141. traceIssuesMock = MockApiClient.addMockResponse({
  142. url: `/issues/${groupId}/related-issues/?type=trace_connected`,
  143. body: onlyTraceConnectedData,
  144. });
  145. issuesMock = MockApiClient.addMockResponse({
  146. url: orgIssuesEndpoint,
  147. body: issuesData,
  148. });
  149. render(
  150. <GroupRelatedIssues
  151. params={params}
  152. location={router.location}
  153. router={router}
  154. routeParams={router.params}
  155. routes={router.routes}
  156. route={{}}
  157. />
  158. );
  159. // Wait for the issues showing up on the table
  160. expect(await screen.findByText(`EARTH-${group1}`)).toBeInTheDocument();
  161. expect(await screen.findByText(`EARTH-${group2}`)).toBeInTheDocument();
  162. expect(traceIssuesMock).toHaveBeenCalled();
  163. expect(issuesMock).toHaveBeenCalled();
  164. expect(
  165. await screen.findByText('No same-root-cause related issues were found.')
  166. ).toBeInTheDocument();
  167. const linkElement = screen.getByRole('link', {name: /this trace/i});
  168. expect(linkElement).toHaveAttribute(
  169. 'href',
  170. '/organizations/org-slug/performance/trace/1234/?node=error-abcd'
  171. );
  172. const linkButton = screen.getByRole('button', {name: /open in issues/i});
  173. // The Issue search supports using `trace` as a parameter
  174. expect(linkButton).toHaveAttribute(
  175. 'href',
  176. `/organizations/org-slug/issues/?project=-1&query=trace:1234`
  177. );
  178. });
  179. });