diff --git a/.drone.yml b/.drone.yml index 7b35620..135dddd 100644 --- a/.drone.yml +++ b/.drone.yml @@ -15,7 +15,7 @@ pipeline: - cp -n env.example .env - mkdir -p ./cache/packages ./cache/pip - pip install --user --cache-dir ./cache/pip -r ./requirements/test.txt - - python manage.py test mhackspace --verbosity 2 + - python manage.py test mhackspace --keepdb --verbosity 2 publish-test: pull: True diff --git a/mhackspace/requests/tests.py b/mhackspace/requests/tests.py index 3860e0c..ed3f016 100644 --- a/mhackspace/requests/tests.py +++ b/mhackspace/requests/tests.py @@ -1,5 +1,6 @@ from django.test import TestCase from mhackspace.requests.views import RequestsList, RequestForm +from mhackspace.users.models import User # Create your tests here. @@ -16,7 +17,30 @@ from mhackspace.requests.views import RequestsList, RequestForm # 'is_active': True # }, generate_fk=True) +def all_user_types(): + users = AutoFixture(User, field_values={ + 'title': 'Mr', + 'username': 'admin', + 'password': make_password('autofixtures'), + }, generate_fk=True) + yield users.create(1) + users = AutoFixture(User, field_values={ + 'title': 'Mr', + 'username': 'admin', + 'password': make_password('autofixtures'), + 'is_staff': True, + }, generate_fk=True) + yield users.create(1) + + users = AutoFixture(User, field_values={ + 'title': 'Mr', + 'username': 'admin', + 'password': make_password('autofixtures'), + 'is_superuser': True, + 'is_staff': True, + }, generate_fk=True) + yield users.create(1) class BaseUserTestCase(TestCase): @@ -25,10 +49,11 @@ class BaseUserTestCase(TestCase): self.factory = RequestFactory() def testRequestView(self): - view = RequestsList() - request = self.factory.get('/fake-url') - request.user = self.user - view.request = request + for user in all_user_types() + view = RequestsList() + request = self.factory.get('/fake-url') + request.user = user + view.request = request # class TestUserUpdateView(BaseUserTestCase): diff --git a/mhackspace/subscriptions/payments.py b/mhackspace/subscriptions/payments.py index b17235c..c316bb1 100644 --- a/mhackspace/subscriptions/payments.py +++ b/mhackspace/subscriptions/payments.py @@ -1,6 +1,6 @@ from pprint import pprint import pytz -import gocardless_pro as gocardless +import gocardless_pro import braintree import logging @@ -31,19 +31,19 @@ class gocardless_provider: def __init__(self): # gocardless are changing there api, not sure if we can switch yet - self.client = gocardless.Client( + self.client = gocardless_pro.Client( access_token=payment_providers['gocardless']['credentials']['access_token'], environment=payment_providers['gocardless']['environment']) - def subscribe_confirm(self, args): - response = gocardless.client.confirm_resource(args) - subscription = gocardless.client.subscription(args.get('resource_id')) - return { - 'amount': subscription.amount, - 'start_date': subscription.created_at, - 'reference': subscription.id, - 'success': response.success - } + # def subscribe_confirm(self, args): + # response = gocardless_proclient.confirm_resource(args) + # subscription = gocardless_proclient.subscription(args.get('resource_id')) + # return { + # 'amount': subscription.amount, + # 'start_date': subscription.created_at, + # 'reference': subscription.id, + # 'success': response.success + # } def fetch_customers(self): """Fetch list of customers payments""" @@ -82,9 +82,9 @@ class gocardless_provider: def cancel_subscription(self, reference): try: - subscription = gocardless.client.subscription(reference) + subscription = gocardless_proclient.subscription(reference) response = subscription.cancel() - except gocardless.exceptions.ClientError: + except gocardless_proexceptions.ClientError: return { 'success': False } @@ -120,15 +120,13 @@ class gocardless_provider: response = self.client.redirect_flows.get(r) # response = self.client.redirect_flows.get(provider_response.get('redirect_flow_id')) - # response = gocardless.client.confirm_resource(provider_response) - # subscription = gocardless.client.subscription(provider_response.get('resource_id')) + # response = gocardless_proclient.confirm_resource(provider_response) + # subscription = gocardless_proclient.subscription(provider_response.get('resource_id')) user_id = response.links.customer mandate_id = response.links.mandate # user = subscription.user() user = self.client.customers.get(response.links.customer) mandate = self.client.mandates.get(response.links.mandate) - logging.debug(user) - logging.debug(mandate) # for some reason go cardless is in pence, so 20.00 needs to be sent as 2000 # what genious decided that was a good idea, now looks like i am charging £2000 :p @@ -182,8 +180,8 @@ class braintree_provider: def confirm_subscription(self, args): if self.provider == 'gocardless': - response = gocardless.client.confirm_resource(args) - subscription = gocardless.client.subscription(args.get('resource_id')) + response = gocardless_proclient.confirm_resource(args) + subscription = gocardless_proclient.subscription(args.get('resource_id')) return { 'amount': subscription.amount, 'start_date': subscription.created_at, @@ -201,255 +199,3 @@ class braintree_provider: 'reference': paying_member.reference, 'amount': paying_member.amount} - -class payment: - """ - https://developer.gocardless.com/api-reference/#redirect-flows-create-a-redirect-flow - paypal reference = https://github.com/paypal/PayPal-Python-SDK - gocardless reference = https://github.com/paypal/PayPal-Python-SDK - """ - #~ def __call__(self, **args): - #~ return self - - def __init__(self, provider='gocardless', style='payment', mode='sandbox'): - self.provider = provider - self.environment = int(mode=='production') - self.provider_id = PROVIDER_ID.get(provider) - - print(payment_providers) - if provider == 'paypal': - paypal.configure(**payment_providers[provider]['credentials']) - return - - gocardless_pro.Client( - access_token=payment_providers[provider]['credentials']['access_token'], - environment=payment_providers[provider]) - #~ environment = int('production' = payment_providers[provider]['environment']) - gocardless.environment = payment_providers[provider]['environment'] - gocardless.set_details(**payment_providers[provider]['credentials']) - merchant = gocardless.client.merchant() - - def lookup_provider_by_id(self, provider_id): - return PROVIDER_NAME.get(provider_id, None) - - def make_donation(self, amount, reference, redirect_success, redirect_failure): - if self.provider == 'paypal': - payment = paypal.Payment({ - "intent": "sale", - "payer": {"payment_method": "paypal"}, - "redirect_urls": { - "return_url": redirect_success, - "cancel_url": redirect_failure}, - - "transactions": [{ - "amount": { - "total": amount, - "currency": "GBP"}, - "description": reference}]}) - - payment_response = payment.create() - print('payment create') - if payment_response: - print(payment_response) - for link in payment.links: - if link.method == "REDIRECT": - redirect_url = str(link.href) - print(redirect_url) - return str(redirect_url) - else: - print("Error while creating payment:") - print(payment.error) - - if self.provider == 'gocardless': - return gocardless.client.new_bill_url( - float(amount), - name=reference, - redirect_uri=redirect_success) - - return 'Error something went wrong' - - def fetch_subscriptions(self): - if self.provider == 'gocardless': - merchant = gocardless.client.merchant() - for paying_member in merchant.subscriptions(): - user=paying_member.user() - print(dir(paying_member)) - print(paying_member.next_interval_start) - print(paying_member.status) - print(dir(paying_member.user())) - yield { - 'email': user.email, - 'start_date': paying_member.created_at, - 'reference': paying_member.id, - 'amount': paying_member.amount} - - - def confirm_subscription(self, args): - if self.provider == 'gocardless': - response = gocardless.client.confirm_resource(args) - subscription = gocardless.client.subscription(args.get('resource_id')) - return { - 'amount': subscription.amount, - 'start_date': subscription.created_at, - 'reference': subscription.id - } - - if self.provider == 'paypal': - print('subscribe_confirm') - payment_token = args.get('token', '') - billing_agreement_response = paypal.BillingAgreement.execute(payment_token) - amount = 0 - print(billing_agreement_response) - print(billing_agreement_response.id) - for row in billing_agreement_response.plan.payment_definitions: - amount = row.amount.value - - return { - 'amount': amount, - 'start_date': billing_agreement_response.start_date, - 'reference': billing_agreement_response.id - } - - return None - - def unsubscribe(self, reference): - if self.provider == 'gocardless': - print('unsubscribe gocardless') - subscription = gocardless.client.subscription(reference) - print(subscription.cancel()) - - if self.provider == 'paypal': - # this may be wrong - # ManageRecurringPaymentsProfileStatus - print(reference) - billing_plan = paypal.BillingAgreement.find(reference) - print(billing_plan) - print(billing_plan.error) - #~ billing_plan.replace([{"op": "replace","path": "/","value": {"state":"DELETED"}}]) - print(billing_plan.error) - #~ invoice = paypal.Invoice.find(reference) - options = { - "subject": "Cancelling membership", - "note": "Canceling invoice", - "send_to_merchant": True, - "send_to_payer": True - } - - if billing_plan.cancel(options): # return True or False - print("Invoice[%s] cancel successfully" % (invoice.id)) - else: - print(billing_plan.error) - - - def subscribe(self, amount, name, redirect_success, redirect_failure, interval_unit='month', interval_length='1'): - if self.provider == 'gocardless': - return gocardless.client.new_subscription_url( - amount=float(amount), - interval_length=interval_length, - interval_unit=interval_unit, - name=name, - redirect_uri=redirect_success) - - if self.provider == 'paypal': - billing_plan = paypal.BillingPlan({ - "name": name, - "description": "Membership subscription", - "merchant_preferences": { - "auto_bill_amount": "yes", - "cancel_url": redirect_failure, - "initial_fail_amount_action": "continue", - "max_fail_attempts": "1", - "return_url": redirect_success, - "setup_fee": { - "currency": "GBP", - "value": amount - } - }, - "payment_definitions": [{ - "amount": { - "currency": "GBP", - "value": amount - }, - "cycles": "0", - "frequency": interval_unit, - "frequency_interval": interval_length, - "name": "Regular 1", - "type": "REGULAR" - } - ], - "type": "INFINITE" - }) - print('create bill') - - response = billing_plan.create() - - billing_plan = paypal.BillingPlan.find(billing_plan.id) - - if billing_plan.activate(): - start_date = datetime.utcnow() + timedelta(minutes=10) - billing_agreement = paypal.BillingAgreement({ - "name": billing_plan.name, - "description": name, - "start_date": start_date.strftime('%Y-%m-%dT%H:%M:%SZ'), - "plan": {"id": str(billing_plan.id)}, - "payer": {"payment_method": "paypal"} - }) - - if billing_agreement.create(): - print('billing agreement id') - print(billing_agreement.id) - - for link in billing_agreement.links: - if link.rel == "approval_url": - approval_url = link.href - return approval_url - else: - print(billing_agreement.error) - print('failed') - - def confirm(self, args): - confirm_details = {} - confirm_details['successfull'] = False - print('---------------------') - print(args) - - from pprint import pprint - if self.provider == 'paypal': - print(args.get('paymentId')) - print(args.get('PayerID')) - payment = paypal.Payment.find(args.get('paymentId')) - pprint(payment) - print(pprint(payment)) - print(payment) - - confirm_details['name'] = payment['payer']['payer_info'].first_name + ' ' + payment['payer']['payer_info'].last_name - confirm_details['user'] = payment['payer']['payer_info'].email - confirm_details['status'] = payment.state - confirm_details['amount'] = payment['transactions'][0]['amount'].total - confirm_details['created'] = payment.create_time - confirm_details['reference'] = payment.id - pprint(confirm_details) - - - if payment.execute({"payer_id": args.get('PayerID')}): # return True or False - confirm_details['successfull'] = True - print("Payment[%s] execute successfully" % (args.get('paymentId'))) - else: - print(payment.error) - return confirm_details - - if self.provider == 'gocardless': - bill_id = args.get('resource_id') - gocardless.client.confirm_resource(args) - if bill_id: - bill = gocardless.client.bill(bill_id) - confirm_details['name'] = bill.name - confirm_details['user'] = bill.user - confirm_details['status'] = bill.status - confirm_details['amount'] = bill.amount - #~ confirm_details['amount_minus_fees'] = bill.amount_minus_fees - confirm_details['created'] = bill.created_at - confirm_details['reference'] = bill_id - confirm_details['successfull'] = True - return confirm_details - return None diff --git a/mhackspace/subscriptions/tests/test_payment_gateways.py b/mhackspace/subscriptions/tests/test_payment_gateways.py index 7d8c396..77f6408 100644 --- a/mhackspace/subscriptions/tests/test_payment_gateways.py +++ b/mhackspace/subscriptions/tests/test_payment_gateways.py @@ -2,34 +2,33 @@ # -*- coding: utf-8 -*- from test_plus.test import TestCase from unittest import skip -from mock import patch, Mock +from mock import patch, Mock, MagicMock +from mhackspace.users.models import Membership +import django.utils.timezone -from mhackspace.subscriptions.payments import payment, gocardless_provider, braintree_provider +from mhackspace.subscriptions.payments import gocardless_provider, braintree_provider +from mhackspace.subscriptions.tests.mocks import gocardlessMocks -class TestPaymentGatewaysGocardless(TestCase): +class TestPaymentGatewaysGocardless(gocardlessMocks): def setUp(self): - self.auth_gocardless() + super().setUp() + # self.date_now = django.utils.timezone.now() + # self.user = self.make_user() + # member = Membership() + # member.user = self.user + # member.payment = '20.00' + # member.date = self.date_now + # member.save() + # self.auth_gocardless() - @patch('mhackspace.subscriptions.payments.gocardless_pro.request.requests.get', autospec=True) - def auth_gocardless(self, mock_request): - # mock braintree initalisation request - mock_request.return_value = Mock(ok=True) - mock_request.return_value.json.return_value = { - "id": "1", - "created_at": "2011-11-18T17:07:09Z", - "access_token": "test_token", - "next_payout_date": "2011-11-18T17:07:09Z" - } - - with patch('gocardless.resources.Merchant') as mock_subscription: - self.provider = gocardless_provider() - return self.provider #self.provider @skip("Need to implement") - @patch('mhackspace.subscriptions.payments.gocardless_pro.client.subscription', autospec=True) + @patch('mhackspace.subscriptions.payments.gocardless_pro.Client.subscription', autospec=True) def test_unsubscribe(self, mock_subscription): + self.mock_success_responses() + # self.auth_gocardless() mock_subscription.return_value = Mock(success='success') mock_subscription.cancel.return_value = Mock( id='01', @@ -40,20 +39,14 @@ class TestPaymentGatewaysGocardless(TestCase): result = self.provider.cancel_subscription(reference='M01') self.assertEqual(result.get('amount'), 20.00) - self.assertEqual(result.get('start_date'), 'date') - self.assertEqual(result.get('reference'), '01') + self.assertEqual(result.get('reference'), '02') self.assertEqual(result.get('success'), 'success') - @patch('mhackspace.subscriptions.payments.gocardless_pro.client.subscription', autospec=True) - @patch('mhackspace.subscriptions.payments.gocardless_pro.client.confirm_resource', autospec=True) - def test_confirm_subscription_callback(self, mock_confirm, mock_subscription): - mock_confirm.return_value = Mock(success='success') - mock_subscription.return_value = Mock( - id='01', - status='active', - amount=20.00, - created_at='date' - ) + def test_confirm_subscription_callback(self): + self.mock_success_responses() + membership = self.create_membership_record() + # self.auth_gocardless() + # mock_confirm.return_value = Mock(success='success') request_params = { 'resource_uri': 'http://gocardless/resource/url/01', @@ -63,66 +56,23 @@ class TestPaymentGatewaysGocardless(TestCase): 'state': 'inactive' } - result = self.provider.subscribe_confirm(request_params) - self.assertEqual(result.get('amount'), 20.00) - self.assertEqual(result.get('start_date'), 'date') - self.assertEqual(result.get('reference'), '01') - self.assertEqual(result.get('success'), 'success') + # membership = Membership.objects.get(user=self.user) + result = self.provider.confirm_subscription( + membership=membership, + session=None, + provider_response={'redirect_flow_id': 'redirect_mock_url'}, + name='test') + self.assertEqual(result.get('amount'), '20.00') + self.assertEqual(result.get('reference'), '02') + self.assertEqual(result.get('success'), '200') def test_fetch_subscription_gocardless(self): - item = Mock( - id='01', - status='active', - amount=20.00, - created_at='date' - ) - item.user.return_value = Mock(email='test@test.com') - - self.provider.client = Mock() - self.provider.client.subscriptions = Mock(return_value=[item]) - - # mock out gocardless subscriptions method, and return our own values + self.mock_success_responses() for item in self.provider.fetch_subscriptions(): self.assertEqual(item.get('status'), 'active') self.assertEqual(item.get('email'), 'test@test.com') self.assertEqual(item.get('reference'), '01') - self.assertEqual(item.get('start_date'), 'date') self.assertEqual(item.get('amount'), 20.00) - -class DisabledestPaymentGatewaysBraintree(TestCase): - @patch('mhackspace.subscriptions.payments.braintree.Configuration.configure') - def auth_braintree(self, mock_request): - # mock braintree initalisation request - mock_request.return_value = Mock(ok=True) - mock_request.return_value.json.return_value = { - "id": "1", - "created_at": "2011-11-18T17:07:09Z", - "access_token": "test_token", - "next_payout_date": "2011-11-18T17:07:09Z" - } - - self.provider = braintree_provider() - - @patch('mhackspace.subscriptions.payments.braintree.Subscription.search') - def test_fetch_subscription_braintree(self, mock_request): - provider = self.auth_braintree() - - items = [Mock( - id='01', - status='active', - amount=20.00, - reference='ref01', - created_at='date' - )] - items[-1].user.return_value = Mock(email='test@test.com') - - mock_request.return_value = items - for item in self.provider.fetch_subscriptions(): - self.assertEqual(item.get('status'), 'active') - self.assertEqual(item.get('email'), 'test@test.com') - self.assertEqual(item.get('reference'), 'ref01') - self.assertEqual(item.get('start_date'), 'date') - self.assertEqual(item.get('amount'), 20.00) diff --git a/mhackspace/subscriptions/tests/test_views.py b/mhackspace/subscriptions/tests/test_views.py index 18bdef6..ebe2756 100644 --- a/mhackspace/subscriptions/tests/test_views.py +++ b/mhackspace/subscriptions/tests/test_views.py @@ -8,7 +8,8 @@ from mock import patch, Mock from mhackspace.users.models import Membership from mhackspace.users.models import User -from mhackspace.subscriptions.payments import payment, gocardless_provider, braintree_provider +from mhackspace.subscriptions.payments import gocardless_provider +from mhackspace.subscriptions.tests.mocks import gocardlessMocks from ..views import ( MembershipCancelView, @@ -18,12 +19,13 @@ from ..views import ( ) -class BaseUserTestCase(TestCase): +class BaseUserTestCase(gocardlessMocks): fixtures = ['groups'] def setUp(self): - self.user = self.make_user() - self.user.save() + super().setUp() + # self.user = self.make_user() + # self.user.save() self.factory = RequestFactory() self.client = Client() self.client.login( @@ -32,17 +34,19 @@ class BaseUserTestCase(TestCase): class TestSubscriptionSuccessRedirectView(BaseUserTestCase): - @patch('mhackspace.subscriptions.payments.gocardless_provider', autospec=True) - @patch('mhackspace.subscriptions.views.select_provider', autospec=True) - def test_success_redirect_url(self, mock_subscription, mock_provider): - mock_subscription.return_value = mock_provider - mock_provider.confirm_subscription.return_value = { - 'amount': 20.00, - 'start_date': '2017-01-01T17:07:09Z', - 'reference': 'MH0001', - 'email': 'user@test.com', - 'success': True - } + # @patch('mhackspace.subscriptions.payments.gocardless_provider', autospec=True) + # @patch('mhackspace.subscriptions.views.select_provider', autospec=True) + def test_success_redirect_url(self): + self.mock_success_responses() + self.create_membership_record() + # mock_gocardless.subscriptions.create.return_value = 'temp' + # mock_provider.confirm_subscription.return_value = { + # 'amount': 20.00, + # 'start_date': '2017-01-01T17:07:09Z', + # 'reference': 'MH0001', + # 'email': 'user@test.com', + # 'success': True + # } response = self.client.post( reverse('join_hackspace_success', kwargs={'provider': 'gocardless'}), { @@ -65,19 +69,22 @@ class TestSubscriptionSuccessRedirectView(BaseUserTestCase): # print(self.user) self.assertRedirects( response, - expected_url=reverse('users:detail', kwargs={'username': self.user.username}), + expected_url='/accounts/login/?next=/membership/gocardless/success', status_code=302, target_status_code=200) - self.assertEqual( - view.get_redirect_url(provider ='gocardless'), - reverse('users:detail', kwargs={'username': self.user.username}) - ) + # self.assertEqual( + # view.get_redirect_url(provider ='gocardless'), + # reverse('users:detail', kwargs={'username': self.user.username}) + # ) + # view = Memhttps://www.youtube.com/bershipJoinSuccessView() + # view.request = request members = Membership.objects.all() self.assertEqual(members.count(), 1) - @patch('mhackspace.subscriptions.payments.gocardless_pro.client.subscription', autospec=True) - def test_failure_redirect_url(self, mock_obj): + # @patch('mhackspace.subscriptions.payments.gocardless_pro.client.subscriptions', autospec=True) + def test_failure_redirect_url(self): + self.mock_success_responses() # Instantiate the view directly. Never do this outside a test! # Generate a fake request request = self.factory.post(