import uuid from unittest.mock import patch import stripe from django.http.request import HttpRequest from django.test import Client from django.test import TestCase from model_mommy import mommy from datacenterlight.models import StripePlan from membership.models import StripeCustomer from utils.stripe_utils import StripeUtils class BaseTestCase(TestCase): """ Base class to initialize the test cases """ def setUp(self): # Password self.dummy_password = 'test_password' # Users self.customer, self.another_customer = mommy.make('membership.CustomUser', _quantity=2) self.customer.set_password(self.dummy_password) self.customer.save() self.another_customer.set_password(self.dummy_password) self.another_customer.save() # Stripe mocked data self.stripe_mocked_customer = self.customer_stripe_mocked_data() # Clients self.customer_client = self.get_client(self.customer) self.another_customer_client = self.get_client(self.another_customer) # Request Object self.request = HttpRequest() self.request.META['SERVER_NAME'] = 'ungleich.com' self.request.META['SERVER_PORT'] = '80' def get_client(self, user): """ Authenticate a user and return the client """ client = Client() client.login(email=user.email, password=self.dummy_password) return client def customer_stripe_mocked_data(self): return { "id": "cus_8R1y9UWaIIjZqr", "object": "customer", "currency": "usd", "default_source": "card_18A9up2eZvKYlo2Cq2RJMGeF", "email": "vmedixtodd+1@gmail.com", "livemode": False, "metadata": { }, "shipping": None, "sources": { "object": "list", "data": [{ "id": "card_18A9up2eZvKYlo2Cq2RJMGeF", "object": "card", "brand": "Visa", "country": "US", "customer": "cus_8R1y9UWaIIjZqr", "cvc_check": "pass", "dynamic_last4": None, "exp_month": 12, "exp_year": 2018, "funding": "credit", "last4": "4242", }] } } def setup_view(self, view, *args, **kwargs): """Mimic as_view() returned callable, but returns view instance. args and kwargs are the same you would pass to ``reverse()`` """ view.request = self.request view.args = args view.kwargs = kwargs view.config = None return view class TestStripeCustomerDescription(TestCase): """ A class to test setting the description field of the stripe customer https://stripe.com/docs/api#metadata """ def setUp(self): self.customer_password = 'test_password' self.customer_email = 'test@ungleich.ch' self.customer_name = "Monty Python" self.customer = mommy.make('membership.CustomUser') self.customer.set_password(self.customer_password) self.customer.email = self.customer_email self.customer.save() self.stripe_utils = StripeUtils() self.token = stripe.Token.create( card={ "number": '4111111111111111', "exp_month": 12, "exp_year": 2022, "cvc": '123' }, ) self.failed_token = stripe.Token.create( card={ "number": '4000000000000341', "exp_month": 12, "exp_year": 2022, "cvc": '123' }, ) def test_creating_stripe_customer(self): stripe_data = self.stripe_utils.create_customer(self.token.id, self.customer.email, self.customer_name) self.assertEqual(stripe_data.get('error'), None) customer_data = stripe_data.get('response_object') self.assertEqual(customer_data.description, self.customer_name) class StripePlanTestCase(TestStripeCustomerDescription): """ A class to test Stripe plans """ def test_get_stripe_plan_id_string(self): plan_id_string = StripeUtils.get_stripe_plan_id(cpu=2, ram=20, ssd=100, version=1, app='dcl') self.assertEqual(plan_id_string, 'dcl-v1-cpu-2-ram-20gb-ssd-100gb') def test_get_or_create_plan(self): stripe_plan = self.stripe_utils.get_or_create_stripe_plan(2000, "test plan 1", stripe_plan_id='test-plan-1') self.assertIsNone(stripe_plan.get('error')) self.assertIsInstance(stripe_plan.get('response_object'), StripePlan) @patch('utils.stripe_utils.logger') def test_create_duplicate_plans_error_handling(self, mock_logger): """ Test details: 1. Create a test plan in Stripe with a particular id 2. Try to recreate the plan with the same id 3. This creates a Stripe error, the code should be able to handle the error :param mock_logger: :return: """ unique_id = str(uuid.uuid4().hex) new_plan_id_str = 'test-plan-{}'.format(unique_id) stripe_plan = self.stripe_utils.get_or_create_stripe_plan(2000, "test plan {}".format(unique_id), stripe_plan_id=new_plan_id_str) self.assertIsInstance(stripe_plan.get('response_object'), StripePlan) self.assertEqual(stripe_plan.get('response_object').stripe_plan_id, new_plan_id_str) # Test creating the same plan again and expect the PLAN_EXISTS_ERROR_MSG # We first delete the local Stripe Plan, so that the code tries to create a new plan in Stripe StripePlan.objects.filter(stripe_plan_id=new_plan_id_str).all().delete() stripe_plan_1 = self.stripe_utils.get_or_create_stripe_plan(2000, "test plan {}".format(unique_id), stripe_plan_id=new_plan_id_str) mock_logger.debug.assert_called_with(self.stripe_utils.PLAN_EXISTS_ERROR_MSG.format(new_plan_id_str)) self.assertIsInstance(stripe_plan_1.get('response_object'), StripePlan) self.assertEqual(stripe_plan_1.get('response_object').stripe_plan_id, new_plan_id_str) # Delete the test stripe plan that we just created delete_result = self.stripe_utils.delete_stripe_plan(new_plan_id_str) self.assertIsInstance(delete_result, dict) self.assertEqual(delete_result.get('response_object'), True) @patch('utils.stripe_utils.logger') def test_delete_unexisting_plan_should_fail(self, mock_logger): plan_id = 'crazy-plan-id-that-does-not-exist' result = self.stripe_utils.delete_stripe_plan(plan_id) self.assertIsInstance(result, dict) self.assertEqual(result.get('response_object'), False) mock_logger.debug.assert_called_with(self.stripe_utils.PLAN_DOES_NOT_EXIST_ERROR_MSG.format(plan_id)) def test_subscribe_customer_to_plan(self): stripe_plan = self.stripe_utils.get_or_create_stripe_plan(2000, "test plan 1", stripe_plan_id='test-plan-1') stripe_customer = StripeCustomer.get_or_create(email=self.customer_email, token=self.token) result = self.stripe_utils.subscribe_customer_to_plan(stripe_customer.stripe_id, [{"plan": stripe_plan.get( 'response_object').stripe_plan_id}]) self.assertIsInstance(result.get('response_object'), stripe.Subscription) self.assertIsNone(result.get('error')) self.assertEqual(result.get('response_object').get('status'), 'active') def test_subscribe_customer_to_plan_failed_payment(self): stripe_plan = self.stripe_utils.get_or_create_stripe_plan(2000, "test plan 1", stripe_plan_id='test-plan-1') stripe_customer = StripeCustomer.get_or_create(email=self.customer_email, token=self.failed_token) result = self.stripe_utils.subscribe_customer_to_plan(stripe_customer.stripe_id, [{"plan": stripe_plan.get( 'response_object').stripe_plan_id}]) self.assertIsNone(result.get('response_object'), None) self.assertIsNotNone(result.get('error'))