test_organization_group_index.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. group1 = self.event_a.group
  73. self.page.visit_issue_list(self.org.slug)
  74. self.page.wait_for_stream()
  75. self.page.select_issue(1)
  76. self.page.resolve_issues()
  77. group1.update(status=GroupStatus.RESOLVED)
  78. self.page.wait_for_issue_removal()
  79. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  80. assert len(groups) == 1
  81. @patch("django.utils.timezone.now")
  82. def test_resolve_issues_multi_projects(self, mock_now):
  83. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  84. self.create_issues()
  85. group1 = self.event_a.group
  86. with self.feature("organizations:global-views"):
  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()
  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_ignore_issues(self, mock_now):
  97. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  98. self.create_issues()
  99. group1 = self.event_a.group
  100. self.page.visit_issue_list(self.org.slug)
  101. self.page.wait_for_stream()
  102. self.page.select_issue(1)
  103. self.page.ignore_issues()
  104. group1.update(status=GroupStatus.IGNORED)
  105. self.page.wait_for_issue_removal()
  106. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  107. assert len(groups) == 1
  108. @patch("django.utils.timezone.now")
  109. def test_ignore_issues_multi_projects(self, mock_now):
  110. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  111. self.create_issues()
  112. group1 = self.event_a.group
  113. with self.feature("organizations:global-views"):
  114. self.page.visit_issue_list(self.org.slug)
  115. self.page.wait_for_stream()
  116. self.page.select_issue(1)
  117. self.page.ignore_issues()
  118. group1.update(status=GroupStatus.IGNORED)
  119. self.page.wait_for_issue_removal()
  120. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  121. assert len(groups) == 1
  122. @patch("django.utils.timezone.now")
  123. def test_delete_issues(self, mock_now):
  124. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  125. self.create_issues()
  126. group1 = self.event_a.group
  127. self.page.visit_issue_list(self.org.slug)
  128. self.page.wait_for_stream()
  129. self.page.select_issue(1)
  130. self.page.delete_issues()
  131. group1.update(status=GroupStatus.PENDING_DELETION)
  132. self.page.wait_for_issue_removal()
  133. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  134. assert len(groups) == 1
  135. @patch("django.utils.timezone.now")
  136. def test_delete_issues_multi_projects(self, mock_now):
  137. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  138. self.create_issues()
  139. group1 = self.event_a.group
  140. with self.feature("organizations:global-views"):
  141. self.page.visit_issue_list(self.org.slug)
  142. self.page.wait_for_stream()
  143. self.page.select_issue(1)
  144. self.page.delete_issues()
  145. group1.update(status=GroupStatus.PENDING_DELETION)
  146. self.page.wait_for_issue_removal()
  147. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  148. assert len(groups) == 1
  149. @patch("django.utils.timezone.now")
  150. def test_merge_issues(self, mock_now):
  151. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  152. self.create_issues()
  153. group1 = self.event_a.group
  154. group2 = self.event_b.group
  155. self.page.visit_issue_list(self.org.slug)
  156. self.page.wait_for_stream()
  157. self.page.select_issue(1)
  158. self.page.select_issue(2)
  159. self.page.merge_issues()
  160. group1.update(status=GroupStatus.PENDING_MERGE)
  161. group2.update(status=GroupStatus.PENDING_MERGE)
  162. self.page.wait_for_issue_removal()
  163. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  164. assert len(groups) == 1
  165. @patch("django.utils.timezone.now")
  166. def test_merge_issues_multi_projects(self, mock_now):
  167. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  168. self.create_issues()
  169. group1 = self.event_a.group
  170. group2 = self.event_b.group
  171. with self.feature("organizations:global-views"):
  172. self.page.visit_issue_list(self.org.slug)
  173. self.page.wait_for_stream()
  174. self.page.select_issue(1)
  175. self.page.select_issue(2)
  176. self.page.merge_issues()
  177. group1.update(status=GroupStatus.PENDING_MERGE)
  178. group2.update(status=GroupStatus.PENDING_MERGE)
  179. self.page.wait_for_issue_removal()
  180. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  181. assert len(groups) == 1
  182. @patch("django.utils.timezone.now")
  183. def test_inbox_results(self, mock_now):
  184. mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
  185. self.create_issues()
  186. # Disable for_review_guide
  187. AssistantActivity.objects.create(user=self.user, guide_id=9, viewed_ts=timezone.now())
  188. self.page.visit_issue_list(
  189. self.org.slug,
  190. query="?query=is%3Aunresolved+is%3Afor_review+assigned_or_suggested%3A[me, none]",
  191. )
  192. self.page.wait_for_stream()
  193. self.browser.snapshot("organization issues inbox results")
  194. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  195. assert len(groups) == 2
  196. self.page.select_issue(1)
  197. self.page.mark_reviewed_issues()
  198. self.page.visit_issue_list(
  199. self.org.slug,
  200. query="?query=is%3Aunresolved+is%3Afor_review+assigned_or_suggested%3A[me, none]",
  201. )
  202. self.page.wait_for_stream()
  203. groups = self.browser.elements('[data-test-id="event-issue-header"]')
  204. assert len(groups) == 1