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 sentry.models import AssistantActivity, GroupInboxReason, GroupStatus
  6. from sentry.models.groupinbox import add_group_to_inbox
  7. from sentry.testutils import AcceptanceTestCase, SnubaTestCase
  8. from sentry.testutils.helpers.datetime import before_now, iso_format
  9. from tests.acceptance.page_objects.issue_list import IssueListPage
  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