groupEventAttachments.spec.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import {EnvironmentsFixture} from 'sentry-fixture/environments';
  2. import {EventAttachmentFixture} from 'sentry-fixture/eventAttachment';
  3. import {GroupFixture} from 'sentry-fixture/group';
  4. import {ProjectFixture} from 'sentry-fixture/project';
  5. import {RouterFixture} from 'sentry-fixture/routerFixture';
  6. import {TagsFixture} from 'sentry-fixture/tags';
  7. import {initializeOrg} from 'sentry-test/initializeOrg';
  8. import {
  9. render,
  10. renderGlobalModal,
  11. screen,
  12. userEvent,
  13. within,
  14. } from 'sentry-test/reactTestingLibrary';
  15. import GroupStore from 'sentry/stores/groupStore';
  16. import ModalStore from 'sentry/stores/modalStore';
  17. import PageFiltersStore from 'sentry/stores/pageFiltersStore';
  18. import ProjectsStore from 'sentry/stores/projectsStore';
  19. import type {Project} from 'sentry/types/project';
  20. import GroupEventAttachments from './groupEventAttachments';
  21. describe('GroupEventAttachments', function () {
  22. const groupId = 'group-id';
  23. const group = GroupFixture({id: groupId});
  24. const {organization, router} = initializeOrg({
  25. organization: {
  26. features: ['event-attachments'],
  27. orgRole: 'member',
  28. attachmentsRole: 'member',
  29. },
  30. });
  31. const {router: screenshotRouter} = initializeOrg({
  32. router: {
  33. params: {orgId: 'org-slug', groupId: 'group-id'},
  34. location: {query: {attachmentFilter: 'screenshot'}},
  35. },
  36. });
  37. let project: Project;
  38. let getAttachmentsMock: jest.Mock;
  39. beforeEach(function () {
  40. project = ProjectFixture({platform: 'apple-ios'});
  41. ProjectsStore.loadInitialData([project]);
  42. GroupStore.init();
  43. MockApiClient.addMockResponse({
  44. url: `/organizations/${organization.slug}/environments/`,
  45. body: EnvironmentsFixture(),
  46. });
  47. getAttachmentsMock = MockApiClient.addMockResponse({
  48. url: `/organizations/org-slug/issues/${groupId}/attachments/`,
  49. body: [EventAttachmentFixture()],
  50. });
  51. MockApiClient.addMockResponse({
  52. url: `/organizations/${organization.slug}/issues/${group.id}/tags/`,
  53. body: TagsFixture(),
  54. method: 'GET',
  55. });
  56. });
  57. afterEach(() => {
  58. MockApiClient.clearMockResponses();
  59. ModalStore.reset();
  60. });
  61. it('calls attachments api with screenshot filter', async function () {
  62. render(<GroupEventAttachments project={project} group={group} />, {
  63. router: screenshotRouter,
  64. organization,
  65. });
  66. expect(screen.getByRole('radio', {name: 'Screenshots'})).toBeInTheDocument();
  67. await userEvent.click(screen.getByRole('radio', {name: 'Screenshots'}));
  68. expect(getAttachmentsMock).toHaveBeenCalledWith(
  69. '/organizations/org-slug/issues/group-id/attachments/',
  70. expect.objectContaining({
  71. query: {screenshot: '1'},
  72. })
  73. );
  74. });
  75. it('calls opens modal when clicking on panel body', async function () {
  76. render(<GroupEventAttachments project={project} group={group} />, {
  77. router: screenshotRouter,
  78. organization,
  79. });
  80. renderGlobalModal();
  81. await userEvent.click(await screen.findByTestId('screenshot-1'));
  82. expect(await screen.findByRole('dialog')).toBeInTheDocument();
  83. });
  84. it('links event id to event detail', async function () {
  85. render(<GroupEventAttachments project={project} group={group} />, {
  86. router,
  87. organization,
  88. });
  89. expect(await screen.findByRole('link', {name: '12345678'})).toHaveAttribute(
  90. 'href',
  91. '/organizations/org-slug/issues/group-id/events/12345678901234567890123456789012/'
  92. );
  93. });
  94. it('links to the download URL', async function () {
  95. render(<GroupEventAttachments project={project} group={group} />, {
  96. router: screenshotRouter,
  97. organization,
  98. });
  99. await userEvent.click(await screen.findByLabelText('Actions'));
  100. expect(
  101. await screen.findByRole('menuitemradio', {name: 'Download'})
  102. ).toBeInTheDocument();
  103. });
  104. it('displays error message when request fails', async function () {
  105. MockApiClient.addMockResponse({
  106. url: '/organizations/org-slug/issues/group-id/attachments/',
  107. statusCode: 500,
  108. });
  109. render(<GroupEventAttachments project={project} group={group} />, {
  110. router,
  111. organization,
  112. });
  113. expect(await screen.findByText(/error loading/i)).toBeInTheDocument();
  114. });
  115. it('can delete an attachment', async function () {
  116. const deleteMock = MockApiClient.addMockResponse({
  117. url: '/projects/org-slug/project-slug/events/12345678901234567890123456789012/attachments/1/',
  118. method: 'DELETE',
  119. });
  120. render(<GroupEventAttachments project={project} group={group} />, {
  121. router,
  122. organization,
  123. });
  124. renderGlobalModal();
  125. expect(await screen.findByText('12345678')).toBeInTheDocument();
  126. expect(screen.getByRole('button', {name: 'Delete'})).toBeEnabled();
  127. await userEvent.click(screen.getByRole('button', {name: 'Delete'}));
  128. expect(
  129. await screen.findByText('Are you sure you wish to delete this file?')
  130. ).toBeInTheDocument();
  131. await userEvent.click(
  132. within(screen.getByRole('dialog')).getByRole('button', {name: 'Delete'})
  133. );
  134. expect(deleteMock).toHaveBeenCalled();
  135. expect(screen.queryByText('12345678')).not.toBeInTheDocument();
  136. });
  137. it('filters by date/query when using Streamlined UI', function () {
  138. PageFiltersStore.init();
  139. PageFiltersStore.onInitializeUrlState(
  140. {
  141. projects: [parseInt(project.id, 10)],
  142. environments: ['staging'],
  143. datetime: {
  144. period: '3d',
  145. start: null,
  146. end: null,
  147. utc: null,
  148. },
  149. },
  150. new Set()
  151. );
  152. const testRouter = RouterFixture();
  153. testRouter.location.query = {
  154. query: 'user.email:leander.rodrigues@sentry.io',
  155. };
  156. render(<GroupEventAttachments project={project} group={group} />, {
  157. router: testRouter,
  158. organization: {...organization, features: ['issue-details-streamline-enforce']},
  159. });
  160. expect(getAttachmentsMock).toHaveBeenCalledWith(
  161. '/organizations/org-slug/issues/group-id/attachments/',
  162. expect.objectContaining({
  163. query: {
  164. environment: ['staging'],
  165. query: 'user.email:leander.rodrigues@sentry.io',
  166. statsPeriod: '3d',
  167. },
  168. })
  169. );
  170. });
  171. });