123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- from unittest import skipIf
- from django.conf import settings
- from django.test import TestCase
- from django.urls import reverse
- from django.utils import timezone
- from djstripe.enums import BillingScheme
- from freezegun import freeze_time
- from model_bakery import baker
- class SubscriptionAPITestCase(TestCase):
- @classmethod
- def setUpTestData(cls):
- cls.user = baker.make("users.user")
- cls.organization = baker.make("organizations_ext.Organization")
- cls.organization.add_user(cls.user)
- cls.url = reverse("api:create_subscription")
- def setUp(self):
- self.client.force_login(self.user)
- def test_detail(self):
- customer = baker.make("djstripe.Customer", subscriber=self.organization)
- subscription = baker.make(
- "djstripe.Subscription",
- status="active",
- customer=customer,
- livemode=False,
- created=timezone.make_aware(timezone.datetime(2020, 1, 2)),
- )
- # Should get most recent
- baker.make(
- "djstripe.Subscription",
- status="active",
- customer=customer,
- livemode=False,
- created=timezone.make_aware(timezone.datetime(2020, 1, 1)),
- )
- # should not get canceled subscriptions
- baker.make(
- "djstripe.Subscription",
- status="canceled",
- customer=customer,
- livemode=False,
- created=timezone.make_aware(timezone.datetime(2020, 1, 3)),
- )
- baker.make("djstripe.Subscription")
- url = reverse("api:get_subscription", args=[self.organization.slug])
- res = self.client.get(url)
- self.assertContains(res, subscription.id)
- def test_events_count(self):
- """
- Event count should be accurate and work when there are multiple subscriptions for a given customer
- """
- customer = baker.make("djstripe.Customer", subscriber=self.organization)
- baker.make(
- "djstripe.Subscription",
- customer=customer,
- livemode=False,
- current_period_start=timezone.make_aware(timezone.datetime(2020, 1, 2)),
- current_period_end=timezone.make_aware(timezone.datetime(2020, 2, 2)),
- )
- baker.make(
- "djstripe.Subscription",
- customer=customer,
- livemode=False,
- status="Cancelled",
- current_period_start=timezone.make_aware(timezone.datetime(2019, 1, 2)),
- current_period_end=timezone.make_aware(timezone.datetime(2019, 2, 2)),
- )
- url = reverse(
- "api:get_subscription_events_count", args=[self.organization.slug]
- )
- with freeze_time(timezone.datetime(2020, 3, 1)):
- baker.make(
- "issue_events.IssueEvent",
- issue__project__organization=self.organization,
- )
- with freeze_time(timezone.datetime(2020, 1, 5)):
- baker.make("issue_events.IssueEvent")
- baker.make(
- "issue_events.IssueEvent",
- issue__project__organization=self.organization,
- )
- baker.make(
- "projects.IssueEventProjectHourlyStatistic",
- project__organization=self.organization,
- count=1,
- )
- baker.make(
- "performance.TransactionEvent",
- group__project__organization=self.organization,
- )
- baker.make(
- "projects.TransactionEventProjectHourlyStatistic",
- project__organization=self.organization,
- count=1,
- )
- baker.make(
- "releases.ReleaseFile",
- file__blob__size=1000000,
- release__organization=self.organization,
- _quantity=2,
- )
- res = self.client.get(url)
- self.assertEqual(
- res.json(),
- {
- "eventCount": 1,
- "fileSizeMB": 2,
- "transactionEventCount": 1,
- "uptimeCheckEventCount": 0,
- },
- )
- def test_events_count_without_customer(self):
- """
- Due to async nature of Stripe integration, a customer may not exist
- """
- baker.make("djstripe.Subscription", livemode=False)
- url = reverse(
- "api:get_subscription_events_count", args=[self.organization.slug]
- )
- res = self.client.get(url)
- self.assertEqual(sum(res.json().values()), 0)
- @skipIf(
- settings.STRIPE_TEST_PUBLIC_KEY == "fake", "requires real Stripe test API key"
- )
- def test_create_free(self):
- """
- Users should not be able to create a free subscription if they have another non-canceled subscription
- """
- price = baker.make(
- "djstripe.Price",
- unit_amount=0,
- id="price_1KO6e1J4NuO0bv3IEXhpWpzt",
- billing_scheme=BillingScheme.per_unit,
- )
- baker.make("djstripe.Product", id="prod_L4F8CtH20Oad6S", default_price=price)
- data = {"price": price.id, "organization": self.organization.id}
- res = self.client.post(self.url, data, content_type="application/json")
- self.assertEqual(res.json()["price"], price.id)
- # Second attempt should fail
- res = self.client.post(self.url, data)
- self.assertEqual(res.status_code, 400)
- def test_create_invalid_org(self):
- """Only owners may create subscriptions"""
- user = baker.make("users.user") # Non owner member
- plan = baker.make("djstripe.Plan", amount=0)
- self.organization.add_user(user)
- self.client.force_login(user)
- data = {"plan": plan.id, "organization": self.organization.id}
- res = self.client.post(self.url, data)
- self.assertEqual(res.status_code, 400)
- class ProductAPITestCase(TestCase):
- def test_product_list(self):
- price = baker.make(
- "djstripe.Price",
- unit_amount=0,
- billing_scheme=BillingScheme.per_unit,
- active=True,
- product__active=True,
- product__livemode=False,
- product__metadata={"events": 10, "is_public": "true"},
- )
- inactive_price = baker.make(
- "djstripe.Price",
- unit_amount=0,
- billing_scheme=BillingScheme.per_unit,
- active=False,
- product__active=False,
- product__livemode=False,
- product__metadata={"events": 10, "is_public": "true"},
- )
- hidden_price = baker.make(
- "djstripe.Price",
- unit_amount=0,
- billing_scheme=BillingScheme.per_unit,
- active=True,
- product__active=True,
- product__livemode=False,
- product__metadata={"events": 10, "is_public": "false"},
- )
- user = baker.make("users.user")
- self.client.force_login(user)
- res = self.client.get(reverse("api:list_products"))
- self.assertContains(res, price.id)
- self.assertNotContains(res, inactive_price.id)
- self.assertNotContains(res, hidden_price.id)
- # Price ID must be from a real price actually set up on Stripe Test account
- class StripeAPITestCase(TestCase):
- @skipIf(
- settings.STRIPE_TEST_PUBLIC_KEY == "fake", "requires real Stripe test API key"
- )
- def test_create_checkout(self):
- price = baker.make(
- "djstripe.Price",
- id="price_1MZhMWJ4NuO0bv3IGMoDoFFI",
- )
- user = baker.make("users.user")
- organization = baker.make("organizations_ext.Organization")
- organization.add_user(user)
- url = reverse(
- "api:create_stripe_subscription_checkout", args=[organization.slug]
- )
- self.client.force_login(user)
- data = {"price": price.id}
- res = self.client.post(url, data, content_type="application/json")
- self.assertEqual(res.status_code, 200)
- @skipIf(
- settings.STRIPE_TEST_PUBLIC_KEY == "fake", "requires real Stripe test API key"
- )
- def test_manage_billing(self):
- user = baker.make("users.user")
- organization = baker.make("organizations_ext.Organization")
- url = reverse("api:stripe_billing_portal", args=[organization.slug])
- organization.add_user(user)
- self.client.force_login(user)
- data = {"organization": organization.id}
- res = self.client.post(url, data)
- self.assertEqual(res.status_code, 200)
|