diff --git a/make_post_sell/tests/test_functional.py b/make_post_sell/tests/test_functional.py index 8e285a6..b29a9a8 100644 --- a/make_post_sell/tests/test_functional.py +++ b/make_post_sell/tests/test_functional.py @@ -1030,345 +1030,3 @@ class AuthenticatedFunctionalTests(FunctionalTests): del coupon_params["code"] res = self.make_new_coupon_for_shop(coupon_params) self.assertIn("Please submit all required fields.", res.body.decode()) - - # this patch requires an argument added to test method `mock_smtp`. - @patch("make_post_sell.models.Product.is_ready") - @patch("smtplib.SMTP") - @patch("stripe.SetupIntent.retrieve") - @patch("stripe.Customer.list_payment_methods") - def test_checkout_with_coupon_code( - self, - mock_list_payment_methods, - mock_setup_intent, - mock_smtp, - mock_product_ready, - ): - # Debug: Confirm mock objects - print(f"Mock SetupIntent: {mock_setup_intent}") - print(f"Mock SMTP: {mock_smtp}") - print(f"Mock Product.is_ready: {mock_product_ready}") - print(f"Mock list_payment_methods: {mock_list_payment_methods}") - - # Configure mocks - mock_product_ready.return_value = True - mock_setup_intent.return_value = { - "id": "seti_123", - "status": "succeeded", - "payment_method": "pm_card_visa", - "customer": "cus_123", - "client_secret": "seti_123_secret", - "payment_method_types": ["card"], - "payment_method_options": {"card": {}}, - "metadata": {"card_id": "pm_card_visa"}, - } - # Mock PaymentMethod object - payment_method = MagicMock() - payment_method.id = "pm_card_visa" - payment_method.type = "card" - payment_method.card.brand = "visa" - payment_method.card.last4 = "4242" - mock_list_payment_methods.return_value = {"data": [payment_method]} - - # Step 1: Create a coupon as user1 - res = self.make_new_coupon_for_shop() - res = res.follow() - self.assertIn("You created a new coupon!", res.body.decode()) - - # Re-query users and shop - self.user1 = get_or_create_user_by_email(self.dbsession, self.user1_creds[0]) - self.user2 = get_or_create_user_by_email(self.dbsession, self.user2_creds[0]) - shop = get_shop_by_name(self.dbsession, self.shop1_params["name"]) - - # Log out user1 - self.testapp.get("/log-out") - - # Log in user2 - self.log_in_user(self.user2_creds) - - # Refresh the shop to ensure it's committed - self.dbsession.refresh(shop) - print( - f"Shop UUID: {shop.uuid_str}, Ready: {shop.is_ready}, " - f"Public key: {shop.stripe_public_api_key}, " - f"Secret key: {shop.stripe_secret_api_key}" - ) - - # Verify shop is ready - self.assertTrue( - shop.is_ready, - f"Shop {shop.name} is not ready. " - f"stripe_public_api_key: {shop.stripe_public_api_key}, " - f"stripe_secret_api_key: {shop.stripe_secret_api_key}", - ) - - # Step 2: Visit /billing to create StripeUserShop record for user2 - shop_id = str(shop.uuid_str) - res_billing_init = self.testapp.get(f"/billing?shop_id={shop_id}", status=200) - print(f"Billing init response: {res_billing_init.body.decode()}") # Debug - self.assertIn( - "The active card will be charged during checkout.", - res_billing_init.body.decode(), - ) # Verify billing page - - # Commit transaction to persist StripeUserShop - transaction.manager.commit() - - # Re-query users and shop - self.user1 = get_or_create_user_by_email(self.dbsession, self.user1_creds[0]) - self.user2 = get_or_create_user_by_email(self.dbsession, self.user2_creds[0]) - shop = get_shop_by_name(self.dbsession, self.shop1_params["name"]) - - # Step 3: Add billing details for user2 - csrf_token = self.get_csrf_token(shop.uuid_str) - if not csrf_token: - self.fail("CSRF token not found in session cookie (_csrft_)") - - print(f"Using shop_id for billing: {shop_id}") - res_billing_redirect = self.testapp.post( - f"/billing/add-card?shop_id={shop_id}", - { - "email": self.user2.email, - "setup_intent": "seti_123", - "setup_intent_client_secret": "seti_123_secret", - "csrf_token": csrf_token, - }, - status=302, - ) - res_billing = res_billing_redirect.follow() - res_billing = res_billing.follow() - print(f"Billing response: {res_billing.body.decode()}") # Debug - self.assertIn( - "You saved a new card.", res_billing.body.decode() - ) # Match view's flash message - - # Commit transaction to persist card - transaction.manager.commit() - - # Re-query users and shop - self.user1 = get_or_create_user_by_email(self.dbsession, self.user1_creds[0]) - self.user2 = get_or_create_user_by_email(self.dbsession, self.user2_creds[0]) - shop = get_shop_by_name(self.dbsession, self.shop1_params["name"]) - - # Verify StripeUserShop and set active card - stripe_user_shop = ( - self.dbsession.query(StripeUserShop) - .filter_by(user_id=self.user2.id, shop_id=shop.id) - .first() - ) - print(f"StripeUserShop for {self.user2.email}: {stripe_user_shop}") - print( - f"Card IDs before: {stripe_user_shop.stripe_card_ids if stripe_user_shop else None}" - ) - if stripe_user_shop and not stripe_user_shop.active_card_id: - stripe_user_shop.active_card_id = "pm_card_visa" - self.dbsession.add(stripe_user_shop) - self.dbsession.flush() - print(f"Manually set active card ID: {stripe_user_shop.active_card_id}") - print( - f"Active card ID: {stripe_user_shop.active_card_id if stripe_user_shop else None}" - ) - - # Commit transaction to persist StripeUserShop changes - transaction.manager.commit() - - # Re-query users and shop - self.user1 = get_or_create_user_by_email(self.dbsession, self.user1_creds[0]) - self.user2 = get_or_create_user_by_email(self.dbsession, self.user2_creds[0]) - shop = get_shop_by_name(self.dbsession, self.shop1_params["name"]) - - # Re-query StripeUserShop to verify persistence - stripe_user_shop = ( - self.dbsession.query(StripeUserShop) - .filter_by(user_id=self.user2.id, shop_id=shop.id) - .first() - ) - print(f"StripeUserShop after commit: {stripe_user_shop}") - print( - f"Active card ID after commit: {stripe_user_shop.active_card_id if stripe_user_shop else None}" - ) - print( - f"Card IDs after commit: {stripe_user_shop.stripe_card_ids if stripe_user_shop else None}" - ) - - # Query the coupon from the database - coupons = get_coupons_by_code(self.dbsession, self.coupon1_params["code"]) - coupon = coupons[0] - - # Step 4: Extract CSRF token for applying the coupon - csrf_token = self.get_csrf_token(shop.uuid_str) - if not csrf_token: - self.fail("CSRF token not found in session cookie (_csrft_)") - - # Step 5: Apply coupon to user2's active cart - res_coupon_apply_redirect = self.testapp.post( - f"/coupon/apply?shop_id={shop_id}", - { - "coupon_id": coupon.id, - "shop_id": shop_id, - "csrf_token": csrf_token, - }, - status=302, - ) - res_coupon_apply = res_coupon_apply_redirect.follow() - res_body = res_coupon_apply.body.decode() - - # Verify coupon was applied - self.assertIn("Slippery Halloween Party", res_body) - self.assertIn("3.50", res_body) - self.assertIn("camp31", res_body) - - # Commit transaction to persist coupon application - transaction.manager.commit() - - # Re-query users and shop - self.user1 = get_or_create_user_by_email(self.dbsession, self.user1_creds[0]) - self.user2 = get_or_create_user_by_email(self.dbsession, self.user2_creds[0]) - shop = get_shop_by_name(self.dbsession, self.shop1_params["name"]) - - # Step 6: Query the product from the database - all_products = get_all_products(self.dbsession) - product = all_products.one() - product_id = product.uuid_str - - # Step 7: Extract CSRF token for adding product to cart - csrf_token = self.get_csrf_token(shop.uuid_str) - if not csrf_token: - self.fail("CSRF token not found in session cookie (_csrft_)") - - # Step 8: Add product to user2's active cart - res_add_product_redirect = self.testapp.post( - f"/cart/add?shop_id={shop_id}", - { - "product_id": product_id, - "shop_id": shop_id, - "csrf_token": csrf_token, - }, - status=302, - ) - res_add_product = res_add_product_redirect.follow() - res_add_product = res_add_product.follow() - res_body = res_add_product.body.decode() - self.assertIn('You added "russell\'s product" to your cart.', res_body) - - # Commit transaction to persist cart - transaction.manager.commit() - - # Re-query users, shop, and cart - self.user1 = get_or_create_user_by_email(self.dbsession, self.user1_creds[0]) - self.user2 = get_or_create_user_by_email(self.dbsession, self.user2_creds[0]) - shop = get_shop_by_name(self.dbsession, self.shop1_params["name"]) - user_2_cart = shop.get_active_cart_for_user(self.user2) - - # Step 9: Get user2's active cart - self.assertIsNotNone(user_2_cart, "User2's active cart should not be None") - - # Step 10: Attempt checkout with insufficient cart total - csrf_token = self.get_csrf_token(shop.uuid_str) - if not csrf_token: - self.fail("CSRF token not found in session cookie (_csrft_)") - - res_checkout = self.testapp.post( - f"/u/cart/{user_2_cart.uuid_str}/checkout?shop_id={shop_id}", - { - "shop_id": shop_id, - "csrf_token": csrf_token, - }, - status=302, - ) - res_body = res_checkout.follow().body.decode() - print(f"First checkout response: {res_body}") # Debug - self.assertIn("Please review the terms for coupon", res_body) - self.assertIn("shop total not met.", res_body) - - # Commit transaction to persist checkout attempt - transaction.manager.commit() - - # Re-query users, shop, and cart - self.user1 = get_or_create_user_by_email(self.dbsession, self.user1_creds[0]) - self.user2 = get_or_create_user_by_email(self.dbsession, self.user2_creds[0]) - shop = get_shop_by_name(self.dbsession, self.shop1_params["name"]) - user_2_cart = shop.get_active_cart_for_user(self.user2) - - # Step 11: Add more products to meet coupon qualifier - for _ in range(2): - csrf_token = self.get_csrf_token(shop.uuid_str) - if not csrf_token: - self.fail("CSRF token not found in session cookie (_csrft_)") - - res_add_product_redirect = self.testapp.post( - f"/cart/add?shop_id={shop_id}", - { - "product_id": product_id, - "shop_id": shop_id, - "csrf_token": csrf_token, - }, - status=302, - ) - res_add_product = res_add_product_redirect.follow() - res_add_product = res_add_product.follow() - print(f"Add product response: {res_add_product.body.decode()}") # Debug - transaction.manager.commit() - - # Re-query users, shop, and cart - self.user1 = get_or_create_user_by_email( - self.dbsession, self.user1_creds[0] - ) - self.user2 = get_or_create_user_by_email( - self.dbsession, self.user2_creds[0] - ) - shop = get_shop_by_name(self.dbsession, self.shop1_params["name"]) - user_2_cart = shop.get_active_cart_for_user(self.user2) - - # Step 12: Attempt checkout again - csrf_token = self.get_csrf_token(shop.uuid_str) - if not csrf_token: - self.fail("CSRF token not found in session cookie (_csrft_)") - - # Step 12: Configure Stripe keys through settings form - # Login as shop owner (user1) to access settings - self.testapp.post('/log-in', self.user1_creds_dict, status=302) - - # Configure Stripe keys using proper settings form - stripe_settings_data = { - "stripe_public_api_key": environ["MPS_TEST_STRIPE_PUBLIC_API_KEY"], - "stripe_secret_api_key": environ["MPS_TEST_STRIPE_SECRET_API_KEY"], - "csrf_token": self.get_csrf_token(shop.uuid_str), - } - stripe_settings_res = self.testapp.post(f"/s/{shop.id}/settings", stripe_settings_data) - - # Check if the database values actually changed despite no flash messages - self.dbsession.refresh(shop) - keys_actually_set = (shop.stripe_public_api_key == environ["MPS_TEST_STRIPE_PUBLIC_API_KEY"] and - shop.stripe_secret_api_key == environ["MPS_TEST_STRIPE_SECRET_API_KEY"]) - self.assertTrue(keys_actually_set, "Stripe keys should be set in database") - self.assertTrue(shop.is_ready, "Shop should be ready for checkout after setting Stripe keys") - - # Log back in as user2 (the purchaser) - self.testapp.get("/log-out") - self.testapp.post('/log-in', self.user2_creds_dict, status=302) - - # Step 13: Complete checkout now that shop is ready - csrf_token = self.get_csrf_token(shop.uuid_str) - if not csrf_token: - self.fail("CSRF token not found in session cookie (_csrft_)") - - print(f"Shop before checkout: UUID: {shop.uuid_str}, Ready: {shop.is_ready}") - res_checkout_final = self.testapp.post( - f"/u/cart/{user_2_cart.uuid_str}/checkout?shop_id={shop_id}", - { - "shop_id": shop_id, - "csrf_token": csrf_token, - }, - status=302, # Should redirect to complete checkout since it's a free cart - ) - - # Follow the redirect to the invoice page - invoice_res = res_checkout_final.follow() - invoice_body = invoice_res.body.decode() - print(f"Invoice page response: {invoice_body}") # Debug - - # Step 14: Verify invoice displays coupon information - self.assertIn("TESTOFF100", invoice_body, "Invoice should show coupon code") - self.assertIn("100% off test coupon", invoice_body, "Invoice should show coupon description") - self.assertIn("Total Breakdown", invoice_body, "Invoice should show pricing breakdown") - self.assertIn("Discounts Applied", invoice_body, "Invoice should show discounts section")