chore: more tests

This commit is contained in:
Livio Bieri 2023-11-20 17:06:45 +01:00 committed by Christian Cueni
parent 33bea6c08a
commit 7a21988a5c
4 changed files with 151 additions and 12 deletions

View File

@ -12,7 +12,7 @@ from vbv_lernwelt.shop.models import CheckoutState
logger = structlog.get_logger(__name__)
class PaymentException(Exception):
class InitTransactionException(Exception):
pass
@ -81,7 +81,7 @@ def init_transaction(
logger.info("Initiating transaction", payload=payload)
response = requests.post(
f"{settings.DATATRANS_API_ENDPOINT}/v1/transactions",
url=f"{settings.DATATRANS_API_ENDPOINT}/v1/transactions",
json=payload,
headers={
"Authorization": f"Basic {settings.DATATRANS_BASIC_AUTH_KEY}",
@ -94,7 +94,7 @@ def init_transaction(
logger.info("Transaction initiated", transaction_id=transaction_id)
return transaction_id
else:
raise PaymentException(
raise InitTransactionException(
"Transaction initiation failed:",
response.json().get("error"),
)

View File

@ -11,6 +11,7 @@ from vbv_lernwelt.shop.models import (
Product,
VV_PRODUCT_SKU,
)
from vbv_lernwelt.shop.services import InitTransactionException
USER_USERNAME = "testuser"
USER_EMAIL = "test@example.com"
@ -117,3 +118,32 @@ class CheckoutAPITestCase(APITestCase):
)
self.assertEqual(expected, response.json()["next_step_url"])
@patch("vbv_lernwelt.shop.views.init_transaction")
def test_checkout_init_transaction_exception(self, mock_init_transaction):
# GIVEN
mock_init_transaction.side_effect = InitTransactionException(
"Something went wrong"
)
# WHEN
response = self.client.post(
path=reverse("checkout-vv"),
format="json",
data={
"redirect_url": REDIRECT_URL,
"address": TEST_ADDRESS_DATA,
},
)
# THEN
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
f"{REDIRECT_URL}/onboarding/vv/checkout/address?error",
response.json()["next_step_url"],
)
self.assertEqual(
0,
CheckoutInformation.objects.count(),
)

View File

@ -0,0 +1,99 @@
import uuid
from unittest.mock import patch
from django.test import override_settings, TestCase
from vbv_lernwelt.core.models import User
from vbv_lernwelt.shop.services import (
get_payment_url,
init_transaction,
InitTransactionException,
)
REDIRECT_URL = "http://testserver/redirect-url"
class DatatransServiceTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username=uuid.uuid4().hex,
email=uuid.uuid4().hex,
password="password",
is_active=True,
)
@override_settings(DATATRANS_BASIC_AUTH_KEY="BASIC_AUTH_KEY")
@patch("vbv_lernwelt.shop.services.requests.post")
@patch("vbv_lernwelt.shop.services.uuid.uuid4")
def test_init_transaction_201(self, mock_uuid, mock_post):
# GIVEN
mock_uuid.return_value = uuid.uuid4()
mock_post.return_value.status_code = 201
mock_post.return_value.json.return_value = {
"transactionId": 1234567890,
}
self.user.language = "it"
# WHEN
transaction_id = init_transaction(
user=self.user,
amount_chf_centimes=300_00,
redirect_url_success=f"{REDIRECT_URL}/success",
redirect_url_error=f"{REDIRECT_URL}/error",
redirect_url_cancel=f"{REDIRECT_URL}/cancel",
webhook_url=f"{REDIRECT_URL}/webhook",
)
self.assertEqual(1234567890, transaction_id)
# THEN
mock_post.assert_called_once_with(
url="https://api.sandbox.datatrans.com/v1/transactions",
json={
"autoSettle": True,
"amount": 300_00,
"currency": "CHF",
"language": self.user.language,
"refno": str(mock_uuid()),
"webhook": {"url": f"{REDIRECT_URL}/webhook"},
"redirect": {
"successUrl": f"{REDIRECT_URL}/success",
"errorUrl": f"{REDIRECT_URL}/error",
"cancelUrl": f"{REDIRECT_URL}/cancel",
},
},
headers={
"Authorization": "Basic BASIC_AUTH_KEY",
"Content-Type": "application/json",
},
)
@patch("vbv_lernwelt.shop.services.requests.post")
def test_init_transaction_500(self, mock_post):
# GIVEN
mock_post.return_value.status_code = 500
# WHEN / THEN
with self.assertRaises(InitTransactionException):
init_transaction(
user=self.user,
amount_chf_centimes=300_00,
redirect_url_success=f"/success",
redirect_url_error=f"/error",
redirect_url_cancel=f"/cancel",
webhook_url=f"/webhook",
)
def test_get_payment_url(self):
# GIVEN
transaction_id = "1234567890"
# WHEN
url = get_payment_url(transaction_id)
# THEN
self.assertEqual(
url,
f"https://pay.sandbox.datatrans.com/v1/start/{transaction_id}",
)

View File

@ -18,6 +18,7 @@ from vbv_lernwelt.shop.serializers import BillingAddressSerializer
from vbv_lernwelt.shop.services import (
get_payment_url,
init_transaction,
InitTransactionException,
is_signature_valid,
)
@ -137,16 +138,25 @@ def checkout_vv(request):
return JsonResponse({"next_step_url": get_payment_url(checkout.transaction_id)})
# not yet initialized at all, or canceled/failed
transaction_id = init_transaction(
user=request.user,
amount_chf_centimes=product.price,
redirect_url_success=checkout_success_url(base_redirect_url),
redirect_url_error=checkout_error_url(base_redirect_url),
redirect_url_cancel=checkout_cancel_url(base_redirect_url),
webhook_url=webhook_url(base_redirect_url),
)
# -> create new transaction and checkout
try:
transaction_id = init_transaction(
user=request.user,
amount_chf_centimes=product.price,
redirect_url_success=checkout_success_url(base_redirect_url),
redirect_url_error=checkout_error_url(base_redirect_url),
redirect_url_cancel=checkout_cancel_url(base_redirect_url),
webhook_url=webhook_url(base_redirect_url),
)
except InitTransactionException as e:
return JsonResponse(
{
"next_step_url": checkout_error_url(
base_url=base_redirect_url,
)
},
)
# immutable snapshot of data at time of purchase
CheckoutInformation.objects.create(
user=request.user,
state="initialized",