Browse Source

Adding tests to hc.payments

pull/25/merge
Pēteris Caune 9 years ago
parent
commit
7b98cf23a4
8 changed files with 144 additions and 65 deletions
  1. +1
    -0
      hc/front/views.py
  2. +13
    -43
      hc/payments/models.py
  3. +0
    -3
      hc/payments/tests.py
  4. +0
    -0
      hc/payments/tests/__init__.py
  5. +67
    -0
      hc/payments/tests/test_create_plan.py
  6. +23
    -0
      hc/payments/tests/test_get_client_token.py
  7. +27
    -0
      hc/payments/tests/test_pricing.py
  8. +13
    -19
      hc/payments/views.py

+ 1
- 0
hc/front/views.py View File

@ -278,6 +278,7 @@ def add_channel(request):
assert request.method == "POST" assert request.method == "POST"
return do_add_channel(request, request.POST) return do_add_channel(request, request.POST)
@login_required @login_required
@uuid_or_400 @uuid_or_400
def channel_checks(request, code): def channel_checks(request, code):


+ 13
- 43
hc/payments/models.py View File

@ -1,8 +1,19 @@
import braintree
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db import models from django.db import models
class SubscriptionManager(models.Manager):
def for_user(self, user):
try:
sub = self.get(user_id=user.id)
except Subscription.DoesNotExist:
sub = Subscription(user=user)
sub.save()
return sub
class Subscription(models.Model): class Subscription(models.Model):
user = models.OneToOneField(User, blank=True, null=True) user = models.OneToOneField(User, blank=True, null=True)
customer_id = models.CharField(max_length=36, blank=True) customer_id = models.CharField(max_length=36, blank=True)
@ -10,24 +21,7 @@ class Subscription(models.Model):
subscription_id = models.CharField(max_length=10, blank=True) subscription_id = models.CharField(max_length=10, blank=True)
plan_id = models.CharField(max_length=10, blank=True) plan_id = models.CharField(max_length=10, blank=True)
def _get_braintree_sub(self):
if not hasattr(self, "_sub"):
self._sub = braintree.Subscription.find(self.subscription_id)
return self._sub
def _get_braintree_payment_method(self):
if not hasattr(self, "_pm"):
self._pm = braintree.PaymentMethod.find(self.payment_method_token)
return self._pm
def is_active(self):
if not self.subscription_id:
return False
o = self._get_braintree_sub()
return o.status == "Active"
objects = SubscriptionManager()
def price(self): def price(self):
if self.plan_id == "P5": if self.plan_id == "P5":
@ -36,27 +30,3 @@ class Subscription(models.Model):
return 20 return 20
return 0 return 0
def next_billing_date(self):
o = self._get_braintree_sub()
return o.next_billing_date
def pm_is_credit_card(self):
return isinstance(self._get_braintree_payment_method(),
braintree.credit_card.CreditCard)
def pm_is_paypal(self):
return isinstance(self._get_braintree_payment_method(),
braintree.paypal_account.PayPalAccount)
def card_type(self):
o = self._get_braintree_payment_method()
return o.card_type
def last_4(self):
o = self._get_braintree_payment_method()
return o.last_4
def paypal_email(self):
o = self._get_braintree_payment_method()
return o.email

+ 0
- 3
hc/payments/tests.py View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

+ 0
- 0
hc/payments/tests/__init__.py View File


+ 67
- 0
hc/payments/tests/test_create_plan.py View File

@ -0,0 +1,67 @@
from django.contrib.auth.models import User
from django.test import TestCase
from hc.accounts.models import Profile
from hc.payments.models import Subscription
from mock import patch
class CreatePlanTestCase(TestCase):
def setUp(self):
self.alice = User(username="alice")
self.alice.set_password("password")
self.alice.save()
def _setup_mock(self, mock):
""" Set up Braintree calls that the controller will use. """
mock.Customer.create.return_value.is_success = True
mock.Customer.create.return_value.customer.id = "test-customer-id"
mock.PaymentMethod.create.return_value.is_success = True
mock.PaymentMethod.create.return_value.payment_method.token = "t-token"
mock.Subscription.create.return_value.is_success = True
mock.Subscription.create.return_value.subscription.id = "t-sub-id"
def run_create_plan(self, plan_id="P5"):
form = {"plan_id": plan_id, "payment_method_nonce": "test-nonce"}
self.client.login(username="alice", password="password")
return self.client.post("/pricing/create_plan/", form)
@patch("hc.payments.views.braintree")
def test_it_works(self, mock):
self._setup_mock(mock)
r = self.run_create_plan()
self.assertEqual(r.status_code, 302)
# Subscription should be filled out:
sub = Subscription.objects.get(user=self.alice)
self.assertEqual(sub.customer_id, "test-customer-id")
self.assertEqual(sub.payment_method_token, "t-token")
self.assertEqual(sub.subscription_id, "t-sub-id")
self.assertEqual(sub.plan_id, "P5")
# User's profile should have a higher ping log limit:
profile = Profile.objects.get(user=self.alice)
self.assertEqual(profile.ping_log_limit, 1000)
# braintree.Subscription.cancel should have not been called
assert not mock.Subscription.cancel.called
def test_bad_plan_id(self):
r = self.run_create_plan(plan_id="this-is-wrong")
self.assertEqual(r.status_code, 400)
@patch("hc.payments.views.braintree")
def test_it_cancels_previous_subscription(self, mock):
self._setup_mock(mock)
sub = Subscription(user=self.alice)
sub.subscription_id = "prev-sub"
sub.save()
r = self.run_create_plan()
self.assertEqual(r.status_code, 302)
assert mock.Subscription.cancel.called

+ 23
- 0
hc/payments/tests/test_get_client_token.py View File

@ -0,0 +1,23 @@
from django.contrib.auth.models import User
from django.test import TestCase
from hc.payments.models import Subscription
from mock import patch
class GetClientTokenTestCase(TestCase):
def setUp(self):
self.alice = User(username="alice")
self.alice.set_password("password")
self.alice.save()
@patch("hc.payments.views.braintree")
def test_it_works(self, mock_braintree):
mock_braintree.ClientToken.generate.return_value = "test-token"
self.client.login(username="alice", password="password")
r = self.client.get("/pricing/get_client_token/")
self.assertContains(r, "test-token", status_code=200)
# A subscription object should have been created
assert Subscription.objects.count() == 1

+ 27
- 0
hc/payments/tests/test_pricing.py View File

@ -0,0 +1,27 @@
from django.contrib.auth.models import User
from django.test import TestCase
from hc.payments.models import Subscription
class PricingTestCase(TestCase):
def setUp(self):
self.alice = User(username="alice")
self.alice.set_password("password")
self.alice.save()
def test_anonymous(self):
r = self.client.get("/pricing/")
self.assertContains(r, "Unlimited Checks", status_code=200)
# A subscription object should have NOT been created
assert Subscription.objects.count() == 0
def test_authenticated(self):
self.client.login(username="alice", password="password")
r = self.client.get("/pricing/")
self.assertContains(r, "Unlimited Checks", status_code=200)
# A subscription object should have been created
assert Subscription.objects.count() == 1

+ 13
- 19
hc/payments/views.py View File

@ -1,17 +1,18 @@
import braintree import braintree
from django.contrib.auth.decorators import login_required
from django.contrib import messages from django.contrib import messages
from django.http import HttpResponseForbidden, JsonResponse
from django.contrib.auth.decorators import login_required
from django.http import (HttpResponseBadRequest, HttpResponseForbidden,
JsonResponse)
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
from hc.accounts.models import Profile from hc.accounts.models import Profile
from .models import Subscription from .models import Subscription
@login_required @login_required
def get_client_token(request): def get_client_token(request):
sub = Subscription.objects.get(user=request.user)
sub = Subscription.objects.for_user(request.user)
client_token = braintree.ClientToken.generate({ client_token = braintree.ClientToken.generate({
"customer_id": sub.customer_id "customer_id": sub.customer_id
}) })
@ -22,21 +23,12 @@ def get_client_token(request):
def pricing(request): def pricing(request):
sub = None sub = None
if request.user.is_authenticated(): if request.user.is_authenticated():
try:
sub = Subscription.objects.get(user=request.user)
except Subscription.DoesNotExist:
sub = Subscription(user=request.user)
sub.save()
first_charge = False
if "first_charge" in request.session:
first_charge = True
del request.session["first_charge"]
sub = Subscription.objects.for_user(request.user)
ctx = { ctx = {
"page": "pricing", "page": "pricing",
"sub": sub, "sub": sub,
"first_charge": first_charge
"first_charge": request.session.pop("first_charge", False)
} }
return render(request, "payments/pricing.html", ctx) return render(request, "payments/pricing.html", ctx)
@ -55,9 +47,10 @@ def log_and_bail(request, result):
@require_POST @require_POST
def create_plan(request): def create_plan(request):
plan_id = request.POST["plan_id"] plan_id = request.POST["plan_id"]
assert plan_id in ("P5", "P20")
if plan_id not in ("P5", "P20"):
return HttpResponseBadRequest()
sub = Subscription.objects.get(user=request.user)
sub = Subscription.objects.for_user(request.user)
# Cancel the previous plan # Cancel the previous plan
if sub.subscription_id: if sub.subscription_id:
@ -133,9 +126,10 @@ def cancel_plan(request):
def billing(request): def billing(request):
sub = Subscription.objects.get(user=request.user) sub = Subscription.objects.get(user=request.user)
transactions = braintree.Transaction.search(braintree.TransactionSearch.customer_id == sub.customer_id)
ctx = {"transactions": transactions}
transactions = braintree.Transaction.search(
braintree.TransactionSearch.customer_id == sub.customer_id)
ctx = {"transactions": transactions}
return render(request, "payments/billing.html", ctx) return render(request, "payments/billing.html", ctx)


Loading…
Cancel
Save