Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

test: Stripe tests clean up and update #4157

Merged
merged 4 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ecommerce/extensions/payment/processors/stripe.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,8 @@ def get_transaction_parameters(self, basket, request=None, use_client_side_check
def handle_processor_response(self, response, basket=None):
# pretty sure we should simply return/error if basket is None, as not
# sure what it would mean if there
payment_intent_id = response['payment_intent_id']
dynamic_payment_methods_enabled = response['dynamic_payment_methods_enabled']
payment_intent_id = response.get('payment_intent_id', None)
dynamic_payment_methods_enabled = response.get('dynamic_payment_methods_enabled', None) == 'true'
# NOTE: In the future we may want to get/create a Customer. See https://stripe.com/docs/api#customers.

# rewrite order amount so it's updated for coupon & quantity and unchanged by the user
Expand Down
123 changes: 46 additions & 77 deletions ecommerce/extensions/payment/tests/processors/test_stripe.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@


import json
import logging

import mock
Expand All @@ -17,93 +18,61 @@
BillingAddress = get_model('order', 'BillingAddress')
Country = get_model('address', 'Country')

STRIPE_TEST_FIXTURE_PATH = 'ecommerce/extensions/payment/tests/views/fixtures/test_stripe_test_payment_flow.json'


class StripeTests(PaymentProcessorTestCaseMixin, TestCase):
processor_class = Stripe
processor_name = 'stripe'

def _get_response_data(self, response_type):
with open(STRIPE_TEST_FIXTURE_PATH, 'r') as fixtures: # pylint: disable=unspecified-encoding
return json.load(fixtures)['happy_path'][response_type]

def test_get_transaction_parameters(self):
transaction_params = self.processor.get_transaction_parameters(self.basket)
assert 'payment_page_url' in transaction_params.keys()

# TODO: update or remove these tests
def test_handle_processor_response(self):
assert True
# payment_intent_1 = stripe.PaymentIntent.construct_from({
# 'id': 'pi_testtesttest',
# 'source': {
# 'brand': 'visa',
# 'last4': '4242',
# },
# }, 'fake-key')

# payment_intent_2 = stripe.PaymentIntent.construct_from({
# 'id': 'pi_testtesttest',
# 'source': {
# 'brand': 'visa',
# 'last4': '4242',
# },
# 'status': 'succeeded',
# "charges": {
# "object": "list",
# "data": [
# {
# "id": "ch_testtesttest",
# "object": "charge",
# "status": "succeeded",
# "payment_method_details": {
# "card": {
# "brand": "visa",
# "country": "US",
# "exp_month": 5,
# "exp_year": 2020,
# "fingerprint": "Xt5EWLLDS7FJjR1c",
# "funding": "credit",
# "last4": "4242",
# "network": "visa",
# },
# "type": "card"
# },
# }
# ]
# }
# }, 'fake-key')

# with mock.patch('stripe.PaymentIntent.modify') as payment_intent_modify_mock:
# with mock.patch('stripe.PaymentIntent.confirm') as payment_intent_confirm_mock:
# payment_intent_modify_mock.return_value = payment_intent_1
# payment_intent_confirm_mock.return_value = payment_intent_2
# actual = self.processor.handle_processor_response(payment_intent_1, self.basket)

# assert actual.transaction_id == payment_intent_1.id
# assert actual.total == self.basket.total_incl_tax
# assert actual.currency == self.basket.currency

# self.assert_processor_response_recorded(
# self.processor_name,
# payment_intent_2.id,
# payment_intent_2,
# basket=self.basket
# )

# def test_handle_processor_response_error(self):
# payment_intent_1 = stripe.PaymentIntent.construct_from({
# 'id': 'pi_testtesttest',
# 'source': {
# 'brand': 'visa',
# 'last4': '4242',
# },
# }, 'fake-key')
# with mock.patch('stripe.PaymentIntent.modify') as charge_mock:
# charge_mock.side_effect = stripe.error.CardError(
# 'fake-msg', 'fake-param', 'fake-code', http_body='fake-body', http_status=500
# )
# self.assertRaises(
# TransactionDeclined,
# self.processor.handle_processor_response,
# payment_intent_1,
# self.basket
# )
with mock.patch('stripe.PaymentIntent.modify') as mock_modify:
mock_modify.return_value = self._get_response_data('modify_resp')
with mock.patch('stripe.PaymentIntent.confirm') as mock_confirm:
confirm_response_data = self._get_response_data('confirm_resp')
mock_confirm.return_value = confirm_response_data
response = {
'payment_intent_id': confirm_response_data['id'],
'skus': self.basket.lines.first().stockrecord.partner_sku,
'dynamic_payment_methods_enabled': 'false'
}
actual = self.processor.handle_processor_response(response, self.basket)

assert actual.transaction_id == confirm_response_data['id']
assert actual.total == self.basket.total_incl_tax
assert actual.currency == self.basket.currency

self.assert_processor_response_recorded(
self.processor_name,
confirm_response_data['id'],
confirm_response_data,
basket=self.basket
)

def test_handle_processor_response_error(self):
with self.assertLogs(level='ERROR') as logger:
with mock.patch('stripe.PaymentIntent.modify') as mock_modify:
mock_modify.return_value = self._get_response_data('modify_resp')
with mock.patch('stripe.PaymentIntent.confirm') as mock_confirm:
mock_confirm.side_effect = stripe.error.CardError(
'fake-msg', 'fake-param', 'fake-code', http_body='fake-body', http_status=500
)
confirm_response_data = self._get_response_data('confirm_resp')
self.assertRaises(
stripe.error.CardError,
self.processor.handle_processor_response,
confirm_response_data,
self.basket
)
self.assertIn('Card Error for basket [{}]'.format(self.basket.id), logger.output[0])

def test_issue_credit(self):
charge_reference_number = '9436'
Expand Down
26 changes: 16 additions & 10 deletions ecommerce/extensions/payment/tests/views/test_stripe.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def test_payment_flow(
"""
Verify that the stripe payment flow, hitting capture-context and
stripe-checkout urls, results in a basket associated with the correct
stripe payment_intent_id.
stripe payment_intent_id, and a processor response is recorded.

Args:
confirm_resp: Response for confirm call on payment purchase
Expand Down Expand Up @@ -211,9 +211,9 @@ def test_payment_flow(
self.client.post(
self.stripe_checkout_url,
data={
'payment_intent_id': 'pi_3LsftNIadiFyUl1x2TWxaADZ',
'payment_intent_id': create_resp['id'],
'skus': basket.lines.first().stockrecord.partner_sku,
'dynamic_payment_methods_enabled': False,
'dynamic_payment_methods_enabled': 'false',
},
)
assert mock_retrieve.call_count == 1
Expand All @@ -235,8 +235,14 @@ def test_payment_flow(
pprs = PaymentProcessorResponse.objects.filter(
transaction_id="pi_3LsftNIadiFyUl1x2TWxaADZ"
)
# created when andle_processor_response is successful
# created when handle_processor_response is successful
assert pprs.count() == 1
self.assert_processor_response_recorded(
Stripe.NAME,
confirm_resp['id'],
confirm_resp,
basket=basket
)

def test_capture_context_basket_price_change(self):
"""
Expand Down Expand Up @@ -468,7 +474,7 @@ def test_payment_error_no_basket(self):
data={
'payment_intent_id': 'pi_3LsftNIadiFyUl1x2TWxaADZ',
'skus': '',
'dynamic_payment_methods_enabled': False,
'dynamic_payment_methods_enabled': 'false',
},
)
assert response.status_code == 302
Expand All @@ -486,7 +492,7 @@ def test_payment_error_sku_mismatch(self):
{
'payment_intent_id': 'pi_3LsftNIadiFyUl1x2TWxaADZ',
'skus': 'totally_the_wrong_sku',
'dynamic_payment_methods_enabled': False,
'dynamic_payment_methods_enabled': 'false',
},
)
assert response.json() == {'sku_error': True}
Expand All @@ -513,7 +519,7 @@ def test_payment_check_sdn_returns_hits(self):
{
'payment_intent_id': 'pi_3LsftNIadiFyUl1x2TWxaADZ',
'skus': basket.lines.first().stockrecord.partner_sku,
'dynamic_payment_methods_enabled': False,
'dynamic_payment_methods_enabled': 'false',
},
)
assert response.status_code == 400
Expand All @@ -531,7 +537,7 @@ def test_payment_handle_payment_intent_in_progress(self):
{
'payment_intent_id': 'pi_3LsftNIadiFyUl1x2TWxaADZ',
'skus': basket.lines.first().stockrecord.partner_sku,
'dynamic_payment_methods_enabled': True,
'dynamic_payment_methods_enabled': 'true',
},
in_progress_payment=True,
)
Expand All @@ -552,7 +558,7 @@ def test_handle_payment_fails_with_carderror(self):
{
'payment_intent_id': 'pi_3LsftNIadiFyUl1x2TWxaADZ',
'skus': basket.lines.first().stockrecord.partner_sku,
'dynamic_payment_methods_enabled': False,
'dynamic_payment_methods_enabled': 'false',
},
confirm_side_effect=stripe.error.CardError('Oops!', {}, 'card_declined'),
)
Expand All @@ -573,7 +579,7 @@ def test_handle_payment_fails_with_unexpected_error(self):
{
'payment_intent_id': 'pi_3LsftNIadiFyUl1x2TWxaADZ',
'skus': basket.lines.first().stockrecord.partner_sku,
'dynamic_payment_methods_enabled': False,
'dynamic_payment_methods_enabled': 'false',
},
)
assert response.status_code == 400
Expand Down
Loading