projectIssues.spec.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import {initializeOrg} from 'sentry-test/initializeOrg';
  2. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  3. import ProjectIssues from 'sentry/views/projectDetail/projectIssues';
  4. describe('ProjectDetail > ProjectIssues', function () {
  5. let endpointMock: ReturnType<typeof MockApiClient.addMockResponse>,
  6. filteredEndpointMock: ReturnType<typeof MockApiClient.addMockResponse>,
  7. newIssuesEndpointMock: ReturnType<typeof MockApiClient.addMockResponse>;
  8. const {organization, router, project, routerContext} = initializeOrg({
  9. organization: {
  10. features: ['discover-basic'],
  11. },
  12. });
  13. beforeEach(function () {
  14. endpointMock = MockApiClient.addMockResponse({
  15. url: `/organizations/${organization.slug}/issues/?limit=5&query=error.unhandled%3Atrue%20is%3Aunresolved&sort=freq&statsPeriod=14d`,
  16. body: [TestStubs.Group(), TestStubs.Group({id: '2'})],
  17. });
  18. filteredEndpointMock = MockApiClient.addMockResponse({
  19. url: `/organizations/${organization.slug}/issues/?environment=staging&limit=5&query=error.unhandled%3Atrue%20is%3Aunresolved&sort=freq&statsPeriod=7d`,
  20. body: [TestStubs.Group(), TestStubs.Group({id: '2'})],
  21. });
  22. newIssuesEndpointMock = MockApiClient.addMockResponse({
  23. url: `/organizations/${organization.slug}/issues/?limit=5&query=is%3Aunresolved%20is%3Afor_review&sort=freq&statsPeriod=14d`,
  24. body: [TestStubs.Group(), TestStubs.Group({id: '2'})],
  25. });
  26. MockApiClient.addMockResponse({
  27. url: `/organizations/${organization.slug}/users/`,
  28. body: [],
  29. });
  30. MockApiClient.addMockResponse({
  31. url: `/organizations/${organization.slug}/issues-count/?project=${project.id}&query=is%3Aunresolved%20is%3Afor_review&query=&query=is%3Aresolved&query=error.unhandled%3Atrue%20is%3Aunresolved&query=regressed_in_release%3Alatest&statsPeriod=14d`,
  32. body: {},
  33. });
  34. MockApiClient.addMockResponse({
  35. url: `/organizations/${organization.slug}/issues-count/?environment=staging&project=${project.id}&query=is%3Aunresolved%20is%3Afor_review&query=&query=is%3Aresolved&query=error.unhandled%3Atrue%20is%3Aunresolved&query=regressed_in_release%3Alatest&statsPeriod=7d`,
  36. body: {},
  37. });
  38. });
  39. afterEach(function () {
  40. MockApiClient.clearMockResponses();
  41. jest.clearAllMocks();
  42. });
  43. it('renders a list', async function () {
  44. MockApiClient.addMockResponse({
  45. url: `/organizations/org-slug/issues/?limit=5&query=error.unhandled%3Atrue%20is%3Aunresolved&sort=freq&statsPeriod=14d`,
  46. body: [TestStubs.Group(), TestStubs.Group({id: '2'})],
  47. });
  48. render(
  49. <ProjectIssues
  50. api={new MockApiClient()}
  51. organization={organization}
  52. location={router.location}
  53. projectId={parseInt(project.id, 10)}
  54. />,
  55. {
  56. context: routerContext,
  57. organization,
  58. }
  59. );
  60. expect(await screen.findAllByTestId('group')).toHaveLength(2);
  61. });
  62. it('renders a link to Issues', async function () {
  63. render(
  64. <ProjectIssues
  65. api={new MockApiClient()}
  66. organization={organization}
  67. projectId={parseInt(project.id, 10)}
  68. location={router.location}
  69. />,
  70. {
  71. context: routerContext,
  72. organization,
  73. }
  74. );
  75. const link = screen.getByLabelText('Open in Issues');
  76. expect(link).toBeInTheDocument();
  77. await userEvent.click(link);
  78. expect(router.push).toHaveBeenCalledWith({
  79. pathname: '/organizations/org-slug/issues/',
  80. query: {
  81. limit: 5,
  82. query: 'error.unhandled:true is:unresolved',
  83. sort: 'freq',
  84. statsPeriod: '14d',
  85. },
  86. });
  87. });
  88. it('renders a segmented control', async function () {
  89. render(
  90. <ProjectIssues
  91. api={new MockApiClient()}
  92. organization={organization}
  93. location={router.location}
  94. projectId={parseInt(project.id, 10)}
  95. />,
  96. {
  97. context: routerContext,
  98. organization,
  99. }
  100. );
  101. // "Unhandled" segment is selected
  102. const unhandledSegment = screen.getByRole('radio', {name: 'Unhandled 0'});
  103. expect(unhandledSegment).toBeInTheDocument();
  104. expect(unhandledSegment).toBeChecked();
  105. // Select "New Issues" segment
  106. const newIssuesSegment = screen.getByRole('radio', {name: 'New Issues 0'});
  107. expect(newIssuesSegment).toBeInTheDocument();
  108. expect(newIssuesSegment).not.toBeChecked();
  109. await userEvent.click(newIssuesSegment);
  110. await waitFor(() => expect(newIssuesSegment).toBeChecked());
  111. expect(newIssuesEndpointMock).toHaveBeenCalled();
  112. });
  113. it('renders a link to Discover', async function () {
  114. render(
  115. <ProjectIssues
  116. api={new MockApiClient()}
  117. organization={organization}
  118. location={router.location}
  119. projectId={parseInt(project.id, 10)}
  120. />,
  121. {
  122. context: routerContext,
  123. organization,
  124. }
  125. );
  126. const link = screen.getByLabelText('Open in Discover');
  127. expect(link).toBeInTheDocument();
  128. await userEvent.click(link);
  129. expect(router.push).toHaveBeenCalledWith({
  130. pathname: `/organizations/${organization.slug}/discover/results/`,
  131. query: {
  132. display: 'top5',
  133. field: ['issue', 'title', 'count()', 'count_unique(user)', 'project'],
  134. name: 'Frequent Unhandled Issues',
  135. query: 'event.type:error error.unhandled:true',
  136. sort: ['-count'],
  137. statsPeriod: '14d',
  138. },
  139. });
  140. });
  141. it('changes according to global header', async function () {
  142. render(
  143. <ProjectIssues
  144. organization={organization}
  145. api={new MockApiClient()}
  146. projectId={parseInt(project.id, 10)}
  147. location={{
  148. ...router.location,
  149. query: {statsPeriod: '7d', environment: 'staging', somethingBad: 'nope'},
  150. }}
  151. />,
  152. {context: routerContext, organization}
  153. );
  154. expect(endpointMock).toHaveBeenCalledTimes(0);
  155. expect(filteredEndpointMock).toHaveBeenCalledTimes(1);
  156. const link = screen.getByLabelText('Open in Issues');
  157. expect(link).toBeInTheDocument();
  158. await userEvent.click(link);
  159. expect(router.push).toHaveBeenCalledWith({
  160. pathname: `/organizations/${organization.slug}/issues/`,
  161. query: {
  162. limit: 5,
  163. environment: 'staging',
  164. statsPeriod: '7d',
  165. query: 'error.unhandled:true is:unresolved',
  166. sort: 'freq',
  167. },
  168. });
  169. });
  170. });