index.spec.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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 onlySameRootData = {
  20. type: 'same_root_cause',
  21. data: [group1, group2],
  22. };
  23. const onlyTraceConnectedData = {
  24. type: 'trace_connected',
  25. data: [group1, group2],
  26. meta: {
  27. event_id: 'abcd',
  28. trace_id: '1234',
  29. },
  30. };
  31. const issuesData = [
  32. {
  33. id: group1,
  34. shortId: `EARTH-${group1}`,
  35. project: {id: '3', name: 'Earth', slug: 'earth', platform: null},
  36. type: 'error',
  37. metadata: {
  38. type: errorType,
  39. },
  40. issueCategory: 'error',
  41. lastSeen: '2024-03-15T20:15:30Z',
  42. },
  43. {
  44. id: group2,
  45. shortId: `EARTH-${group2}`,
  46. project: {id: '3', name: 'Earth', slug: 'earth', platform: null},
  47. type: 'error',
  48. metadata: {
  49. type: errorType,
  50. },
  51. issueCategory: 'error',
  52. lastSeen: '2024-03-16T20:15:30Z',
  53. },
  54. ];
  55. beforeEach(function () {
  56. // GroupList calls this but we don't need it for this test
  57. MockApiClient.addMockResponse({
  58. url: `/organizations/${orgSlug}/users/`,
  59. body: {},
  60. });
  61. });
  62. afterEach(() => {
  63. MockApiClient.clearMockResponses();
  64. jest.clearAllMocks();
  65. });
  66. it('renders with same root issues', async function () {
  67. sameRootIssuesMock = MockApiClient.addMockResponse({
  68. url: `/issues/${groupId}/related-issues/?type=same_root_cause`,
  69. body: onlySameRootData,
  70. });
  71. MockApiClient.addMockResponse({
  72. url: `/issues/${groupId}/related-issues/?type=trace_connected`,
  73. body: [],
  74. });
  75. issuesMock = MockApiClient.addMockResponse({
  76. url: orgIssuesEndpoint,
  77. body: issuesData,
  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. // Wait for the issues showing up on the table
  90. expect(await screen.findByText(`EARTH-${group1}`)).toBeInTheDocument();
  91. expect(await screen.findByText(`EARTH-${group2}`)).toBeInTheDocument();
  92. expect(sameRootIssuesMock).toHaveBeenCalled();
  93. expect(issuesMock).toHaveBeenCalled();
  94. const linkButton = screen.getByRole('button', {name: /open in issues/i});
  95. expect(linkButton).toHaveAttribute(
  96. 'href',
  97. // Opening in Issues needs to include the group we are currently viewing
  98. `/organizations/org-slug/issues/?project=-1&query=issue.id:[${groupId},${group1},${group2}]`
  99. );
  100. });
  101. it('renders with trace connected issues', async function () {
  102. MockApiClient.addMockResponse({
  103. url: `/issues/${groupId}/related-issues/?type=same_root_cause`,
  104. body: [],
  105. });
  106. traceIssuesMock = MockApiClient.addMockResponse({
  107. url: `/issues/${groupId}/related-issues/?type=trace_connected`,
  108. body: onlyTraceConnectedData,
  109. });
  110. issuesMock = MockApiClient.addMockResponse({
  111. url: orgIssuesEndpoint,
  112. body: issuesData,
  113. });
  114. render(
  115. <GroupRelatedIssues
  116. params={params}
  117. location={router.location}
  118. router={router}
  119. routeParams={router.params}
  120. routes={router.routes}
  121. route={{}}
  122. />
  123. );
  124. // Wait for the issues showing up on the table
  125. expect(await screen.findByText(`EARTH-${group1}`)).toBeInTheDocument();
  126. expect(await screen.findByText(`EARTH-${group2}`)).toBeInTheDocument();
  127. expect(traceIssuesMock).toHaveBeenCalled();
  128. expect(issuesMock).toHaveBeenCalled();
  129. const linkElement = screen.getByRole('link', {name: /this trace/i});
  130. expect(linkElement).toHaveAttribute(
  131. 'href',
  132. '/organizations/org-slug/performance/trace/1234/?node=error-abcd'
  133. );
  134. const linkButton = screen.getByRole('button', {name: /open in issues/i});
  135. // The Issue search supports using `trace` as a parameter
  136. expect(linkButton).toHaveAttribute(
  137. 'href',
  138. `/organizations/org-slug/issues/?project=-1&query=trace:1234`
  139. );
  140. });
  141. });