Add basic paypal unit tests.
authorRadek Czajka <rczajka@rczajka.pl>
Mon, 17 Dec 2018 20:11:01 +0000 (21:11 +0100)
committerRadek Czajka <rczajka@rczajka.pl>
Wed, 19 Dec 2018 20:42:27 +0000 (21:42 +0100)
src/paypal/rest.py
src/paypal/tests.py [new file with mode: 0644]
src/paypal/views.py

index 3590c6f..8927cab 100644 (file)
@@ -9,9 +9,8 @@ import pytz
 from django.contrib.sites.models import Site
 from django.core.urlresolvers import reverse
 from django.utils import timezone
-from paypalrestsdk import BillingPlan, BillingAgreement, ResourceNotFound
 from django.conf import settings
-from .models import BillingPlan as BillingPlanModel, BillingAgreement as BillingAgreementModel
+from .models import BillingPlan, BillingAgreement
 
 paypalrestsdk.configure(settings.PAYPAL_CONFIG)
 
@@ -25,7 +24,7 @@ def absolute_url(url_name):
 
 
 def create_plan(amount):
-    billing_plan = BillingPlan({
+    billing_plan = paypalrestsdk.BillingPlan({
         "name": "Cykliczna darowizna na Wolne Lektury: %s zł" % amount,
         "description": "Cykliczna darowizna na wsparcie Wolnych Lektur",
         "merchant_preferences": {
@@ -55,7 +54,7 @@ def create_plan(amount):
         raise PaypalError(billing_plan.error)
     if not billing_plan.activate():
         raise PaypalError(billing_plan.error)
-    plan, created = BillingPlanModel.objects.get_or_create(amount=amount, defaults={'plan_id': billing_plan.id})
+    plan, created = BillingPlan.objects.get_or_create(amount=amount, defaults={'plan_id': billing_plan.id})
     return plan.plan_id
 
 
@@ -67,13 +66,13 @@ def get_link(links, rel):
 
 def create_agreement(amount, app=False):
     try:
-        plan = BillingPlanModel.objects.get(amount=amount)
-    except BillingPlanModel.DoesNotExist:
+        plan = BillingPlan.objects.get(amount=amount)
+    except BillingPlan.DoesNotExist:
         plan_id = create_plan(amount)
     else:
         plan_id = plan.plan_id
     start = (timezone.now() + timedelta(0, 3600*24)).astimezone(pytz.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
-    billing_agreement = BillingAgreement({
+    billing_agreement = paypalrestsdk.BillingAgreement({
         "name": u"Subskrypcja klubu WL",
         "description": u"Stałe wsparcie Wolnych Lektur kwotą %s złotych" % amount,
         "start_date": start,
@@ -103,8 +102,8 @@ def agreement_approval_url(amount, app=False):
 
 def get_agreement(agreement_id):
     try:
-        return BillingAgreement.find(agreement_id)
-    except ResourceNotFound:
+        return paypalrestsdk.BillingAgreement.find(agreement_id)
+    except paypalrestsdk.ResourceNotFound:
         return None
 
 
@@ -115,9 +114,9 @@ def check_agreement(agreement_id):
 
 
 def user_is_subscribed(user):
-    agreements = BillingAgreementModel.objects.filter(user=user)
+    agreements = BillingAgreement.objects.filter(user=user)
     return any(agreement.check_agreement() for agreement in agreements)
 
 
 def execute_agreement(token):
-    return BillingAgreement.execute(token)
+    return paypalrestsdk.BillingAgreement.execute(token)
diff --git a/src/paypal/tests.py b/src/paypal/tests.py
new file mode 100644 (file)
index 0000000..7522842
--- /dev/null
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from django.contrib.auth.models import User
+from mock import Mock, patch, DEFAULT
+from catalogue.test_utils import WLTestCase
+from .models import BillingPlan
+
+
+BillingAgreementMock = Mock(
+    execute=Mock(
+        return_value=Mock(
+            plan=Mock(
+                payment_definitions=[
+                    Mock(
+                        amount={'value': '100'}
+                    )
+                ]
+            )
+        )
+    )
+)
+
+
+class PaypalTests(WLTestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.user = User(username='test')
+        cls.user.set_password('test')
+        cls.user.save()
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.user.delete()
+
+    def test_paypal_form(self):
+        response = self.client.get('/paypal/form/')
+        self.assertEqual(response.status_code, 200)
+
+    def test_paypal_form_unauthorized(self):
+        """Legacy flow: only allow payment for logged-in users."""
+        response = self.client.post('/paypal/form/', {"amount": "0"})
+        self.assertEqual(response.status_code, 403)
+
+    def test_paypal_form_invalid(self):
+        """Paypal form: error on bad input."""
+        self.client.login(username='test', password='test')
+
+        response = self.client.post('/paypal/form/', {"amount": "0"})
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(
+            len(response.context['form'].errors['amount']),
+            1)
+
+    @patch.multiple('paypalrestsdk',
+        BillingPlan=DEFAULT,
+        BillingAgreement=DEFAULT
+    )
+    def test_paypal_form_valid(self, BillingPlan, BillingAgreement):
+        self.client.login(username='test', password='test')
+        response = self.client.post('/paypal/form/', {"amount": "100"})
+        self.assertEqual(response.status_code, 302)
+        # Assert: BillingPlan created? BillingAgreement created?
+        # Models created?
+
+    @patch.multiple('paypalrestsdk',
+        BillingPlan=DEFAULT,
+        BillingAgreement=DEFAULT,
+    )
+    def test_paypal_form_valid(self, BillingPlan, BillingAgreement):
+        self.client.login(username='test', password='test')
+        response = self.client.post('/paypal/app-form/', {"amount": "100"})
+        self.assertEqual(response.status_code, 302)
+
+    @patch.multiple('paypalrestsdk',
+        BillingAgreement=BillingAgreementMock
+    )
+    def test_paypal_return(self):
+        self.client.login(username='test', password='test')
+        BillingPlan.objects.create(amount=100)
+        response = self.client.get('/paypal/return/?token=secret-token')
+
+    def test_paypal_cancel(self):
+        response = self.client.get('/paypal/cancel/')
+        self.assertEqual(response.status_code, 200)
index 6708f2d..15a7cf6 100644 (file)
@@ -12,7 +12,7 @@ from django.shortcuts import render
 from api.piston_patch import HttpResponseAppRedirect
 from paypal.forms import PaypalSubscriptionForm
 from paypal.rest import execute_agreement, check_agreement, agreement_approval_url, PaypalError
-from paypal.models import BillingAgreement as BillingAgreementModel, BillingPlan
+from paypal.models import BillingAgreement, BillingPlan
 
 
 def paypal_form(request, app=False):
@@ -37,13 +37,13 @@ def paypal_return(request, app=False):
     token = request.GET.get('token')
     if not token:
         raise Http404
-    if not BillingAgreementModel.objects.filter(token=token):
+    if not BillingAgreement.objects.filter(token=token):
         resource = execute_agreement(token)
         if resource.id:
             amount = int(Decimal(resource.plan.payment_definitions[0].amount['value']))
             plan = BillingPlan.objects.get(amount=amount)
             active = check_agreement(resource.id)
-            BillingAgreementModel.objects.create(
+            BillingAgreement.objects.create(
                 agreement_id=resource.id, user=request.user, plan=plan, active=active, token=token)
     else:
         resource = None