chore: more tests
This commit is contained in:
parent
33bea6c08a
commit
7a21988a5c
|
|
@ -12,7 +12,7 @@ from vbv_lernwelt.shop.models import CheckoutState
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PaymentException(Exception):
|
class InitTransactionException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ def init_transaction(
|
||||||
logger.info("Initiating transaction", payload=payload)
|
logger.info("Initiating transaction", payload=payload)
|
||||||
|
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
f"{settings.DATATRANS_API_ENDPOINT}/v1/transactions",
|
url=f"{settings.DATATRANS_API_ENDPOINT}/v1/transactions",
|
||||||
json=payload,
|
json=payload,
|
||||||
headers={
|
headers={
|
||||||
"Authorization": f"Basic {settings.DATATRANS_BASIC_AUTH_KEY}",
|
"Authorization": f"Basic {settings.DATATRANS_BASIC_AUTH_KEY}",
|
||||||
|
|
@ -94,7 +94,7 @@ def init_transaction(
|
||||||
logger.info("Transaction initiated", transaction_id=transaction_id)
|
logger.info("Transaction initiated", transaction_id=transaction_id)
|
||||||
return transaction_id
|
return transaction_id
|
||||||
else:
|
else:
|
||||||
raise PaymentException(
|
raise InitTransactionException(
|
||||||
"Transaction initiation failed:",
|
"Transaction initiation failed:",
|
||||||
response.json().get("error"),
|
response.json().get("error"),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ from vbv_lernwelt.shop.models import (
|
||||||
Product,
|
Product,
|
||||||
VV_PRODUCT_SKU,
|
VV_PRODUCT_SKU,
|
||||||
)
|
)
|
||||||
|
from vbv_lernwelt.shop.services import InitTransactionException
|
||||||
|
|
||||||
USER_USERNAME = "testuser"
|
USER_USERNAME = "testuser"
|
||||||
USER_EMAIL = "test@example.com"
|
USER_EMAIL = "test@example.com"
|
||||||
|
|
@ -117,3 +118,32 @@ class CheckoutAPITestCase(APITestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(expected, response.json()["next_step_url"])
|
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(),
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -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}",
|
||||||
|
)
|
||||||
|
|
@ -18,6 +18,7 @@ from vbv_lernwelt.shop.serializers import BillingAddressSerializer
|
||||||
from vbv_lernwelt.shop.services import (
|
from vbv_lernwelt.shop.services import (
|
||||||
get_payment_url,
|
get_payment_url,
|
||||||
init_transaction,
|
init_transaction,
|
||||||
|
InitTransactionException,
|
||||||
is_signature_valid,
|
is_signature_valid,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -137,16 +138,25 @@ def checkout_vv(request):
|
||||||
return JsonResponse({"next_step_url": get_payment_url(checkout.transaction_id)})
|
return JsonResponse({"next_step_url": get_payment_url(checkout.transaction_id)})
|
||||||
|
|
||||||
# not yet initialized at all, or canceled/failed
|
# not yet initialized at all, or canceled/failed
|
||||||
transaction_id = init_transaction(
|
# -> create new transaction and checkout
|
||||||
user=request.user,
|
try:
|
||||||
amount_chf_centimes=product.price,
|
transaction_id = init_transaction(
|
||||||
redirect_url_success=checkout_success_url(base_redirect_url),
|
user=request.user,
|
||||||
redirect_url_error=checkout_error_url(base_redirect_url),
|
amount_chf_centimes=product.price,
|
||||||
redirect_url_cancel=checkout_cancel_url(base_redirect_url),
|
redirect_url_success=checkout_success_url(base_redirect_url),
|
||||||
webhook_url=webhook_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(
|
CheckoutInformation.objects.create(
|
||||||
user=request.user,
|
user=request.user,
|
||||||
state="initialized",
|
state="initialized",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue