groupActivity.spec.jsx 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. import {initializeOrg} from 'sentry-test/initializeOrg';
  2. import {
  3. act,
  4. render,
  5. renderGlobalModal,
  6. screen,
  7. userEvent,
  8. waitFor,
  9. } from 'sentry-test/reactTestingLibrary';
  10. import ConfigStore from 'sentry/stores/configStore';
  11. import GroupStore from 'sentry/stores/groupStore';
  12. import OrganizationStore from 'sentry/stores/organizationStore';
  13. import ProjectsStore from 'sentry/stores/projectsStore';
  14. import TeamStore from 'sentry/stores/teamStore';
  15. import {GroupActivity} from 'sentry/views/organizationGroupDetails/groupActivity';
  16. describe('GroupActivity', function () {
  17. let project;
  18. beforeEach(function () {
  19. project = TestStubs.Project();
  20. ProjectsStore.loadInitialData([project]);
  21. ConfigStore.init();
  22. ConfigStore.set('user', {id: '123'});
  23. GroupStore.init();
  24. });
  25. afterEach(() => {
  26. MockApiClient.clearMockResponses();
  27. jest.clearAllMocks();
  28. });
  29. function createWrapper({activity, organization: additionalOrg} = {}) {
  30. const group = TestStubs.Group({
  31. id: '1337',
  32. activity: activity ?? [
  33. {type: 'note', id: 'note-1', data: {text: 'Test Note'}, user: TestStubs.User()},
  34. ],
  35. project,
  36. });
  37. const {organization, routerContext} = initializeOrg({
  38. organization: additionalOrg,
  39. group,
  40. });
  41. GroupStore.add([group]);
  42. TeamStore.loadInitialData([TestStubs.Team({id: '999', slug: 'no-team'})]);
  43. OrganizationStore.onUpdate(organization, {replace: true});
  44. return render(
  45. <GroupActivity
  46. api={new MockApiClient()}
  47. params={{orgId: 'org-slug'}}
  48. group={group}
  49. organization={organization}
  50. />,
  51. {context: routerContext}
  52. );
  53. }
  54. it('renders a NoteInput', function () {
  55. createWrapper();
  56. expect(screen.getByTestId('activity-note-body')).toBeInTheDocument();
  57. });
  58. it('renders a marked reviewed activity', function () {
  59. const user = TestStubs.User({name: 'Samwise'});
  60. createWrapper({
  61. activity: [{type: 'mark_reviewed', id: 'reviewed-1', data: {}, user}],
  62. });
  63. expect(screen.getByText('marked this issue as reviewed')).toBeInTheDocument();
  64. expect(screen.getByText(user.name)).toBeInTheDocument();
  65. });
  66. it('renders a assigned to self activity', function () {
  67. const user = TestStubs.User({id: '301', name: 'Mark'});
  68. createWrapper({
  69. activity: [
  70. {
  71. data: {
  72. assignee: user.id,
  73. assigneeEmail: user.email,
  74. assigneeType: 'user',
  75. },
  76. dateCreated: '2021-10-01T15:31:38.950115Z',
  77. id: '117',
  78. type: 'assigned',
  79. user,
  80. },
  81. ],
  82. });
  83. expect(screen.getAllByTestId('activity-item').at(-1)).toHaveTextContent(
  84. /Mark assigned this issue to themselves/
  85. );
  86. });
  87. it('renders an assigned via codeowners activity', function () {
  88. createWrapper({
  89. activity: [
  90. {
  91. data: {
  92. assignee: '123',
  93. assigneeEmail: 'anotheruser@sentry.io',
  94. assigneeType: 'user',
  95. integration: 'codeowners',
  96. rule: 'path:something/*.py #workflow',
  97. },
  98. dateCreated: '2021-10-01T15:31:38.950115Z',
  99. id: '117',
  100. type: 'assigned',
  101. user: null,
  102. },
  103. ],
  104. });
  105. expect(screen.getAllByTestId('activity-item').at(-1)).toHaveTextContent(
  106. /Sentry auto-assigned this issue to anotheruser@sentry.io/
  107. );
  108. });
  109. it('renders an assigned via slack activity', function () {
  110. const user = TestStubs.User({id: '301', name: 'Mark'});
  111. createWrapper({
  112. activity: [
  113. {
  114. data: {
  115. assignee: '123',
  116. assigneeEmail: 'anotheruser@sentry.io',
  117. assigneeType: 'user',
  118. integration: 'slack',
  119. },
  120. dateCreated: '2021-10-01T15:31:38.950115Z',
  121. id: '117',
  122. type: 'assigned',
  123. user,
  124. },
  125. ],
  126. });
  127. const item = screen.getAllByTestId('activity-item').at(-1);
  128. expect(item).toHaveTextContent(/Mark assigned this issue to anotheruser@sentry.io/);
  129. expect(item).toHaveTextContent(/Assigned via Slack/);
  130. });
  131. it('resolved in commit with no releases', function () {
  132. createWrapper({
  133. activity: [
  134. {
  135. type: 'set_resolved_in_commit',
  136. id: '123',
  137. data: {
  138. author: 'hello',
  139. commit: {
  140. id: 'komal-commit',
  141. repository: {},
  142. releases: [],
  143. },
  144. },
  145. user: TestStubs.User(),
  146. },
  147. ],
  148. });
  149. expect(screen.getAllByTestId('activity-item').at(-1)).toHaveTextContent(
  150. 'Foo Bar marked this issue as resolved in komal-commit'
  151. );
  152. });
  153. it('resolved in commit with one release', function () {
  154. createWrapper({
  155. activity: [
  156. {
  157. type: 'set_resolved_in_commit',
  158. id: '123',
  159. data: {
  160. author: 'hello',
  161. commit: {
  162. id: 'komal-commit',
  163. repository: {},
  164. releases: [
  165. {
  166. dateCreated: '2022-05-01',
  167. dateReleased: '2022-05-02',
  168. version: 'random',
  169. },
  170. ],
  171. },
  172. },
  173. user: TestStubs.User(),
  174. },
  175. ],
  176. });
  177. expect(screen.getAllByTestId('activity-item').at(-1)).toHaveTextContent(
  178. 'Foo Bar marked this issue as resolved in komal-commit This commit was released in random'
  179. );
  180. });
  181. it('resolved in commit with multiple releases', function () {
  182. createWrapper({
  183. activity: [
  184. {
  185. type: 'set_resolved_in_commit',
  186. id: '123',
  187. data: {
  188. commit: {
  189. id: 'komal-commit',
  190. repository: {},
  191. releases: [
  192. {
  193. dateCreated: '2022-05-01',
  194. dateReleased: '2022-05-02',
  195. version: 'random',
  196. },
  197. {
  198. dateCreated: '2022-06-01',
  199. dateReleased: '2022-06-02',
  200. version: 'newest',
  201. },
  202. {
  203. dateCreated: '2021-08-03',
  204. dateReleased: '2021-08-03',
  205. version: 'oldest-release',
  206. },
  207. {
  208. dateCreated: '2022-04-21',
  209. dateReleased: '2022-04-21',
  210. version: 'randomTwo',
  211. },
  212. ],
  213. },
  214. },
  215. user: TestStubs.User(),
  216. },
  217. ],
  218. });
  219. expect(screen.getAllByTestId('activity-item').at(-1)).toHaveTextContent(
  220. 'Foo Bar marked this issue as resolved in komal-commit This commit was released in oldest-release and 3 others'
  221. );
  222. });
  223. it('requests assignees that are not in the team store', async function () {
  224. const team = TestStubs.Team({id: '123', name: 'workflow'});
  225. const teamRequest = MockApiClient.addMockResponse({
  226. url: `/organizations/org-slug/teams/`,
  227. body: [team],
  228. });
  229. createWrapper({
  230. activity: [
  231. {
  232. id: '123',
  233. user: null,
  234. type: 'assigned',
  235. data: {
  236. assignee: team.id,
  237. assigneeEmail: null,
  238. assigneeType: 'team',
  239. },
  240. dateCreated: '2021-10-28T13:40:10.634821Z',
  241. },
  242. ],
  243. });
  244. await waitFor(() => expect(teamRequest).toHaveBeenCalledTimes(1));
  245. expect(await screen.findByText(`#${team.slug}`)).toBeInTheDocument();
  246. expect(screen.getAllByTestId('activity-item').at(-1)).toHaveTextContent(
  247. /Sentry assigned this issue to #team-slug/
  248. );
  249. });
  250. describe('Delete', function () {
  251. let deleteMock;
  252. beforeEach(function () {
  253. deleteMock = MockApiClient.addMockResponse({
  254. url: '/issues/1337/comments/note-1/',
  255. method: 'DELETE',
  256. });
  257. ConfigStore.set('user', {id: '123', isSuperuser: true});
  258. });
  259. it('should do nothing if not present in GroupStore', function () {
  260. createWrapper();
  261. renderGlobalModal();
  262. act(() => {
  263. // Remove note from group activity
  264. GroupStore.removeActivity('1337', 'note-1');
  265. });
  266. userEvent.click(screen.getByText('Remove'));
  267. expect(
  268. screen.getByText('Are you sure you wish to delete this comment?')
  269. ).toBeInTheDocument();
  270. userEvent.click(screen.getByRole('button', {name: 'Confirm'}));
  271. expect(deleteMock).not.toHaveBeenCalled();
  272. });
  273. it('should remove remove the item from the GroupStore make a DELETE API request', function () {
  274. createWrapper();
  275. renderGlobalModal();
  276. userEvent.click(screen.getByText('Remove'));
  277. expect(
  278. screen.getByText('Are you sure you wish to delete this comment?')
  279. ).toBeInTheDocument();
  280. userEvent.click(screen.getByRole('button', {name: 'Confirm'}));
  281. expect(deleteMock).toHaveBeenCalledTimes(1);
  282. });
  283. });
  284. });