test_issue_details.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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_details import IssueDetailsPage
  6. from sentry.testutils.cases import AcceptanceTestCase, SnubaTestCase
  7. from sentry.testutils.silo import no_silo_test
  8. from sentry.utils.samples import load_data
  9. now = datetime.utcnow().replace(tzinfo=pytz.utc)
  10. @no_silo_test(stable=True)
  11. class IssueDetailsTest(AcceptanceTestCase, SnubaTestCase):
  12. def setUp(self):
  13. super().setUp()
  14. patcher = patch("django.utils.timezone.now", return_value=now)
  15. patcher.start()
  16. self.addCleanup(patcher.stop)
  17. self.user = self.create_user("foo@example.com")
  18. self.org = self.create_organization(owner=self.user, name="Rowdy Tiger")
  19. self.team = self.create_team(organization=self.org, name="Mariachi Band")
  20. self.project = self.create_project(organization=self.org, teams=[self.team], name="Bengal")
  21. self.login_as(self.user)
  22. self.page = IssueDetailsPage(self.browser, self.client)
  23. self.dismiss_assistant()
  24. def create_sample_event(self, platform, default=None, sample_name=None, time=None, tags=None):
  25. event_data = load_data(platform, default=default, sample_name=sample_name)
  26. event_data["event_id"] = "d964fdbd649a4cf8bfc35d18082b6b0e"
  27. # Only set these properties if we were given a time.
  28. # event processing will mark old time values as processing errors.
  29. if time:
  30. event_data["received"] = time.isoformat()
  31. if tags:
  32. event_data["tags"] = tags
  33. # We need a fallback datetime for the event
  34. if time is None:
  35. time = now - timedelta(days=2)
  36. time = time.replace(hour=0, minute=0, second=0, microsecond=0)
  37. event_data["timestamp"] = time.isoformat()
  38. event = self.store_event(
  39. data=event_data, project_id=self.project.id, assert_no_errors=False
  40. )
  41. event.group.update(
  42. first_seen=datetime(2015, 8, 13, 3, 8, 25, tzinfo=timezone.utc), last_seen=time
  43. )
  44. return event
  45. def test_python_event(self):
  46. tags = [
  47. ["server_name", "web02.example.org"],
  48. ["environment", "staging"],
  49. ]
  50. self.create_sample_event(platform="python", tags=tags)
  51. event = self.create_sample_event(platform="python")
  52. self.page.visit_issue(self.org.slug, event.group.id)
  53. # Wait for tag bars to load
  54. self.browser.wait_until_test_id("loaded-device-name")
  55. self.browser.snapshot("issue details python")
  56. def test_python_rawbody_event(self):
  57. event = self.create_sample_event(platform="python-rawbody")
  58. self.page.visit_issue(self.org.slug, event.group.id)
  59. self.browser.move_to('[data-test-id="rich-http-content-body-section-pre"]')
  60. self.browser.snapshot("issue details python raw body", desktop_only=True)
  61. def test_python_formdata_event(self):
  62. event = self.create_sample_event(platform="python-formdata")
  63. self.page.visit_issue(self.org.slug, event.group.id)
  64. self.browser.snapshot("issue details python formdata", desktop_only=True)
  65. def test_pii_tooltips(self):
  66. event = self.create_sample_event(platform="pii-tooltips")
  67. self.page.visit_issue(self.org.slug, event.group.id)
  68. self.browser.snapshot("issue details pii tooltips", desktop_only=True)
  69. def test_cocoa_event(self):
  70. event = self.create_sample_event(platform="cocoa")
  71. self.page.visit_issue(self.org.slug, event.group.id)
  72. self.browser.snapshot("issue details cocoa", desktop_only=True)
  73. def test_cocoa_event_frame_line_hover(self):
  74. event = self.create_sample_event(platform="cocoa")
  75. self.page.visit_issue(self.org.slug, event.group.id)
  76. self.browser.wait_until_not(".loading")
  77. self.browser.move_to(".traceback li:nth-child(2)")
  78. self.browser.snapshot("issue details cocoa frame line hover", desktop_only=True)
  79. def test_unity_event(self):
  80. event = self.create_sample_event(default="unity", platform="csharp")
  81. self.page.visit_issue(self.org.slug, event.group.id)
  82. self.browser.snapshot("issue details unity", desktop_only=True)
  83. def test_android_event(self):
  84. event = self.create_sample_event(platform="android")
  85. self.page.visit_issue(self.org.slug, event.group.id)
  86. self.browser.snapshot("issue details android", desktop_only=True)
  87. def test_android_ndk_event(self):
  88. event = self.create_sample_event(default="android-ndk", platform="android-ndk")
  89. self.page.visit_issue(self.org.slug, event.group.id)
  90. self.browser.snapshot("issue details android-ndk", desktop_only=True)
  91. def test_aspnetcore_event(self):
  92. event = self.create_sample_event(default="aspnetcore", platform="csharp")
  93. self.page.visit_issue(self.org.slug, event.group.id)
  94. self.browser.snapshot("issue details aspnetcore", desktop_only=True)
  95. def test_javascript_specific_event(self):
  96. event = self.create_sample_event(platform="javascript")
  97. self.page.visit_issue(self.org.slug, event.group.id)
  98. self.browser.snapshot("issue details javascript - event details", desktop_only=True)
  99. self.browser.click('label[data-test-id="curl"]')
  100. self.browser.snapshot(
  101. "issue details javascript - event details - curl command", desktop_only=True
  102. )
  103. def test_rust_event(self):
  104. # TODO: This should become its own "rust" platform type
  105. event = self.create_sample_event(platform="native", sample_name="Rust")
  106. self.page.visit_issue(self.org.slug, event.group.id)
  107. self.browser.snapshot("issue details rust", desktop_only=True)
  108. def test_cordova_event(self):
  109. event = self.create_sample_event(platform="cordova")
  110. self.page.visit_issue(self.org.slug, event.group.id)
  111. self.browser.snapshot("issue details cordova", desktop_only=True)
  112. def test_stripped_event(self):
  113. event = self.create_sample_event(platform="pii")
  114. self.page.visit_issue(self.org.slug, event.group.id)
  115. self.browser.snapshot("issue details pii stripped", desktop_only=True)
  116. def test_empty_exception(self):
  117. event = self.create_sample_event(platform="empty-exception")
  118. self.page.visit_issue(self.org.slug, event.group.id)
  119. self.browser.snapshot("issue details empty exception", desktop_only=True)
  120. def test_empty_stacktrace(self):
  121. event = self.create_sample_event(platform="empty-stacktrace")
  122. self.page.visit_issue(self.org.slug, event.group.id)
  123. self.browser.snapshot("issue details empty stacktrace", desktop_only=True)
  124. def test_invalid_interfaces(self):
  125. event = self.create_sample_event(platform="invalid-interfaces")
  126. self.page.visit_issue(self.org.slug, event.group.id)
  127. self.browser.click('[data-test-id="event-error-alert"]')
  128. self.browser.wait_until_test_id("event-error-details")
  129. self.browser.snapshot("issue details invalid interfaces", desktop_only=True)
  130. def test_activity_page(self):
  131. event = self.create_sample_event(platform="python")
  132. self.page.visit_issue(self.org.slug, event.group.id)
  133. self.page.go_to_subtab("activity")
  134. self.browser.wait_until_test_id("activity-item")
  135. self.browser.blur()
  136. self.browser.snapshot("issue activity python", desktop_only=True)
  137. def test_resolved(self):
  138. event = self.create_sample_event(platform="python")
  139. self.page.visit_issue(self.org.slug, event.group.id)
  140. self.page.resolve_issue()
  141. self.browser.snapshot("issue details resolved", desktop_only=True)
  142. def test_ignored(self):
  143. event = self.create_sample_event(platform="python")
  144. self.page.visit_issue(self.org.slug, event.group.id)
  145. self.page.ignore_issue()
  146. self.browser.snapshot("issue details ignored", desktop_only=True)
  147. def test_exception_and_no_threads_event(self):
  148. event = self.create_sample_event(platform="exceptions-and-no-threads")
  149. self.page.visit_issue(self.org.slug, event.group.id)
  150. self.browser.snapshot("issue details exceptions and no threads", desktop_only=True)
  151. def test_exception_with_stack_trace_and_crashed_thread_without_stack_trace_event(self):
  152. event = self.create_sample_event(
  153. platform="exception-with-stack-trace-and-crashed-thread-without-stack-trace"
  154. )
  155. self.page.visit_issue(self.org.slug, event.group.id)
  156. self.browser.snapshot(
  157. "issue details exception with stack trace and crashed thread without stack trace",
  158. desktop_only=True,
  159. )
  160. def test_exception_without_stack_trace_and_crashed_thread_with_stack_trace_event(self):
  161. event = self.create_sample_event(
  162. platform="exception-without-stack-trace-and-crashed-thread-with-stack-trace"
  163. )
  164. self.page.visit_issue(self.org.slug, event.group.id)
  165. self.browser.snapshot(
  166. "issue details exception without stack trace and crashed thread with stack trace",
  167. desktop_only=True,
  168. )
  169. def test_exception_with_stack_trace_and_crashed_thread_with_stack_trace_event(self):
  170. event = self.create_sample_event(
  171. platform="exception-with-stack-trace-and-crashed-thread-with-stack-trace"
  172. )
  173. self.page.visit_issue(self.org.slug, event.group.id)
  174. self.browser.snapshot(
  175. "issue details exception with stack trace and crashed thread with stack trace",
  176. desktop_only=True,
  177. )
  178. def test_python_invalid_json_error(self):
  179. event = self.create_sample_event(default="python-invalid-json-error", platform="native")
  180. self.page.visit_issue(self.org.slug, event.group.id)
  181. self.browser.snapshot("issue details invalid json error exception", desktop_only=True)
  182. def test_exception_with_address_instruction(self):
  183. event = self.create_sample_event(
  184. default="exception-with-address-instruction", platform="cocoa"
  185. )
  186. self.page.visit_issue(self.org.slug, event.group.id)
  187. self.browser.snapshot("issue details exception with address instruction", desktop_only=True)