index.spec.tsx 4.6 KB

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