test_onboarding.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. from django.utils import timezone
  2. from sentry.models import (
  3. OnboardingTask,
  4. OnboardingTaskStatus,
  5. OrganizationOnboardingTask,
  6. OrganizationOption,
  7. Rule,
  8. )
  9. from sentry.plugins.bases import IssueTrackingPlugin
  10. from sentry.signals import (
  11. alert_rule_created,
  12. event_processed,
  13. first_event_pending,
  14. first_event_received,
  15. first_transaction_received,
  16. issue_tracker_used,
  17. member_invited,
  18. member_joined,
  19. plugin_enabled,
  20. project_created,
  21. )
  22. from sentry.testutils import TestCase
  23. from sentry.testutils.helpers.datetime import before_now, iso_format
  24. from sentry.utils.samples import load_data
  25. class OrganizationOnboardingTaskTest(TestCase):
  26. def test_no_existing_task(self):
  27. now = timezone.now()
  28. project = self.create_project(first_event=now)
  29. event = self.store_event(data={}, project_id=project.id)
  30. first_event_received.send(project=project, event=event, sender=type(project))
  31. task = OrganizationOnboardingTask.objects.get(
  32. organization=project.organization, task=OnboardingTask.FIRST_EVENT
  33. )
  34. assert task.status == OnboardingTaskStatus.COMPLETE
  35. assert task.project_id == project.id
  36. assert task.date_completed == project.first_event
  37. def test_existing_pending_task(self):
  38. now = timezone.now()
  39. project = self.create_project(first_event=now)
  40. first_event_pending.send(project=project, user=self.user, sender=type(project))
  41. task = OrganizationOnboardingTask.objects.get(
  42. organization=project.organization, task=OnboardingTask.FIRST_EVENT
  43. )
  44. assert task.status == OnboardingTaskStatus.PENDING
  45. assert task.project_id == project.id
  46. event = self.store_event(data={}, project_id=project.id)
  47. first_event_received.send(project=project, event=event, sender=type(project))
  48. task = OrganizationOnboardingTask.objects.get(
  49. organization=project.organization, task=OnboardingTask.FIRST_EVENT
  50. )
  51. assert task.status == OnboardingTaskStatus.COMPLETE
  52. assert task.project_id == project.id
  53. assert task.date_completed == project.first_event
  54. def test_existing_complete_task(self):
  55. now = timezone.now()
  56. project = self.create_project(first_event=now)
  57. task = OrganizationOnboardingTask.objects.create(
  58. organization=project.organization,
  59. task=OnboardingTask.FIRST_PROJECT,
  60. status=OnboardingTaskStatus.COMPLETE,
  61. )
  62. event = self.store_event(data={}, project_id=project.id)
  63. first_event_received.send(project=project, event=event, sender=type(project))
  64. task = OrganizationOnboardingTask.objects.get(id=task.id)
  65. assert task.status == OnboardingTaskStatus.COMPLETE
  66. assert not task.project_id
  67. # Tests on the receivers
  68. def test_event_processed(self):
  69. now = timezone.now()
  70. project = self.create_project(first_event=now)
  71. event = self.store_event(
  72. data={
  73. "event_id": "a" * 32,
  74. "platform": "javascript",
  75. "timestamp": iso_format(before_now(minutes=1)),
  76. "tags": {
  77. "sentry:release": "e1b5d1900526feaf20fe2bc9cad83d392136030a",
  78. "sentry:user": "id:41656",
  79. },
  80. "user": {"ip_address": "0.0.0.0", "id": "41656", "email": "test@example.com"},
  81. "exception": {
  82. "values": [
  83. {
  84. "stacktrace": {
  85. "frames": [
  86. {
  87. "data": {
  88. "sourcemap": "https://media.sentry.io/_static/29e365f8b0d923bc123e8afa38d890c3/sentry/dist/vendor.js.map"
  89. }
  90. }
  91. ]
  92. },
  93. "type": "TypeError",
  94. }
  95. ]
  96. },
  97. },
  98. project_id=project.id,
  99. )
  100. event_processed.send(project=project, event=event, sender=type(project))
  101. task = OrganizationOnboardingTask.objects.get(
  102. organization=project.organization,
  103. task=OnboardingTask.RELEASE_TRACKING,
  104. status=OnboardingTaskStatus.COMPLETE,
  105. )
  106. assert task is not None
  107. task = OrganizationOnboardingTask.objects.get(
  108. organization=project.organization,
  109. task=OnboardingTask.USER_CONTEXT,
  110. status=OnboardingTaskStatus.COMPLETE,
  111. )
  112. assert task is not None
  113. task = OrganizationOnboardingTask.objects.get(
  114. organization=project.organization,
  115. task=OnboardingTask.SOURCEMAPS,
  116. status=OnboardingTaskStatus.COMPLETE,
  117. )
  118. assert task is not None
  119. def test_project_created(self):
  120. now = timezone.now()
  121. project = self.create_project(first_event=now)
  122. project_created.send(project=project, user=self.user, sender=type(project))
  123. task = OrganizationOnboardingTask.objects.get(
  124. organization=project.organization,
  125. task=OnboardingTask.FIRST_PROJECT,
  126. status=OnboardingTaskStatus.COMPLETE,
  127. )
  128. assert task is not None
  129. def test_first_event_pending(self):
  130. now = timezone.now()
  131. project = self.create_project(first_event=now)
  132. first_event_pending.send(project=project, user=self.user, sender=type(project))
  133. task = OrganizationOnboardingTask.objects.get(
  134. organization=project.organization,
  135. task=OnboardingTask.FIRST_EVENT,
  136. status=OnboardingTaskStatus.PENDING,
  137. )
  138. assert task is not None
  139. def test_first_event_received(self):
  140. now = timezone.now()
  141. project = self.create_project(first_event=now)
  142. project_created.send(project=project, user=self.user, sender=type(project))
  143. event = self.store_event(
  144. data={"platform": "javascript", "message": "javascript error message"},
  145. project_id=project.id,
  146. )
  147. first_event_received.send(project=project, event=event, sender=type(project))
  148. task = OrganizationOnboardingTask.objects.get(
  149. organization=project.organization,
  150. task=OnboardingTask.FIRST_EVENT,
  151. status=OnboardingTaskStatus.COMPLETE,
  152. )
  153. assert task is not None
  154. assert "platform" in task.data
  155. assert task.data["platform"] == "javascript"
  156. second_project = self.create_project(first_event=now)
  157. project_created.send(project=second_project, user=self.user, sender=type(second_project))
  158. second_task = OrganizationOnboardingTask.objects.get(
  159. organization=second_project.organization,
  160. task=OnboardingTask.SECOND_PLATFORM,
  161. status=OnboardingTaskStatus.PENDING,
  162. )
  163. assert second_task is not None
  164. second_event = self.store_event(
  165. data={"platform": "python", "message": "python error message"},
  166. project_id=second_project.id,
  167. )
  168. first_event_received.send(
  169. project=second_project, event=second_event, sender=type(second_project)
  170. )
  171. second_task = OrganizationOnboardingTask.objects.get(
  172. organization=second_project.organization,
  173. task=OnboardingTask.SECOND_PLATFORM,
  174. status=OnboardingTaskStatus.COMPLETE,
  175. )
  176. assert second_task is not None
  177. assert "platform" in second_task.data
  178. assert second_task.data["platform"] == "python"
  179. assert task.data["platform"] != second_task.data["platform"]
  180. def test_first_transaction_received(self):
  181. project = self.create_project()
  182. event_data = load_data("transaction")
  183. min_ago = iso_format(before_now(minutes=1))
  184. event_data.update({"start_timestamp": min_ago, "timestamp": min_ago})
  185. event = self.store_event(data=event_data, project_id=project.id)
  186. first_event_received.send(project=project, event=event, sender=type(project))
  187. first_transaction_received.send(project=project, event=event, sender=type(project))
  188. task = OrganizationOnboardingTask.objects.get(
  189. organization=project.organization,
  190. task=OnboardingTask.FIRST_TRANSACTION,
  191. status=OnboardingTaskStatus.COMPLETE,
  192. )
  193. assert task is not None
  194. assert project.flags.has_transactions
  195. def test_member_invited(self):
  196. user = self.create_user(email="test@example.org")
  197. member = self.create_member(organization=self.organization, teams=[self.team], user=user)
  198. member_invited.send(member=member, user=user, sender=type(member))
  199. task = OrganizationOnboardingTask.objects.get(
  200. organization=self.organization,
  201. task=OnboardingTask.INVITE_MEMBER,
  202. status=OnboardingTaskStatus.PENDING,
  203. )
  204. assert task is not None
  205. def test_member_joined(self):
  206. user = self.create_user(email="test@example.org")
  207. member = self.create_member(organization=self.organization, teams=[self.team], user=user)
  208. member_joined.send(member=member, organization=self.organization, sender=type(member))
  209. task = OrganizationOnboardingTask.objects.get(
  210. organization=self.organization,
  211. task=OnboardingTask.INVITE_MEMBER,
  212. status=OnboardingTaskStatus.COMPLETE,
  213. )
  214. assert task is not None
  215. user2 = self.create_user(email="test@example.com")
  216. member2 = self.create_member(organization=self.organization, teams=[self.team], user=user2)
  217. member_joined.send(member=member2, organization=self.organization, sender=type(member2))
  218. task = OrganizationOnboardingTask.objects.get(
  219. organization=self.organization,
  220. task=OnboardingTask.INVITE_MEMBER,
  221. status=OnboardingTaskStatus.COMPLETE,
  222. )
  223. assert task.data["invited_member_id"] == member.id
  224. def test_issue_tracker_onboarding(self):
  225. plugin_enabled.send(
  226. plugin=IssueTrackingPlugin(),
  227. project=self.project,
  228. user=self.user,
  229. sender=type(IssueTrackingPlugin),
  230. )
  231. task = OrganizationOnboardingTask.objects.get(
  232. organization=self.organization,
  233. task=OnboardingTask.ISSUE_TRACKER,
  234. status=OnboardingTaskStatus.PENDING,
  235. )
  236. assert task is not None
  237. issue_tracker_used.send(
  238. plugin=IssueTrackingPlugin(),
  239. project=self.project,
  240. user=self.user,
  241. sender=type(IssueTrackingPlugin),
  242. )
  243. task = OrganizationOnboardingTask.objects.get(
  244. organization=self.organization,
  245. task=OnboardingTask.ISSUE_TRACKER,
  246. status=OnboardingTaskStatus.COMPLETE,
  247. )
  248. assert task is not None
  249. def test_alert_added(self):
  250. alert_rule_created.send(
  251. rule=Rule(id=1),
  252. project=self.project,
  253. user=self.user,
  254. rule_type="issue",
  255. sender=type(Rule),
  256. is_api_token=False,
  257. )
  258. task = OrganizationOnboardingTask.objects.get(
  259. organization=self.organization,
  260. task=OnboardingTask.ALERT_RULE,
  261. status=OnboardingTaskStatus.COMPLETE,
  262. )
  263. assert task is not None
  264. def test_onboarding_complete(self):
  265. now = timezone.now()
  266. user = self.create_user(email="test@example.org")
  267. project = self.create_project(first_event=now)
  268. second_project = self.create_project(first_event=now)
  269. second_event = self.store_event(
  270. data={"platform": "python", "message": "python error message"},
  271. project_id=second_project.id,
  272. )
  273. event = self.store_event(
  274. data={
  275. "event_id": "a" * 32,
  276. "platform": "javascript",
  277. "timestamp": iso_format(before_now(minutes=1)),
  278. "tags": {
  279. "sentry:release": "e1b5d1900526feaf20fe2bc9cad83d392136030a",
  280. "sentry:user": "id:41656",
  281. },
  282. "user": {"ip_address": "0.0.0.0", "id": "41656", "email": "test@example.com"},
  283. "exception": {
  284. "values": [
  285. {
  286. "stacktrace": {
  287. "frames": [
  288. {
  289. "data": {
  290. "sourcemap": "https://media.sentry.io/_static/29e365f8b0d923bc123e8afa38d890c3/sentry/dist/vendor.js.map"
  291. }
  292. }
  293. ]
  294. },
  295. "type": "TypeError",
  296. }
  297. ]
  298. },
  299. },
  300. project_id=project.id,
  301. )
  302. event_data = load_data("transaction")
  303. min_ago = iso_format(before_now(minutes=1))
  304. event_data.update({"start_timestamp": min_ago, "timestamp": min_ago})
  305. transaction = self.store_event(data=event_data, project_id=project.id)
  306. first_event_received.send(project=project, event=transaction, sender=type(project))
  307. first_transaction_received.send(project=project, event=transaction, sender=type(project))
  308. member = self.create_member(organization=self.organization, teams=[self.team], user=user)
  309. event_processed.send(project=project, event=event, sender=type(project))
  310. project_created.send(project=project, user=user, sender=type(project))
  311. project_created.send(project=second_project, user=user, sender=type(second_project))
  312. first_event_received.send(project=project, event=event, sender=type(project))
  313. first_event_received.send(
  314. project=second_project, event=second_event, sender=type(second_project)
  315. )
  316. member_joined.send(member=member, organization=self.organization, sender=type(member))
  317. plugin_enabled.send(
  318. plugin=IssueTrackingPlugin(),
  319. project=project,
  320. user=user,
  321. sender=type(IssueTrackingPlugin),
  322. )
  323. issue_tracker_used.send(
  324. plugin=IssueTrackingPlugin(),
  325. project=project,
  326. user=user,
  327. sender=type(IssueTrackingPlugin),
  328. )
  329. alert_rule_created.send(
  330. rule=Rule(id=1),
  331. project=self.project,
  332. user=self.user,
  333. rule_type="issue",
  334. sender=type(Rule),
  335. is_api_token=False,
  336. )
  337. assert (
  338. OrganizationOption.objects.filter(
  339. organization=self.organization, key="onboarding:complete"
  340. ).count()
  341. == 1
  342. )