test_organization_group_index.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. from datetime import datetime
  2. from unittest.mock import patch
  3. import pytz
  4. from django.utils import timezone
  5. from fixtures.page_objects.issue_list import IssueListPage
  6. from sentry.models import AssistantActivity, GroupInboxReason, GroupStatus
  7. from sentry.models.groupinbox import add_group_to_inbox
  8. from sentry.testutils import AcceptanceTestCase, SnubaTestCase
  9. from sentry.testutils.helpers.datetime import before_now, iso_format
  10. event_time = before_now(days=3).replace(tzinfo=pytz.utc)
  11. class OrganizationGroupIndexTest(AcceptanceTestCase, SnubaTestCase):
  12. def setUp(self):
  13. super().setUp()
  14. self.user = self.create_user("foo@example.com")
  15. self.org = self.create_organization(owner=self.user, name="Rowdy Tiger")
  16. self.team = self.create_team(
  17. organization=self.org, name="Mariachi Band", members=[self.user]
  18. )
  19. self.project = self.create_project(organization=self.org, teams=[self.team], name="Bengal")
  20. self.other_project = self.create_project(
  21. organization=self.org, teams=[self.team], name="Sumatra"
  22. )
  23. self.login_as(self.user)
  24. self.page = IssueListPage(self.browser, self.client)
  25. self.dismiss_assistant()
  26. def create_issues(self):
  27. self.event_a = self.store_event(
  28. data={
  29. "event_id": "a" * 32,
  30. "message": "oh no",
  31. "timestamp": iso_format(event_time),
  32. "fingerprint": ["group-1"],
  33. },
  34. project_id=self.project.id,
  35. )
  36. add_group_to_inbox(self.event_a.group, GroupInboxReason.NEW)
  37. self.event_b = self.store_event(
  38. data={
  39. "event_id": "b" * 32,
  40. "message": "oh snap",
  41. "timestamp": iso_format(event_time),
  42. "fingerprint": ["group-2"],
  43. },
  44. project_id=self.project.id,
  45. )
  46. add_group_to_inbox(self.event_b.group, GroupInboxReason.NEW)
  47. def test_with_onboarding(self):
  48. self.project.update(first_event=None)
  49. self.page.visit_issue_list(self.org.slug)
  50. self.browser.wait_until_test_id("awaiting-events")
  51. self.browser.snapshot("organization issues onboarding")
  52. def test_with_no_results(self):
  53. self.project.update(first_event=timezone.now())
  54. self.page.visit_issue_list(self.org.slug, query="?query=assigned%3Ame")
  55. self.browser.wait_until_test_id("empty-state")
  56. self.browser.snapshot("organization issues no results")
  57. @patch("django.utils.timezone.now")
  58. def test_with_results(self, mock_now):
  59. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  60. self.create_issues()
  61. self.page.visit_issue_list(self.org.slug)
  62. self.page.wait_for_stream()
  63. self.browser.snapshot("organization issues with issues")
  64. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  65. assert len(groups) == 2
  66. assert "oh snap" in groups[0].text
  67. assert "oh no" in groups[1].text
  68. @patch("django.utils.timezone.now")
  69. def test_resolve_issues(self, mock_now):
  70. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  71. self.create_issues()
  72. self.page.visit_issue_list(self.org.slug)
  73. self.page.wait_for_stream()
  74. self.page.select_issue(1)
  75. self.page.select_issue(2)
  76. self.page.resolve_issues()
  77. self.page.wait_for_resolved_issue()
  78. resolved_groups = self.page.find_resolved_issues()
  79. assert len(resolved_groups) == 2
  80. @patch("django.utils.timezone.now")
  81. def test_resolve_issues_removal(self, mock_now):
  82. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  83. self.create_issues()
  84. # TODO(Kelly): update once issue-list-removal-action feature is stable
  85. with self.feature("organizations:issue-list-removal-action"):
  86. group1 = self.event_a.group
  87. self.page.visit_issue_list(self.org.slug)
  88. self.page.wait_for_stream()
  89. self.page.select_issue(1)
  90. self.page.resolve_issues_removal()
  91. group1.update(status=GroupStatus.RESOLVED)
  92. self.page.wait_for_issue_removal()
  93. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  94. assert len(groups) == 1
  95. @patch("django.utils.timezone.now")
  96. def test_resolve_issues_multi_projects(self, mock_now):
  97. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  98. self.create_issues()
  99. with self.feature("organizations:global-views"):
  100. self.page.visit_issue_list(self.org.slug)
  101. self.page.wait_for_stream()
  102. self.page.select_issue(1)
  103. self.page.select_issue(2)
  104. self.page.resolve_issues()
  105. self.page.wait_for_resolved_issue()
  106. resolved_groups = self.page.find_resolved_issues()
  107. assert len(resolved_groups) == 2
  108. @patch("django.utils.timezone.now")
  109. def test_resolve_issues_removal_multi_projects(self, mock_now):
  110. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  111. self.create_issues()
  112. # TODO(Kelly): update once issue-list-removal-action feature is stable
  113. with self.feature(
  114. ["organizations:global-views", "organizations:issue-list-removal-action"]
  115. ):
  116. group1 = self.event_a.group
  117. self.page.visit_issue_list(self.org.slug)
  118. self.page.wait_for_stream()
  119. self.page.select_issue(1)
  120. self.page.resolve_issues_removal()
  121. group1.update(status=GroupStatus.RESOLVED)
  122. self.page.wait_for_issue_removal()
  123. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  124. assert len(groups) == 1
  125. @patch("django.utils.timezone.now")
  126. def test_ignore_issues(self, mock_now):
  127. # TODO(Kelly): update once issue-list-removal-action feature is stable
  128. with self.feature("organizations:issue-list-removal-action"):
  129. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  130. self.create_issues()
  131. group1 = self.event_a.group
  132. self.page.visit_issue_list(self.org.slug)
  133. self.page.wait_for_stream()
  134. self.page.select_issue(1)
  135. self.page.ignore_issues()
  136. group1.update(status=GroupStatus.IGNORED)
  137. self.page.wait_for_issue_removal()
  138. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  139. assert len(groups) == 1
  140. @patch("django.utils.timezone.now")
  141. def test_ignore_issues_multi_projects(self, mock_now):
  142. # TODO(Kelly): update once issue-list-removal-action feature is stable
  143. with self.feature("organizations:issue-list-removal-action"):
  144. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  145. self.create_issues()
  146. group1 = self.event_a.group
  147. with self.feature("organizations:global-views"):
  148. self.page.visit_issue_list(self.org.slug)
  149. self.page.wait_for_stream()
  150. self.page.select_issue(1)
  151. self.page.ignore_issues()
  152. group1.update(status=GroupStatus.IGNORED)
  153. self.page.wait_for_issue_removal()
  154. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  155. assert len(groups) == 1
  156. @patch("django.utils.timezone.now")
  157. def test_delete_issues(self, mock_now):
  158. # TODO(Kelly): update once issue-list-removal-action feature is stable
  159. with self.feature("organizations:issue-list-removal-action"):
  160. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  161. self.create_issues()
  162. group1 = self.event_a.group
  163. self.page.visit_issue_list(self.org.slug)
  164. self.page.wait_for_stream()
  165. self.page.select_issue(1)
  166. self.page.delete_issues()
  167. group1.update(status=GroupStatus.PENDING_DELETION)
  168. self.page.wait_for_issue_removal()
  169. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  170. assert len(groups) == 1
  171. @patch("django.utils.timezone.now")
  172. def test_delete_issues_multi_projects(self, mock_now):
  173. # TODO(Kelly): update once issue-list-removal-action feature is stable
  174. with self.feature("organizations:issue-list-removal-action"):
  175. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  176. self.create_issues()
  177. group1 = self.event_a.group
  178. with self.feature("organizations:global-views"):
  179. self.page.visit_issue_list(self.org.slug)
  180. self.page.wait_for_stream()
  181. self.page.select_issue(1)
  182. self.page.delete_issues()
  183. group1.update(status=GroupStatus.PENDING_DELETION)
  184. self.page.wait_for_issue_removal()
  185. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  186. assert len(groups) == 1
  187. @patch("django.utils.timezone.now")
  188. def test_merge_issues(self, mock_now):
  189. # TODO(Kelly): update once issue-list-removal-action feature is stable
  190. with self.feature("organizations:issue-list-removal-action"):
  191. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  192. self.create_issues()
  193. group1 = self.event_a.group
  194. group2 = self.event_b.group
  195. self.page.visit_issue_list(self.org.slug)
  196. self.page.wait_for_stream()
  197. self.page.select_issue(1)
  198. self.page.select_issue(2)
  199. self.page.merge_issues()
  200. group1.update(status=GroupStatus.PENDING_MERGE)
  201. group2.update(status=GroupStatus.PENDING_MERGE)
  202. self.page.wait_for_issue_removal()
  203. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  204. assert len(groups) == 1
  205. @patch("django.utils.timezone.now")
  206. def test_inbox_results(self, mock_now):
  207. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  208. self.create_issues()
  209. # Disable for_review_guide
  210. AssistantActivity.objects.create(user=self.user, guide_id=9, viewed_ts=timezone.now())
  211. self.page.visit_issue_list(
  212. self.org.slug,
  213. query="?query=is%3Aunresolved+is%3Afor_review+assigned_or_suggested%3A[me, none]",
  214. )
  215. self.page.wait_for_stream()
  216. self.browser.snapshot("organization issues inbox results")
  217. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  218. assert len(groups) == 2
  219. self.page.select_issue(1)
  220. self.page.mark_reviewed_issues()
  221. self.page.visit_issue_list(
  222. self.org.slug,
  223. query="?query=is%3Aunresolved+is%3Afor_review+assigned_or_suggested%3A[me, none]",
  224. )
  225. self.page.wait_for_stream()
  226. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  227. assert len(groups) == 1