"""Tests for Stripe Checkout Session API (mocked Stripe SDK).""" from unittest.mock import MagicMock, patch from django.test import override_settings from django.urls import reverse from rest_framework import status from rest_framework.test import APITestCase from chat_backend.tests.factories import make_company, make_user from finance.models import Invoice class CreateCheckoutSessionViewTestCase(APITestCase): def setUp(self): self.company = make_company() self.user = make_user(company=self.company) self.client.force_authenticate(user=self.user) self.url = reverse("finance_checkout") @override_settings( STRIPE_SECRET_KEY="sk_test_fake", SUBSCRIPTION_PRICE_AMOUNT_CENTS=1000, SUBSCRIPTION_PRICE_CURRENCY="usd", SUBSCRIPTION_PRICE_INTERVAL="month", SUBSCRIPTION_PRODUCT_NAME="Chat Subscription", STRIPE_PRICE_ID="", STRIPE_CHECKOUT_SUCCESS_URL="http://localhost:3000/ok", STRIPE_CHECKOUT_CANCEL_URL="http://localhost:3000/cancel", ) @patch("finance.services.stripe_service.stripe.checkout.Session.create") def test_creates_checkout_session_and_draft_invoice(self, mock_create): mock_session = MagicMock() mock_session.id = "cs_test_abc" mock_session.url = "https://checkout.stripe.com/c/pay/cs_test_abc" mock_session.customer = None mock_create.return_value = mock_session response = self.client.post(self.url, {}, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual( response.data["checkout_url"], "https://checkout.stripe.com/c/pay/cs_test_abc", ) self.assertEqual(response.data["session_id"], "cs_test_abc") mock_create.assert_called_once() kwargs = mock_create.call_args.kwargs self.assertEqual(kwargs["mode"], "subscription") line_item = kwargs["line_items"][0] self.assertEqual(line_item["price_data"]["unit_amount"], 1000) self.assertEqual(line_item["price_data"]["currency"], "usd") self.assertEqual( line_item["price_data"]["recurring"]["interval"], "month" ) self.assertEqual(kwargs["metadata"]["user_id"], str(self.user.pk)) invoice = Invoice.objects.get(stripe_checkout_session_id="cs_test_abc") self.assertEqual(invoice.user, self.user) self.assertEqual(invoice.company, self.company) self.assertEqual(invoice.amount_due, 1000) self.assertEqual(invoice.status, Invoice.Status.OPEN) @override_settings(STRIPE_SECRET_KEY="", STRIPE_PRICE_ID="") def test_missing_stripe_key_returns_503(self): response = self.client.post(self.url, {}, format="json") self.assertEqual(response.status_code, status.HTTP_503_SERVICE_UNAVAILABLE) def test_unauthenticated_rejected(self): self.client.force_authenticate(user=None) response = self.client.post(self.url, {}, format="json") self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) @override_settings( STRIPE_SECRET_KEY="sk_test_fake", STRIPE_PRICE_ID="price_abc123", STRIPE_CHECKOUT_SUCCESS_URL="http://localhost:3000/ok", STRIPE_CHECKOUT_CANCEL_URL="http://localhost:3000/cancel", ) @patch("finance.services.stripe_service.stripe.checkout.Session.create") def test_uses_stripe_price_id_when_set(self, mock_create): mock_session = MagicMock() mock_session.id = "cs_test_price" mock_session.url = "https://checkout.stripe.com/c/pay/cs_test_price" mock_session.customer = None mock_create.return_value = mock_session response = self.client.post(self.url, {}, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) line_item = mock_create.call_args.kwargs["line_items"][0] self.assertEqual(line_item, {"price": "price_abc123", "quantity": 1}) class InvoicePaymentListViewTestCase(APITestCase): def setUp(self): self.company = make_company() self.user = make_user(company=self.company) self.other = make_user( email="other@test.com", username="other@test.com", company=self.company, ) self.client.force_authenticate(user=self.user) Invoice.objects.create( user=self.user, company=self.company, amount_due=1000, stripe_checkout_session_id="cs_mine", ) Invoice.objects.create( user=self.other, company=self.company, amount_due=1000, stripe_checkout_session_id="cs_other", ) def test_list_own_invoices_only(self): response = self.client.get(reverse("finance_invoices")) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 1) self.assertEqual(response.data[0]["stripe_checkout_session_id"], "cs_mine")