tests.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. from unittest.mock import patch
  2. from unittest import skipIf
  3. from django.shortcuts import reverse
  4. from django.conf import settings
  5. from django.utils import timezone
  6. from rest_framework.test import APITestCase
  7. from model_bakery import baker
  8. from freezegun import freeze_time
  9. from glitchtip import test_utils # pylint: disable=unused-import
  10. class SubscriptionAPITestCase(APITestCase):
  11. def setUp(self):
  12. self.user = baker.make("users.user")
  13. self.organization = baker.make("organizations_ext.Organization")
  14. self.organization.add_user(self.user)
  15. self.client.force_login(self.user)
  16. self.url = reverse("subscription-list")
  17. def test_list(self):
  18. customer = baker.make("djstripe.Customer", subscriber=self.organization)
  19. subscription = baker.make(
  20. "djstripe.Subscription", customer=customer, livemode=False
  21. )
  22. subscription2 = baker.make("djstripe.Subscription", livemode=False)
  23. subscription3 = baker.make(
  24. "djstripe.Subscription", customer=customer, livemode=True
  25. )
  26. res = self.client.get(self.url)
  27. self.assertContains(res, subscription.id)
  28. self.assertNotContains(res, subscription2.id)
  29. self.assertNotContains(res, subscription3.id)
  30. def test_detail(self):
  31. customer = baker.make("djstripe.Customer", subscriber=self.organization)
  32. subscription = baker.make(
  33. "djstripe.Subscription",
  34. customer=customer,
  35. livemode=False,
  36. created=timezone.make_aware(timezone.datetime(2020, 1, 2)),
  37. )
  38. # Should only get most recent
  39. baker.make(
  40. "djstripe.Subscription",
  41. customer=customer,
  42. livemode=False,
  43. created=timezone.make_aware(timezone.datetime(2020, 1, 1)),
  44. )
  45. baker.make("djstripe.Subscription")
  46. url = reverse("subscription-detail", args=[self.organization.slug])
  47. res = self.client.get(url)
  48. self.assertContains(res, subscription.id)
  49. def test_events_count(self):
  50. """
  51. Event count should be accurate and work when there are multiple subscriptions for a given customer
  52. """
  53. customer = baker.make("djstripe.Customer", subscriber=self.organization)
  54. baker.make(
  55. "djstripe.Subscription",
  56. customer=customer,
  57. livemode=False,
  58. current_period_start=timezone.make_aware(timezone.datetime(2020, 1, 2)),
  59. current_period_end=timezone.make_aware(timezone.datetime(2020, 2, 2)),
  60. )
  61. baker.make(
  62. "djstripe.Subscription",
  63. customer=customer,
  64. livemode=False,
  65. status="Cancelled",
  66. current_period_start=timezone.make_aware(timezone.datetime(2019, 1, 2)),
  67. current_period_end=timezone.make_aware(timezone.datetime(2019, 2, 2)),
  68. )
  69. url = (
  70. reverse("subscription-detail", args=[self.organization.slug])
  71. + "events_count/"
  72. )
  73. with freeze_time(timezone.datetime(2020, 3, 1)):
  74. baker.make("events.Event", issue__project__organization=self.organization)
  75. with freeze_time(timezone.datetime(2020, 1, 5)):
  76. baker.make("events.Event")
  77. baker.make("events.Event", issue__project__organization=self.organization)
  78. baker.make(
  79. "performance.TransactionEvent",
  80. group__project__organization=self.organization,
  81. )
  82. baker.make(
  83. "releases.ReleaseFile",
  84. file__blob__size=1000000,
  85. release__organization=self.organization,
  86. _quantity=2,
  87. )
  88. res = self.client.get(url)
  89. self.assertEqual(
  90. res.data,
  91. {
  92. "eventCount": 1,
  93. "fileSizeMB": 2,
  94. "transactionEventCount": 1,
  95. "uptimeCheckEventCount": 0,
  96. },
  97. )
  98. def test_events_count_without_customer(self):
  99. """
  100. Due to async nature of Stripe integration, a customer may not exist
  101. """
  102. baker.make("djstripe.Subscription", livemode=False)
  103. url = (
  104. reverse("subscription-detail", args=[self.organization.slug])
  105. + "events_count/"
  106. )
  107. res = self.client.get(url)
  108. self.assertEqual(sum(res.data.values()), 0)
  109. @patch("djstripe.models.Customer.subscribe")
  110. def test_create(self, djstripe_customer_subscribe_mock):
  111. customer = baker.make(
  112. "djstripe.Customer", subscriber=self.organization, livemode=False
  113. )
  114. plan = baker.make("djstripe.Plan", amount=0)
  115. subscription = baker.make(
  116. "djstripe.Subscription",
  117. customer=customer,
  118. livemode=False,
  119. )
  120. djstripe_customer_subscribe_mock.return_value = subscription
  121. data = {"plan": plan.id, "organization": self.organization.id}
  122. res = self.client.post(self.url, data)
  123. self.assertEqual(res.data["plan"], plan.id)
  124. def test_create_invalid_org(self):
  125. """Only owners may create subscriptions"""
  126. user = baker.make("users.user") # Non owner member
  127. plan = baker.make("djstripe.Plan", amount=0)
  128. self.organization.add_user(user)
  129. self.client.force_login(user)
  130. data = {"plan": plan.id, "organization": self.organization.id}
  131. res = self.client.post(self.url, data)
  132. self.assertEqual(res.status_code, 400)
  133. class ProductAPITestCase(APITestCase):
  134. def test_product_list(self):
  135. plan = baker.make(
  136. "djstripe.Plan",
  137. amount=0,
  138. livemode=False,
  139. active=True,
  140. product__active=True,
  141. product__livemode=False,
  142. product__metadata={"events": 10, "is_public": "true"},
  143. )
  144. inactive_plan = baker.make(
  145. "djstripe.Plan",
  146. amount=0,
  147. livemode=False,
  148. active=False,
  149. product__active=False,
  150. product__livemode=False,
  151. product__metadata={"events": 10, "is_public": "true"},
  152. )
  153. hidden_plan = baker.make(
  154. "djstripe.Plan",
  155. amount=0,
  156. livemode=False,
  157. active=True,
  158. product__active=True,
  159. product__livemode=False,
  160. product__metadata={"events": 10, "is_public": "false"},
  161. )
  162. user = baker.make("users.user")
  163. self.client.force_login(user)
  164. res = self.client.get(reverse("product-list"))
  165. self.assertContains(res, plan.id)
  166. self.assertNotContains(res, inactive_plan.id)
  167. self.assertNotContains(res, hidden_plan.id)
  168. class StripeAPITestCase(APITestCase):
  169. @skipIf(
  170. settings.STRIPE_TEST_PUBLIC_KEY == "fake", "requires real Stripe test API key"
  171. )
  172. def test_create_checkout(self):
  173. url = reverse("create-stripe-subscription-checkout")
  174. plan = baker.make(
  175. "djstripe.Plan",
  176. amount=1,
  177. livemode=False,
  178. active=True,
  179. id="price_HNfVNr3ohLWkmv",
  180. description="Small - 100k events",
  181. product__active=True,
  182. product__livemode=False,
  183. )
  184. user = baker.make("users.user")
  185. organization = baker.make("organizations_ext.Organization")
  186. organization.add_user(user)
  187. self.client.force_login(user)
  188. data = {"plan": plan.id, "organization": organization.id}
  189. res = self.client.post(url, data)
  190. self.assertEqual(res.status_code, 200)
  191. @skipIf(
  192. settings.STRIPE_TEST_PUBLIC_KEY == "fake", "requires real Stripe test API key"
  193. )
  194. def test_manage_billing(self):
  195. url = reverse("create-billing-portal")
  196. user = baker.make("users.user")
  197. organization = baker.make("organizations_ext.Organization")
  198. organization.add_user(user)
  199. self.client.force_login(user)
  200. data = {"organization": organization.id}
  201. res = self.client.post(url, data)
  202. self.assertEqual(res.status_code, 200)
  203. class SubscriptionIntegrationAPITestCase(APITestCase):
  204. def setUp(self):
  205. self.user = baker.make("users.user")
  206. self.organization = baker.make("organizations_ext.Organization")
  207. self.organization.add_user(self.user)
  208. # Make these in this manner to avoid syncing data to stripe actual
  209. self.plan = baker.make("djstripe.Plan", active=True, amount=0)
  210. self.customer = baker.make(
  211. "djstripe.Customer", subscriber=self.organization, livemode=False
  212. )
  213. self.client.force_login(self.user)
  214. self.list_url = reverse("subscription-list")
  215. self.detail_url = reverse("subscription-detail", args=[self.organization.slug])
  216. @patch("djstripe.models.Customer.subscribe")
  217. def test_new_org_flow(self, djstripe_customer_subscribe_mock):
  218. """Test checking if subscription exists and when not, creating a free tier one"""
  219. res = self.client.get(self.detail_url)
  220. self.assertFalse(res.data["id"]) # No subscription, user should create one
  221. subscription = baker.make(
  222. "djstripe.Subscription",
  223. customer=self.customer,
  224. livemode=False,
  225. )
  226. djstripe_customer_subscribe_mock.return_value = subscription
  227. data = {"plan": self.plan.id, "organization": self.organization.id}
  228. res = self.client.post(self.list_url, data)
  229. self.assertContains(res, self.plan.id, status_code=201)
  230. djstripe_customer_subscribe_mock.assert_called_once()
  231. res = self.client.get(self.detail_url)
  232. self.assertEqual(res.data["id"], subscription.id)