test_organization_group_index.py 8.9 KB

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