test_group_details.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. from unittest import mock
  2. from rest_framework.exceptions import ErrorDetail
  3. from sentry.models import Environment, GroupInboxReason, Release
  4. from sentry.models.groupinbox import add_group_to_inbox, remove_group_from_inbox
  5. from sentry.testutils import APITestCase, SnubaTestCase
  6. from sentry.testutils.helpers.datetime import before_now, iso_format
  7. class GroupDetailsTest(APITestCase, SnubaTestCase):
  8. def test_multiple_environments(self):
  9. group = self.create_group()
  10. self.login_as(user=self.user)
  11. environment = Environment.get_or_create(group.project, "production")
  12. environment2 = Environment.get_or_create(group.project, "staging")
  13. url = f"/api/0/issues/{group.id}/"
  14. from sentry.api.endpoints.group_details import tsdb
  15. with mock.patch(
  16. "sentry.api.endpoints.group_details.tsdb.get_range", side_effect=tsdb.get_range
  17. ) as get_range:
  18. response = self.client.get(
  19. f"{url}?environment=production&environment=staging", format="json"
  20. )
  21. assert response.status_code == 200
  22. assert get_range.call_count == 2
  23. for args, kwargs in get_range.call_args_list:
  24. assert kwargs["environment_ids"] == [environment.id, environment2.id]
  25. response = self.client.get(f"{url}?environment=invalid", format="json")
  26. assert response.status_code == 404
  27. def test_with_first_last_release(self):
  28. self.login_as(user=self.user)
  29. first_release = {
  30. "firstEvent": before_now(minutes=3),
  31. "lastEvent": before_now(minutes=2, seconds=30),
  32. }
  33. last_release = {
  34. "firstEvent": before_now(minutes=1, seconds=30),
  35. "lastEvent": before_now(minutes=1),
  36. }
  37. for timestamp in first_release.values():
  38. self.store_event(
  39. data={"release": "1.0", "timestamp": iso_format(timestamp)},
  40. project_id=self.project.id,
  41. )
  42. self.store_event(
  43. data={"release": "1.1", "timestamp": iso_format(before_now(minutes=2))},
  44. project_id=self.project.id,
  45. )
  46. event = None
  47. for timestamp in last_release.values():
  48. event = self.store_event(
  49. data={"release": "1.0a", "timestamp": iso_format(timestamp)},
  50. project_id=self.project.id,
  51. )
  52. group = event.group
  53. url = f"/api/0/issues/{group.id}/"
  54. response = self.client.get(url, format="json")
  55. assert response.status_code == 200, response.content
  56. assert response.data["id"] == str(group.id)
  57. release = response.data["firstRelease"]
  58. assert release["version"] == "1.0"
  59. for event, timestamp in first_release.items():
  60. assert release[event].ctime() == timestamp.ctime()
  61. release = response.data["lastRelease"]
  62. assert release["version"] == "1.0a"
  63. for event, timestamp in last_release.items():
  64. assert release[event].ctime() == timestamp.ctime()
  65. def test_first_last_only_one_tagstore(self):
  66. self.login_as(user=self.user)
  67. event = self.store_event(
  68. data={"release": "1.0", "timestamp": iso_format(before_now(days=3))},
  69. project_id=self.project.id,
  70. )
  71. self.store_event(
  72. data={"release": "1.1", "timestamp": iso_format(before_now(minutes=3))},
  73. project_id=self.project.id,
  74. )
  75. group = event.group
  76. url = f"/api/0/issues/{group.id}/"
  77. with mock.patch(
  78. "sentry.api.endpoints.group_details.tagstore.get_release_tags"
  79. ) as get_release_tags:
  80. response = self.client.get(url, format="json")
  81. assert response.status_code == 200
  82. assert get_release_tags.call_count == 1
  83. def test_first_release_only(self):
  84. self.login_as(user=self.user)
  85. first_event = before_now(days=3)
  86. self.store_event(
  87. data={"release": "1.0", "timestamp": iso_format(first_event)},
  88. project_id=self.project.id,
  89. )
  90. event = self.store_event(
  91. data={"release": "1.1", "timestamp": iso_format(before_now(days=1))},
  92. project_id=self.project.id,
  93. )
  94. # Forcibly remove one of the releases
  95. Release.objects.get(version="1.1").delete()
  96. group = event.group
  97. url = f"/api/0/issues/{group.id}/"
  98. response = self.client.get(url, format="json")
  99. assert response.status_code == 200, response.content
  100. assert response.data["firstRelease"]["version"] == "1.0"
  101. # only one event
  102. assert (
  103. response.data["firstRelease"]["firstEvent"]
  104. == response.data["firstRelease"]["lastEvent"]
  105. )
  106. assert response.data["firstRelease"]["firstEvent"].ctime() == first_event.ctime()
  107. assert response.data["lastRelease"] is None
  108. def test_group_expand_inbox(self):
  109. self.login_as(user=self.user)
  110. event = self.store_event(
  111. data={"timestamp": iso_format(before_now(minutes=3))},
  112. project_id=self.project.id,
  113. )
  114. group = event.group
  115. add_group_to_inbox(group, GroupInboxReason.NEW)
  116. url = f"/api/0/issues/{group.id}/?expand=inbox"
  117. response = self.client.get(url, format="json")
  118. assert response.status_code == 200, response.content
  119. assert response.data["inbox"] is not None
  120. assert response.data["inbox"]["reason"] == GroupInboxReason.NEW.value
  121. assert response.data["inbox"]["reason_details"] is None
  122. remove_group_from_inbox(event.group)
  123. response = self.client.get(url, format="json")
  124. assert response.status_code == 200, response.content
  125. assert response.data["inbox"] is None
  126. def test_assigned_to_unknown(self):
  127. self.login_as(user=self.user)
  128. event = self.store_event(
  129. data={"timestamp": iso_format(before_now(minutes=3))},
  130. project_id=self.project.id,
  131. )
  132. group = event.group
  133. url = f"/api/0/issues/{group.id}/"
  134. response = self.client.put(
  135. url, {"assignedTo": "admin@localhost", "status": "unresolved"}, format="json"
  136. )
  137. assert response.status_code == 200
  138. response = self.client.put(
  139. url, {"assignedTo": "user@doesntexist.com", "status": "unresolved"}, format="json"
  140. )
  141. assert response.status_code == 400
  142. assert response.data == {
  143. "assignedTo": [
  144. ErrorDetail(
  145. string="Could not parse actor. Format should be `type:id` where type is `team` or `user`.",
  146. code="invalid",
  147. )
  148. ]
  149. }