activitySection.spec.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import {GroupFixture} from 'sentry-fixture/group';
  2. import {ProjectFixture} from 'sentry-fixture/project';
  3. import {UserFixture} from 'sentry-fixture/user';
  4. import {
  5. render,
  6. renderGlobalModal,
  7. screen,
  8. userEvent,
  9. } from 'sentry-test/reactTestingLibrary';
  10. import ConfigStore from 'sentry/stores/configStore';
  11. import GroupStore from 'sentry/stores/groupStore';
  12. import ProjectsStore from 'sentry/stores/projectsStore';
  13. import type {GroupActivity} from 'sentry/types/group';
  14. import {GroupActivityType} from 'sentry/types/group';
  15. import StreamlinedActivitySection from 'sentry/views/issueDetails/streamline/activitySection';
  16. describe('StreamlinedActivitySection', function () {
  17. const project = ProjectFixture();
  18. const user = UserFixture();
  19. user.options.prefersIssueDetailsStreamlinedUI = true;
  20. ConfigStore.set('user', user);
  21. ProjectsStore.loadInitialData([project]);
  22. GroupStore.init();
  23. const group = GroupFixture({
  24. id: '1337',
  25. activity: [
  26. {
  27. type: GroupActivityType.NOTE,
  28. id: 'note-1',
  29. data: {text: 'Test Note'},
  30. dateCreated: '2020-01-01T00:00:00',
  31. user: user,
  32. project,
  33. },
  34. ],
  35. project,
  36. });
  37. GroupStore.add([group]);
  38. beforeEach(() => {
  39. jest.restoreAllMocks();
  40. MockApiClient.clearMockResponses();
  41. });
  42. it('renders the input with a comment button', async function () {
  43. const comment = 'nice work friends';
  44. const postMock = MockApiClient.addMockResponse({
  45. url: '/organizations/org-slug/issues/1337/comments/',
  46. method: 'POST',
  47. body: {
  48. id: 'note-2',
  49. user: UserFixture({id: '2'}),
  50. type: 'note',
  51. data: {text: comment},
  52. dateCreated: '2024-10-31T00:00:00.000000Z',
  53. },
  54. });
  55. render(<StreamlinedActivitySection group={group} />);
  56. const commentInput = screen.getByRole('textbox', {name: 'Add a comment'});
  57. expect(commentInput).toBeInTheDocument();
  58. const submitButton = screen.getByRole('button', {name: 'Submit comment'});
  59. expect(submitButton).toBeInTheDocument();
  60. expect(submitButton).toBeDisabled();
  61. await userEvent.type(commentInput, comment);
  62. expect(submitButton).toBeEnabled();
  63. await userEvent.click(submitButton);
  64. expect(postMock).toHaveBeenCalled();
  65. });
  66. it('allows submitting the comment field with hotkeys', async function () {
  67. const comment = 'nice work friends';
  68. const postMock = MockApiClient.addMockResponse({
  69. url: '/organizations/org-slug/issues/1337/comments/',
  70. method: 'POST',
  71. body: {
  72. id: 'note-3',
  73. user: UserFixture({id: '2'}),
  74. type: 'note',
  75. data: {text: comment},
  76. dateCreated: '2024-10-31T00:00:00.000000Z',
  77. },
  78. });
  79. render(<StreamlinedActivitySection group={group} />);
  80. const commentInput = screen.getByRole('textbox', {name: 'Add a comment'});
  81. await userEvent.type(commentInput, comment);
  82. await userEvent.keyboard('{Meta>}{Enter}{/Meta}');
  83. expect(postMock).toHaveBeenCalled();
  84. });
  85. it('renders note and allows for delete', async function () {
  86. const deleteMock = MockApiClient.addMockResponse({
  87. url: '/organizations/org-slug/issues/1337/comments/note-1/',
  88. method: 'DELETE',
  89. });
  90. render(<StreamlinedActivitySection group={group} />);
  91. renderGlobalModal();
  92. expect(await screen.findByText('Test Note')).toBeInTheDocument();
  93. expect(screen.getByRole('button', {name: 'Comment Actions'})).toBeInTheDocument();
  94. await userEvent.click(screen.getByRole('button', {name: 'Comment Actions'}));
  95. await userEvent.click(screen.getByRole('menuitemradio', {name: 'Remove'}));
  96. expect(
  97. screen.getByText('Are you sure you want to remove this comment?')
  98. ).toBeInTheDocument();
  99. await userEvent.click(screen.getByRole('button', {name: 'Remove comment'}));
  100. expect(deleteMock).toHaveBeenCalledTimes(1);
  101. expect(screen.queryByText('Test Note')).not.toBeInTheDocument();
  102. });
  103. it('renders note but does not allow for deletion if written by someone else', async function () {
  104. const updatedActivityGroup = GroupFixture({
  105. id: '1338',
  106. activity: [
  107. {
  108. type: GroupActivityType.NOTE,
  109. id: 'note-1',
  110. data: {text: 'Test Note'},
  111. dateCreated: '2020-01-01T00:00:00',
  112. user: UserFixture({id: '2'}),
  113. project,
  114. },
  115. ],
  116. project,
  117. });
  118. render(<StreamlinedActivitySection group={updatedActivityGroup} />);
  119. expect(await screen.findByText('Test Note')).toBeInTheDocument();
  120. expect(
  121. screen.queryByRole('button', {name: 'Comment Actions'})
  122. ).not.toBeInTheDocument();
  123. });
  124. it('collapses activity when there are more than 5 items', async function () {
  125. const activities: GroupActivity[] = Array.from({length: 7}, (_, index) => ({
  126. type: GroupActivityType.NOTE,
  127. id: `note-${index + 1}`,
  128. data: {text: `Test Note ${index + 1}`},
  129. dateCreated: '2020-01-01T00:00:00',
  130. user: UserFixture({id: '2'}),
  131. project,
  132. }));
  133. const updatedActivityGroup = GroupFixture({
  134. id: '1338',
  135. activity: activities,
  136. project,
  137. });
  138. render(<StreamlinedActivitySection group={updatedActivityGroup} />);
  139. expect(await screen.findByText('Test Note 1')).toBeInTheDocument();
  140. expect(await screen.findByText('Test Note 7')).toBeInTheDocument();
  141. expect(screen.queryByText('Test Note 6')).not.toBeInTheDocument();
  142. expect(await screen.findByText('4 activities hidden')).toBeInTheDocument();
  143. await userEvent.click(await screen.findByRole('button', {name: 'Show all activity'}));
  144. expect(await screen.findByText('Test Note 6')).toBeInTheDocument();
  145. });
  146. });