test_organization_group_index.py 8.8 KB

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