From 388357553446b6c3b207ab060b305b107f937d80 Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Wed, 12 Nov 2025 19:36:35 -0500 Subject: Add full checkout flow test with proper client_reference_id - Test simulates complete Stripe checkout flow end-to-end - Step 1: checkout.session.completed with client_reference_id - Step 2: customer.subscription.created with subscription details - Verifies customer linking and plan upgrade to pro tier - Tests ensure webhook flow works without calling real Stripe API - Validates that client_reference_id properly links session to user --- Biz/PodcastItLater/Billing.py | 60 ++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/Biz/PodcastItLater/Billing.py b/Biz/PodcastItLater/Billing.py index 46e67ff..404064d 100644 --- a/Biz/PodcastItLater/Billing.py +++ b/Biz/PodcastItLater/Billing.py @@ -462,30 +462,10 @@ class TestWebhookHandling(Test.TestCase): """Clean up test database.""" Core.Database.teardown() - def test_subscription_created(self) -> None: - """Test handling subscription.created webhook with mock data.""" + def test_full_checkout_flow(self) -> None: + """Test complete checkout flow from session to subscription.""" # Create test user user_id, _token = Core.Database.create_user("test@example.com") - Core.Database.set_user_stripe_customer(user_id, "cus_test123") - - # Mock subscription event - subscription = { - "id": "sub_test123", - "customer": "cus_test123", - "status": "active", - "current_period_start": 1700000000, - "current_period_end": 1702592000, - "cancel_at_period_end": False, - "items": { - "data": [ - { - "price": { - "id": "price_test_pro", - }, - }, - ], - }, - } # Temporarily set price mapping for test global PRICE_TO_TIER @@ -493,15 +473,49 @@ class TestWebhookHandling(Test.TestCase): PRICE_TO_TIER["price_test_pro"] = "pro" try: + # Step 1: Handle checkout.session.completed + checkout_session = { + "id": "cs_test123", + "client_reference_id": str(user_id), + "customer": "cus_test123", + "metadata": {"user_id": str(user_id), "tier": "pro"}, + } + _handle_checkout_completed(checkout_session) + + # Verify customer was linked + user = Core.Database.get_user_by_id(user_id) + self.assertIsNotNone(user) + assert user is not None + self.assertEqual(user["stripe_customer_id"], "cus_test123") + + # Step 2: Handle customer.subscription.created + subscription = { + "id": "sub_test123", + "customer": "cus_test123", + "status": "active", + "current_period_start": 1700000000, + "current_period_end": 1702592000, + "cancel_at_period_end": False, + "items": { + "data": [ + { + "price": { + "id": "price_test_pro", + }, + }, + ], + }, + } _update_subscription_state(subscription) - # Verify user was updated + # Verify subscription was created and user upgraded user = Core.Database.get_user_by_id(user_id) self.assertIsNotNone(user) assert user is not None self.assertEqual(user["plan_tier"], "pro") self.assertEqual(user["subscription_status"], "active") self.assertEqual(user["stripe_subscription_id"], "sub_test123") + self.assertEqual(user["stripe_customer_id"], "cus_test123") finally: PRICE_TO_TIER = old_mapping -- cgit v1.2.3