inital commit
This commit is contained in:
159
payment/tests.py
Normal file
159
payment/tests.py
Normal file
@@ -0,0 +1,159 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db import IntegrityError
|
||||
from django.test import TestCase
|
||||
from django.utils import timezone
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from accounts.models import VendorProfile
|
||||
from booking.models import Booking
|
||||
from equipment.models import EquipmentCategory, EquipmentItem
|
||||
|
||||
from .models import PaymentRecord, WebhookEvent
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class PaymentModelTests(TestCase):
|
||||
def setUp(self):
|
||||
vendor_user = User.objects.create_user(
|
||||
email="vendor-payment@example.com",
|
||||
password="Pass123456!",
|
||||
is_vendor=True,
|
||||
is_customer=False,
|
||||
)
|
||||
vendor = VendorProfile.objects.create(user=vendor_user, business_name="Payment Vendor")
|
||||
customer = User.objects.create_user(
|
||||
email="customer-payment@example.com",
|
||||
password="Pass123456!",
|
||||
is_vendor=False,
|
||||
is_customer=True,
|
||||
)
|
||||
category = EquipmentCategory.objects.create(name="Canoe", slug="canoe")
|
||||
item = EquipmentItem.objects.create(
|
||||
vendor=vendor,
|
||||
category=category,
|
||||
title="Canoe",
|
||||
public_id="canoe-001",
|
||||
price_per_day="45.00",
|
||||
is_active=True,
|
||||
)
|
||||
starts = timezone.now() + timedelta(days=3)
|
||||
ends = starts + timedelta(days=1)
|
||||
self.booking = Booking.objects.create(
|
||||
customer=customer,
|
||||
vendor=vendor,
|
||||
equipment_item=item,
|
||||
starts_at=starts,
|
||||
ends_at=ends,
|
||||
status=Booking.Status.APPROVED,
|
||||
total_price="45.00",
|
||||
)
|
||||
|
||||
def test_payment_idempotency_constraints(self):
|
||||
PaymentRecord.objects.create(
|
||||
booking=self.booking,
|
||||
stripe_payment_intent_id="pi_mock_dup",
|
||||
amount="45.00",
|
||||
currency="usd",
|
||||
)
|
||||
with self.assertRaises(IntegrityError):
|
||||
PaymentRecord.objects.create(
|
||||
booking=self.booking,
|
||||
stripe_payment_intent_id="pi_mock_dup",
|
||||
amount="45.00",
|
||||
currency="usd",
|
||||
)
|
||||
|
||||
WebhookEvent.objects.create(
|
||||
stripe_event_id="evt_mock_dup",
|
||||
event_type="payment_intent.succeeded",
|
||||
payload={},
|
||||
)
|
||||
with self.assertRaises(IntegrityError):
|
||||
WebhookEvent.objects.create(
|
||||
stripe_event_id="evt_mock_dup",
|
||||
event_type="payment_intent.succeeded",
|
||||
payload={},
|
||||
)
|
||||
|
||||
|
||||
class PaymentApiTests(APITestCase):
|
||||
def setUp(self):
|
||||
self.vendor_user = User.objects.create_user(
|
||||
email="vendor-api-payment@example.com",
|
||||
password="Pass123456!",
|
||||
is_vendor=True,
|
||||
is_customer=False,
|
||||
)
|
||||
self.vendor = VendorProfile.objects.create(user=self.vendor_user, business_name="Webhook Vendor")
|
||||
self.customer = User.objects.create_user(
|
||||
email="customer-api-payment@example.com",
|
||||
password="Pass123456!",
|
||||
is_vendor=False,
|
||||
is_customer=True,
|
||||
)
|
||||
category = EquipmentCategory.objects.create(name="Raft", slug="raft")
|
||||
item = EquipmentItem.objects.create(
|
||||
vendor=self.vendor,
|
||||
category=category,
|
||||
title="River Raft",
|
||||
public_id="raft-001",
|
||||
price_per_day="110.00",
|
||||
is_active=True,
|
||||
)
|
||||
starts = timezone.now() + timedelta(days=2)
|
||||
ends = starts + timedelta(days=1)
|
||||
self.booking = Booking.objects.create(
|
||||
customer=self.customer,
|
||||
vendor=self.vendor,
|
||||
equipment_item=item,
|
||||
starts_at=starts,
|
||||
ends_at=ends,
|
||||
status=Booking.Status.APPROVED,
|
||||
total_price="110.00",
|
||||
)
|
||||
|
||||
def test_mock_payment_intent_status_and_webhook_flow(self):
|
||||
self.client.force_authenticate(self.customer)
|
||||
create_res = self.client.post(
|
||||
"/api/v1/payment/intents/",
|
||||
{"booking_id": self.booking.id, "currency": "usd"},
|
||||
format="json",
|
||||
)
|
||||
self.assertEqual(create_res.status_code, status.HTTP_201_CREATED)
|
||||
payment_id = create_res.data["payment"]["id"]
|
||||
intent_id = create_res.data["payment"]["stripe_payment_intent_id"]
|
||||
|
||||
status_res = self.client.get(f"/api/v1/payment/{payment_id}/status/")
|
||||
self.assertEqual(status_res.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(status_res.data["status"], PaymentRecord.Status.REQUIRES_PAYMENT)
|
||||
|
||||
webhook_res = self.client.post(
|
||||
"/api/v1/payment/webhooks/stripe/",
|
||||
{
|
||||
"stripe_event_id": "evt_mock_1001",
|
||||
"event_type": "payment_intent.succeeded",
|
||||
"stripe_payment_intent_id": intent_id,
|
||||
"payload": {"source": "test"},
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
self.assertEqual(webhook_res.status_code, status.HTTP_200_OK)
|
||||
self.booking.refresh_from_db()
|
||||
self.assertEqual(self.booking.status, Booking.Status.CONFIRMED)
|
||||
|
||||
idempotent_res = self.client.post(
|
||||
"/api/v1/payment/webhooks/stripe/",
|
||||
{
|
||||
"stripe_event_id": "evt_mock_1001",
|
||||
"event_type": "payment_intent.succeeded",
|
||||
"stripe_payment_intent_id": intent_id,
|
||||
"payload": {},
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
self.assertEqual(idempotent_res.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(idempotent_res.data["idempotent"])
|
||||
Reference in New Issue
Block a user