groupEventAttachments.spec.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import {EventAttachmentFixture} from 'sentry-fixture/eventAttachment';
  2. import {ProjectFixture} from 'sentry-fixture/project';
  3. import {initializeOrg} from 'sentry-test/initializeOrg';
  4. import {
  5. render,
  6. renderGlobalModal,
  7. screen,
  8. userEvent,
  9. within,
  10. } from 'sentry-test/reactTestingLibrary';
  11. import GroupStore from 'sentry/stores/groupStore';
  12. import ModalStore from 'sentry/stores/modalStore';
  13. import ProjectsStore from 'sentry/stores/projectsStore';
  14. import type {Project} from 'sentry/types/project';
  15. import GroupEventAttachments from './groupEventAttachments';
  16. describe('GroupEventAttachments', function () {
  17. const groupId = 'group-id';
  18. const {organization, router} = initializeOrg({
  19. organization: {
  20. features: ['event-attachments'],
  21. orgRole: 'member',
  22. attachmentsRole: 'member',
  23. },
  24. });
  25. const {router: screenshotRouter} = initializeOrg({
  26. router: {
  27. params: {orgId: 'org-slug', groupId: 'group-id'},
  28. location: {query: {attachmentFilter: 'screenshot'}},
  29. },
  30. });
  31. let project: Project;
  32. let getAttachmentsMock: jest.Mock;
  33. beforeEach(function () {
  34. project = ProjectFixture({platform: 'apple-ios'});
  35. ProjectsStore.loadInitialData([project]);
  36. GroupStore.init();
  37. getAttachmentsMock = MockApiClient.addMockResponse({
  38. url: `/organizations/org-slug/issues/${groupId}/attachments/`,
  39. body: [EventAttachmentFixture()],
  40. });
  41. });
  42. afterEach(() => {
  43. MockApiClient.clearMockResponses();
  44. ModalStore.reset();
  45. });
  46. it('calls attachments api with screenshot filter', async function () {
  47. render(<GroupEventAttachments project={project} groupId={groupId} />, {
  48. router: screenshotRouter,
  49. organization,
  50. });
  51. expect(screen.getByRole('radio', {name: 'Screenshots'})).toBeInTheDocument();
  52. await userEvent.click(screen.getByRole('radio', {name: 'Screenshots'}));
  53. expect(getAttachmentsMock).toHaveBeenCalledWith(
  54. '/organizations/org-slug/issues/group-id/attachments/',
  55. expect.objectContaining({
  56. query: {screenshot: '1'},
  57. })
  58. );
  59. });
  60. it('does not render screenshots tab if not mobile platform', function () {
  61. project.platform = 'javascript';
  62. render(<GroupEventAttachments project={project} groupId={groupId} />, {
  63. router: screenshotRouter,
  64. organization,
  65. });
  66. expect(screen.queryByText('Screenshots')).not.toBeInTheDocument();
  67. });
  68. it('calls opens modal when clicking on panel body', async function () {
  69. render(<GroupEventAttachments project={project} groupId={groupId} />, {
  70. router: screenshotRouter,
  71. organization,
  72. });
  73. renderGlobalModal();
  74. await userEvent.click(await screen.findByTestId('screenshot-1'));
  75. expect(await screen.findByRole('dialog')).toBeInTheDocument();
  76. });
  77. it('links event id to event detail', async function () {
  78. render(<GroupEventAttachments project={project} groupId={groupId} />, {
  79. router,
  80. organization,
  81. });
  82. expect(await screen.findByRole('link', {name: '12345678'})).toHaveAttribute(
  83. 'href',
  84. '/organizations/org-slug/issues/group-id/events/12345678901234567890123456789012/'
  85. );
  86. });
  87. it('links to the download URL', async function () {
  88. render(<GroupEventAttachments project={project} groupId={groupId} />, {
  89. router: screenshotRouter,
  90. organization,
  91. });
  92. await userEvent.click(await screen.findByLabelText('Actions'));
  93. expect(
  94. await screen.findByRole('menuitemradio', {name: 'Download'})
  95. ).toBeInTheDocument();
  96. });
  97. it('displays error message when request fails', async function () {
  98. MockApiClient.addMockResponse({
  99. url: '/organizations/org-slug/issues/group-id/attachments/',
  100. statusCode: 500,
  101. });
  102. render(<GroupEventAttachments project={project} groupId={groupId} />, {
  103. router,
  104. organization,
  105. });
  106. expect(await screen.findByText(/error loading/i)).toBeInTheDocument();
  107. });
  108. it('can delete an attachment', async function () {
  109. const deleteMock = MockApiClient.addMockResponse({
  110. url: '/projects/org-slug/project-slug/events/12345678901234567890123456789012/attachments/1/',
  111. method: 'DELETE',
  112. });
  113. render(<GroupEventAttachments project={project} groupId={groupId} />, {
  114. router,
  115. organization,
  116. });
  117. renderGlobalModal();
  118. expect(await screen.findByText('12345678')).toBeInTheDocument();
  119. expect(screen.getByRole('button', {name: 'Delete'})).toBeEnabled();
  120. await userEvent.click(screen.getByRole('button', {name: 'Delete'}));
  121. expect(
  122. await screen.findByText('Are you sure you wish to delete this file?')
  123. ).toBeInTheDocument();
  124. await userEvent.click(
  125. within(screen.getByRole('dialog')).getByRole('button', {name: 'Delete'})
  126. );
  127. expect(deleteMock).toHaveBeenCalled();
  128. expect(screen.queryByText('12345678')).not.toBeInTheDocument();
  129. });
  130. });